Function call constant propagation in C++
I couldn't find the answer through searching, so next step is asking. Say I have some code like this:
template<class Int>
inline Int onbit(Int value, int n) {
return value | (static_cast<Int>(1) << n);
}
If I call the code, like this onbit(A, 4)
, would the constant 4
be propagated through and optimized, or should I make it a template (template<int n, class Int>
) so that it would be constant. Is C++0x constexpr neccessary here and if so, how exactly should I use it (should int n
be const or constexpr?).
I know that constexpr would work with constant parameters, but would it partially be optimized if part of the parameters were constant and part were variable?
Summary: Is it poss开发者_运维知识库ible for a function (it has to be inline right?) to be partially optimized with constant propagation, and, if so, what are the requirements to do it?
Even as I am writing this I am thinking that an inline function call would propagate constants...
You can't guarantee that all compilers will optimize this code, although most modern compilers (MSVC and gcc) will, at least in most cases (it depends on the context) without regard to const-ness, since the function is so simple.
On the other hand, you can't guarantee that any compiler will optimize it strictly better when you do use const.
So, if optimization is important for you, in all cases the only answer is - check your assembly in the cases when it matters. Your compiler may optimize it in one file, but not the other (e.g. when this function is called deep inside a convoluted template, it is conceivable though improbable that your compiler's optimizer will give up and not optimize it in some cases).
I believe you should rely on const only when it's needed for compile-time checks, and you should rely on checking generated assembly when it's needed for run-time efficiency.
In most probable scenario, yes it should do it where you are calling Onbit(A,4) even in the form you have given the code. However, again, we can just hope here that the compiler does it. There is no way that you can be SURE that the optimization will be done. Standards have left it to the implementation of compilers to do it as the way they want.
You need to add int n to the template arguments to enforce "constant propagation". Do keep in mind that you will be generating new machine code for every place you invoke onbit() with a different n as the template argument (which I guess is what you would have to live with if you propagated the constant).
Templating a function doesn't mean that the compiler will inline it. It is up to the compiler to inline the generated code from the template (you should be able to override it using compiler specific extensions if you are sure that you are thinking better than the compiler).
However, if you are thinking of enforcing a combination of constant propagation and inline expansion, I would suggest going with macros. There is really nothing else in C/C++ which can get you the combination of inlining and constant propagation in one cross-platform way.
#define ON_BIT(v,n) ((v) | 1 << (n))
or something similar. I know it is evil to use macros... but I guess you are a bad boy anyways, thinking about pre-mature optimization :).
精彩评论