Hi,
I’m have found that LLVM can infer variable value, and it may lead to bad situations.
here is a simple function(t.c) :
1 extern unsigned NestCount1;
2 extern unsigned NestCount2;
3 unsigned foo(unsigned a)
4 {
5 if (NestCount1 > 0) {
6 NestCount1–;
7 }
8 if (NestCount1 == 0 && NestCount2 == 0) {
9 return a;
10 }
11 return 0;
12 }
and when I run : `clang -O3 -S -emit-llvm t.c -o t.ll ', I get the following code:
9 define i32 @foo(i32 %a) #0 {
10 %1 = load i32* @NestCount1, align 4, !tbaa !1
11 %2 = icmp eq i32 %1, 0
12 br i1 %2, label %5, label %3
13
14 ; :3 ; preds = %0
15 %4 = add i32 %1, -1
16 store i32 %4, i32* @NestCount1, align 4, !tbaa !1
17 br label %5
18
19 ; :5 ; preds = %0, %3
20 %6 = phi i32 [ 0, %0 ], [ %4, %3 ]
21 %7 = load i32* @NestCount2, align 4
22 %8 = or i32 %7, %6
23 %9 = icmp eq i32 %8, 0
24 %a. = select i1 %9, i32 %a, i32 0
25 ret i32 %a.
26 }
what confused me is LINE20: %6 = phi i32 [ 0, %0 ], [ %4, %3 ]
If I’m understanding it right, a phi will finally replaced by serveral move instructions. So, there will be an imm move instruction (like movl %0, %esi ) . However, if we change LINE20 to %6 = phi i32 [ %1, %0 ], [ %4, %3 ] and when the reg allocator map %1, %4 to the same register, we can save an imm move.
%6 = phi i32 [ 0, %0 ], [ %4, %3 ] seems harder to generate, so I think this should be an optimization taking by LLVM.
And here are my questions:
-
which optimization pass infer variable values ?
-
is it any bad to change to %6 = phi i32 [ %1, %0 ], [ %4, %3 ], (incresing register pressure ?)
Any ideas? Thanks.
Cheers.
Huang