Index: include/llvm/LinkAllPasses.h =================================================================== --- include/llvm/LinkAllPasses.h +++ include/llvm/LinkAllPasses.h @@ -186,6 +186,7 @@ (void) llvm::createScalarizerPass(); (void) llvm::createSeparateConstOffsetFromGEPPass(); (void) llvm::createSpeculativeExecutionPass(); + (void) llvm::createSpeculativeExecutionIfHasBranchDivergencePass(); (void) llvm::createRewriteSymbolsPass(); (void) llvm::createStraightLineStrengthReducePass(); (void) llvm::createMemDerefPrinter(); Index: include/llvm/Transforms/Scalar.h =================================================================== --- include/llvm/Transforms/Scalar.h +++ include/llvm/Transforms/Scalar.h @@ -424,6 +424,10 @@ // FunctionPass *createSpeculativeExecutionPass(); +// Same as createSpeculativeExecutionPass, but does nothing unless +// TargetTransformInfo::hasBranchDivergence() is true. +FunctionPass *createSpeculativeExecutionIfHasBranchDivergencePass(); + //===----------------------------------------------------------------------===// // // LoadCombine - Combine loads into bigger loads. Index: lib/Transforms/Scalar/SpeculativeExecution.cpp =================================================================== --- lib/Transforms/Scalar/SpeculativeExecution.cpp +++ lib/Transforms/Scalar/SpeculativeExecution.cpp @@ -50,6 +50,15 @@ // aggressive speculation while counting on later passes to either capitalize on // that or clean it up. // +// This pass operates in one of two modes: +// +// - ALWAYS: The pass always runs. +// - ONLY_IF_DIVERGENT_ARCH: The pass is a nop unless +// TargetTransformInfo::hasBranchDivergence() is true. +// +// The ONLY_IF_DIVERGENT_ARCH mode lets you include this pass unconditionally in +// the IR pass pipeline, but only enable it for relevant targets. +// //===----------------------------------------------------------------------===// #include "llvm/ADT/SmallSet.h" @@ -84,18 +93,33 @@ "exceeds this limit.")); namespace { +enum ExecutionMode { ALWAYS, ONLY_IF_DIVERGENT_ARCH }; + class SpeculativeExecution : public FunctionPass { public: - static char ID; - SpeculativeExecution(): FunctionPass(ID) {} + static char ID; + SpeculativeExecution() : SpeculativeExecution(ALWAYS) {} + explicit SpeculativeExecution(ExecutionMode Mode) + : FunctionPass(ID), Mode(Mode) {} - void getAnalysisUsage(AnalysisUsage &AU) const override; - bool runOnFunction(Function &F) override; + void getAnalysisUsage(AnalysisUsage &AU) const override; + bool runOnFunction(Function &F) override; + + const char *getPassName() const override { + switch (Mode) { + case ALWAYS: + return "Speculatively execute instructions"; + case ONLY_IF_DIVERGENT_ARCH: + return "Speculatively execute instructions if target has divergent " + "branches"; + } + } private: bool runOnBasicBlock(BasicBlock &B); bool considerHoistingFromTo(BasicBlock &FromBlock, BasicBlock &ToBlock); + const ExecutionMode Mode; const TargetTransformInfo *TTI = nullptr; }; } // namespace @@ -105,7 +129,7 @@ "Speculatively execute instructions", false, false) INITIALIZE_PASS_DEPENDENCY(TargetTransformInfoWrapperPass) INITIALIZE_PASS_END(SpeculativeExecution, "speculative-execution", - "Speculatively execute instructions", false, false) + "Speculatively execute instructions", false, false) void SpeculativeExecution::getAnalysisUsage(AnalysisUsage &AU) const { AU.addRequired(); @@ -116,6 +140,11 @@ return false; TTI = &getAnalysis().getTTI(F); + if (Mode == ONLY_IF_DIVERGENT_ARCH && !TTI->hasBranchDivergence()) { + DEBUG(dbgs() << "Not running SpeculativeExecution because " + "TTI->hasBranchDivergence() is false."); + return false; + } bool Changed = false; for (auto& B : F) { @@ -237,7 +266,11 @@ namespace llvm { FunctionPass *createSpeculativeExecutionPass() { - return new SpeculativeExecution(); + return new SpeculativeExecution(ALWAYS); +} + +FunctionPass *createSpeculativeExecutionIfHasBranchDivergencePass() { + return new SpeculativeExecution(ONLY_IF_DIVERGENT_ARCH); } } // namespace llvm