c++ force compiler to opt out some piece of code - c++

I have a piece of code:
// some code, which only do sanity check
expensive checks
// sanity check end
Now how do I tell the compiler to force it to opt out
this piece? Basically it means when I compile with -O2 or
O3, I don't want it to be there...
Thanks!

You can accomplish this with a constant and a single if/def pair. This allows the code to still be compiled and checked for errors but omitted during optimization. This can prevent changes that might break the check code from going undetected.
#if defined(USE_EXPENSIVE_CHECKS) || defined(DEBUG)
#define USE_EXPENSIVE_CHECKS_VALUE true
#else
#define USE_EXPENSIVE_CHECKS_VALUE false
#endif
namespace {
const bool useExpensiveChecks = USE_EXPENSIVE_CHECKS_VALUE;
};
void function()
{
if(useExpensiveChecks == true)
{
// expensive checks
}
}

Instead of relying on the compiler to optimize the code out, you could pass the compiler an additional symbol definition only when you want the code to run:
// some code, which only do sanity check
#ifdef my_symbol
expensive checks
#endif
// sanity check end

Using macros and conditionals in the preprocessor is really the only way to avoid code being generated by the compiler.
So, here's how I would do it:
#ifdef NEED_EXPENSIVE_CHECKS
inline expensive_checking(params...)
{
... do expensive checking here ...
}
#else
inline expensive_checking(params...)
{
}
#endif
Then just call:
some code
expensive_checking(some_parameters...)
some other code
An empty inlined function will result in "no code" in any decent, modern compiler. Use -DNEED_EXPENSIVE_CHECKS in your debug build settings, and don't use that in release build.
I have also been known to use a combination of macro and function, such as this:
#ifdef NEED_EXPENSIVE_CHECKS
#define EXPENSIVE_CHECKS(stuff...) expensive_checks(__FILE__, __LINE__, stuff...)
inline expensive_checks(const char *file, int line, stuff ...)
{
if (some_checking)
{
cerr << "Error, some_checking failed at " << file << ":" << line << endl;
}
}
#else
#define EXPENSIVE_CHECKS(stuff...)
#endif
Now, you get information on which file and what line when something fails, which can be very useful if the checks are made in many places (and you can use __function__ or __pretty_function__ to get the function name as well, if you wish).
Obviously, the assert() macro will essentially do what my macro solution does, except it usually doesn't provide the filename and line-number.

Move your checks into a different function, then import cassert and write assert(expensive_check()). When you want to disable the checks, use #define NDEBUG before the inclusion of cassert.

Related

How to use preprocessor IF on DEFINE that is an ENUM member?

I am struggling with this for a while now, and cant get it to work!
I have a preprocessor define for LOG_LEVEL which defines what logs my program should emit.
I Have a lot of LOG points, so performance is needed,
therefore, no use of runtime check for log_level.
I trimmed my code to the minimal problematic construct which can be played with (here)[https://onlinegdb.com/u39ueqNAI]:
#include <iostream>
typedef enum {
LOG_SILENT=0,
LOG_ERROR,
LOG_WARNING,
LOG_INFO,
LOG_DEBUG
} E_LOG_LEVELS;
// this define is set using -DLOG_LEVEL=LOG_WARNING to the compiler.
#define LOG_LEVEL LOG_WARNING
int main() {
std::cout << "Logging Level Value is " << LOG_LEVEL << std::endl; // output 2 (correctly)
#if LOG_LEVEL==LOG_WARNING
std::cout << "Log Level Warning!" << std::endl; // outputs (correctly)
#endif
#if LOG_LEVEL==LOG_ERROR
std::cout << "Log Level Error!" << std::endl; // outputs (Why ??? )
#endif
return 0;
}
The main issue is that the #if LOG_LEVEL==LOG_* always true.
I also tried #if LOG_LEVEL==2 but this returned FALSE (uff).
what's going on ?
how can I test that a define is an enum value ?
You don't need the preprocessor for this. A normal
if (LOG_LEVEL <= LOG_WARNING)
will not create a runtime test when the condition involves only constants and the build has any optimization at all.
Modern C++ allows you to force the compiler to implement the conditional at compile-time, using if constexpr (...). This will prune away dead branches even with optimization disabled.
Finally, if you insist on using the preprocessor, and you can guarantee that the macro will use the symbolic name (you'll never build with g++ -DLOG_LEVEL=2), then you can
#define STRINGIFY(x) #x
#define STRINGY2(x) STRINGIFY(x)
#define PP_LOG_LEVEL STRINGY2(LOG_LEVEL)
#define LOG_LEVEL_IS(x) STRINGY2(LOG_LEVEL)==STRINGIFY(x)
then either
#if PP_LOG_LEVEL=="LOG_WARNING"
or
#if PP_LOG_LEVEL_IS(LOG_WARNING)
But I would recommend avoiding preprocessor string comparison for this.
If you do use the preprocessor, I recommend checking the actual value against a whitelist and using #error to stop the build in case LOG_LEVEL isn't set to any of the approved names.

Replace 'Define macro' with empty implementation

I usually use the #define macro to add code that will be here while compiling as debug time and not while compiling as release. For instance:
#ifdef NDEBUG
# define LOG(msg) (void)msg
#else
# define LOG(msg) MyDebugLogger(msg)
#endif
Instead of that, I was thinking of using plain function and, just not providing the body for the release method:
void MyDebugLogger(std::string const& msg);
In MyDebugLogger.cpp:
void MyDebugLogger(std::string const& msg)
{
#ifdef NDEBUG
std::clog << msg << "\n"; // Or whatever
#else
(void)msg;
#endif
}
I'm expecting that the compilers will have the power to strip out the call and add no extra cost in Release. Am I correct?
For some reason, could it be a bad practice?
EDIT: My question is: If I use macros as before, I know that in Release mode, the executable will be smaller and faster, as all the code has been removed.
If I use the function, will it be the same? As the compiler may understand that the function does nothing and is not necessary. (Or it will add an extra, even small, for calling an empty function)
practically you would do the same as with the macro:
void MyDebugLogger(std::string const& msg)
{
#ifdef NDEBUG
std::clog << msg << "\n"; // Or whatever
#endif
}
You'r example should work, with a little tweak. In your current version the compiler "sees" just the function signature and will emit a call to it's symbol, which will later be resolved via the linker, so it can't optimize it out on it's own. (Link Time Optimizations might help with that, but that depends very much on you'r setup and dynamic linking would make this impossible). So maybe try something like this
in the header:
// Assuming you are using clang or gcc,
// but is required to not give an error by the standard and probably
// not even needed.
[[gnu::always_inline]]
void MyDebugLogger(std::string const& msg [[maybe_unused]])
{
#ifdef NDEBUG
MyDebugLoggerImplementation(msg);
#endif
}
And then implement it in you .cpp file. Another benefit of this method is that you
method needs the Logger to be compiled with NDEBUG while this method gives the client code the choice.

Somehow tell compiler to "Do not process line of code"

I'm trying to create a macro for debug logging purposes. Here is an extra simplified version:
#if defined _DEBUG
#define LOG std::cout
#else
#define LOG IGNORETHISLINEOFCODE
#endif
/* ... */
LOG << "Here's some debug code";
I've been thinking of the ways I can tell the compiler to ignore this line of code that starts with "LOG". I'm personally not looking for alternative ways, such as #define LOG( ... ) (void)0. Here's what I've tried:
Overloading the leftshift operator for void as an inline constexpr that does nothing (which still results in it being visible in the disassembly; I don't want that)
Defining LOG as: #define LOG //, but the comment identifier isn't substituted in
Any ideas? Like I said earlier, I don't want any alternatives, such as surrounding all the log code with #if defined _DEBUG
If your version of C++ handles if constexpr I've come to like things along this line for what you're asking.
#include <iostream>
template <bool Log>
struct LOGGER {
template <typename T>
LOGGER& operator<<(T const &t) {
if constexpr (Log)
std::cout << t;
return *this;
}
};
LOGGER<false> LOG;
int main (int argc, char const* argv[])
{
LOG << "A log statement." << '\n';
return 0;
}
Your question and constraint ("I don't want any alternatives") are weirdly specific.
I've been thinking of the ways I can tell the compiler to ignore this line of code that starts with "LOG"
Don't do that, it'll be trivially broken by a multi-line logging statement. Any code that can suddenly break due to otherwise-legal reformatting is best avoided.
Next we have
... which still results in it being visible in the disassembly ...
which shouldn't be true if the code is genuinely dead, you have a decent compiler, and you turn on optimization. It's still some work, though.
The usual solution is something like
#ifdef NDEBUG
#define LOG(EXPR)
#else
#define LOG(EXPR) std::cerr << EXPR
#endif
This is an alternative, but it's not an alternative such as surrounding all the log code with #if defined, so I don't know if it's a problem for you or not.
It does have the advantage of genuinely compiling to nothing at any optimization level.
another possibility based on the compiler optimization abilities:
#define LOG if (DEBUG) std::cout
now you can use
#define DEBUG false
LOG << "hello " << " world 1" << endl;
you should be able to use const bool DEBUG = false as well.
#if defined _DEBUG
#define LOG std::cout
#else
#define LOG /##/
#endif
This works as well. It's the answer to the original question, so I'll mark it as such, but just know that this does not support multiline operations.
I suppose you could do something like the following for multiline operations. I don't know how well it'd work.
#if defined _DEBUG
#define LOG( in ) std::cout << in
#else
#define LOG( in ) /##/
#endif
Better logic would be to define tracer policy, where you can set the logging level at the start of the application and then use the tracing level to make the decision to either log the degug information. Tracing level can be defined as an enum like
enum Tracelevel{CRITICAL, ERROR, INFO, TEST, DEBUG};
setTraceLevel(TraceLevel trcLvl){
_traceLevel = trcLvl;
};
#if defined _DEBUG
if(_traceLevel == DEBUG) {\
#define LOG std::cout
}
#endif
A lightweight logger can be found http://www.drdobbs.com/cpp/a-lightweight-logger-for-c/240147505?pgno=1

How to remove log debugging statements from a program

I am using boost::log as a logger for my C++ program.
During development I often use it this way, for example:
#define LOG(severity) BOOST_LOG_SEV(boost::logger::get(), (severity))
#define LOG_ERR LOG(Severity::error)
#define LOG_INFO LOG(Severity::info)
#define LOG_DEBUG LOG(Severity::debug)
where BOOST_LOG_SEV is the facility provided by boost::log, while LOG, LOG_ERROR, LOG_INFO, LOG_DEBUG are shortcuts defined by me.
In short, BOOST_LOG_SEV dynamically compares the current debugging severity with the severity passed to the macro itself to decide whether to emit the output or not.
This is an example of a program which use the above macros for debugging purposes:
// set at compile time
#define MAX_LOG_SEVERITY Severity::debug
int main() {
// Print all the messages with a
// Severity <= MAX_LOG_SEVERITY defined before compiling
boost::log::set_severity(boost::logger::get(), MAX_LOG_SEVERITY); // set_severity() is fictitious just to give you an idea
// bool err = ...
if (err)
LOG_ERR << "An error occurred";
else
LOG_INFO << "Okay;
LOG_DEBUG << "main() called";
}
Now, when releasing the program for a production environment, debugging messages with a Severity::debug level do not really make sense. I could hide them from the output by simply decreasing MAX_LOG_SEVERITY to Severity::info, but the problem is that the calls made by LOG_DEBUG will not be removed from the executable code. This has a bad impact on both efficiency and object size.
The code is full of logging statements and I'd really like to preserve the simple use of operator<<().
Without touching those statements themselves, is there any better macro definition/trick for LOG_DEBUG that would make the pre-processor or the compiler (during its optimizations) "skip" or "remove" the debugging statements when MAX_LOG_SEVERITY is set to the Severity::debug constant ?
While I can't make any guarantees, something like this might work. It depends on what your optimizer does and whether or not you have side effects in the parameters to operator<<.
#ifdef NO_LOG_DEBUG
static class DevNull
{
} dev_null;
template <typename T>
DevNull & operator<<(DevNull & dest, T)
{
return dest;
}
#define LOG_DEBUG dev_null
#else
#define LOG_DEBUG LOG(Severity::debug)
#endif
#MartinShobe's accepted answer works on:
g++ (4.7.2) with -O1 and higher
clang++ (3.4) with -O2 and higher
Visual Studio (2008) with linker flag /OPT:REF
The accepted answer does not work for me (MSVC 2019, stdc++17).
My solution is a bit whacky though. But the optimization should definitely take care of it:
#ifdef NDEBUG
#define LOG_DEBUG if (false) std::cout
#else
#define LOG_DEBUG if (true) std::cout
#endif
Usage:
LOG_DEBUG << ... << std::endl;
Turns off all optimizations in the program and speeds compilation.
/Od
or boot_log_stop

C++ performance, optimizing compiler, empty function in .cpp

I've a very basic class, name it Basic, used in nearly all other files in a bigger project. In some cases, there needs to be debug output, but in release mode, this should not be enabled and be a NOOP.
Currently there is a define in the header, which switches a makro on or off, depending on the setting. So this is definetely a NOOP, when switched off. I'm wondering, if I have the following code, if a compiler (MSVS / gcc) is able to optimize out the function call, so that it is again a NOOP. (By doing that, the switch could be in the .cpp and switching will be much faster, compile/link time wise).
--Header--
void printDebug(const Basic* p);
class Basic {
Basic() {
simpleSetupCode;
// this should be a NOOP in release,
// but constructor could be inlined
printDebug(this);
}
};
--Source--
// PRINT_DEBUG defined somewhere else or here
#if PRINT_DEBUG
void printDebug(const Basic* p) {
// Lengthy debug print
}
#else
void printDebug(const Basic* p) {}
#endif
As with all questions like this, the answer is - if it really matters to you, try the approach and examine the emitted assembly language.
Compiler possibly may optimize this code, if it knows printDebug function implementation at compilation time. If printDebug is in another object module, this possibly may be optimized only by linker, using the whole program optimization. But the only way to test this is to read compiler-generated Assembly code.
If you already have PRINT_DEBUG macro, you can extend it by the way as TRACE is defined:
#define PRINT_DEBUG // optional
#ifdef PRINT_DEBUG
#define PRINT_DEBUG_CALL(p) printDebug(p)
#else
#define PRINT_DEBUG_CALL(p)
#endif
void printDebug(const Basic* p);
class Basic {
Basic() {
simpleSetupCode;
// this should be a NOOP in release,
// but constructor could be inlined
PRINT_DEBUG_CALL(this);
}
};
--Source--
// PRINT_DEBUG defined somewhere else or here
#if PRINT_DEBUG
void printDebug(const Basic* p) {
// Lengthy debug print
}
#endif
#if PRINT_DEBUG
#define printDebug _real_print_debug
#else
#define printDebug(...)
#endif
This way the preprocessor will strip all debug code before it even gets to the compiler.
Currently most of the optimizations are done at compile time. Some compilers as LLVM are able to optimize at link time. This is a really interesting idea. I suggest you to take a look at.
Waiting for these kind of optimization, what you can do is the following. Define a macro that let you include the following statement depending on whether DEBUG is defined or not.
#ifdef DEBUG
#define IF_DEBUG (false) {} else
#else
#define IF_DEBUG
#endif
You can the use it like this
Basic() {
simpleSetupCode;
// this should be a NOOP in release,
// but constructor could be inlined
IF_DEBUG printDebug(this);
}
which is already much more readable than
Basic() {
simpleSetupCode;
// this should be a NOOP in release,
// but constructor could be inlined
#if DEBUG
printDebug(this);
#endif
}
Note that you can use it as if it was a keyword
IF_DEBUG {
printDebug(this);
printDebug(thas);
}
errm, why not use the pre-processor macro differently?
Just of the top of my head, something like:
#define DEBUG_TRACE(p)
#ifdef PRINT_DEBUG
printDebug(p);
#else
;
#endif