| //===- SpeculativeExecution.h -----------------------------------*- C++ -*-===// |
| // |
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
| // See https://llvm.org/LICENSE.txt for license information. |
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
| // |
| //===----------------------------------------------------------------------===// |
| // |
| // This pass hoists instructions to enable speculative execution on |
| // targets where branches are expensive. This is aimed at GPUs. It |
| // currently works on simple if-then and if-then-else |
| // patterns. |
| // |
| // Removing branches is not the only motivation for this |
| // pass. E.g. consider this code and assume that there is no |
| // addressing mode for multiplying by sizeof(*a): |
| // |
| // if (b > 0) |
| // c = a[i + 1] |
| // if (d > 0) |
| // e = a[i + 2] |
| // |
| // turns into |
| // |
| // p = &a[i + 1]; |
| // if (b > 0) |
| // c = *p; |
| // q = &a[i + 2]; |
| // if (d > 0) |
| // e = *q; |
| // |
| // which could later be optimized to |
| // |
| // r = &a[i]; |
| // if (b > 0) |
| // c = r[1]; |
| // if (d > 0) |
| // e = r[2]; |
| // |
| // Later passes sink back much of the speculated code that did not enable |
| // further optimization. |
| // |
| // This pass is more aggressive than the function SpeculativeyExecuteBB in |
| // SimplifyCFG. SimplifyCFG will not speculate if no selects are introduced and |
| // it will speculate at most one instruction. It also will not speculate if |
| // there is a value defined in the if-block that is only used in the then-block. |
| // These restrictions make sense since the speculation in SimplifyCFG seems |
| // aimed at introducing cheap selects, while this pass is intended to do more |
| // aggressive speculation while counting on later passes to either capitalize on |
| // 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. |
| // |
| //===----------------------------------------------------------------------===// |
| #ifndef LLVM_TRANSFORMS_SCALAR_SPECULATIVEEXECUTION_H |
| #define LLVM_TRANSFORMS_SCALAR_SPECULATIVEEXECUTION_H |
| |
| #include "llvm/Analysis/TargetTransformInfo.h" |
| #include "llvm/IR/PassManager.h" |
| |
| namespace llvm { |
| class SpeculativeExecutionPass |
| : public PassInfoMixin<SpeculativeExecutionPass> { |
| public: |
| SpeculativeExecutionPass(bool OnlyIfDivergentTarget = false); |
| |
| PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM); |
| |
| // Glue for old PM |
| bool runImpl(Function &F, TargetTransformInfo *TTI); |
| |
| private: |
| bool runOnBasicBlock(BasicBlock &B); |
| bool considerHoistingFromTo(BasicBlock &FromBlock, BasicBlock &ToBlock); |
| |
| // If true, this pass is a nop unless the target architecture has branch |
| // divergence. |
| const bool OnlyIfDivergentTarget = false; |
| |
| TargetTransformInfo *TTI = nullptr; |
| }; |
| } |
| |
| #endif //LLVM_TRANSFORMS_SCALAR_SPECULATIVEEXECUTION_H |