[llvm] r221627 - [SwitchLowering] Fix the "fixPhis" function.

Juergen Ributzka juergen at apple.com
Mon Nov 10 13:05:27 PST 2014


Author: ributzka
Date: Mon Nov 10 15:05:27 2014
New Revision: 221627

URL: http://llvm.org/viewvc/llvm-project?rev=221627&view=rev
Log:
[SwitchLowering] Fix the "fixPhis" function.

Switch statements may have more than one incoming edge into the same BB if they
all have the same value. When the switch statement is converted these incoming
edges are now coming from multiple BBs. Updating all incoming values to be from
a single BB is incorrect and would generate invalid LLVM IR.

The fix is to only update the first occurrence of an incoming value. Switch
lowering will perform subsequent calls to this helper function for each incoming
edge with a new basic block - updating all edges in the process.

This fixes rdar://problem/18916275.

Added:
    llvm/trunk/test/Transforms/Util/lowerswitch.ll
Modified:
    llvm/trunk/lib/Transforms/Utils/LowerSwitch.cpp

Modified: llvm/trunk/lib/Transforms/Utils/LowerSwitch.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Utils/LowerSwitch.cpp?rev=221627&r1=221626&r2=221627&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/Utils/LowerSwitch.cpp (original)
+++ llvm/trunk/lib/Transforms/Utils/LowerSwitch.cpp Mon Nov 10 15:05:27 2014
@@ -131,17 +131,24 @@ static raw_ostream& operator<<(raw_ostre
   return O << "]";
 }
 
-static void fixPhis(BasicBlock *Succ,
-                    BasicBlock *OrigBlock,
-                    BasicBlock *NewNode) {
-  for (BasicBlock::iterator I = Succ->begin(),
-                            E = Succ->getFirstNonPHI();
+/// \brief Update the first occurrence of the "switch statement" BB in the PHI
+/// node with the "new" BB. The other occurrences will be updated by subsequent
+/// calls to this function.
+///
+/// Switch statements may have more than one incoming edge into the same BB if
+/// they all have the same value. When the switch statement is converted these
+/// incoming edges are now coming from multiple BBs.
+static void fixPhis(BasicBlock *SuccBB, BasicBlock *OrigBB, BasicBlock *NewBB) {
+  for (BasicBlock::iterator I = SuccBB->begin(), E = SuccBB->getFirstNonPHI();
        I != E; ++I) {
     PHINode *PN = cast<PHINode>(I);
 
-    for (unsigned I = 0, E = PN->getNumIncomingValues(); I != E; ++I) {
-      if (PN->getIncomingBlock(I) == OrigBlock)
-        PN->setIncomingBlock(I, NewNode);
+    // Only update the first occurence.
+    for (unsigned Idx = 0, E = PN->getNumIncomingValues(); Idx != E; ++Idx) {
+      if (PN->getIncomingBlock(Idx) == OrigBB) {
+        PN->setIncomingBlock(Idx, NewBB);
+        break;
+      }
     }
   }
 }

Added: llvm/trunk/test/Transforms/Util/lowerswitch.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Util/lowerswitch.ll?rev=221627&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/Util/lowerswitch.ll (added)
+++ llvm/trunk/test/Transforms/Util/lowerswitch.ll Mon Nov 10 15:05:27 2014
@@ -0,0 +1,22 @@
+; RUN: opt -lowerswitch -S < %s | FileCheck %s
+
+; Test that we don't crash and have a different basic block for each incoming edge.
+define void @test_lower_switch() {
+; CHECK-LABEL: @test_lower_switch
+; CHECK: %merge = phi i64 [ 1, %BB3 ], [ 0, %NewDefault ], [ 0, %NodeBlock5 ], [ 0, %LeafBlock1 ]
+BB1:
+  switch i32 undef, label %BB2 [
+    i32 3, label %BB2
+    i32 5, label %BB2
+    i32 0, label %BB3
+    i32 2, label %BB3
+    i32 4, label %BB3
+  ]
+
+BB2:
+  %merge = phi i64 [ 1, %BB3 ], [ 0, %BB1 ], [ 0, %BB1 ], [ 0, %BB1 ]
+  ret void
+
+BB3:
+  br label %BB2
+}





More information about the llvm-commits mailing list