Index: llvm/trunk/lib/Transforms/Utils/SimplifyCFG.cpp =================================================================== --- llvm/trunk/lib/Transforms/Utils/SimplifyCFG.cpp +++ llvm/trunk/lib/Transforms/Utils/SimplifyCFG.cpp @@ -4450,16 +4450,46 @@ static bool ForwardSwitchConditionToPHI(SwitchInst *SI) { typedef DenseMap> ForwardingNodesMap; ForwardingNodesMap ForwardingNodes; - + BasicBlock *SwitchBlock = SI->getParent(); + bool Changed = false; for (auto &Case : SI->cases()) { ConstantInt *CaseValue = Case.getCaseValue(); BasicBlock *CaseDest = Case.getCaseSuccessor(); + + // Replace phi operands in successor blocks that are using the constant case + // value rather than the switch condition variable: + // switchbb: + // switch i32 %x, label %default [ + // i32 17, label %succ + // ... + // succ: + // %r = phi i32 ... [ 17, %switchbb ] ... + // --> + // %r = phi i32 ... [ %x, %switchbb ] ... + + for (Instruction &InstInCaseDest : *CaseDest) { + auto *Phi = dyn_cast(&InstInCaseDest); + if (!Phi) break; + + // This only works if there is exactly 1 incoming edge from the switch to + // a phi. If there is >1, that means multiple cases of the switch map to 1 + // value in the phi, and that phi value is not the switch condition. Thus, + // this transform would not make sense (the phi would be invalid because + // a phi can't have different incoming values from the same block). + int SwitchBBIdx = Phi->getBasicBlockIndex(SwitchBlock); + if (Phi->getIncomingValue(SwitchBBIdx) == CaseValue && + count(Phi->blocks(), SwitchBlock) == 1) { + Phi->setIncomingValue(SwitchBBIdx, SI->getCondition()); + Changed = true; + } + } + + // Collect phi nodes that are indirectly using this switch's case constants. int PhiIdx; if (auto *Phi = FindPHIForConditionForwarding(CaseValue, CaseDest, &PhiIdx)) ForwardingNodes[Phi].push_back(PhiIdx); } - bool Changed = false; for (auto &ForwardingNode : ForwardingNodes) { PHINode *Phi = ForwardingNode.first; SmallVectorImpl &Indexes = ForwardingNode.second; Index: llvm/trunk/test/Transforms/SimplifyCFG/ForwardSwitchConditionToPHI.ll =================================================================== --- llvm/trunk/test/Transforms/SimplifyCFG/ForwardSwitchConditionToPHI.ll +++ llvm/trunk/test/Transforms/SimplifyCFG/ForwardSwitchConditionToPHI.ll @@ -50,17 +50,13 @@ ; CHECK-NEXT: entry: ; CHECK-NEXT: switch i32 [[X:%.*]], label [[ELSE3:%.*]] [ ; CHECK-NEXT: i32 17, label [[RETURN:%.*]] -; CHECK-NEXT: i32 19, label [[IF19:%.*]] -; CHECK-NEXT: i32 42, label [[IF42:%.*]] +; CHECK-NEXT: i32 19, label [[RETURN]] +; CHECK-NEXT: i32 42, label [[RETURN]] ; CHECK-NEXT: ] -; CHECK: if19: -; CHECK-NEXT: br label [[RETURN]] -; CHECK: if42: -; CHECK-NEXT: br label [[RETURN]] ; CHECK: else3: ; CHECK-NEXT: br label [[RETURN]] ; CHECK: return: -; CHECK-NEXT: [[R:%.*]] = phi i32 [ [[X]], [[IF19]] ], [ [[X]], [[IF42]] ], [ 0, [[ELSE3]] ], [ 17, [[ENTRY:%.*]] ] +; CHECK-NEXT: [[R:%.*]] = phi i32 [ 0, [[ELSE3]] ], [ [[X]], [[ENTRY:%.*]] ], [ [[X]], [[ENTRY]] ], [ [[X]], [[ENTRY]] ] ; CHECK-NEXT: ret i32 [[R]] ; entry: