diff options
Diffstat (limited to 'llvm/lib/Transforms/Scalar/SpeculativeExecution.cpp')
-rw-r--r-- | llvm/lib/Transforms/Scalar/SpeculativeExecution.cpp | 40 |
1 files changed, 29 insertions, 11 deletions
diff --git a/llvm/lib/Transforms/Scalar/SpeculativeExecution.cpp b/llvm/lib/Transforms/Scalar/SpeculativeExecution.cpp index c8d899bb4871c..f82a2936c762d 100644 --- a/llvm/lib/Transforms/Scalar/SpeculativeExecution.cpp +++ b/llvm/lib/Transforms/Scalar/SpeculativeExecution.cpp @@ -65,6 +65,7 @@ #include "llvm/Analysis/GlobalsModRef.h" #include "llvm/Analysis/ValueTracking.h" #include "llvm/IR/Instructions.h" +#include "llvm/IR/IntrinsicInst.h" #include "llvm/IR/Module.h" #include "llvm/IR/Operator.h" #include "llvm/InitializePasses.h" @@ -244,19 +245,35 @@ static unsigned ComputeSpeculationCost(const Instruction *I, case Instruction::FNeg: case Instruction::ICmp: case Instruction::FCmp: - return TTI.getUserCost(I); + return TTI.getUserCost(I, TargetTransformInfo::TCK_SizeAndLatency); default: - return UINT_MAX; // Disallow anything not whitelisted. + return UINT_MAX; // Disallow anything not explicitly listed. } } bool SpeculativeExecutionPass::considerHoistingFromTo( BasicBlock &FromBlock, BasicBlock &ToBlock) { SmallPtrSet<const Instruction *, 8> NotHoisted; - const auto AllPrecedingUsesFromBlockHoisted = [&NotHoisted](User *U) { - for (Value* V : U->operand_values()) { - if (Instruction *I = dyn_cast<Instruction>(V)) { + const auto AllPrecedingUsesFromBlockHoisted = [&NotHoisted](const User *U) { + // Debug variable has special operand to check it's not hoisted. + if (const auto *DVI = dyn_cast<DbgVariableIntrinsic>(U)) { + if (const auto *I = + dyn_cast_or_null<Instruction>(DVI->getVariableLocation())) + if (NotHoisted.count(I) == 0) + return true; + return false; + } + + // Usially debug label instrinsic corresponds to label in LLVM IR. In these + // cases we should not move it here. + // TODO: Possible special processing needed to detect it is related to a + // hoisted instruction. + if (isa<DbgLabelInst>(U)) + return false; + + for (const Value *V : U->operand_values()) { + if (const Instruction *I = dyn_cast<Instruction>(V)) { if (NotHoisted.count(I) > 0) return false; } @@ -265,7 +282,8 @@ bool SpeculativeExecutionPass::considerHoistingFromTo( }; unsigned TotalSpeculationCost = 0; - for (auto& I : FromBlock) { + unsigned NotHoistedInstCount = 0; + for (const auto &I : FromBlock) { const unsigned Cost = ComputeSpeculationCost(&I, *TTI); if (Cost != UINT_MAX && isSafeToSpeculativelyExecute(&I) && AllPrecedingUsesFromBlockHoisted(&I)) { @@ -273,15 +291,15 @@ bool SpeculativeExecutionPass::considerHoistingFromTo( if (TotalSpeculationCost > SpecExecMaxSpeculationCost) return false; // too much to hoist } else { - NotHoisted.insert(&I); - if (NotHoisted.size() > SpecExecMaxNotHoisted) + // Debug info instrinsics should not be counted for threshold. + if (!isa<DbgInfoIntrinsic>(I)) + NotHoistedInstCount++; + if (NotHoistedInstCount > SpecExecMaxNotHoisted) return false; // too much left behind + NotHoisted.insert(&I); } } - if (TotalSpeculationCost == 0) - return false; // nothing to hoist - for (auto I = FromBlock.begin(); I != FromBlock.end();) { // We have to increment I before moving Current as moving Current // changes the list that I is iterating through. |