forked from OSchip/llvm-project
[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:
parent
812e559589
commit
cad81cf6b3
|
@ -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();
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
}
|
Loading…
Reference in New Issue