[llvm-commits] [llvm] r121671 - in /llvm/trunk: lib/Transforms/Utils/SimplifyCFG.cpp test/Transforms/SimplifyCFG/switch_create.ll

Frits van Bommel fvbommel at gmail.com
Mon Dec 13 04:29:42 PST 2010


On Mon, Dec 13, 2010 at 4:18 AM, Chris Lattner <sabre at nondot.org> wrote:
> Author: lattner
> Date: Sun Dec 12 21:18:54 2010
> New Revision: 121671
>
> URL: http://llvm.org/viewvc/llvm-project?rev=121671&view=rev
> Log:
> fix a fairly serious oversight with switch formation from
> or'd conditions.  Previously we'd compile something like this:
>
> int crud (unsigned char c) {
>   return c == 62 || c == 34 || c == 92;
> }
>
> into:
>
>  switch i8 %c, label %lor.rhs [
>    i8 62, label %lor.end
>    i8 34, label %lor.end
>  ]
>
> lor.rhs:                                          ; preds = %entry
>  %cmp8 = icmp eq i8 %c, 92
>  br label %lor.end
>
> lor.end:                                          ; preds = %entry, %entry, %lor.rhs
>  %0 = phi i1 [ true, %entry ], [ %cmp8, %lor.rhs ], [ true, %entry ]
>  %lor.ext = zext i1 %0 to i32
>  ret i32 %lor.ext
>
> which failed to merge the compare-with-92 into the switch.  With this patch
> we simplify this all the way to:
>
>  switch i8 %c, label %lor.rhs [
>    i8 62, label %lor.end
>    i8 34, label %lor.end
>    i8 92, label %lor.end
>  ]
>
> lor.rhs:                                          ; preds = %entry
>  br label %lor.end
>
> lor.end:                                          ; preds = %entry, %entry, %entry, %lor.rhs
>  %0 = phi i1 [ true, %entry ], [ false, %lor.rhs ], [ true, %entry ], [ true, %entry ]
>  %lor.ext = zext i1 %0 to i32
>  ret i32 %lor.ext
>
> which is much better for codegen's switch lowering stuff.  This kicks in 33 times
> on 176.gcc (for example) cutting 103 instructions off the generated code.

I have some code where this doesn't work, probably due to the
requirement for the only use of the icmp to be a phi. A reduced test
case:
=====
bool foo(int x) { return x == 1; }
bool bar(int x) { return x == 2; }
bool baz(int x) { return x == 3; }

bool quux(int x) {
  return foo(x) || bar(x) || baz(x);
}
=====
The problem seems to be that the return gets duplicated into the two
branches before inlining, causing quux() to come out of clang -O3 like
this:
=====
define zeroext i1 @quux(int)(i32 %x) nounwind readnone {
entry:
  switch i32 %x, label %lor.rhs [
    i32 1, label %lor.end
    i32 2, label %lor.end
  ]

lor.rhs:                                          ; preds = %entry
  %cmp.i5 = icmp eq i32 %x, 3                     ; [#uses=1]
  ret i1 %cmp.i5

lor.end:                                          ; preds = %entry, %entry
  ret i1 true
}
=====




More information about the llvm-commits mailing list