Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++: optimizing function with no side effects

Is there a way in C++ to declare that a function has no side effects? Consider:

LOG("message").SetCategory(GetCategory()); 

Now suppose that the LOG macro in release builds creates a NullLogEntry object that has SetCategory() defined as an empty function. So basically the whole expression could (and should) be optimized away -- expcept that, in theory, the GetCategory() call may have some side effects, so I guess the compiler is not permitted to just throw it away.

Another example could be a function template specialization that ignores some (or all) of its arguments, yet the compiler is not allowed to save the evaluation of such arguments at the call site due to possible side effects.

Am I right? Or can compilers optimize away such calls anyway? If not, is there a way to hint the compiler that this function has no side effects, so if the return value is ignored then the whole call can be skipped?

like image 213
imre Avatar asked Jul 08 '11 11:07

imre


2 Answers

There is no standard way of doing so, but some compilers have annotations that you can use to that effect, for example, in GCC you can use the __attribute_pure__ tag in a function (alternatively __attribute__((pure))) to tell the compiler that the function is pure (i.e. has no side effects). That is used in the standard C library extensively, so that for example:

char * str = get_some_string();
for ( int i = 0; i < strlen( str ); ++i ) {
    str[i] = toupper(str[i]);
}

Can be optimized by the compiler into:

char * str = get_some_string();
int __length = strlen( str );
for ( int i = 0; i < __length; ++ i ) {
   str[i] = toupper(str[i]);
}

The function is declared in the string.h header as:

extern size_t strlen (__const char *__s)
     __THROW __attribute_pure__ __nonnull ((1));

Where __THROW is a no throw exception in case that it is a C++ compiler parsing the function, and __nonnull((1)) tells the compiler that the first argument should not be null (i.e. trigger a warning if the argument is null and -Wnonnull flag is used).

like image 103
David Rodríguez - dribeas Avatar answered Sep 20 '22 07:09

David Rodríguez - dribeas


The compiler cannot optimize away a call to the opaque function. However, if GetCategory is inline, and, hence visible at the call site, the compiler is allowed to, and it most cases, will optimize it away if it sees that it doesn't have side effects, but is not mandated to do so.

To achieve what you want with 100% certainty you need to wrap the entire statement in a macro that will evaluate to an empty statement for your release configuration.

like image 25
Alex B Avatar answered Sep 23 '22 07:09

Alex B