HiRoel
In SimplifyCFG.cpp, SpeculativelyExecuteBB will turn a BB with a single
instruction into a select. Your case has the two instructions, icmp and select,
so it skips that BB.
You could try change that code to allow your case but I have no idea if its a
good idea performance wise on all the test suite.
Cheers,
Pete
On Mar 29, 2012, at 5:53 AM, Roel Jordans <r.jordans at tue.nl> wrote:
> 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
> _______________________________________________
> LLVM Developers mailing list
> LLVMdev at cs.uiuc.edu http://llvm.cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev