[LLVMdev] Problem recognizing nested select operations
    Roel Jordans 
    r.jordans at tue.nl
       
    Thu Mar 29 05:53:56 PDT 2012
    
    
  
Hello all,
I just noticed that LLVM has trouble recognizing nested simple select 
operations.
My testcase is as follows:
-------------------------- snip ------------------------------
#include <stdio.h>
int main(int argc, char **argv)
{
	int a;
	scanf("%d", &a);
	a = a > 255 ? 255 : a < 0 ? 0 : a;
	printf("A: %d\n", a);
	return 0;
}
-------------------------- snip ------------------------------
Compiling using 'clang -emit-llvm -O3 -S test.c -o -' results in the 
following:
-------------------------- snip ------------------------------
define i32 @main(i32 %argc, i8** nocapture %argv) nounwind {
entry:
   %a = alloca i32, align 4
   %call = call i32 (i8*, ...)* @__isoc99_scanf(i8* getelementptr 
inbounds ([3 x i8]* @.str, i32 0, i32 0), i32* %a) nounwind
   %0 = load i32* %a, align 4, !tbaa !0
   %cmp = icmp sgt i32 %0, 255
   br i1 %cmp, label %cond.end4, label %cond.false
cond.false:                                       ; preds = %entry
   %cmp1 = icmp slt i32 %0, 0
   %cond = select i1 %cmp1, i32 0, i32 %0
   br label %cond.end4
cond.end4:                                        ; preds = %cond.false, 
%entry
   %cond5 = phi i32 [ 255, %entry ], [ %cond, %cond.false ]
   store i32 %cond5, i32* %a, align 4, !tbaa !0
   %call6 = call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([7 
x i8]* @.str1, i32 0, i32 0), i32 %cond5) nounwind
   ret i32 0
}
-------------------------- snip ------------------------------
But the following output is much more efficient in this case:
-------------------------- snip ------------------------------
define i32 @main(i32 %argc, i8** nocapture %argv) nounwind {
entry:
   %a = alloca i32, align 4
   %call = call i32 (i8*, ...)* @__isoc99_scanf(i8* getelementptr 
inbounds ([3 x i8]* @.str, i32 0, i32 0), i32* %a) nounwind
   %0 = load i32* %a, align 4, !tbaa !0
   %cmp = icmp sgt i32 %0, 255
   %cond = select i1 %cmp, i32 255, i32 %0
   %cmp1 = icmp slt i32 %cond, 0
   %cond5 = select i1 %cmp1, i32 0, i32 %cond
   store i32 %cond5, i32* %a, align 4, !tbaa !0
   %call6 = call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([7 
x i8]* @.str1, i32 0, i32 0), i32 %cond5) nounwind
   ret i32 0
}
-------------------------- snip ------------------------------
Is this something I should expect LLVM to solve or is there a reason for 
lazy evaluation of the inner nested select? I suppose that lazy 
evaluation is in the C standard and may be expected but in this case it 
would be perfectly safe to speculatively evaluate the inner nested 
select and transform the phi statement into a second select... Is there 
a transformation available capable of such a speculative move?
Cheers,
  Roel
    
    
More information about the llvm-dev
mailing list