summaryrefslogtreecommitdiffstats
path: root/llvm/lib/Transforms/Utils/LowerSwitch.cpp
diff options
context:
space:
mode:
authorBruno Cardoso Lopes <bruno.cardoso@gmail.com>2014-11-28 19:47:33 +0000
committerBruno Cardoso Lopes <bruno.cardoso@gmail.com>2014-11-28 19:47:33 +0000
commitbc7ba2c7667b8b5b5563b3b1429ca70468d0f251 (patch)
tree5bad17ad33055be0b1989b29d11068b577196440 /llvm/lib/Transforms/Utils/LowerSwitch.cpp
parente57f3c0a4235573d824e18b01799e6a8e21a6f22 (diff)
downloadbcm5719-llvm-bc7ba2c7667b8b5b5563b3b1429ca70468d0f251.tar.gz
bcm5719-llvm-bc7ba2c7667b8b5b5563b3b1429ca70468d0f251.zip
[SwitchLowering] Handle multiple destinations on condensed case stmts
Switch cases statements with sequential values that branch to the same destination BB may often be handled together in a single new source BB. In this scenario we need to remove remaining incoming values from PHI instructions in the destination BB, as to match the number of source branches. Differential Revision: http://reviews.llvm.org/D6415 rdar://problem/19040894 llvm-svn: 222926
Diffstat (limited to 'llvm/lib/Transforms/Utils/LowerSwitch.cpp')
-rw-r--r--llvm/lib/Transforms/Utils/LowerSwitch.cpp41
1 files changed, 29 insertions, 12 deletions
diff --git a/llvm/lib/Transforms/Utils/LowerSwitch.cpp b/llvm/lib/Transforms/Utils/LowerSwitch.cpp
index a0105c23d75..e25956299c6 100644
--- a/llvm/lib/Transforms/Utils/LowerSwitch.cpp
+++ b/llvm/lib/Transforms/Utils/LowerSwitch.cpp
@@ -131,25 +131,38 @@ static raw_ostream& operator<<(raw_ostream &O,
return O << "]";
}
-/// \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) {
+// \brief Update the first occurrence of the "switch statement" BB in the PHI
+// node with the "new" BB. The other occurrences will:
+//
+// 1) Be updated by subsequent calls to this function. Switch statements may
+// have more than one outcoming 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.
+// 2) Removed if subsequent incoming values now share the same case, i.e.,
+// multiple outcome edges are condensed into one. This is necessary to keep the
+// number of phi values equal to the number of branches to SuccBB.
+static void fixPhis(BasicBlock *SuccBB, BasicBlock *OrigBB, BasicBlock *NewBB,
+ unsigned NumMergedCases) {
+ for (BasicBlock::iterator I = SuccBB->begin(), IE = SuccBB->getFirstNonPHI();
+ I != IE; ++I) {
PHINode *PN = cast<PHINode>(I);
// Only update the first occurence.
- for (unsigned Idx = 0, E = PN->getNumIncomingValues(); Idx != E; ++Idx) {
+ unsigned Idx = 0, E = PN->getNumIncomingValues();
+ for (; Idx != E; ++Idx) {
if (PN->getIncomingBlock(Idx) == OrigBB) {
PN->setIncomingBlock(Idx, NewBB);
break;
}
}
+
+ // Remove additional occurences coming from condensed cases and keep the
+ // number of incoming values equal to the number of branches to SuccBB.
+ for (++Idx; NumMergedCases > 0 && Idx != E; ++Idx)
+ if (PN->getIncomingBlock(Idx) == OrigBB) {
+ PN->removeIncomingValue(Idx);
+ NumMergedCases--;
+ }
}
}
@@ -172,7 +185,11 @@ BasicBlock *LowerSwitch::switchConvert(CaseItr Begin, CaseItr End,
// emitting the code that checks if the value actually falls in the range
// because the bounds already tell us so.
if (Begin->Low == LowerBound && Begin->High == UpperBound) {
- fixPhis(Begin->BB, OrigBlock, Predecessor);
+ unsigned NumMergedCases = 0;
+ if (LowerBound && UpperBound)
+ NumMergedCases =
+ UpperBound->getSExtValue() - LowerBound->getSExtValue();
+ fixPhis(Begin->BB, OrigBlock, Predecessor, NumMergedCases);
return Begin->BB;
}
return newLeafBlock(*Begin, Val, OrigBlock, Default);
OpenPOWER on IntegriCloud