PR9450: Make switch optimization in SimplifyCFG not dependent on the ordering
authorEli Friedman <eli.friedman@gmail.com>
Tue, 15 Mar 2011 02:23:35 +0000 (02:23 +0000)
committerEli Friedman <eli.friedman@gmail.com>
Tue, 15 Mar 2011 02:23:35 +0000 (02:23 +0000)
of pointers in an std::map.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@127650 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Transforms/Utils/SimplifyCFG.cpp
test/Transforms/SimplifyCFG/UnreachableEliminate.ll

index 09f4fb2e1393a461b5bff434420d4bec45cfe71d..f924eebb0dfed53daf9f9335f7b05e2777341cbc 100644 (file)
@@ -2211,17 +2211,28 @@ bool SimplifyCFGOpt::SimplifyUnreachable(UnreachableInst *UI) {
       // If the default value is unreachable, figure out the most popular
       // destination and make it the default.
       if (SI->getSuccessor(0) == BB) {
-        std::map<BasicBlock*, unsigned> Popularity;
-        for (unsigned i = 1, e = SI->getNumCases(); i != e; ++i)
-          Popularity[SI->getSuccessor(i)]++;
-        
+        std::map<BasicBlock*, std::pair<unsigned, unsigned> > Popularity;
+        for (unsigned i = 1, e = SI->getNumCases(); i != e; ++i) {
+          std::pair<unsigned, unsigned>& entry =
+              Popularity[SI->getSuccessor(i)];
+          if (entry.first == 0) {
+            entry.first = 1;
+            entry.second = i;
+          } else {
+            entry.first++;
+          }
+        }
+
         // Find the most popular block.
         unsigned MaxPop = 0;
+        unsigned MaxIndex = 0;
         BasicBlock *MaxBlock = 0;
-        for (std::map<BasicBlock*, unsigned>::iterator
+        for (std::map<BasicBlock*, std::pair<unsigned, unsigned> >::iterator
              I = Popularity.begin(), E = Popularity.end(); I != E; ++I) {
-          if (I->second > MaxPop) {
-            MaxPop = I->second;
+          if (I->second.first > MaxPop || 
+              (I->second.first == MaxPop && MaxIndex > I->second.second)) {
+            MaxPop = I->second.first;
+            MaxIndex = I->second.second;
             MaxBlock = I->first;
           }
         }
index 7133d9875cafb473b0fd5df3e11b8567bea9521d..4a692f3622ec8e991d7574b90aa565437eb8b4ed 100644 (file)
@@ -1,33 +1,73 @@
-; RUN: opt < %s -simplifycfg -S | not grep unreachable
+; RUN: opt < %s -simplifycfg -S | FileCheck %s
 
 define void @test1(i1 %C, i1* %BP) {
+; CHECK: @test1
+; CHECK: entry:
+; CHECK-NEXT: ret void
+entry:
         br i1 %C, label %T, label %F
-T:              ; preds = %0
+T:
         store i1 %C, i1* %BP
         unreachable
-F:              ; preds = %0
+F:
         ret void
 }
 
 define void @test2() {
+; CHECK: @test2
+; CHECK: entry:
+; CHECK-NEXT: call void @test2()
+; CHECK-NEXT: ret void
+entry:
         invoke void @test2( )
                         to label %N unwind label %U
-U:              ; preds = %0
+U:
         unreachable
-N:              ; preds = %0
+N:
         ret void
 }
 
 define i32 @test3(i32 %v) {
+; CHECK: @test3
+; CHECK: entry:
+; CHECK-NEXT: [[CMP:%[A-Za-z0-9]+]] = icmp eq i32 %v, 2
+; CHECK-NEXT: select i1 [[CMP]], i32 2, i32 1
+; CHECK-NEXT: ret
+entry:
         switch i32 %v, label %default [
                  i32 1, label %U
                  i32 2, label %T
         ]
-default:                ; preds = %0
+default:
         ret i32 1
-U:              ; preds = %0
+U:
         unreachable
-T:              ; preds = %0
+T:
         ret i32 2
 }
 
+; PR9450
+define i32 @test4(i32 %v) {
+; CHECK: entry:
+; CHECK-NEXT:  switch i32 %v, label %T [
+; CHECK-NEXT:    i32 3, label %V
+; CHECK-NEXT:    i32 2, label %U
+; CHECK-NEXT:  ]
+
+entry:
+        br label %SWITCH
+V:
+        ret i32 7
+SWITCH:
+        switch i32 %v, label %default [
+                 i32 1, label %T
+                 i32 2, label %U
+                 i32 3, label %V
+        ]
+default:
+        unreachable
+U:
+        ret i32 1
+T:
+        ret i32 2
+}