diff --git a/lib/Transforms/Utils/LowerSwitch.cpp b/lib/Transforms/Utils/LowerSwitch.cpp index d6e5bb62680..a0105c23d75 100644 --- a/lib/Transforms/Utils/LowerSwitch.cpp +++ b/lib/Transforms/Utils/LowerSwitch.cpp @@ -131,17 +131,24 @@ static raw_ostream& operator<<(raw_ostream &O, 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(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; + } } } } diff --git a/test/Transforms/Util/lowerswitch.ll b/test/Transforms/Util/lowerswitch.ll new file mode 100644 index 00000000000..06bd4ccd11c --- /dev/null +++ b/test/Transforms/Util/lowerswitch.ll @@ -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 +}