From e84178a0bd3a218238b15ef646f2e740f3a48037 Mon Sep 17 00:00:00 2001 From: Owen Anderson Date: Wed, 14 Jul 2010 19:52:16 +0000 Subject: [PATCH] Extend SimplifyCFG's common-destination folding heuristic to allow a single "bonus" instruction to be speculatively executed. Add a heuristic to ensure we're not tripping up out-of-order execution by checking that this bonus instruction only uses values that were already guaranteed to be available. This allows us to eliminate the short circuit in (x&1)&&(x&2). git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@108351 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Transforms/Utils/SimplifyCFG.cpp | 72 ++++++++++++++++++++++++++-- 1 file changed, 67 insertions(+), 5 deletions(-) diff --git a/lib/Transforms/Utils/SimplifyCFG.cpp b/lib/Transforms/Utils/SimplifyCFG.cpp index fd3ed3ea2d6..08f312e5eb8 100644 --- a/lib/Transforms/Utils/SimplifyCFG.cpp +++ b/lib/Transforms/Utils/SimplifyCFG.cpp @@ -1377,8 +1377,9 @@ static bool SimplifyCondBranchToTwoReturns(BranchInst *BI) { bool llvm::FoldBranchToCommonDest(BranchInst *BI) { BasicBlock *BB = BI->getParent(); Instruction *Cond = dyn_cast(BI->getCondition()); - if (Cond == 0) return false; - + if (Cond == 0 || (!isa(Cond) && !isa(Cond)) || + Cond->getParent() != BB || !Cond->hasOneUse()) + return false; // Only allow this if the condition is a simple instruction that can be // executed unconditionally. It must be in the same block as the branch, and @@ -1387,11 +1388,24 @@ bool llvm::FoldBranchToCommonDest(BranchInst *BI) { // Ignore dbg intrinsics. while(isa(FrontIt)) ++FrontIt; - if ((!isa(Cond) && !isa(Cond)) || - Cond->getParent() != BB || &*FrontIt != Cond || !Cond->hasOneUse()) { - return false; + + // Allow a single instruction to be hoisted in addition to the compare + // that feeds the branch. We later ensure that any values that _it_ uses + // were also live in the predecessor, so that we don't unnecessarily create + // register pressure or inhibit out-of-order execution. + Instruction *BonusInst = 0; + if (&*FrontIt != Cond && + (*FrontIt).hasOneUse() && *(*FrontIt).use_begin() == Cond && + (*FrontIt).isSafeToSpeculativelyExecute() && + !(*FrontIt).mayReadFromMemory()) { + BonusInst = &*FrontIt; + ++FrontIt; } + // Only a single bonus inst is allowed. + if (&*FrontIt != Cond) + return false; + // Make sure the instruction after the condition is the cond branch. BasicBlock::iterator CondIt = Cond; ++CondIt; // Ingore dbg intrinsics. @@ -1429,6 +1443,44 @@ bool llvm::FoldBranchToCommonDest(BranchInst *BI) { !SafeToMergeTerminators(BI, PBI)) continue; + // Ensure that any values used in the bonus instruction are also used + // by the terminator of the predecessor. This means that those values + // must already have been resolved, so we won't be inhibiting the + // out-of-order core by speculating them earlier. + if (BonusInst) { + // Collect the values used by the bonus inst + SmallPtrSet UsedValues; + for (Instruction::op_iterator OI = BonusInst->op_begin(), + OE = BonusInst->op_end(); OI != OE; ++OI) { + Value* V = *OI; + if (!isa(V)) + UsedValues.insert(V); + } + + SmallVector, 4> Worklist; + Worklist.push_back(std::make_pair(PBI->getOperand(0), 0)); + + // Walk up to four levels back up the use-def chain of the predecessor's + // terminator to see if all those values were used. The choice of four + // levels is arbitrary, to provide a compile-time-cost bound. + while (!Worklist.empty()) { + std::pair Pair = Worklist.back(); + Worklist.pop_back(); + + if (Pair.second >= 4) continue; + UsedValues.erase(Pair.first); + if (UsedValues.empty()) break; + + if (Instruction* I = dyn_cast(Pair.first)) { + for (Instruction::op_iterator OI = I->op_begin(), OE = I->op_end(); + OI != OE; ++OI) + Worklist.push_back(std::make_pair(OI->get(), Pair.second+1)); + } + } + + if (!UsedValues.empty()) return false; + } + Instruction::BinaryOps Opc; bool InvertPredCond = false; @@ -1457,9 +1509,19 @@ bool llvm::FoldBranchToCommonDest(BranchInst *BI) { PBI->setSuccessor(1, OldTrue); } + // If we have a bonus inst, clone it into the predecessor block. + Instruction *NewBonus = 0; + if (BonusInst) { + NewBonus = BonusInst->clone(); + PredBlock->getInstList().insert(PBI, NewBonus); + NewBonus->takeName(BonusInst); + BonusInst->setName(BonusInst->getName()+".old"); + } + // Clone Cond into the predecessor basic block, and or/and the // two conditions together. Instruction *New = Cond->clone(); + if (BonusInst) New->replaceUsesOfWith(BonusInst, NewBonus); PredBlock->getInstList().insert(PBI, New); New->takeName(Cond); Cond->setName(New->getName()+".old"); -- 2.34.1