0

I have this class template defined in test.hpp:

#pragma once

extern void Foo();

template <typename F>
class MyClass {
public:
  void Compute() {
    Foo();
  }
};

And a function test() instantiate MyClass in test.cpp:

#include "test.hpp"

void test() {
  MyClass<int> a;
  a.Compute();
}

If compiled with clang++ test.cpp -S -emit-llvm, MyClass<int> and MyClass<int>::Compute() are kept in generated ll file.

  6 %class.MyClass = type { i8 }
  7 ; Function Attrs: noinline optnone ssp uwtable
  8 define void @_Z4testv() #0 {
  9   %1 = alloca %class.MyClass, align 1
 10   call void @_ZN7MyClassIiE7ComputeEv(%class.MyClass* %1)
 11   ret void
 12 }
 13 ; Function Attrs: noinline optnone ssp uwtable
 14 define linkonce_odr void @_ZN7MyClassIiE7ComputeEv(%class.MyClass* %0) #0 align 2 {
 15   %2 = alloca %class.MyClass*, align 8
 16   store %class.MyClass* %0, %class.MyClass** %2, align 8
 17   %3 = load %class.MyClass*, %class.MyClass** %2, align 8
 18   call void @_Z3Foov()
 19   ret void
 20 }

But for O2 compilation, MyClass<int>::Compute() is inlined and deleted, together with the MyClass<int> definition. For some reason, I want them kept in the generated file, like in O0. So my question is that is there a way to keep them not deleted? I'd expect a simple attribute on the class or the member function.

----Edit----

The reason I want to keep the class is because I need to register it into a framework. That framework will find its 'Compute' method and call it on demand. I thought it may fail the framework if the class definition is deleted. But in my real senario, 'MyClass' needs to be derived from a base class provided by the framework, and 'Compute' is a virtual function that 'MyClass' needs to override. On registering this class, I must provide a builder which returns a pointer of base class, pointing to 'MyClass' (like template <typename F> BaseClass *Builder() { return new MyClass<F>{}; }. And with all these present, the compiler won't delete 'MyClass'. When I was asking this question, I was trying to implement this derived class as a template class in a header file, and thought it might be a little bit different than a regular class implemented in cpp file that the framework usually expect. It turns out not that special. So I guess my question is not a good question. Thanks for all the comments and answers, still help me a lot, thanks.

Long
  • 247
  • 1
  • 7
  • 3
    A C++ compiler is allowed to perform any optimization that has no observable effects. Your compiler has determined that performing this optimization has no observable effect, hence it is removed. What actual, real problem does this optimization create for you? – Sam Varshavchik Jan 23 '21 at 15:10
  • make it volatile – bakaDev Jan 23 '21 at 15:15
  • Can you explain why you need to to keep it? What problem do you try to solve with that? Depending on why you need that the correct answer might be different. – t.niese Jan 23 '21 at 15:34
  • The reason I want to keep it is because I need to register the class `MyClass` (actually `MyClass` into a framework, and that framework calls its `Compute()` function. So if they are deleted, I'm afraid the framework won't find them. – Long Jan 24 '21 at 02:35
  • @Long Not enough context to tell, but maybe you are looking for [explicit template instantiation](https://stackoverflow.com/questions/2351148/explicit-template-instantiation-when-is-it-used). – dxiv Jan 24 '21 at 08:03
  • @dxiv Close to what I want. But in my case, the type parameter `F` in the template will be a lambda function given by user, which is not predictable.. – Long Jan 24 '21 at 14:07
  • @Long You should [edit](https://stackoverflow.com/posts/65860737/edit) the question to reflect what you actually mean to ask. – dxiv Jan 24 '21 at 23:09

1 Answers1

2

according to How to prevent gcc optimizing some statements in C?

for GCC You can use

#pragma GCC push_options
#pragma GCC optimize ("O0")

your code

#pragma GCC pop_options

or

 __attribute__((optimize("O0")))

for CLANG use:

[[clang::optnone]]

https://clang.llvm.org/docs/AttributeReference.html#id318


if your use this flags for generating ll file it will produce the correct code and you won't need to change the code:

-O2 -Xclang -disable-llvm-passes -S -emit-llvm

https://gcc.godbolt.org/z/oe31nv

bakaDev
  • 367
  • 2
  • 7