I have a piece of code with this structure:
__forceinline void problemFunction(bool condition, int & value)
{
if (condition)
{
value = 0;
return;
}
// ...
// a lot of calculations
// ...
}
void caller()
{
bool condition;
int value;
// ...
problemFunction(condition, value);
someOtherStuff();
}
But after building Release configuration with optimization turned on in Disassembly I get something like this:
void caller()
{
bool condition;
int value;
// ...
if (condition)
value = 0;
else
goto CalculateLabel;
ReturnProblemFunctionLabel:
someOtherStuff();
goto ReturnLabel;
CalculateLabel:
// ...
// a lot of calculations
// ...
goto ReturnProblemFunctionLabel;
ReturnLabel:
}
ProblemFunction was splitted into two parts. And the proble is that the second part is located after the someOtherStuff function call.
How can I locally suppress this kind of optimization?
I am using Visual Studio 2019 Version 16.4.2 on Windows 10.
In C++20 you can mark branches with the likely/unlikely attribute (see this question and cppreference), which can give the compiler a hint on how to better optimize the code. In your original post I'm assuming that the condition passed to problemFunction is usually false, which would mean an unnecessary jump in most cases.
As you can see on godbolt, if you mark your if statement with [[unlikely]] g++ will output your desired result, but msvc will not change the generated code. Note that this example is just a basic demo. Compiling your actual program may give different results.
Also note that jumps do not necessarily mean worse performance, because of branch prediction. You have to measure your execution time to make any meaningful conclusions.
Related
I have to admit I appreciate the effort the Visual Studio static code analyzer does. It has found some issues in my C/C++ code that could, under certain circumstances, lead to some unusual bugs.
However, there are some other places where it finds issues that I have already prepared for.
Take for instance something like this: I have a C array, with a static size somewhere:
static const int DataSize = 100;
int Data[DataSize];
...and then I have a method or function that accesses this data:
void DoSomething(size_t index)
{
if (index >= DataSize)
Panic("Out of bounds");
Data[index] = DoSomethingElse();
}
This Panic() function is meant to notify me when the precondition is not met, and points to an error that can't be recovered from. In a debug build, it breaks into the debugger so I can analyze what happened, while in a release build, it will intentionally crash the program, leaving some useful debug information.
However, if I compile this, Visual Studio 2019 gives me the following warning:
Warning C6386: Buffer overrun while writing to 'Data': the writable size is '400' bytes, but 'index' bytes might be written.
The warning is indeed valid, if I were not performing the precondition check just before.
One way to suppress this warning is by changing the code to something like:
void DoSomething(size_t index)
{
if (index >= DataSize)
{
Panic("Out of bounds");
return; // This is never reached...
}
Data[index] = DoSomethingElse();
}
But, not only this is unnecessarily verbose, it also may confuse the static code analyzer even more, because it can make it think that returning is a valid code path, further confusing it.
Another example, this time unrelated to arrays, and applicable to C and C++. Consider a function or method like this:
int DoSomeOperation(int operationType, int value)
{
int foo;
switch (operationType)
{
case 0:
foo = 10;
break;
case 1:
foo = value + 1;
break;
case 2:
foo = value - 1;
break;
// ... many more cases
default:
Panic("Invalid operationType");
// We never reach this line...
}
DoSomeOtherOperation(foo);
}
This raises the following warning in the DoSomeOtherOperation() line:
Warning C6001: Using uninitialized memory 'foo'.
Once again, I can either explicitly initialize foo, initialize it to something in the default case, or return from the function after Panic(), but technically, neither is necessary, since for all semantically valid values of operationType, foo is indeed initialized.
In fact, I might prefer to leave foo uninitialized at the beginning, so the static analyzer -does- catch a case where I did indeed missed the initialization.
Now, is there a way to annotate the Panic function, so the static code analyzer knows that this function will validate the precondition, or alternatively, that it terminates the program in all cases, so it doesn't have to consider the case where the function returns and the program continues?
I am not aware of any way to tell the analyzer that a parameter is checked in the code but isn't this a job exactly for the In_range(low, hi) annotation?
Change the declaration to the following and the analyzer should be able to check the precondition (So long as it picks up the values of static like DataSize in this example, I am not sure whether it does or not).
void DoSomething(_In_range_(0, DataSize)
SAL is described at
https://learn.microsoft.com/en-us/cpp/code-quality/using-sal-annotations-to-reduce-c-cpp-code-defects?view=msvc-160
I am writing a very simple compiler where users are allowed to define functions that return either void, int or char. However, users' function may be malformed. They may not return a value for a function that does not return void, or return a value for a function that returns void as declared. Currently my compiler is unable to detect this kind of errors and fails to generate proper code for function that returns void as this class of functions can return without a return; (they return implicitly). These two problems have cost me quite some time to phrase them out clearly. See the example code below:
// Problem A: detect implicit return.
void Foo(int Arg) {
if (Arg)
return;
else {
Arg = 1;
// Foo returns here! How can I know!
}
}
// Problem B: detect "forgotten return".
int Bar(int Arg) {
if (Arg > 1) {
return 1;
}
// this is an error: control flow reaches end at non-void function!
// How can I know!
}
I think the more general question may be: how can I tell the control flow reaches end at some point in a function? By saying reach end I mean the it reaches a point after which the function has no code to execute. If I can detect the end of control flow, I can look for a return at this point and either report an error if the function ought to return something or generate an explicit return for a void function. If I enumerate all such points of a function, I can ensure that the function is fully checked or complemented.
I see this problem as a well-solved one in compiler engineering since modern C/C++ can do that pretty well. Is LLVM can offer any API to do this? Or is there simple algorithm to achieve this? Thanks very much.
Edit: I am currently using LLVM and have BasicBlock emitted already. I hope a guide in doing this in LLVM specifically.
Edit: In this question we assume that the return type declared in the function prototype always matches that of its return stmt. I primarily focus on the absence of a required return.
The answer is simple. After all BB's of a function are emitted, loop over them and pick up those ends without a Terminator (see the llvm document for what is a Terminator Instruction). Assuming the emission of all kinds of control flow statements (While, For, etc.) follows the rule (One BB is ended by one and only one Terminator), the only possible explanation of these rule-breakers is that they miss a Return IR in the end. If the current function return void, append a ReturnVoid to them. Otherwise, this is an error, report it.
The reasoning is largely correct as it rely on the well-formed property of LLVM's BB and it is easy to implement, cheap to run. Here is the code:
/// Generate body for a Function.
void visitFuncDef(FuncDef *FD) {
// Unrelated code omitted...
/// Generate the body
for (Stmt *S : FD->stmts) {
visitStmt(S);
}
/// Check for well-formness of all BBs. In particular, look for
/// any unterminated BB and try to add a Return to it.
for (BasicBlock &BB : *Fn) {
Instruction *Terminator = BB.getTerminator();
if (Terminator != nullptr) continue; /// Well-formed
if (Fn->getReturnType()->isVoidTy()) {
/// Make implicit return of void Function explicit.
Builder.SetInsertPoint(&BB);
Builder.CreateRetVoid();
} else {
// How to attach source location?
EM.Error("control flow reaches end of non-void function");
// No source location, make errors short
return;
}
}
/// Verify the function body
String ErrorMsg;
llvm::raw_string_ostream OS(ErrorMsg);
if (llvm::verifyFunction(*Fn, &OS)) {
EM.Error(ErrorMsg);
}
}
Let's say you have a function in C/C++, that behaves a certain way the first time it runs. And then, all other times it behaves another way (see below for example). After it runs the first time, the if statement becomes redundant and could be optimized away if speed is important. Is there any way to make this optimization?
bool val = true;
void function1() {
if (val == true) {
// do something
val = false;
}
else {
// do other stuff, val is never set to true again
}
}
gcc has a builtin function that let you inform the implementation about branch prediction:
__builtin_expect
http://gcc.gnu.org/onlinedocs/gcc/Other-Builtins.html
For example in your case:
bool val = true;
void function1()
{
if (__builtin_expect(val, 0)) {
// do something
val = false;
}
else {
// do other stuff, val is never set to true again
}
}
You should only make the change if you're certain that it truly is a bottleneck. With branch-prediction, the if statement is probably instant, since it's a very predictable pattern.
That said, you can use callbacks:
#include <iostream>
using namespace std;
typedef void (*FunPtr) (void);
FunPtr method;
void subsequentRun()
{
std::cout << "subsequent call" << std::endl;
}
void firstRun()
{
std::cout << "first run" << std::endl;
method = subsequentRun;
}
int main()
{
method = firstRun;
method();
method();
method();
}
produces the output:
first run subsequent call subsequent call
You could use a function pointer but then it will require an indirect call in any case:
void (*yourFunction)(void) = &firstCall;
void firstCall() {
..
yourFunction = &otherCalls;
}
void otherCalls() {
..
}
void main()
{
yourFunction();
}
One possible method is to compile two different versions of the function (this can be done from a single function in the source with templates), and use a function pointer or object to decide at runtime. However, the pointer overhead will likely outweigh any potential gains unless your function is really expensive.
You could use a static member variable instead of a global variable..
Or, if the code you're running the first time changes something for all future uses (eg, opening a file?), you could use that change as a check to determine whether or not to run the code (ie, check if the file is open). This would save you the extra variable. Also, it might help with error checking - if for some reason the initial change is be unchanged by another operation (eg, the file is on removable media that is removed improperly), your check could try to re-do the change.
A compiler can only optimize what is known at compile time.
In your case, the value of val is only known at runtime, so it can't be optimized.
The if test is very quick, you shouldn't worry about optimizing it.
If you'd like to make the code a little bit cleaner you could make the variable local to the function using static:
void function() {
static bool firstRun = true;
if (firstRun) {
firstRun = false;
...
}
else {
...
}
}
On entering the function for the first time, firstRun would be true, and it would persist so each time the function is called, the firstRun variable will be the same instance as the ones before it (and will be false each subsequent time).
This could be used well with #ouah's solution.
Compilers like g++ (and I'm sure msvc) support generating profile data upon a first run, then using that data to better guess what branches are most likely to be followed, and optimizing accordingly. If you're using gcc, look at the -fprofile-generate option.
The expected behavior is that the compiler will optimize that if statement such that the else will be ordered first, thus avoiding the jmp operation on all your subsequent calls, making it pretty much as fast as if it wern't there, especially if you return somewhere in that else (thus avoiding having to jump past the 'if' statements)
One way to make this optimization is to split the function in two. Instead of:
void function1()
{
if (val == true) {
// do something
val = false;
} else {
// do other stuff
}
}
Do this:
void function1()
{
// do something
}
void function2()
{
// do other stuff
}
One thing you can do is put the logic into the constructor of an object, which is then defined static. If such a static object occurs in a block scope, the constructor is run the fist time that an execution of that scope takes place. The once-only check is emitted by the compiler.
You can also put static objects at file scope, and then they are initialized before main is called.
I'm giving this answer because perhaps you're not making effective use of C++ classes.
(Regarding C/C++, there is no such language. There is C and there is C++. Are you working in C that has to also compile as C++ (sometimes called, unofficially, "Clean C"), or are you really working in C++?)
What is "Clean C" and how does it differ from standard C?
To remain compiler INDEPENDENT you can code the parts of if() in one function and else{} in another. almost all compilers optimize the if() else{} - so, once the most LIKELY being the else{} - hence code the occasional executable code in if() and the rest in a separate function that's called in else
I have a "MyFunction" I keep obsessing over if I should or shouldn't use goto on it and in similar (hopefully rare) circumstances. So I'm trying to establish a hard-and-fast habit for this situation. To-do or not-to-do.
int MyFunction()
{ if (likely_condition)
{
condition_met:
// ...
return result;
}
else /*unlikely failure*/
{ // meet condition
goto condition_met;
}
}
I was intending to net the benefits of the failed conditional jump instruction for the likely case. However I don't see how the compiler could know which to streamline for case probability without something like this.
it works right?
are the benefits worth the confusion?
are there better (less verbose, more structured, more expressive) ways to enable this optimization?
It appears to me that the optimization you're trying to do is mostly obsolete. Most modern processors have branch prediction built in, so (assuming it's used enough to notice) they track how often a branch is taken or not and predict whether the branch is likely to be taken or not based on its past pattern of being taken or not. In this case, speed depends primarily on how accurate that prediction is, not whether the prediction is for taken vs. not taken.
As such, you're probably best off with rather simpler code:
int MyFunction() {
if (!likely_condition) {
meet_condition();
}
// ...
return result;
}
A modern CPU will take that branch either way with equal performance if it makes the correct branch prediction. So if that is in an inner loop, the performance of if (unlikely) { meet condition } common code; will match what you have written.
Also, if you spell out the common code in both branches the compiler will generate code that is identical to what you have written: The common case will be emitted for the if clause and the else clause will jmp to the common code. You see this all the time with simpler terminal cases like *out = whatever; return result;. When debugging it can be hard to tell which return you're looking at because they've all been merged.
It looks like the code should work as you expect as long as condition_met: doesn't skip variable initializations.
No, and you don't even know that the obfuscated version compiles into more optimal code. Compiler optimizations (and processor branch prediction) are getting very smart in recent times.
3.
int MyFunction()
{
if (!likely_condition)
{
// meet condition
}
condition_met:
// ...
return result;
}
or, if it helps your compiler (check the assembly)
int MyFunction()
{
if (likely_condition); else
{
// meet condition
}
condition_met:
// ...
return result;
}
I would highly recommend using the __builtin_expect() macro (GCC) or alike for your particular C++ compiler (see Portable branch prediction hints) instead of using goto:
int MyFunction()
{ if (__builtin_expect(likely_condition))
{
// ...
return result;
}
else /*unlikely failure*/
{ // meet condition
}
}
As others also mentioned goto is error prone and evil from the bones.
Sun Studio 12.1 prints the warning
Warning: The last statement should return a value.
frequently for functions like that:
int f()
{
/* some code that may return */
// if we end up here, something is broken
throw std::runtime_error("Error ...");
}
It is perfectly clear that we do not need a return value at the end of the function. I hesitate to insert something like
// Silence a compiler warning
return 42;
at the end of such a function, since it is dead code anyway. For more complicated return types, it might actually be difficult to construct a 'sensible' bogus value.
What is the recommended way to silence such a warning?
Can you reorganize the code in the function in such a way (hopefully more logical as well) that the normal path happens at the end of the function so that a return can be used, and the exceptional path happens earlier, NOT as the last statement?
EDIT: If reorganizing the function really doesn't make sense, you can always just put a dummy return 0; with a comment. It's better to squelch the warning that way than more globally.
If you really want to quiet the warning permanently, you can use #pragma error_messages (off, wnoretvalue) but note that the warning really is useful most of the time so I absolutely don't suggest turning it off. You can use the on version of the pragma to re-enable the warning after the function, but the compiler will still emit the warning if your function is ever inlined. If you put the function in its own source file and use the pragma that should shush the warning relatively safely though, since it can't affect other translation units.
Another really wacky possibility is to switch to g++. Unless you're compiling for SPARC g++ may actually generate better code than Sun studio.
I find it a perfect spot for abort(). You should never end there, according to you, so something like:
UNREACHABLE("message")
which expands into:
#ifdef NDEBUG
#define UNREACHABLE(Message_) abort();
#else
#define UNREACHABLE(Message_) assert(0 && Message_);
#endif
Looks appropriate
Since you know the exception will be systematically called, why don't you simply return a 0?
Perhaps encapsulate the contents in a do { } while (false); construct:
int my_function()
{
int result = DEFAULT_VALUE;
do
{
result = /*...*/
// Whatever
if (error)
{
throw std::runtime_error("Error ...");
}
} while (false);
return result;
}
The idea is for normal operation to set the result value then let the execution flow to the end or use a break to jump to the return statement.
I don't know of a "recommended" way to deal with it, but to answer your question about coping with more complex types, what about:
ComplexType foo()
{
...
throw std::runtime( "Error..." );
return *(ComplexType*)(0);
}
This would then work with any return type. I realise it looks evil, but its there just to silence the warning. As you say, this code will never be executed, and it may even be optimised out.