[llvm] r247309 - [SimplifyCFG] Use known bits to eliminate dead switch defaults

David Majnemer via llvm-commits llvm-commits at lists.llvm.org
Thu Sep 10 13:17:52 PDT 2015


On Thu, Sep 10, 2015 at 10:44 AM, Philip Reames via llvm-commits <
llvm-commits at lists.llvm.org> wrote:

> Author: reames
> Date: Thu Sep 10 12:44:47 2015
> New Revision: 247309
>
> URL: http://llvm.org/viewvc/llvm-project?rev=247309&view=rev
> Log:
> [SimplifyCFG] Use known bits to eliminate dead switch defaults
>
> This is a follow up to http://reviews.llvm.org/D11995 implementing the
> suggestion by Hans.
>
> If we know some of the bits of the value being switched on, we know that
> the maximum number of unique cases covers the unknown bits. This allows to
> eliminate switch defaults for large integers (i32) when most bits in the
> value are known.
>
> Note that I had to make the transform contingent on not having any dead
> cases. This is conservatively correct with the old code, but required for
> the new code since we might have a dead case which varies one of the known
> bits. Counting that towards our number of covering cases would be bad.  If
> we do have dead cases, we'll eliminate them first, then revisit the
> possibly dead default.
>
> Differential Revision: http://reviews.llvm.org/D12497
>
>
> Modified:
>     llvm/trunk/lib/Transforms/Utils/SimplifyCFG.cpp
>     llvm/trunk/test/Transforms/SimplifyCFG/switch-dead-default.ll
>
> Modified: llvm/trunk/lib/Transforms/Utils/SimplifyCFG.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Utils/SimplifyCFG.cpp?rev=247309&r1=247308&r2=247309&view=diff
>
> ==============================================================================
> --- llvm/trunk/lib/Transforms/Utils/SimplifyCFG.cpp (original)
> +++ llvm/trunk/lib/Transforms/Utils/SimplifyCFG.cpp Thu Sep 10 12:44:47
> 2015
> @@ -3423,11 +3423,17 @@ static bool EliminateDeadSwitchCases(Swi
>    }
>
>    // If we can prove that the cases must cover all possible values, the
> -  // default destination becomes dead and we can remove it.
> +  // default destination becomes dead and we can remove it.  If we know
> some
> +  // of the bits in the value, we can use that to more precisely compute
> the
> +  // number of possible unique case values.
>    bool HasDefault =
>      !isa<UnreachableInst>(SI->getDefaultDest()->getFirstNonPHIOrDbg());
> -  if (HasDefault && Bits < 64 /* avoid overflow */ &&
> -      SI->getNumCases() == (1ULL << Bits)) {
> +  const unsigned NumUnknownBits = Bits -
> +    (KnownZero.Or(KnownOne)).countPopulation();
> +  assert(0 <= NumUnknownBits && NumUnknownBits <= Bits);
>

Isn't the first half of this assert vacuously true? NumUnknownBits is
unsigned and thus always greater than or equal to zero.


> +  if (HasDefault && DeadCases.empty() &&
> +      NumUnknownBits < 64 /* avoid overflow */ &&
> +      SI->getNumCases() == (1ULL << NumUnknownBits)) {
>      DEBUG(dbgs() << "SimplifyCFG: switch default is dead.\n");
>      BasicBlock *NewDefault = SplitBlockPredecessors(SI->getDefaultDest(),
>                                                      SI->getParent(), "");
>
> Modified: llvm/trunk/test/Transforms/SimplifyCFG/switch-dead-default.ll
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/SimplifyCFG/switch-dead-default.ll?rev=247309&r1=247308&r2=247309&view=diff
>
> ==============================================================================
> --- llvm/trunk/test/Transforms/SimplifyCFG/switch-dead-default.ll
> (original)
> +++ llvm/trunk/test/Transforms/SimplifyCFG/switch-dead-default.ll Thu Sep
> 10 12:44:47 2015
> @@ -2,7 +2,7 @@
>  declare void @foo(i32)
>
>  define void @test(i1 %a) {
> -; CHECK-LABEL @test
> +; CHECK-LABEL: @test
>  ; CHECK: br i1 [[IGNORE:%.*]], label %true, label %false
>    switch i1 %a, label %default [i1 1, label %true
>                                  i1 0, label %false]
> @@ -18,7 +18,7 @@ default:
>  }
>
>  define void @test2(i2 %a) {
> -; CHECK-LABEL @test2
> +; CHECK-LABEL: @test2
>    switch i2 %a, label %default [i2 0, label %case0
>                                  i2 1, label %case1
>                                  i2 2, label %case2
> @@ -45,7 +45,7 @@ default:
>  ; This one is a negative test - we know the value of the default,
>  ; but that's about it
>  define void @test3(i2 %a) {
> -; CHECK-LABEL @test3
> +; CHECK-LABEL: @test3
>    switch i2 %a, label %default [i2 0, label %case0
>                                  i2 1, label %case1
>                                  i2 2, label %case2]
> @@ -69,7 +69,7 @@ default:
>  ; Negative test - check for possible overflow when computing
>  ; number of possible cases.
>  define void @test4(i128 %a) {
> -; CHECK-LABEL @test4
> +; CHECK-LABEL: @test4
>    switch i128 %a, label %default [i128 0, label %case0
>                                    i128 1, label %case1]
>
> @@ -85,3 +85,95 @@ default:
>    call void @foo(i32 0)
>    ret void
>  }
> +
> +; All but one bit known zero
> +define void @test5(i8 %a) {
> +; CHECK-LABEL: @test5
> +; CHECK: br i1 [[IGNORE:%.*]], label %true, label %false
> +  %cmp = icmp ult i8 %a, 2
> +  call void @llvm.assume(i1 %cmp)
> +  switch i8 %a, label %default [i8 1, label %true
> +                                i8 0, label %false]
> +true:
> +  call void @foo(i32 1)
> +  ret void
> +false:
> +  call void @foo(i32 3)
> +  ret void
> +default:
> +  call void @foo(i32 2)
> +  ret void
> +}
> +
> +;; All but one bit known one
> +define void @test6(i8 %a) {
> +; CHECK-LABEL: @test6
> +; CHECK: @llvm.assume
> +; CHECK: br i1 [[IGNORE:%.*]], label %true, label %false
> +  %and = and i8 %a, 254
> +  %cmp = icmp eq i8 %and, 254
> +  call void @llvm.assume(i1 %cmp)
> +  switch i8 %a, label %default [i8 255, label %true
> +                                i8 254, label %false]
> +true:
> +  call void @foo(i32 1)
> +  ret void
> +false:
> +  call void @foo(i32 3)
> +  ret void
> +default:
> +  call void @foo(i32 2)
> +  ret void
> +}
> +
> +; Check that we can eliminate both dead cases and dead defaults
> +; within a single run of simplify-cfg
> +define void @test7(i8 %a) {
> +; CHECK-LABEL: @test7
> +; CHECK: @llvm.assume
> +; CHECK: br i1 [[IGNORE:%.*]], label %true, label %false
> +  %and = and i8 %a, 254
> +  %cmp = icmp eq i8 %and, 254
> +  call void @llvm.assume(i1 %cmp)
> +  switch i8 %a, label %default [i8 255, label %true
> +                                i8 254, label %false
> +                                i8 0, label %also_dead]
> +true:
> +  call void @foo(i32 1)
> +  ret void
> +false:
> +  call void @foo(i32 3)
> +  ret void
> +also_dead:
> +  call void @foo(i32 5)
> +  ret void
> +default:
> +  call void @foo(i32 2)
> +  ret void
> +}
> +
> +;; All but one bit known undef
> +;; Note: This is currently testing an optimization which doesn't trigger.
> The
> +;; case this is protecting against is that a bit could be assumed both
> zero
> +;; *or* one given we know it's undef.  ValueTracking doesn't do this
> today,
> +;; but it doesn't hurt to confirm.
> +define void @test8(i8 %a) {
> +; CHECK-LABEL: @test8(
> +; CHECK: switch i8
> +  %and = and i8 %a, 254
> +  %cmp = icmp eq i8 %and, undef
> +  call void @llvm.assume(i1 %cmp)
> +  switch i8 %a, label %default [i8 255, label %true
> +                                i8 254, label %false]
> +true:
> +  call void @foo(i32 1)
> +  ret void
> +false:
> +  call void @foo(i32 3)
> +  ret void
> +default:
> +  call void @foo(i32 2)
> +  ret void
> +}
> +
> +declare void @llvm.assume(i1)
>
>
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at lists.llvm.org
> http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20150910/474df06e/attachment.html>


More information about the llvm-commits mailing list