diff options
author | Momchil Velikov <momchil.velikov@arm.com> | 2023-07-19 18:31:25 +0100 |
---|---|---|
committer | Momchil Velikov <momchil.velikov@arm.com> | 2023-07-19 18:56:44 +0100 |
commit | 4c95f79cce190a3bc9ad4add2d32a2ae5f035d91 (patch) | |
tree | f5bb9317306b7281f32a5267f04b5d918df5b1e8 /llvm/lib/CodeGen/CodeGenPrepare.cpp | |
parent | 73f09814ee8bbd9f06a54c169ce9370bdf0b11e9 (diff) | |
download | llvm-4c95f79cce190a3bc9ad4add2d32a2ae5f035d91.zip llvm-4c95f79cce190a3bc9ad4add2d32a2ae5f035d91.tar.gz llvm-4c95f79cce190a3bc9ad4add2d32a2ae5f035d91.tar.bz2 |
[CodeGenPrepare] Refactor optimizeSelectInst (NFC)
Refactor to use BasicBlockUtils functions and make life easier for
a subsequent patch for updating the dominator tree.
Reviewed By: dmgreen
Differential Revision: https://reviews.llvm.org/D154053
Diffstat (limited to 'llvm/lib/CodeGen/CodeGenPrepare.cpp')
-rw-r--r-- | llvm/lib/CodeGen/CodeGenPrepare.cpp | 138 |
1 files changed, 65 insertions, 73 deletions
diff --git a/llvm/lib/CodeGen/CodeGenPrepare.cpp b/llvm/lib/CodeGen/CodeGenPrepare.cpp index 4d1754b..b00df0b 100644 --- a/llvm/lib/CodeGen/CodeGenPrepare.cpp +++ b/llvm/lib/CodeGen/CodeGenPrepare.cpp @@ -6997,96 +6997,88 @@ bool CodeGenPrepare::optimizeSelectInst(SelectInst *SI) { // first branch will point directly to select.end, and the corresponding PHI // predecessor block will be the start block. - // First, we split the block containing the select into 2 blocks. + // Collect values that go on the true side and the values that go on the false + // side. + SmallVector<Instruction *> TrueInstrs, FalseInstrs; + for (SelectInst *SI : ASI) { + if (Value *V = SI->getTrueValue(); sinkSelectOperand(TTI, V)) + TrueInstrs.push_back(cast<Instruction>(V)); + if (Value *V = SI->getFalseValue(); sinkSelectOperand(TTI, V)) + FalseInstrs.push_back(cast<Instruction>(V)); + } + + // Split the select block, according to how many (if any) values go on each + // side. BasicBlock *StartBlock = SI->getParent(); BasicBlock::iterator SplitPt = ++(BasicBlock::iterator(LastSI)); - BasicBlock *EndBlock = StartBlock->splitBasicBlock(SplitPt, "select.end"); - if (IsHugeFunc) - FreshBBs.insert(EndBlock); - Loop *L = LI->getLoopFor(StartBlock); - if (L) - L->addBasicBlockToLoop(EndBlock, *LI); - BFI->setBlockFreq(EndBlock, BFI->getBlockFreq(StartBlock).getFrequency()); - // Delete the unconditional branch that was just created by the split. - StartBlock->getTerminator()->eraseFromParent(); - // These are the new basic blocks for the conditional branch. - // At least one will become an actual new basic block. + IRBuilder<> IB(SI); + auto *CondFr = IB.CreateFreeze(SI->getCondition(), SI->getName() + ".frozen"); + BasicBlock *TrueBlock = nullptr; BasicBlock *FalseBlock = nullptr; + BasicBlock *EndBlock = nullptr; BranchInst *TrueBranch = nullptr; BranchInst *FalseBranch = nullptr; - - // Sink expensive instructions into the conditional blocks to avoid executing - // them speculatively. - for (SelectInst *SI : ASI) { - if (sinkSelectOperand(TTI, SI->getTrueValue())) { - if (TrueBlock == nullptr) { - TrueBlock = BasicBlock::Create(SI->getContext(), "select.true.sink", - EndBlock->getParent(), EndBlock); - TrueBranch = BranchInst::Create(EndBlock, TrueBlock); - if (IsHugeFunc) - FreshBBs.insert(TrueBlock); - if (L) - L->addBasicBlockToLoop(TrueBlock, *LI); - TrueBranch->setDebugLoc(SI->getDebugLoc()); - } - auto *TrueInst = cast<Instruction>(SI->getTrueValue()); - TrueInst->moveBefore(TrueBranch); - } - if (sinkSelectOperand(TTI, SI->getFalseValue())) { - if (FalseBlock == nullptr) { - FalseBlock = BasicBlock::Create(SI->getContext(), "select.false.sink", - EndBlock->getParent(), EndBlock); - if (IsHugeFunc) - FreshBBs.insert(FalseBlock); - if (L) - L->addBasicBlockToLoop(FalseBlock, *LI); - FalseBranch = BranchInst::Create(EndBlock, FalseBlock); - FalseBranch->setDebugLoc(SI->getDebugLoc()); - } - auto *FalseInst = cast<Instruction>(SI->getFalseValue()); - FalseInst->moveBefore(FalseBranch); - } + if (TrueInstrs.size() == 0) { + FalseBranch = cast<BranchInst>(SplitBlockAndInsertIfElse( + CondFr, &*SplitPt, false, nullptr, nullptr, LI)); + FalseBlock = FalseBranch->getParent(); + EndBlock = cast<BasicBlock>(FalseBranch->getOperand(0)); + } else if (FalseInstrs.size() == 0) { + TrueBranch = cast<BranchInst>(SplitBlockAndInsertIfThen( + CondFr, &*SplitPt, false, nullptr, nullptr, LI)); + TrueBlock = TrueBranch->getParent(); + EndBlock = cast<BasicBlock>(TrueBranch->getOperand(0)); + } else { + Instruction *ThenTerm = nullptr; + Instruction *ElseTerm = nullptr; + SplitBlockAndInsertIfThenElse(CondFr, &*SplitPt, &ThenTerm, &ElseTerm, + nullptr, nullptr, LI); + TrueBranch = cast<BranchInst>(ThenTerm); + FalseBranch = cast<BranchInst>(ElseTerm); + TrueBlock = TrueBranch->getParent(); + FalseBlock = FalseBranch->getParent(); + EndBlock = cast<BasicBlock>(TrueBranch->getOperand(0)); + } + + EndBlock->setName("select.end"); + if (TrueBlock) + TrueBlock->setName("select.true.sink"); + if (FalseBlock) + FalseBlock->setName(FalseInstrs.size() == 0 ? "select.false" + : "select.false.sink"); + + if (IsHugeFunc) { + if (TrueBlock) + FreshBBs.insert(TrueBlock); + if (FalseBlock) + FreshBBs.insert(FalseBlock); + FreshBBs.insert(EndBlock); } - // If there was nothing to sink, then arbitrarily choose the 'false' side - // for a new input value to the PHI. - if (TrueBlock == FalseBlock) { - assert(TrueBlock == nullptr && - "Unexpected basic block transform while optimizing select"); + BFI->setBlockFreq(EndBlock, BFI->getBlockFreq(StartBlock).getFrequency()); - FalseBlock = BasicBlock::Create(SI->getContext(), "select.false", - EndBlock->getParent(), EndBlock); - if (IsHugeFunc) - FreshBBs.insert(FalseBlock); - if (L) - L->addBasicBlockToLoop(FalseBlock, *LI); - auto *FalseBranch = BranchInst::Create(EndBlock, FalseBlock); - FalseBranch->setDebugLoc(SI->getDebugLoc()); - } + static const unsigned MD[] = { + LLVMContext::MD_prof, LLVMContext::MD_unpredictable, + LLVMContext::MD_make_implicit, LLVMContext::MD_dbg}; + StartBlock->getTerminator()->copyMetadata(*SI, MD); + + // Sink expensive instructions into the conditional blocks to avoid executing + // them speculatively. + for (Instruction *I : TrueInstrs) + I->moveBefore(TrueBranch); + for (Instruction *I : FalseInstrs) + I->moveBefore(FalseBranch); - // Insert the real conditional branch based on the original condition. // If we did not create a new block for one of the 'true' or 'false' paths // of the condition, it means that side of the branch goes to the end block // directly and the path originates from the start block from the point of // view of the new PHI. - BasicBlock *TT, *FT; - if (TrueBlock == nullptr) { - TT = EndBlock; - FT = FalseBlock; + if (TrueBlock == nullptr) TrueBlock = StartBlock; - } else if (FalseBlock == nullptr) { - TT = TrueBlock; - FT = EndBlock; + else if (FalseBlock == nullptr) FalseBlock = StartBlock; - } else { - TT = TrueBlock; - FT = FalseBlock; - } - IRBuilder<> IB(SI); - auto *CondFr = IB.CreateFreeze(SI->getCondition(), SI->getName() + ".frozen"); - IB.CreateCondBr(CondFr, TT, FT, SI); SmallPtrSet<const Instruction *, 2> INS; INS.insert(ASI.begin(), ASI.end()); |