[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 10:44:47 PDT 2015


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);
+  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)




More information about the llvm-commits mailing list