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

Philip Reames via llvm-commits llvm-commits at lists.llvm.org
Thu Sep 10 14:36:31 PDT 2015



On 09/10/2015 01:17 PM, David Majnemer wrote:
>
>
> On Thu, Sep 10, 2015 at 10:44 AM, Philip Reames via llvm-commits 
> <llvm-commits at lists.llvm.org <mailto: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.
Yep.  Will fix.
>
>     + 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 <mailto: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/77451280/attachment.html>


More information about the llvm-commits mailing list