<html>
<head>
<meta content="text/html; charset=utf-8" http-equiv="Content-Type">
</head>
<body bgcolor="#FFFFFF" text="#000000">
<div class="moz-cite-prefix">On 05/19/2015 10:06 AM, Jingyue Wu
wrote:<br>
</div>
<blockquote
cite="mid:CAMROOrFUAjqg3BoWva73gUptimaJOuVfzkmTU+H+nWcpU59x-A@mail.gmail.com"
type="cite">
<div dir="ltr">Sure, I'll update that. Bjarke said something about
it in the review thread (<a moz-do-not-send="true"
href="http://lists.cs.uiuc.edu/pipermail/llvm-commits/Week-of-Mon-20150427/274219.html">http://lists.cs.uiuc.edu/pipermail/llvm-commits/Week-of-Mon-20150427/274219.html</a>).
<br>
</div>
</blockquote>
That was exactly what I was looking for, thanks!<br>
<blockquote
cite="mid:CAMROOrFUAjqg3BoWva73gUptimaJOuVfzkmTU+H+nWcpU59x-A@mail.gmail.com"
type="cite">
<div class="gmail_extra"><br>
<div class="gmail_quote">On Tue, May 19, 2015 at 9:58 AM, Philip
Reames <span dir="ltr"><<a moz-do-not-send="true"
href="mailto:listmail@philipreames.com" target="_blank">listmail@philipreames.com</a>></span>
wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0
.8ex;border-left:1px #ccc solid;padding-left:1ex">Jingyue,<br>
<br>
Can you spell out how this is different from the existing
speculation done in SimplifyCFG? I'd really prefer to see
this addressed in the comments at the top of the pass. It's
something I imagine many readers are going to be wondering
about.<span class="HOEnZb"><font color="#888888"><br>
<br>
Philip</font></span>
<div class="HOEnZb">
<div class="h5"><br>
<br>
On 05/15/2015 10:54 AM, Jingyue Wu wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0
.8ex;border-left:1px #ccc solid;padding-left:1ex">
Author: jingyue<br>
Date: Fri May 15 12:54:48 2015<br>
New Revision: 237459<br>
<br>
URL: <a moz-do-not-send="true"
href="http://llvm.org/viewvc/llvm-project?rev=237459&view=rev"
target="_blank">http://llvm.org/viewvc/llvm-project?rev=237459&view=rev</a><br>
Log:<br>
Add a speculative execution pass<br>
<br>
Summary:<br>
This is a pass for speculative execution of
instructions for simple if-then (triangle) control
flow. It's aimed at GPUs, but could perhaps be used in
other contexts. Enabling this pass gives us a 1.0%
geomean improvement on Google benchmark suites, with
one benchmark improving 33%.<br>
<br>
Credit goes to Jingyue Wu for writing an earlier
version of this pass.<br>
<br>
Patched by Bjarke Roune.<br>
<br>
Test Plan:<br>
This patch adds a set of tests in
test/Transforms/SpeculativeExecution/spec.ll<br>
The pass is controlled by a flag which defaults to
having the pass not run.<br>
<br>
Reviewers: eliben, dberlin, meheff, jingyue, hfinkel<br>
<br>
Reviewed By: jingyue, hfinkel<br>
<br>
Subscribers: majnemer, jholewinski, llvm-commits<br>
<br>
Differential Revision: <a moz-do-not-send="true"
href="http://reviews.llvm.org/D9360" target="_blank">http://reviews.llvm.org/D9360</a><br>
<br>
Added:<br>
llvm/trunk/lib/Transforms/Scalar/SpeculativeExecution.cpp<br>
llvm/trunk/test/Transforms/SpeculativeExecution/<br>
llvm/trunk/test/Transforms/SpeculativeExecution/spec.ll<br>
Modified:<br>
llvm/trunk/include/llvm/IR/BasicBlock.h<br>
llvm/trunk/include/llvm/InitializePasses.h<br>
llvm/trunk/include/llvm/LinkAllPasses.h<br>
llvm/trunk/include/llvm/Transforms/Scalar.h<br>
llvm/trunk/lib/IR/BasicBlock.cpp<br>
llvm/trunk/lib/Transforms/IPO/PassManagerBuilder.cpp<br>
llvm/trunk/lib/Transforms/Scalar/CMakeLists.txt<br>
llvm/trunk/lib/Transforms/Scalar/Scalar.cpp<br>
<br>
Modified: llvm/trunk/include/llvm/IR/BasicBlock.h<br>
URL: <a moz-do-not-send="true"
href="http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/IR/BasicBlock.h?rev=237459&r1=237458&r2=237459&view=diff"
target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/IR/BasicBlock.h?rev=237459&r1=237458&r2=237459&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/include/llvm/IR/BasicBlock.h (original)<br>
+++ llvm/trunk/include/llvm/IR/BasicBlock.h Fri May 15
12:54:48 2015<br>
@@ -206,9 +206,19 @@ public:<br>
return
const_cast<BasicBlock*>(this)->getUniquePredecessor();<br>
}<br>
- /// Return the successor of this block if it has
a unique successor.<br>
- /// Otherwise return a null pointer. This method
is analogous to<br>
- /// getUniquePredeccessor above.<br>
+ /// \brief Return the successor of this block if it
has a single successor.<br>
+ /// Otherwise return a null pointer.<br>
+ ///<br>
+ /// This method is analogous to
getSinglePredecessor above.<br>
+ BasicBlock *getSingleSuccessor();<br>
+ const BasicBlock *getSingleSuccessor() const {<br>
+ return
const_cast<BasicBlock*>(this)->getSingleSuccessor();<br>
+ }<br>
+<br>
+ /// \brief Return the successor of this block if it
has a unique successor.<br>
+ /// Otherwise return a null pointer.<br>
+ ///<br>
+ /// This method is analogous to
getUniquePredecessor above.<br>
BasicBlock *getUniqueSuccessor();<br>
const BasicBlock *getUniqueSuccessor() const {<br>
return
const_cast<BasicBlock*>(this)->getUniqueSuccessor();<br>
<br>
Modified: llvm/trunk/include/llvm/InitializePasses.h<br>
URL: <a moz-do-not-send="true"
href="http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/InitializePasses.h?rev=237459&r1=237458&r2=237459&view=diff"
target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/InitializePasses.h?rev=237459&r1=237458&r2=237459&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/include/llvm/InitializePasses.h
(original)<br>
+++ llvm/trunk/include/llvm/InitializePasses.h Fri May
15 12:54:48 2015<br>
@@ -256,6 +256,7 @@ void
initializeSinkingPass(PassRegistry&<br>
void
initializeSeparateConstOffsetFromGEPPass(PassRegistry
&);<br>
void initializeSlotIndexesPass(PassRegistry&);<br>
void
initializeSpillPlacementPass(PassRegistry&);<br>
+void
initializeSpeculativeExecutionPass(PassRegistry&);<br>
void
initializeStackProtectorPass(PassRegistry&);<br>
void initializeStackColoringPass(PassRegistry&);<br>
void
initializeStackSlotColoringPass(PassRegistry&);<br>
<br>
Modified: llvm/trunk/include/llvm/LinkAllPasses.h<br>
URL: <a moz-do-not-send="true"
href="http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/LinkAllPasses.h?rev=237459&r1=237458&r2=237459&view=diff"
target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/LinkAllPasses.h?rev=237459&r1=237458&r2=237459&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/include/llvm/LinkAllPasses.h (original)<br>
+++ llvm/trunk/include/llvm/LinkAllPasses.h Fri May 15
12:54:48 2015<br>
@@ -170,6 +170,7 @@ namespace {<br>
(void)
llvm::createPartiallyInlineLibCallsPass();<br>
(void) llvm::createScalarizerPass();<br>
(void)
llvm::createSeparateConstOffsetFromGEPPass();<br>
+ (void) llvm::createSpeculativeExecutionPass();<br>
(void) llvm::createRewriteSymbolsPass();<br>
(void)
llvm::createStraightLineStrengthReducePass();<br>
(void) llvm::createMemDerefPrinter();<br>
<br>
Modified: llvm/trunk/include/llvm/Transforms/Scalar.h<br>
URL: <a moz-do-not-send="true"
href="http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Transforms/Scalar.h?rev=237459&r1=237458&r2=237459&view=diff"
target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Transforms/Scalar.h?rev=237459&r1=237458&r2=237459&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/include/llvm/Transforms/Scalar.h
(original)<br>
+++ llvm/trunk/include/llvm/Transforms/Scalar.h Fri
May 15 12:54:48 2015<br>
@@ -423,6 +423,13 @@
createSeparateConstOffsetFromGEPPass(con<br>
//===----------------------------------------------------------------------===//<br>
//<br>
+// SpeculativeExecution - Aggressively hoist
instructions to enable<br>
+// speculative execution on targets where branches
are expensive.<br>
+//<br>
+FunctionPass *createSpeculativeExecutionPass();<br>
+<br>
+//===----------------------------------------------------------------------===//<br>
+//<br>
// LoadCombine - Combine loads into bigger loads.<br>
//<br>
BasicBlockPass *createLoadCombinePass();<br>
<br>
Modified: llvm/trunk/lib/IR/BasicBlock.cpp<br>
URL: <a moz-do-not-send="true"
href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/IR/BasicBlock.cpp?rev=237459&r1=237458&r2=237459&view=diff"
target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/IR/BasicBlock.cpp?rev=237459&r1=237458&r2=237459&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/lib/IR/BasicBlock.cpp (original)<br>
+++ llvm/trunk/lib/IR/BasicBlock.cpp Fri May 15
12:54:48 2015<br>
@@ -238,6 +238,14 @@ BasicBlock
*BasicBlock::getUniquePredece<br>
return PredBB;<br>
}<br>
+BasicBlock *BasicBlock::getSingleSuccessor() {<br>
+ succ_iterator SI = succ_begin(this), E =
succ_end(this);<br>
+ if (SI == E) return nullptr; // no successors<br>
+ BasicBlock *TheSucc = *SI;<br>
+ ++SI;<br>
+ return (SI == E) ? TheSucc : nullptr /* multiple
successors */;<br>
+}<br>
+<br>
BasicBlock *BasicBlock::getUniqueSuccessor() {<br>
succ_iterator SI = succ_begin(this), E =
succ_end(this);<br>
if (SI == E) return NULL; // No successors<br>
<br>
Modified:
llvm/trunk/lib/Transforms/IPO/PassManagerBuilder.cpp<br>
URL: <a moz-do-not-send="true"
href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/IPO/PassManagerBuilder.cpp?rev=237459&r1=237458&r2=237459&view=diff"
target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/IPO/PassManagerBuilder.cpp?rev=237459&r1=237458&r2=237459&view=diff</a><br>
==============================================================================<br>
---
llvm/trunk/lib/Transforms/IPO/PassManagerBuilder.cpp
(original)<br>
+++
llvm/trunk/lib/Transforms/IPO/PassManagerBuilder.cpp
Fri May 15 12:54:48 2015<br>
@@ -231,6 +231,7 @@ void
PassManagerBuilder::populateModuleP<br>
MPM.add(createSROAPass(/*RequiresDomTree*/
false));<br>
else<br>
MPM.add(createScalarReplAggregatesPass(-1,
false));<br>
+<br>
MPM.add(createEarlyCSEPass()); //
Catch trivial redundancies<br>
MPM.add(createJumpThreadingPass()); //
Thread jumps.<br>
MPM.add(createCorrelatedValuePropagationPass());
// Propagate conditionals<br>
<br>
Modified:
llvm/trunk/lib/Transforms/Scalar/CMakeLists.txt<br>
URL: <a moz-do-not-send="true"
href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/CMakeLists.txt?rev=237459&r1=237458&r2=237459&view=diff"
target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/CMakeLists.txt?rev=237459&r1=237458&r2=237459&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/lib/Transforms/Scalar/CMakeLists.txt
(original)<br>
+++ llvm/trunk/lib/Transforms/Scalar/CMakeLists.txt
Fri May 15 12:54:48 2015<br>
@@ -45,6 +45,7 @@ add_llvm_library(LLVMScalarOpts<br>
SeparateConstOffsetFromGEP.cpp<br>
SimplifyCFGPass.cpp<br>
Sink.cpp<br>
+ SpeculativeExecution.cpp<br>
StraightLineStrengthReduce.cpp<br>
StructurizeCFG.cpp<br>
TailRecursionElimination.cpp<br>
<br>
Modified: llvm/trunk/lib/Transforms/Scalar/Scalar.cpp<br>
URL: <a moz-do-not-send="true"
href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/Scalar.cpp?rev=237459&r1=237458&r2=237459&view=diff"
target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/Scalar.cpp?rev=237459&r1=237458&r2=237459&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/lib/Transforms/Scalar/Scalar.cpp
(original)<br>
+++ llvm/trunk/lib/Transforms/Scalar/Scalar.cpp Fri
May 15 12:54:48 2015<br>
@@ -74,6 +74,7 @@ void
llvm::initializeScalarOpts(PassRegi<br>
initializeSinkingPass(Registry);<br>
initializeTailCallElimPass(Registry);<br>
initializeSeparateConstOffsetFromGEPPass(Registry);<br>
+ initializeSpeculativeExecutionPass(Registry);<br>
initializeStraightLineStrengthReducePass(Registry);<br>
initializeLoadCombinePass(Registry);<br>
initializePlaceBackedgeSafepointsImplPass(Registry);<br>
<br>
Added:
llvm/trunk/lib/Transforms/Scalar/SpeculativeExecution.cpp<br>
URL: <a moz-do-not-send="true"
href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/SpeculativeExecution.cpp?rev=237459&view=auto"
target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/SpeculativeExecution.cpp?rev=237459&view=auto</a><br>
==============================================================================<br>
---
llvm/trunk/lib/Transforms/Scalar/SpeculativeExecution.cpp
(added)<br>
+++
llvm/trunk/lib/Transforms/Scalar/SpeculativeExecution.cpp
Fri May 15 12:54:48 2015<br>
@@ -0,0 +1,232 @@<br>
+//===- SpeculativeExecution.cpp
---------------------------------*- C++ -*-===//<br>
+//<br>
+// The LLVM Compiler
Infrastructure<br>
+//<br>
+// This file is distributed under the University of
Illinois Open Source<br>
+// License. See LICENSE.TXT for details.<br>
+//<br>
+//===----------------------------------------------------------------------===//<br>
+//<br>
+// This pass hoists instructions to enable
speculative execution on<br>
+// targets where branches are expensive. This is
aimed at GPUs. It<br>
+// currently works on simple if-then and if-then-else<br>
+// patterns.<br>
+//<br>
+// Removing branches is not the only motivation for
this<br>
+// pass. E.g. consider this code and assume that
there is no<br>
+// addressing mode for multiplying by sizeof(*a):<br>
+//<br>
+// if (b > 0)<br>
+// c = a[i + 1]<br>
+// if (d > 0)<br>
+// e = a[i + 2]<br>
+//<br>
+// turns into<br>
+//<br>
+// p = &a[i + 1];<br>
+// if (b > 0)<br>
+// c = *p;<br>
+// q = &a[i + 2];<br>
+// if (d > 0)<br>
+// e = *q;<br>
+//<br>
+// which could later be optimized to<br>
+//<br>
+// r = &a[i];<br>
+// if (b > 0)<br>
+// c = r[1];<br>
+// if (d > 0)<br>
+// e = r[2];<br>
+//<br>
+// Later passes sink back much of the speculated code
that did not enable<br>
+// further optimization.<br>
+//<br>
+//===----------------------------------------------------------------------===//<br>
+<br>
+#include "llvm/ADT/SmallSet.h"<br>
+#include "llvm/Analysis/TargetTransformInfo.h"<br>
+#include "llvm/Analysis/ValueTracking.h"<br>
+#include "llvm/IR/Instructions.h"<br>
+#include "llvm/IR/Module.h"<br>
+#include "llvm/IR/Operator.h"<br>
+#include "llvm/Support/CommandLine.h"<br>
+#include "llvm/Support/Debug.h"<br>
+<br>
+using namespace llvm;<br>
+<br>
+#define DEBUG_TYPE "speculative-execution"<br>
+<br>
+// The risk that speculation will not pay off
increases with the<br>
+// number of instructions speculated, so we put a
limit on that.<br>
+static cl::opt<unsigned>
SpecExecMaxSpeculationCost(<br>
+ "spec-exec-max-speculation-cost", cl::init(7),
cl::Hidden,<br>
+ cl::desc("Speculative execution is not applied to
basic blocks where "<br>
+ "the cost of the instructions to
speculatively execute "<br>
+ "exceeds this limit."));<br>
+<br>
+// Speculating just a few instructions from a larger
block tends not<br>
+// to be profitable and this limit prevents that. A
reason for that is<br>
+// that small basic blocks are more likely to be
candidates for<br>
+// further optimization.<br>
+static cl::opt<unsigned> SpecExecMaxNotHoisted(<br>
+ "spec-exec-max-not-hoisted", cl::init(5),
cl::Hidden,<br>
+ cl::desc("Speculative execution is not applied to
basic blocks where the "<br>
+ "number of instructions that would not
be speculatively executed "<br>
+ "exceeds this limit."));<br>
+<br>
+class SpeculativeExecution : public FunctionPass {<br>
+ public:<br>
+ static char ID;<br>
+ SpeculativeExecution(): FunctionPass(ID) {}<br>
+<br>
+ void getAnalysisUsage(AnalysisUsage &AU) const
override;<br>
+ bool runOnFunction(Function &F) override;<br>
+<br>
+ private:<br>
+ bool runOnBasicBlock(BasicBlock &B);<br>
+ bool considerHoistingFromTo(BasicBlock
&FromBlock, BasicBlock &ToBlock);<br>
+<br>
+ const TargetTransformInfo *TTI = nullptr;<br>
+};<br>
+<br>
+char SpeculativeExecution::ID = 0;<br>
+INITIALIZE_PASS_BEGIN(SpeculativeExecution,
"speculative-execution",<br>
+ "Speculatively execute
instructions", false, false)<br>
+INITIALIZE_PASS_DEPENDENCY(TargetTransformInfoWrapperPass)<br>
+INITIALIZE_PASS_END(SpeculativeExecution,
"speculative-execution",<br>
+ "Speculatively execute
instructions", false, false)<br>
+<br>
+void
SpeculativeExecution::getAnalysisUsage(AnalysisUsage
&AU) const {<br>
+
AU.addRequired<TargetTransformInfoWrapperPass>();<br>
+}<br>
+<br>
+bool SpeculativeExecution::runOnFunction(Function
&F) {<br>
+ if (skipOptnoneFunction(F))<br>
+ return false;<br>
+<br>
+ TTI =
&getAnalysis<TargetTransformInfoWrapperPass>().getTTI(F);<br>
+<br>
+ bool Changed = false;<br>
+ for (auto& B : F) {<br>
+ Changed |= runOnBasicBlock(B);<br>
+ }<br>
+ return Changed;<br>
+}<br>
+<br>
+bool SpeculativeExecution::runOnBasicBlock(BasicBlock
&B) {<br>
+ BranchInst *BI =
dyn_cast<BranchInst>(B.getTerminator());<br>
+ if (BI == nullptr)<br>
+ return false;<br>
+<br>
+ if (BI->getNumSuccessors() != 2)<br>
+ return false;<br>
+ BasicBlock &Succ0 = *BI->getSuccessor(0);<br>
+ BasicBlock &Succ1 = *BI->getSuccessor(1);<br>
+<br>
+ if (&B == &Succ0 || &B == &Succ1 ||
&Succ0 == &Succ1) {<br>
+ return false;<br>
+ }<br>
+<br>
+ // Hoist from if-then (triangle).<br>
+ if (Succ0.getSinglePredecessor() != nullptr
&&<br>
+ Succ0.getSingleSuccessor() == &Succ1) {<br>
+ return considerHoistingFromTo(Succ0, B);<br>
+ }<br>
+<br>
+ // Hoist from if-else (triangle).<br>
+ if (Succ1.getSinglePredecessor() != nullptr
&&<br>
+ Succ1.getSingleSuccessor() == &Succ0) {<br>
+ return considerHoistingFromTo(Succ1, B);<br>
+ }<br>
+<br>
+ // Hoist from if-then-else (diamond), but only if
it is equivalent to<br>
+ // an if-else or if-then due to one of the branches
doing nothing.<br>
+ if (Succ0.getSinglePredecessor() != nullptr
&&<br>
+ Succ1.getSinglePredecessor() != nullptr
&&<br>
+ Succ1.getSingleSuccessor() != nullptr
&&<br>
+ Succ1.getSingleSuccessor() != &B &&<br>
+ Succ1.getSingleSuccessor() ==
Succ0.getSingleSuccessor()) {<br>
+ // If a block has only one instruction, then that
is a terminator<br>
+ // instruction so that the block does nothing.
This does happen.<br>
+ if (Succ1.size() == 1) // equivalent to if-then<br>
+ return considerHoistingFromTo(Succ0, B);<br>
+ if (Succ0.size() == 1) // equivalent to if-else<br>
+ return considerHoistingFromTo(Succ1, B);<br>
+ }<br>
+<br>
+ return false;<br>
+}<br>
+<br>
+static unsigned ComputeSpeculationCost(const
Instruction *I,<br>
+ const
TargetTransformInfo &TTI) {<br>
+ switch (Operator::getOpcode(I)) {<br>
+ case Instruction::GetElementPtr:<br>
+ case Instruction::Add:<br>
+ case Instruction::Mul:<br>
+ case Instruction::And:<br>
+ case Instruction::Or:<br>
+ case Instruction::Select:<br>
+ case Instruction::Shl:<br>
+ case Instruction::Sub:<br>
+ case Instruction::LShr:<br>
+ case Instruction::AShr:<br>
+ case Instruction::Xor:<br>
+ case Instruction::ZExt:<br>
+ case Instruction::SExt:<br>
+ return TTI.getUserCost(I);<br>
+<br>
+ default:<br>
+ return UINT_MAX; // Disallow anything not
whitelisted.<br>
+ }<br>
+}<br>
+<br>
+bool
SpeculativeExecution::considerHoistingFromTo(BasicBlock
&FromBlock,<br>
+
BasicBlock &ToBlock) {<br>
+ SmallSet<const Instruction *, 8> NotHoisted;<br>
+ const auto AllPrecedingUsesFromBlockHoisted =
[&NotHoisted](User *U) {<br>
+ for (Value* V : U->operand_values()) {<br>
+ if (Instruction *I =
dyn_cast<Instruction>(V)) {<br>
+ if (NotHoisted.count(I) > 0)<br>
+ return false;<br>
+ }<br>
+ }<br>
+ return true;<br>
+ };<br>
+<br>
+ unsigned TotalSpeculationCost = 0;<br>
+ for (auto& I : FromBlock) {<br>
+ const unsigned Cost =
ComputeSpeculationCost(&I, *TTI);<br>
+ if (Cost != UINT_MAX &&
isSafeToSpeculativelyExecute(&I) &&<br>
+ AllPrecedingUsesFromBlockHoisted(&I)) {<br>
+ TotalSpeculationCost += Cost;<br>
+ if (TotalSpeculationCost >
SpecExecMaxSpeculationCost)<br>
+ return false; // too much to hoist<br>
+ } else {<br>
+ NotHoisted.insert(&I);<br>
+ if (NotHoisted.size() >
SpecExecMaxNotHoisted)<br>
+ return false; // too much left behind<br>
+ }<br>
+ }<br>
+<br>
+ if (TotalSpeculationCost == 0)<br>
+ return false; // nothing to hoist<br>
+<br>
+ for (auto I = FromBlock.begin(); I !=
FromBlock.end();) {<br>
+ // We have to increment I before moving Current
as moving Current<br>
+ // changes the list that I is iterating through.<br>
+ auto Current = I;<br>
+ ++I;<br>
+ if (!NotHoisted.count(Current)) {<br>
+
Current->moveBefore(ToBlock.getTerminator());<br>
+ }<br>
+ }<br>
+ return true;<br>
+}<br>
+<br>
+namespace llvm {<br>
+<br>
+FunctionPass *createSpeculativeExecutionPass() {<br>
+ return new SpeculativeExecution();<br>
+}<br>
+<br>
+} // namespace llvm<br>
<br>
Added:
llvm/trunk/test/Transforms/SpeculativeExecution/spec.ll<br>
URL: <a moz-do-not-send="true"
href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/SpeculativeExecution/spec.ll?rev=237459&view=auto"
target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/SpeculativeExecution/spec.ll?rev=237459&view=auto</a><br>
==============================================================================<br>
---
llvm/trunk/test/Transforms/SpeculativeExecution/spec.ll
(added)<br>
+++
llvm/trunk/test/Transforms/SpeculativeExecution/spec.ll
Fri May 15 12:54:48 2015<br>
@@ -0,0 +1,195 @@<br>
+; RUN: opt < %s -S -speculative-execution \<br>
+; RUN: -spec-exec-max-speculation-cost 4
-spec-exec-max-not-hoisted 3 \<br>
+; RUN: | FileCheck %s<br>
+<br>
+target datalayout =
"e-i64:64-v16:16-v32:32-n16:32:64"<br>
+<br>
+; Hoist in if-then pattern.<br>
+define void @ifThen() {<br>
+; CHECK-LABEL: @ifThen(<br>
+; CHECK: %x = add i32 2, 3<br>
+; CHECK: br i1 true<br>
+ br i1 true, label %a, label %b<br>
+; CHECK: a:<br>
+a:<br>
+ %x = add i32 2, 3<br>
+; CHECK: br label<br>
+ br label %b<br>
+; CHECK: b:<br>
+b:<br>
+; CHECK: ret void<br>
+ ret void<br>
+}<br>
+<br>
+; Hoist in if-else pattern.<br>
+define void @ifElse() {<br>
+; CHECK-LABEL: @ifElse(<br>
+; CHECK: %x = add i32 2, 3<br>
+; CHECK: br i1 true<br>
+ br i1 true, label %b, label %a<br>
+; CHECK: a:<br>
+a:<br>
+ %x = add i32 2, 3<br>
+; CHECK: br label<br>
+ br label %b<br>
+; CHECK: b:<br>
+b:<br>
+; CHECK: ret void<br>
+ ret void<br>
+}<br>
+<br>
+; Hoist in if-then-else pattern if it is equivalent
to if-then.<br>
+define void @ifElseThenAsIfThen() {<br>
+; CHECK-LABEL: @ifElseThenAsIfThen(<br>
+; CHECK: %x = add i32 2, 3<br>
+; CHECK: br<br>
+ br i1 true, label %a, label %b<br>
+; CHECK: a:<br>
+a:<br>
+ %x = add i32 2, 3<br>
+; CHECK: br label<br>
+ br label %c<br>
+; CHECK: b:<br>
+b:<br>
+ br label %c<br>
+; CHECK: c<br>
+c:<br>
+ ret void<br>
+}<br>
+<br>
+; Hoist in if-then-else pattern if it is equivalent
to if-else.<br>
+define void @ifElseThenAsIfElse() {<br>
+; CHECK-LABEL: @ifElseThenAsIfElse(<br>
+; CHECK: %x = add i32 2, 3<br>
+; CHECK: br<br>
+ br i1 true, label %b, label %a<br>
+; CHECK: a:<br>
+a:<br>
+ %x = add i32 2, 3<br>
+; CHECK: br label<br>
+ br label %c<br>
+; CHECK: b:<br>
+b:<br>
+ br label %c<br>
+; CHECK: c<br>
+c:<br>
+ ret void<br>
+}<br>
+<br>
+; Do not hoist if-then-else pattern if it is not
equivalent to if-then<br>
+; or if-else.<br>
+define void @ifElseThen() {<br>
+; CHECK-LABEL: @ifElseThen(<br>
+; CHECK: br<br>
+ br i1 true, label %a, label %b<br>
+; CHECK: a:<br>
+a:<br>
+; CHECK: %x = add<br>
+ %x = add i32 2, 3<br>
+; CHECK: br label<br>
+ br label %c<br>
+; CHECK: b:<br>
+b:<br>
+; CHECK: %y = add<br>
+ %y = add i32 2, 3<br>
+ br label %c<br>
+; CHECK: c<br>
+c:<br>
+ ret void<br>
+}<br>
+<br>
+; Do not hoist loads and do not hoist an instruction
past a definition of<br>
+; an operand.<br>
+define void @doNotHoistPastDef() {<br>
+; CHECK-LABEL: @doNotHoistPastDef(<br>
+ br i1 true, label %b, label %a<br>
+; CHECK-NOT: load<br>
+; CHECK-NOT: add<br>
+; CHECK: a:<br>
+a:<br>
+; CHECK: %def = load<br>
+ %def = load i32, i32* null<br>
+; CHECK: %use = add<br>
+ %use = add i32 %def, 0<br>
+ br label %b<br>
+; CHECK: b:<br>
+b:<br>
+ ret void<br>
+}<br>
+<br>
+; Case with nothing to speculate.<br>
+define void @nothingToSpeculate() {<br>
+; CHECK-LABEL: @nothingToSpeculate(<br>
+ br i1 true, label %b, label %a<br>
+; CHECK: a:<br>
+a:<br>
+; CHECK: %def = load<br>
+ %def = load i32, i32* null<br>
+ br label %b<br>
+; CHECK: b:<br>
+b:<br>
+ ret void<br>
+}<br>
+<br>
+; Still hoist if an operand is defined before the
block or is itself hoisted.<br>
+define void @hoistIfNotPastDef() {<br>
+; CHECK-LABEL: @hoistIfNotPastDef(<br>
+; CHECK: %x = load<br>
+ %x = load i32, i32* null<br>
+; CHECK: %y = add i32 %x, 1<br>
+; CHECK: %z = add i32 %y, 1<br>
+; CHECK: br<br>
+ br i1 true, label %b, label %a<br>
+; CHECK: a:<br>
+a:<br>
+ %y = add i32 %x, 1<br>
+ %z = add i32 %y, 1<br>
+ br label %b<br>
+; CHECK: b:<br>
+b:<br>
+ ret void<br>
+}<br>
+<br>
+; Do not hoist if the speculation cost is too high.<br>
+define void @costTooHigh() {<br>
+; CHECK-LABEL: @costTooHigh(<br>
+; CHECK: br<br>
+ br i1 true, label %b, label %a<br>
+; CHECK: a:<br>
+a:<br>
+; CHECK: %r1 = add<br>
+ %r1 = add i32 1, 1<br>
+; CHECK: %r2 = add<br>
+ %r2 = add i32 1, 1<br>
+; CHECK: %r3 = add<br>
+ %r3 = add i32 1, 1<br>
+; CHECK: %r4 = add<br>
+ %r4 = add i32 1, 1<br>
+; CHECK: %r5 = add<br>
+ %r5 = add i32 1, 1<br>
+ br label %b<br>
+; CHECK: b:<br>
+b:<br>
+ ret void<br>
+}<br>
+<br>
+; Do not hoist if too many instructions are left
behind.<br>
+define void @tooMuchLeftBehind() {<br>
+; CHECK-LABEL: @tooMuchLeftBehind(<br>
+; CHECK: br<br>
+ br i1 true, label %b, label %a<br>
+; CHECK: a:<br>
+a:<br>
+; CHECK: %x = load<br>
+ %x = load i32, i32* null<br>
+; CHECK: %r1 = add<br>
+ %r1 = add i32 %x, 1<br>
+; CHECK: %r2 = add<br>
+ %r2 = add i32 %x, 1<br>
+; CHECK: %r3 = add<br>
+ %r3 = add i32 %x, 1<br>
+ br label %b<br>
+; CHECK: b:<br>
+b:<br>
+ ret void<br>
+}<br>
<br>
<br>
_______________________________________________<br>
llvm-commits mailing list<br>
<a moz-do-not-send="true"
href="mailto:llvm-commits@cs.uiuc.edu"
target="_blank">llvm-commits@cs.uiuc.edu</a><br>
<a moz-do-not-send="true"
href="http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits"
target="_blank">http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits</a><br>
</blockquote>
<br>
</div>
</div>
</blockquote>
</div>
<br>
</div>
</blockquote>
<br>
</body>
</html>