[Speculation] Add a SpeculativeExecution mode where the pass does nothing unless TTI::hasBranchDivergence() is true.

Summary:
This lets us add this pass to the IR pass manager unconditionally; it
will simply not do anything on targets without branch divergence.

Reviewers: tra

Subscribers: llvm-commits, jingyue, rnk, chandlerc

Differential Revision: http://reviews.llvm.org/D18625

llvm-svn: 266398
This commit is contained in:
Justin Lebar 2016-04-15 00:32:09 +00:00
parent 812e559589
commit cad81cf6b3
4 changed files with 70 additions and 5 deletions

View File

@ -186,6 +186,7 @@ namespace {
(void) llvm::createScalarizerPass(); (void) llvm::createScalarizerPass();
(void) llvm::createSeparateConstOffsetFromGEPPass(); (void) llvm::createSeparateConstOffsetFromGEPPass();
(void) llvm::createSpeculativeExecutionPass(); (void) llvm::createSpeculativeExecutionPass();
(void) llvm::createSpeculativeExecutionIfHasBranchDivergencePass();
(void) llvm::createRewriteSymbolsPass(); (void) llvm::createRewriteSymbolsPass();
(void) llvm::createStraightLineStrengthReducePass(); (void) llvm::createStraightLineStrengthReducePass();
(void) llvm::createMemDerefPrinter(); (void) llvm::createMemDerefPrinter();

View File

@ -430,6 +430,10 @@ createSeparateConstOffsetFromGEPPass(const TargetMachine *TM = nullptr,
// //
FunctionPass *createSpeculativeExecutionPass(); FunctionPass *createSpeculativeExecutionPass();
// Same as createSpeculativeExecutionPass, but does nothing unless
// TargetTransformInfo::hasBranchDivergence() is true.
FunctionPass *createSpeculativeExecutionIfHasBranchDivergencePass();
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
// //
// LoadCombine - Combine loads into bigger loads. // LoadCombine - Combine loads into bigger loads.

View File

@ -50,6 +50,15 @@
// aggressive speculation while counting on later passes to either capitalize on // aggressive speculation while counting on later passes to either capitalize on
// that or clean it up. // that or clean it up.
// //
// If the pass was created by calling
// createSpeculativeExecutionIfHasBranchDivergencePass or the
// -spec-exec-only-if-divergent-target option is present, this pass only has an
// effect on targets where TargetTransformInfo::hasBranchDivergence() is true;
// on other targets, it is a nop.
//
// This lets you include this pass unconditionally in the IR pass pipeline, but
// only enable it for relevant targets.
//
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
#include "llvm/ADT/SmallSet.h" #include "llvm/ADT/SmallSet.h"
@ -83,19 +92,39 @@ static cl::opt<unsigned> SpecExecMaxNotHoisted(
"number of instructions that would not be speculatively executed " "number of instructions that would not be speculatively executed "
"exceeds this limit.")); "exceeds this limit."));
static cl::opt<bool> SpecExecOnlyIfDivergentTarget(
"spec-exec-only-if-divergent-target", cl::init(0), cl::Hidden,
cl::desc("Speculative execution is applied only to targets with divergent "
"branches, even if the pass was configured to apply only to all "
"targets."));
namespace { namespace {
class SpeculativeExecution : public FunctionPass { class SpeculativeExecution : public FunctionPass {
public: public:
static char ID; static char ID;
SpeculativeExecution(): FunctionPass(ID) {} explicit SpeculativeExecution(bool OnlyIfDivergentTarget = false)
: FunctionPass(ID),
OnlyIfDivergentTarget(OnlyIfDivergentTarget ||
SpecExecOnlyIfDivergentTarget) {}
void getAnalysisUsage(AnalysisUsage &AU) const override; void getAnalysisUsage(AnalysisUsage &AU) const override;
bool runOnFunction(Function &F) override; bool runOnFunction(Function &F) override;
const char *getPassName() const override {
if (OnlyIfDivergentTarget)
return "Speculatively execute instructions if target has divergent "
"branches";
return "Speculatively execute instructions";
}
private: private:
bool runOnBasicBlock(BasicBlock &B); bool runOnBasicBlock(BasicBlock &B);
bool considerHoistingFromTo(BasicBlock &FromBlock, BasicBlock &ToBlock); bool considerHoistingFromTo(BasicBlock &FromBlock, BasicBlock &ToBlock);
// If true, this pass is a nop unless the target Targetitecture has branch
// divergence.
const bool OnlyIfDivergentTarget;
const TargetTransformInfo *TTI = nullptr; const TargetTransformInfo *TTI = nullptr;
}; };
} // namespace } // namespace
@ -116,6 +145,11 @@ bool SpeculativeExecution::runOnFunction(Function &F) {
return false; return false;
TTI = &getAnalysis<TargetTransformInfoWrapperPass>().getTTI(F); TTI = &getAnalysis<TargetTransformInfoWrapperPass>().getTTI(F);
if (OnlyIfDivergentTarget && !TTI->hasBranchDivergence()) {
DEBUG(dbgs() << "Not running SpeculativeExecution because "
"TTI->hasBranchDivergence() is false.\n");
return false;
}
bool Changed = false; bool Changed = false;
for (auto& B : F) { for (auto& B : F) {
@ -240,4 +274,8 @@ FunctionPass *createSpeculativeExecutionPass() {
return new SpeculativeExecution(); return new SpeculativeExecution();
} }
FunctionPass *createSpeculativeExecutionIfHasBranchDivergencePass() {
return new SpeculativeExecution(/* OnlyIfDivergentTarget = */ true);
}
} // namespace llvm } // namespace llvm

View File

@ -0,0 +1,22 @@
; RUN: opt < %s -S -mtriple=nvptx-nvidia-cuda -speculative-execution | \
; RUN: FileCheck --check-prefix=ON %s
; RUN: opt < %s -S -mtriple=nvptx-nvidia-cuda -speculative-execution \
; RUN: -spec-exec-only-if-divergent-target | \
; RUN: FileCheck --check-prefix=ON %s
; RUN: opt < %s -S -march=x86_64 -speculative-execution \
; RUN: -spec-exec-only-if-divergent-target | \
; RUN: FileCheck --check-prefix=OFF %s
; Hoist in if-then pattern.
define void @f() {
; ON: %x = add i32 2, 3
; ON: br i1 true
; OFF: br i1 true
; OFF: %x = add i32 2, 3
br i1 true, label %a, label %b
a:
%x = add i32 2, 3
br label %b
b:
ret void
}