10b57cec5SDimitry Andric //===- SpeculativeExecution.cpp ---------------------------------*- C++ -*-===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric // 90b57cec5SDimitry Andric // This pass hoists instructions to enable speculative execution on 100b57cec5SDimitry Andric // targets where branches are expensive. This is aimed at GPUs. It 110b57cec5SDimitry Andric // currently works on simple if-then and if-then-else 120b57cec5SDimitry Andric // patterns. 130b57cec5SDimitry Andric // 140b57cec5SDimitry Andric // Removing branches is not the only motivation for this 150b57cec5SDimitry Andric // pass. E.g. consider this code and assume that there is no 160b57cec5SDimitry Andric // addressing mode for multiplying by sizeof(*a): 170b57cec5SDimitry Andric // 180b57cec5SDimitry Andric // if (b > 0) 190b57cec5SDimitry Andric // c = a[i + 1] 200b57cec5SDimitry Andric // if (d > 0) 210b57cec5SDimitry Andric // e = a[i + 2] 220b57cec5SDimitry Andric // 230b57cec5SDimitry Andric // turns into 240b57cec5SDimitry Andric // 250b57cec5SDimitry Andric // p = &a[i + 1]; 260b57cec5SDimitry Andric // if (b > 0) 270b57cec5SDimitry Andric // c = *p; 280b57cec5SDimitry Andric // q = &a[i + 2]; 290b57cec5SDimitry Andric // if (d > 0) 300b57cec5SDimitry Andric // e = *q; 310b57cec5SDimitry Andric // 320b57cec5SDimitry Andric // which could later be optimized to 330b57cec5SDimitry Andric // 340b57cec5SDimitry Andric // r = &a[i]; 350b57cec5SDimitry Andric // if (b > 0) 360b57cec5SDimitry Andric // c = r[1]; 370b57cec5SDimitry Andric // if (d > 0) 380b57cec5SDimitry Andric // e = r[2]; 390b57cec5SDimitry Andric // 400b57cec5SDimitry Andric // Later passes sink back much of the speculated code that did not enable 410b57cec5SDimitry Andric // further optimization. 420b57cec5SDimitry Andric // 430b57cec5SDimitry Andric // This pass is more aggressive than the function SpeculativeyExecuteBB in 440b57cec5SDimitry Andric // SimplifyCFG. SimplifyCFG will not speculate if no selects are introduced and 450b57cec5SDimitry Andric // it will speculate at most one instruction. It also will not speculate if 460b57cec5SDimitry Andric // there is a value defined in the if-block that is only used in the then-block. 470b57cec5SDimitry Andric // These restrictions make sense since the speculation in SimplifyCFG seems 480b57cec5SDimitry Andric // aimed at introducing cheap selects, while this pass is intended to do more 490b57cec5SDimitry Andric // aggressive speculation while counting on later passes to either capitalize on 500b57cec5SDimitry Andric // that or clean it up. 510b57cec5SDimitry Andric // 520b57cec5SDimitry Andric // If the pass was created by calling 530b57cec5SDimitry Andric // createSpeculativeExecutionIfHasBranchDivergencePass or the 540b57cec5SDimitry Andric // -spec-exec-only-if-divergent-target option is present, this pass only has an 550b57cec5SDimitry Andric // effect on targets where TargetTransformInfo::hasBranchDivergence() is true; 560b57cec5SDimitry Andric // on other targets, it is a nop. 570b57cec5SDimitry Andric // 580b57cec5SDimitry Andric // This lets you include this pass unconditionally in the IR pass pipeline, but 590b57cec5SDimitry Andric // only enable it for relevant targets. 600b57cec5SDimitry Andric // 610b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 620b57cec5SDimitry Andric 630b57cec5SDimitry Andric #include "llvm/Transforms/Scalar/SpeculativeExecution.h" 640b57cec5SDimitry Andric #include "llvm/ADT/SmallPtrSet.h" 650b57cec5SDimitry Andric #include "llvm/Analysis/GlobalsModRef.h" 6681ad6265SDimitry Andric #include "llvm/Analysis/TargetTransformInfo.h" 670b57cec5SDimitry Andric #include "llvm/Analysis/ValueTracking.h" 680b57cec5SDimitry Andric #include "llvm/IR/Instructions.h" 695ffd83dbSDimitry Andric #include "llvm/IR/IntrinsicInst.h" 700b57cec5SDimitry Andric #include "llvm/IR/Operator.h" 71480093f4SDimitry Andric #include "llvm/InitializePasses.h" 720b57cec5SDimitry Andric #include "llvm/Support/CommandLine.h" 730b57cec5SDimitry Andric #include "llvm/Support/Debug.h" 740b57cec5SDimitry Andric 750b57cec5SDimitry Andric using namespace llvm; 760b57cec5SDimitry Andric 770b57cec5SDimitry Andric #define DEBUG_TYPE "speculative-execution" 780b57cec5SDimitry Andric 790b57cec5SDimitry Andric // The risk that speculation will not pay off increases with the 800b57cec5SDimitry Andric // number of instructions speculated, so we put a limit on that. 810b57cec5SDimitry Andric static cl::opt<unsigned> SpecExecMaxSpeculationCost( 820b57cec5SDimitry Andric "spec-exec-max-speculation-cost", cl::init(7), cl::Hidden, 830b57cec5SDimitry Andric cl::desc("Speculative execution is not applied to basic blocks where " 840b57cec5SDimitry Andric "the cost of the instructions to speculatively execute " 850b57cec5SDimitry Andric "exceeds this limit.")); 860b57cec5SDimitry Andric 870b57cec5SDimitry Andric // Speculating just a few instructions from a larger block tends not 880b57cec5SDimitry Andric // to be profitable and this limit prevents that. A reason for that is 890b57cec5SDimitry Andric // that small basic blocks are more likely to be candidates for 900b57cec5SDimitry Andric // further optimization. 910b57cec5SDimitry Andric static cl::opt<unsigned> SpecExecMaxNotHoisted( 920b57cec5SDimitry Andric "spec-exec-max-not-hoisted", cl::init(5), cl::Hidden, 930b57cec5SDimitry Andric cl::desc("Speculative execution is not applied to basic blocks where the " 940b57cec5SDimitry Andric "number of instructions that would not be speculatively executed " 950b57cec5SDimitry Andric "exceeds this limit.")); 960b57cec5SDimitry Andric 970b57cec5SDimitry Andric static cl::opt<bool> SpecExecOnlyIfDivergentTarget( 980b57cec5SDimitry Andric "spec-exec-only-if-divergent-target", cl::init(false), cl::Hidden, 990b57cec5SDimitry Andric cl::desc("Speculative execution is applied only to targets with divergent " 1000b57cec5SDimitry Andric "branches, even if the pass was configured to apply only to all " 1010b57cec5SDimitry Andric "targets.")); 1020b57cec5SDimitry Andric 1030b57cec5SDimitry Andric namespace { 1040b57cec5SDimitry Andric 1050b57cec5SDimitry Andric class SpeculativeExecutionLegacyPass : public FunctionPass { 1060b57cec5SDimitry Andric public: 1070b57cec5SDimitry Andric static char ID; 1080b57cec5SDimitry Andric explicit SpeculativeExecutionLegacyPass(bool OnlyIfDivergentTarget = false) 1090b57cec5SDimitry Andric : FunctionPass(ID), OnlyIfDivergentTarget(OnlyIfDivergentTarget || 1100b57cec5SDimitry Andric SpecExecOnlyIfDivergentTarget), 1110b57cec5SDimitry Andric Impl(OnlyIfDivergentTarget) {} 1120b57cec5SDimitry Andric 1130b57cec5SDimitry Andric void getAnalysisUsage(AnalysisUsage &AU) const override; 1140b57cec5SDimitry Andric bool runOnFunction(Function &F) override; 1150b57cec5SDimitry Andric 1160b57cec5SDimitry Andric StringRef getPassName() const override { 1170b57cec5SDimitry Andric if (OnlyIfDivergentTarget) 1180b57cec5SDimitry Andric return "Speculatively execute instructions if target has divergent " 1190b57cec5SDimitry Andric "branches"; 1200b57cec5SDimitry Andric return "Speculatively execute instructions"; 1210b57cec5SDimitry Andric } 1220b57cec5SDimitry Andric 1230b57cec5SDimitry Andric private: 1240b57cec5SDimitry Andric // Variable preserved purely for correct name printing. 1250b57cec5SDimitry Andric const bool OnlyIfDivergentTarget; 1260b57cec5SDimitry Andric 1270b57cec5SDimitry Andric SpeculativeExecutionPass Impl; 1280b57cec5SDimitry Andric }; 1290b57cec5SDimitry Andric } // namespace 1300b57cec5SDimitry Andric 1310b57cec5SDimitry Andric char SpeculativeExecutionLegacyPass::ID = 0; 1320b57cec5SDimitry Andric INITIALIZE_PASS_BEGIN(SpeculativeExecutionLegacyPass, "speculative-execution", 1330b57cec5SDimitry Andric "Speculatively execute instructions", false, false) 1340b57cec5SDimitry Andric INITIALIZE_PASS_DEPENDENCY(TargetTransformInfoWrapperPass) 1350b57cec5SDimitry Andric INITIALIZE_PASS_END(SpeculativeExecutionLegacyPass, "speculative-execution", 1360b57cec5SDimitry Andric "Speculatively execute instructions", false, false) 1370b57cec5SDimitry Andric 1380b57cec5SDimitry Andric void SpeculativeExecutionLegacyPass::getAnalysisUsage(AnalysisUsage &AU) const { 1390b57cec5SDimitry Andric AU.addRequired<TargetTransformInfoWrapperPass>(); 1400b57cec5SDimitry Andric AU.addPreserved<GlobalsAAWrapperPass>(); 1410b57cec5SDimitry Andric AU.setPreservesCFG(); 1420b57cec5SDimitry Andric } 1430b57cec5SDimitry Andric 1440b57cec5SDimitry Andric bool SpeculativeExecutionLegacyPass::runOnFunction(Function &F) { 1450b57cec5SDimitry Andric if (skipFunction(F)) 1460b57cec5SDimitry Andric return false; 1470b57cec5SDimitry Andric 1480b57cec5SDimitry Andric auto *TTI = &getAnalysis<TargetTransformInfoWrapperPass>().getTTI(F); 1490b57cec5SDimitry Andric return Impl.runImpl(F, TTI); 1500b57cec5SDimitry Andric } 1510b57cec5SDimitry Andric 1520b57cec5SDimitry Andric namespace llvm { 1530b57cec5SDimitry Andric 1540b57cec5SDimitry Andric bool SpeculativeExecutionPass::runImpl(Function &F, TargetTransformInfo *TTI) { 15506c3fb27SDimitry Andric if (OnlyIfDivergentTarget && !TTI->hasBranchDivergence(&F)) { 1560b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "Not running SpeculativeExecution because " 1570b57cec5SDimitry Andric "TTI->hasBranchDivergence() is false.\n"); 1580b57cec5SDimitry Andric return false; 1590b57cec5SDimitry Andric } 1600b57cec5SDimitry Andric 1610b57cec5SDimitry Andric this->TTI = TTI; 1620b57cec5SDimitry Andric bool Changed = false; 1630b57cec5SDimitry Andric for (auto& B : F) { 1640b57cec5SDimitry Andric Changed |= runOnBasicBlock(B); 1650b57cec5SDimitry Andric } 1660b57cec5SDimitry Andric return Changed; 1670b57cec5SDimitry Andric } 1680b57cec5SDimitry Andric 1690b57cec5SDimitry Andric bool SpeculativeExecutionPass::runOnBasicBlock(BasicBlock &B) { 1700b57cec5SDimitry Andric BranchInst *BI = dyn_cast<BranchInst>(B.getTerminator()); 1710b57cec5SDimitry Andric if (BI == nullptr) 1720b57cec5SDimitry Andric return false; 1730b57cec5SDimitry Andric 1740b57cec5SDimitry Andric if (BI->getNumSuccessors() != 2) 1750b57cec5SDimitry Andric return false; 1760b57cec5SDimitry Andric BasicBlock &Succ0 = *BI->getSuccessor(0); 1770b57cec5SDimitry Andric BasicBlock &Succ1 = *BI->getSuccessor(1); 1780b57cec5SDimitry Andric 1790b57cec5SDimitry Andric if (&B == &Succ0 || &B == &Succ1 || &Succ0 == &Succ1) { 1800b57cec5SDimitry Andric return false; 1810b57cec5SDimitry Andric } 1820b57cec5SDimitry Andric 1830b57cec5SDimitry Andric // Hoist from if-then (triangle). 1840b57cec5SDimitry Andric if (Succ0.getSinglePredecessor() != nullptr && 1850b57cec5SDimitry Andric Succ0.getSingleSuccessor() == &Succ1) { 1860b57cec5SDimitry Andric return considerHoistingFromTo(Succ0, B); 1870b57cec5SDimitry Andric } 1880b57cec5SDimitry Andric 1890b57cec5SDimitry Andric // Hoist from if-else (triangle). 1900b57cec5SDimitry Andric if (Succ1.getSinglePredecessor() != nullptr && 1910b57cec5SDimitry Andric Succ1.getSingleSuccessor() == &Succ0) { 1920b57cec5SDimitry Andric return considerHoistingFromTo(Succ1, B); 1930b57cec5SDimitry Andric } 1940b57cec5SDimitry Andric 1950b57cec5SDimitry Andric // Hoist from if-then-else (diamond), but only if it is equivalent to 1960b57cec5SDimitry Andric // an if-else or if-then due to one of the branches doing nothing. 1970b57cec5SDimitry Andric if (Succ0.getSinglePredecessor() != nullptr && 1980b57cec5SDimitry Andric Succ1.getSinglePredecessor() != nullptr && 1990b57cec5SDimitry Andric Succ1.getSingleSuccessor() != nullptr && 2000b57cec5SDimitry Andric Succ1.getSingleSuccessor() != &B && 2010b57cec5SDimitry Andric Succ1.getSingleSuccessor() == Succ0.getSingleSuccessor()) { 2020b57cec5SDimitry Andric // If a block has only one instruction, then that is a terminator 2030b57cec5SDimitry Andric // instruction so that the block does nothing. This does happen. 2040b57cec5SDimitry Andric if (Succ1.size() == 1) // equivalent to if-then 2050b57cec5SDimitry Andric return considerHoistingFromTo(Succ0, B); 2060b57cec5SDimitry Andric if (Succ0.size() == 1) // equivalent to if-else 2070b57cec5SDimitry Andric return considerHoistingFromTo(Succ1, B); 2080b57cec5SDimitry Andric } 2090b57cec5SDimitry Andric 2100b57cec5SDimitry Andric return false; 2110b57cec5SDimitry Andric } 2120b57cec5SDimitry Andric 213fe6060f1SDimitry Andric static InstructionCost ComputeSpeculationCost(const Instruction *I, 2140b57cec5SDimitry Andric const TargetTransformInfo &TTI) { 2150b57cec5SDimitry Andric switch (Operator::getOpcode(I)) { 2160b57cec5SDimitry Andric case Instruction::GetElementPtr: 2170b57cec5SDimitry Andric case Instruction::Add: 2180b57cec5SDimitry Andric case Instruction::Mul: 2190b57cec5SDimitry Andric case Instruction::And: 2200b57cec5SDimitry Andric case Instruction::Or: 2210b57cec5SDimitry Andric case Instruction::Select: 2220b57cec5SDimitry Andric case Instruction::Shl: 2230b57cec5SDimitry Andric case Instruction::Sub: 2240b57cec5SDimitry Andric case Instruction::LShr: 2250b57cec5SDimitry Andric case Instruction::AShr: 2260b57cec5SDimitry Andric case Instruction::Xor: 2270b57cec5SDimitry Andric case Instruction::ZExt: 2280b57cec5SDimitry Andric case Instruction::SExt: 2290b57cec5SDimitry Andric case Instruction::Call: 2300b57cec5SDimitry Andric case Instruction::BitCast: 2310b57cec5SDimitry Andric case Instruction::PtrToInt: 2320b57cec5SDimitry Andric case Instruction::IntToPtr: 2330b57cec5SDimitry Andric case Instruction::AddrSpaceCast: 2340b57cec5SDimitry Andric case Instruction::FPToUI: 2350b57cec5SDimitry Andric case Instruction::FPToSI: 2360b57cec5SDimitry Andric case Instruction::UIToFP: 2370b57cec5SDimitry Andric case Instruction::SIToFP: 2380b57cec5SDimitry Andric case Instruction::FPExt: 2390b57cec5SDimitry Andric case Instruction::FPTrunc: 2400b57cec5SDimitry Andric case Instruction::FAdd: 2410b57cec5SDimitry Andric case Instruction::FSub: 2420b57cec5SDimitry Andric case Instruction::FMul: 2430b57cec5SDimitry Andric case Instruction::FDiv: 2440b57cec5SDimitry Andric case Instruction::FRem: 2450b57cec5SDimitry Andric case Instruction::FNeg: 2460b57cec5SDimitry Andric case Instruction::ICmp: 2470b57cec5SDimitry Andric case Instruction::FCmp: 248e8d8bef9SDimitry Andric case Instruction::Trunc: 249e8d8bef9SDimitry Andric case Instruction::Freeze: 250e8d8bef9SDimitry Andric case Instruction::ExtractElement: 251e8d8bef9SDimitry Andric case Instruction::InsertElement: 252e8d8bef9SDimitry Andric case Instruction::ShuffleVector: 253e8d8bef9SDimitry Andric case Instruction::ExtractValue: 254e8d8bef9SDimitry Andric case Instruction::InsertValue: 255bdd1243dSDimitry Andric return TTI.getInstructionCost(I, TargetTransformInfo::TCK_SizeAndLatency); 2560b57cec5SDimitry Andric 2570b57cec5SDimitry Andric default: 258fe6060f1SDimitry Andric return InstructionCost::getInvalid(); // Disallow anything not explicitly 259fe6060f1SDimitry Andric // listed. 2600b57cec5SDimitry Andric } 2610b57cec5SDimitry Andric } 2620b57cec5SDimitry Andric 263*0fca6ea1SDimitry Andric // Do not hoist any debug info intrinsics. 264*0fca6ea1SDimitry Andric // ... 265*0fca6ea1SDimitry Andric // if (cond) { 266*0fca6ea1SDimitry Andric // x = y * z; 267*0fca6ea1SDimitry Andric // foo(); 268*0fca6ea1SDimitry Andric // } 269*0fca6ea1SDimitry Andric // ... 270*0fca6ea1SDimitry Andric // -------- Which then becomes: 271*0fca6ea1SDimitry Andric // ... 272*0fca6ea1SDimitry Andric // if.then: 273*0fca6ea1SDimitry Andric // %x = mul i32 %y, %z 274*0fca6ea1SDimitry Andric // call void @llvm.dbg.value(%x, !"x", !DIExpression()) 275*0fca6ea1SDimitry Andric // call void foo() 276*0fca6ea1SDimitry Andric // 277*0fca6ea1SDimitry Andric // SpeculativeExecution might decide to hoist the 'y * z' calculation 278*0fca6ea1SDimitry Andric // out of the 'if' block, because it is more efficient that way, so the 279*0fca6ea1SDimitry Andric // '%x = mul i32 %y, %z' moves to the block above. But it might also 280*0fca6ea1SDimitry Andric // decide to hoist the 'llvm.dbg.value' call. 281*0fca6ea1SDimitry Andric // This is incorrect, because even if we've moved the calculation of 282*0fca6ea1SDimitry Andric // 'y * z', we should not see the value of 'x' change unless we 283*0fca6ea1SDimitry Andric // actually go inside the 'if' block. 284*0fca6ea1SDimitry Andric 2850b57cec5SDimitry Andric bool SpeculativeExecutionPass::considerHoistingFromTo( 2860b57cec5SDimitry Andric BasicBlock &FromBlock, BasicBlock &ToBlock) { 2870b57cec5SDimitry Andric SmallPtrSet<const Instruction *, 8> NotHoisted; 288*0fca6ea1SDimitry Andric auto HasNoUnhoistedInstr = [&NotHoisted](auto Values) { 289*0fca6ea1SDimitry Andric for (const Value *V : Values) { 290*0fca6ea1SDimitry Andric if (const auto *I = dyn_cast_or_null<Instruction>(V)) 291e8d8bef9SDimitry Andric if (NotHoisted.contains(I)) 2920b57cec5SDimitry Andric return false; 2930b57cec5SDimitry Andric } 2940b57cec5SDimitry Andric return true; 2950b57cec5SDimitry Andric }; 296*0fca6ea1SDimitry Andric auto AllPrecedingUsesFromBlockHoisted = 297*0fca6ea1SDimitry Andric [&HasNoUnhoistedInstr](const User *U) { 298*0fca6ea1SDimitry Andric // Do not hoist any debug info intrinsics. 299*0fca6ea1SDimitry Andric if (isa<DbgInfoIntrinsic>(U)) 300*0fca6ea1SDimitry Andric return false; 301*0fca6ea1SDimitry Andric 302*0fca6ea1SDimitry Andric return HasNoUnhoistedInstr(U->operand_values()); 303*0fca6ea1SDimitry Andric }; 3040b57cec5SDimitry Andric 305fe6060f1SDimitry Andric InstructionCost TotalSpeculationCost = 0; 3065ffd83dbSDimitry Andric unsigned NotHoistedInstCount = 0; 3075ffd83dbSDimitry Andric for (const auto &I : FromBlock) { 308fe6060f1SDimitry Andric const InstructionCost Cost = ComputeSpeculationCost(&I, *TTI); 309fe6060f1SDimitry Andric if (Cost.isValid() && isSafeToSpeculativelyExecute(&I) && 3100b57cec5SDimitry Andric AllPrecedingUsesFromBlockHoisted(&I)) { 3110b57cec5SDimitry Andric TotalSpeculationCost += Cost; 3120b57cec5SDimitry Andric if (TotalSpeculationCost > SpecExecMaxSpeculationCost) 3130b57cec5SDimitry Andric return false; // too much to hoist 3140b57cec5SDimitry Andric } else { 31581ad6265SDimitry Andric // Debug info intrinsics should not be counted for threshold. 3165ffd83dbSDimitry Andric if (!isa<DbgInfoIntrinsic>(I)) 3175ffd83dbSDimitry Andric NotHoistedInstCount++; 3185ffd83dbSDimitry Andric if (NotHoistedInstCount > SpecExecMaxNotHoisted) 3190b57cec5SDimitry Andric return false; // too much left behind 3205ffd83dbSDimitry Andric NotHoisted.insert(&I); 3210b57cec5SDimitry Andric } 3220b57cec5SDimitry Andric } 3230b57cec5SDimitry Andric 3240b57cec5SDimitry Andric for (auto I = FromBlock.begin(); I != FromBlock.end();) { 3250b57cec5SDimitry Andric // We have to increment I before moving Current as moving Current 3260b57cec5SDimitry Andric // changes the list that I is iterating through. 3270b57cec5SDimitry Andric auto Current = I; 3280b57cec5SDimitry Andric ++I; 3290b57cec5SDimitry Andric if (!NotHoisted.count(&*Current)) { 330*0fca6ea1SDimitry Andric Current->moveBefore(ToBlock.getTerminator()); 331*0fca6ea1SDimitry Andric Current->dropLocation(); 3320b57cec5SDimitry Andric } 3330b57cec5SDimitry Andric } 3340b57cec5SDimitry Andric return true; 3350b57cec5SDimitry Andric } 3360b57cec5SDimitry Andric 3370b57cec5SDimitry Andric FunctionPass *createSpeculativeExecutionPass() { 3380b57cec5SDimitry Andric return new SpeculativeExecutionLegacyPass(); 3390b57cec5SDimitry Andric } 3400b57cec5SDimitry Andric 3410b57cec5SDimitry Andric FunctionPass *createSpeculativeExecutionIfHasBranchDivergencePass() { 3420b57cec5SDimitry Andric return new SpeculativeExecutionLegacyPass(/* OnlyIfDivergentTarget = */ true); 3430b57cec5SDimitry Andric } 3440b57cec5SDimitry Andric 3450b57cec5SDimitry Andric SpeculativeExecutionPass::SpeculativeExecutionPass(bool OnlyIfDivergentTarget) 3460b57cec5SDimitry Andric : OnlyIfDivergentTarget(OnlyIfDivergentTarget || 3470b57cec5SDimitry Andric SpecExecOnlyIfDivergentTarget) {} 3480b57cec5SDimitry Andric 3490b57cec5SDimitry Andric PreservedAnalyses SpeculativeExecutionPass::run(Function &F, 3500b57cec5SDimitry Andric FunctionAnalysisManager &AM) { 3510b57cec5SDimitry Andric auto *TTI = &AM.getResult<TargetIRAnalysis>(F); 3520b57cec5SDimitry Andric 3530b57cec5SDimitry Andric bool Changed = runImpl(F, TTI); 3540b57cec5SDimitry Andric 3550b57cec5SDimitry Andric if (!Changed) 3560b57cec5SDimitry Andric return PreservedAnalyses::all(); 3570b57cec5SDimitry Andric PreservedAnalyses PA; 3580b57cec5SDimitry Andric PA.preserveSet<CFGAnalyses>(); 3590b57cec5SDimitry Andric return PA; 3600b57cec5SDimitry Andric } 3615f757f3fSDimitry Andric 3625f757f3fSDimitry Andric void SpeculativeExecutionPass::printPipeline( 3635f757f3fSDimitry Andric raw_ostream &OS, function_ref<StringRef(StringRef)> MapClassName2PassName) { 3645f757f3fSDimitry Andric static_cast<PassInfoMixin<SpeculativeExecutionPass> *>(this)->printPipeline( 3655f757f3fSDimitry Andric OS, MapClassName2PassName); 3665f757f3fSDimitry Andric OS << '<'; 3675f757f3fSDimitry Andric if (OnlyIfDivergentTarget) 3685f757f3fSDimitry Andric OS << "only-if-divergent-target"; 3695f757f3fSDimitry Andric OS << '>'; 3705f757f3fSDimitry Andric } 3710b57cec5SDimitry Andric } // namespace llvm 372