Compiler opt is turned off ?

Hello,

I was trying to run few testcases and see how llvm optmizes different scenarios. I have a small testcase like:

#include <stdio.h>

int a, b, c;

int

main()

{

a = b + c;

c = a;

if (a == b)

b = c;

else

b = a;

printf( " a = %d \n ", a );

return 0;

}

The corresponding llvm IR is ( clang test.c -S -emit-llvm -o - -O3 ) :

define i32 @main() nounwind uwtable {

entry:

%0 = load i32* @b, align 4, !tbaa !4

%1 = load i32* @c, align 4, !tbaa !4

%add = add nsw i32 %1, %0

store i32 %add, i32* @a, align 4, !tbaa !4

store i32 %add, i32* @c, align 4, !tbaa !4

store i32 %add, i32* @b, align 4, !tbaa !4

%call = tail call i32 (i8*, …)* @printf(i8* getelementptr inbounds ([11 x i8]* @.str, i64 0, i64 0), i32 %add) nounwind

ret i32 0

}

Here, I can see, although the copy-propagation is kicked in, but, constant propagation is not happening. I assume the reason behind this is that a, b and c are all global variables. Also, as no one is reading b and c after the statement “a = b + c”, should they not get optimized out ( from “c = a” to end of function)?

Now, if a, b and c are made locals, all the optmizations are kicked in:

define i32 @main() nounwind uwtable {

entry:

%call = tail call i32 (i8*, …)* @printf(i8* getelementptr inbounds ([11 x i8]* @.str, i64 0, i64 0), i32 0) nounwind

ret i32 0

}

Are we little conservative on global variables even though they don’t have readers and debug mode is OFF ? Or, is it supported under some FLAG? Am I missing something … ?

Thanks.

Since a, b, and c are globals, how does the optimize know they are not used elsewhere (e.g. another module)?

Thanks for your reply. So, we don’t do any “use” check (for globals variables) beyond a module scope. If so, it answers my question.

I'm not sure what you mean by "use" check.
If you compile this with LTO and multiple modules, and guarantee that
you have the main function, yes, you could optimize this.
In all other cases, it's not possible to eliminate any of the
remaining loads or stores you see, because you have no guarantee about
what else could read it.

Heck, a conforming implementation of printf could read from any of
these globals, so you don't even need other modules.

I completely agree with you.

The source code I wrote here has the main function and is a complete code. That’s why I was expecting load/store analysis could have been incorporated across the module. Thanks.

I completely agree with you.

The source code I wrote here has the main function and is a complete code.
That's why I was expecting load/store analysis could have been incorporated
across the module. Thanks.

Clang doesn't know it's a complete program. You only told it to compile to
IR, so it has no idea what it will link against. I could write another C
file with "extern int a" and link these two together.

Now if you use static, e.g. "static int a, b, c;", then clang does optimize
them away.