Index: llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp =================================================================== --- llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp +++ llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp @@ -2443,8 +2443,43 @@ return nullptr; } -static Instruction *foldSelectToPhi(SelectInst &Sel, const DominatorTree &DT, - InstCombiner::BuilderTy &Builder) { +static bool isAvailableAt(Value *V, Instruction *P, const DominatorTree &DT) { + if (auto *I = dyn_cast(V)) + return DT.dominates(I, P); + return true; +} + +static Value *propagatePhiInputs(SelectInst &Sel, const DominatorTree &DT, + InstCombiner::BuilderTy &Builder, + BasicBlock *TruePred, BasicBlock *FalsePred) { + Value *TrueInput = Sel.getTrueValue(); + Value *FalseInput = Sel.getFalseValue(); + auto GetPhiInput = [&](Value *V, BasicBlock *BB) { + if (auto *PN = dyn_cast(V)) + if (PN->getParent() == Sel.getParent()) { + Value *PhiInput = PN->getIncomingValueForBlock(BB); + if (isAvailableAt(PhiInput, &Sel, DT)) + return PhiInput; + } + return V; + }; + + Value *NewTrueInput = GetPhiInput(TrueInput, TruePred); + Value *NewFalseInput = GetPhiInput(FalseInput, FalsePred); + + if (NewTrueInput == TrueInput && NewFalseInput == FalseInput) + return nullptr; + + Builder.SetInsertPoint(&Sel); + auto *NewSelect = + Builder.CreateSelect(Sel.getCondition(), NewTrueInput, NewFalseInput); + NewSelect->takeName(&Sel); + return NewSelect; +} + +static Value *foldSelectUsingPhiDominance(SelectInst &Sel, + const DominatorTree &DT, + InstCombiner::BuilderTy &Builder) { // Find the block's immediate dominator that ends with a conditional branch // that matches select's condition (maybe inverted). BasicBlock *BB = Sel.getParent(); @@ -2472,28 +2507,42 @@ BasicBlockEdge TrueEdge(IDom, TrueSucc); BasicBlockEdge FalseEdge(IDom, FalseSucc); DenseMap Inputs; + SmallVector TrueIncomingBlocks, FalseIncomingBlocks; + bool CanReplaceWithPhi = true; for (auto *Pred : predecessors(BB)) { // Check implication. BasicBlockEdge Incoming(Pred, BB); - if (DT.dominates(TrueEdge, Incoming)) + if (DT.dominates(TrueEdge, Incoming)) { Inputs[Pred] = IfTrue; - else if (DT.dominates(FalseEdge, Incoming)) + TrueIncomingBlocks.push_back(Pred); + } else if (DT.dominates(FalseEdge, Incoming)) { Inputs[Pred] = IfFalse; - else + FalseIncomingBlocks.push_back(Pred); + } else return nullptr; // Check availability. - if (auto *Insn = dyn_cast(Inputs[Pred])) - if (!DT.dominates(Insn, Pred->getTerminator())) - return nullptr; + if (!isAvailableAt(Inputs[Pred], Pred->getTerminator(), DT)) + CanReplaceWithPhi = false; } - Builder.SetInsertPoint(&*BB->begin()); - auto *PN = Builder.CreatePHI(Sel.getType(), Inputs.size()); - for (auto *Pred : predecessors(BB)) { - PN->addIncoming(Inputs[Pred], Pred); + // Try to replace this select with a phi node. + if (CanReplaceWithPhi) { + Builder.SetInsertPoint(&*BB->begin()); + auto *PN = Builder.CreatePHI(Sel.getType(), Inputs.size()); + for (auto *Pred : predecessors(BB)) { + PN->addIncoming(Inputs[Pred], Pred); + } + PN->takeName(&Sel); + return PN; } - PN->takeName(&Sel); - return PN; + + // If this select has a Phi argument from the same block, take its input. + if (TrueIncomingBlocks.size() == 1 && FalseIncomingBlocks.size() == 1) + if (auto *V = propagatePhiInputs(Sel, DT, Builder, TrueIncomingBlocks[0], + FalseIncomingBlocks[0])) + return V; + + return nullptr; } Instruction *InstCombiner::visitSelectInst(SelectInst &SI) { @@ -2957,8 +3006,8 @@ if (Instruction *Copysign = foldSelectToCopysign(SI, Builder)) return Copysign; - if (Instruction *PN = foldSelectToPhi(SI, DT, Builder)) - return replaceInstUsesWith(SI, PN); + if (Value *V = foldSelectUsingPhiDominance(SI, DT, Builder)) + return replaceInstUsesWith(SI, V); return nullptr; } Index: llvm/test/Transforms/InstCombine/select.ll =================================================================== --- llvm/test/Transforms/InstCombine/select.ll +++ llvm/test/Transforms/InstCombine/select.ll @@ -1755,7 +1755,6 @@ ret i32 %s } -; TODO: Replace with phi[x, z]. define i32 @select_phi_same_condition(i1 %cond, i32 %x, i32 %y, i32 %z) { ; CHECK-LABEL: @select_phi_same_condition( ; CHECK-NEXT: entry: @@ -1765,8 +1764,7 @@ ; CHECK: if.false: ; CHECK-NEXT: br label [[MERGE]] ; CHECK: merge: -; CHECK-NEXT: [[PHI:%.*]] = phi i32 [ 0, [[IF_TRUE]] ], [ [[Z:%.*]], [[IF_FALSE]] ] -; CHECK-NEXT: [[S:%.*]] = select i1 [[COND]], i32 [[X:%.*]], i32 [[PHI]] +; CHECK-NEXT: [[S:%.*]] = phi i32 [ [[Z:%.*]], [[IF_FALSE]] ], [ [[X:%.*]], [[IF_TRUE]] ] ; CHECK-NEXT: ret i32 [[S]] ; entry: