<div dir="ltr">Fixed in r237724.</div><div class="gmail_extra"><br><div class="gmail_quote">On Tue, May 19, 2015 at 10:12 AM, Philip Reames <span dir="ltr"><<a 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">
  
    
  
  <div bgcolor="#FFFFFF" text="#000000"><span class="">
    <div>On 05/19/2015 10:06 AM, Jingyue Wu
      wrote:<br>
    </div>
    <blockquote type="cite">
      <div dir="ltr">Sure, I'll update that. Bjarke said something about
        it in the review thread (<a href="http://lists.cs.uiuc.edu/pipermail/llvm-commits/Week-of-Mon-20150427/274219.html" target="_blank">http://lists.cs.uiuc.edu/pipermail/llvm-commits/Week-of-Mon-20150427/274219.html</a>).
        <br>
      </div>
    </blockquote></span>
    That was exactly what I was looking for, thanks!<div><div class="h5"><br>
    <blockquote 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 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><font color="#888888"><br>
                <br>
                Philip</font></span>
            <div>
              <div><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 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 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 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 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 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 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 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 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 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 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 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 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 href="mailto:llvm-commits@cs.uiuc.edu" target="_blank">llvm-commits@cs.uiuc.edu</a><br>
                  <a 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>
  </div></div></div>

</blockquote></div><br></div>