10b57cec5SDimitry Andric //===-- EarlyIfConversion.cpp - If-conversion on SSA form machine code ----===// 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 // Early if-conversion is for out-of-order CPUs that don't have a lot of 100b57cec5SDimitry Andric // predicable instructions. The goal is to eliminate conditional branches that 110b57cec5SDimitry Andric // may mispredict. 120b57cec5SDimitry Andric // 130b57cec5SDimitry Andric // Instructions from both sides of the branch are executed specutatively, and a 140b57cec5SDimitry Andric // cmov instruction selects the result. 150b57cec5SDimitry Andric // 160b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 170b57cec5SDimitry Andric 180b57cec5SDimitry Andric #include "llvm/ADT/BitVector.h" 190b57cec5SDimitry Andric #include "llvm/ADT/PostOrderIterator.h" 200b57cec5SDimitry Andric #include "llvm/ADT/SmallPtrSet.h" 210b57cec5SDimitry Andric #include "llvm/ADT/SparseSet.h" 220b57cec5SDimitry Andric #include "llvm/ADT/Statistic.h" 2381ad6265SDimitry Andric #include "llvm/Analysis/OptimizationRemarkEmitter.h" 240b57cec5SDimitry Andric #include "llvm/CodeGen/MachineBranchProbabilityInfo.h" 250b57cec5SDimitry Andric #include "llvm/CodeGen/MachineDominators.h" 260b57cec5SDimitry Andric #include "llvm/CodeGen/MachineFunction.h" 270b57cec5SDimitry Andric #include "llvm/CodeGen/MachineFunctionPass.h" 288bcb0991SDimitry Andric #include "llvm/CodeGen/MachineInstr.h" 290b57cec5SDimitry Andric #include "llvm/CodeGen/MachineLoopInfo.h" 30e8d8bef9SDimitry Andric #include "llvm/CodeGen/MachineOptimizationRemarkEmitter.h" 310b57cec5SDimitry Andric #include "llvm/CodeGen/MachineRegisterInfo.h" 320b57cec5SDimitry Andric #include "llvm/CodeGen/MachineTraceMetrics.h" 330b57cec5SDimitry Andric #include "llvm/CodeGen/TargetInstrInfo.h" 340b57cec5SDimitry Andric #include "llvm/CodeGen/TargetRegisterInfo.h" 350b57cec5SDimitry Andric #include "llvm/CodeGen/TargetSubtargetInfo.h" 36480093f4SDimitry Andric #include "llvm/InitializePasses.h" 370b57cec5SDimitry Andric #include "llvm/Support/CommandLine.h" 380b57cec5SDimitry Andric #include "llvm/Support/Debug.h" 390b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h" 400b57cec5SDimitry Andric 410b57cec5SDimitry Andric using namespace llvm; 420b57cec5SDimitry Andric 430b57cec5SDimitry Andric #define DEBUG_TYPE "early-ifcvt" 440b57cec5SDimitry Andric 450b57cec5SDimitry Andric // Absolute maximum number of instructions allowed per speculated block. 460b57cec5SDimitry Andric // This bypasses all other heuristics, so it should be set fairly high. 470b57cec5SDimitry Andric static cl::opt<unsigned> 480b57cec5SDimitry Andric BlockInstrLimit("early-ifcvt-limit", cl::init(30), cl::Hidden, 490b57cec5SDimitry Andric cl::desc("Maximum number of instructions per speculated block.")); 500b57cec5SDimitry Andric 510b57cec5SDimitry Andric // Stress testing mode - disable heuristics. 520b57cec5SDimitry Andric static cl::opt<bool> Stress("stress-early-ifcvt", cl::Hidden, 530b57cec5SDimitry Andric cl::desc("Turn all knobs to 11")); 540b57cec5SDimitry Andric 550b57cec5SDimitry Andric STATISTIC(NumDiamondsSeen, "Number of diamonds"); 560b57cec5SDimitry Andric STATISTIC(NumDiamondsConv, "Number of diamonds converted"); 570b57cec5SDimitry Andric STATISTIC(NumTrianglesSeen, "Number of triangles"); 580b57cec5SDimitry Andric STATISTIC(NumTrianglesConv, "Number of triangles converted"); 590b57cec5SDimitry Andric 600b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 610b57cec5SDimitry Andric // SSAIfConv 620b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 630b57cec5SDimitry Andric // 640b57cec5SDimitry Andric // The SSAIfConv class performs if-conversion on SSA form machine code after 650b57cec5SDimitry Andric // determining if it is possible. The class contains no heuristics; external 660b57cec5SDimitry Andric // code should be used to determine when if-conversion is a good idea. 670b57cec5SDimitry Andric // 680b57cec5SDimitry Andric // SSAIfConv can convert both triangles and diamonds: 690b57cec5SDimitry Andric // 700b57cec5SDimitry Andric // Triangle: Head Diamond: Head 710b57cec5SDimitry Andric // | \ / \_ 720b57cec5SDimitry Andric // | \ / | 730b57cec5SDimitry Andric // | [TF]BB FBB TBB 740b57cec5SDimitry Andric // | / \ / 750b57cec5SDimitry Andric // | / \ / 760b57cec5SDimitry Andric // Tail Tail 770b57cec5SDimitry Andric // 780b57cec5SDimitry Andric // Instructions in the conditional blocks TBB and/or FBB are spliced into the 790b57cec5SDimitry Andric // Head block, and phis in the Tail block are converted to select instructions. 800b57cec5SDimitry Andric // 810b57cec5SDimitry Andric namespace { 820b57cec5SDimitry Andric class SSAIfConv { 830b57cec5SDimitry Andric const TargetInstrInfo *TII; 840b57cec5SDimitry Andric const TargetRegisterInfo *TRI; 850b57cec5SDimitry Andric MachineRegisterInfo *MRI; 860b57cec5SDimitry Andric 870b57cec5SDimitry Andric public: 880b57cec5SDimitry Andric /// The block containing the conditional branch. 890b57cec5SDimitry Andric MachineBasicBlock *Head; 900b57cec5SDimitry Andric 910b57cec5SDimitry Andric /// The block containing phis after the if-then-else. 920b57cec5SDimitry Andric MachineBasicBlock *Tail; 930b57cec5SDimitry Andric 945ffd83dbSDimitry Andric /// The 'true' conditional block as determined by analyzeBranch. 950b57cec5SDimitry Andric MachineBasicBlock *TBB; 960b57cec5SDimitry Andric 975ffd83dbSDimitry Andric /// The 'false' conditional block as determined by analyzeBranch. 980b57cec5SDimitry Andric MachineBasicBlock *FBB; 990b57cec5SDimitry Andric 1000b57cec5SDimitry Andric /// isTriangle - When there is no 'else' block, either TBB or FBB will be 1010b57cec5SDimitry Andric /// equal to Tail. 1020b57cec5SDimitry Andric bool isTriangle() const { return TBB == Tail || FBB == Tail; } 1030b57cec5SDimitry Andric 1040b57cec5SDimitry Andric /// Returns the Tail predecessor for the True side. 1050b57cec5SDimitry Andric MachineBasicBlock *getTPred() const { return TBB == Tail ? Head : TBB; } 1060b57cec5SDimitry Andric 1070b57cec5SDimitry Andric /// Returns the Tail predecessor for the False side. 1080b57cec5SDimitry Andric MachineBasicBlock *getFPred() const { return FBB == Tail ? Head : FBB; } 1090b57cec5SDimitry Andric 1100b57cec5SDimitry Andric /// Information about each phi in the Tail block. 1110b57cec5SDimitry Andric struct PHIInfo { 1120b57cec5SDimitry Andric MachineInstr *PHI; 1131fd87a68SDimitry Andric unsigned TReg = 0, FReg = 0; 1140b57cec5SDimitry Andric // Latencies from Cond+Branch, TReg, and FReg to DstReg. 1151fd87a68SDimitry Andric int CondCycles = 0, TCycles = 0, FCycles = 0; 1160b57cec5SDimitry Andric 1171fd87a68SDimitry Andric PHIInfo(MachineInstr *phi) : PHI(phi) {} 1180b57cec5SDimitry Andric }; 1190b57cec5SDimitry Andric 1200b57cec5SDimitry Andric SmallVector<PHIInfo, 8> PHIs; 1210b57cec5SDimitry Andric 1225ffd83dbSDimitry Andric /// The branch condition determined by analyzeBranch. 1230b57cec5SDimitry Andric SmallVector<MachineOperand, 4> Cond; 1240b57cec5SDimitry Andric 12506c3fb27SDimitry Andric private: 1260b57cec5SDimitry Andric /// Instructions in Head that define values used by the conditional blocks. 1270b57cec5SDimitry Andric /// The hoisted instructions must be inserted after these instructions. 1280b57cec5SDimitry Andric SmallPtrSet<MachineInstr*, 8> InsertAfter; 1290b57cec5SDimitry Andric 1300b57cec5SDimitry Andric /// Register units clobbered by the conditional blocks. 1310b57cec5SDimitry Andric BitVector ClobberedRegUnits; 1320b57cec5SDimitry Andric 1330b57cec5SDimitry Andric // Scratch pad for findInsertionPoint. 1340b57cec5SDimitry Andric SparseSet<unsigned> LiveRegUnits; 1350b57cec5SDimitry Andric 1360b57cec5SDimitry Andric /// Insertion point in Head for speculatively executed instructions form TBB 1370b57cec5SDimitry Andric /// and FBB. 1380b57cec5SDimitry Andric MachineBasicBlock::iterator InsertionPoint; 1390b57cec5SDimitry Andric 1400b57cec5SDimitry Andric /// Return true if all non-terminator instructions in MBB can be safely 1410b57cec5SDimitry Andric /// speculated. 1420b57cec5SDimitry Andric bool canSpeculateInstrs(MachineBasicBlock *MBB); 1430b57cec5SDimitry Andric 1448bcb0991SDimitry Andric /// Return true if all non-terminator instructions in MBB can be safely 1458bcb0991SDimitry Andric /// predicated. 1468bcb0991SDimitry Andric bool canPredicateInstrs(MachineBasicBlock *MBB); 1478bcb0991SDimitry Andric 1488bcb0991SDimitry Andric /// Scan through instruction dependencies and update InsertAfter array. 1498bcb0991SDimitry Andric /// Return false if any dependency is incompatible with if conversion. 1508bcb0991SDimitry Andric bool InstrDependenciesAllowIfConv(MachineInstr *I); 1518bcb0991SDimitry Andric 1528bcb0991SDimitry Andric /// Predicate all instructions of the basic block with current condition 1538bcb0991SDimitry Andric /// except for terminators. Reverse the condition if ReversePredicate is set. 1548bcb0991SDimitry Andric void PredicateBlock(MachineBasicBlock *MBB, bool ReversePredicate); 1558bcb0991SDimitry Andric 1560b57cec5SDimitry Andric /// Find a valid insertion point in Head. 1570b57cec5SDimitry Andric bool findInsertionPoint(); 1580b57cec5SDimitry Andric 1590b57cec5SDimitry Andric /// Replace PHI instructions in Tail with selects. 1600b57cec5SDimitry Andric void replacePHIInstrs(); 1610b57cec5SDimitry Andric 1620b57cec5SDimitry Andric /// Insert selects and rewrite PHI operands to use them. 1630b57cec5SDimitry Andric void rewritePHIOperands(); 1640b57cec5SDimitry Andric 1650b57cec5SDimitry Andric public: 1660b57cec5SDimitry Andric /// runOnMachineFunction - Initialize per-function data structures. 1670b57cec5SDimitry Andric void runOnMachineFunction(MachineFunction &MF) { 1680b57cec5SDimitry Andric TII = MF.getSubtarget().getInstrInfo(); 1690b57cec5SDimitry Andric TRI = MF.getSubtarget().getRegisterInfo(); 1700b57cec5SDimitry Andric MRI = &MF.getRegInfo(); 1710b57cec5SDimitry Andric LiveRegUnits.clear(); 1720b57cec5SDimitry Andric LiveRegUnits.setUniverse(TRI->getNumRegUnits()); 1730b57cec5SDimitry Andric ClobberedRegUnits.clear(); 1740b57cec5SDimitry Andric ClobberedRegUnits.resize(TRI->getNumRegUnits()); 1750b57cec5SDimitry Andric } 1760b57cec5SDimitry Andric 1770b57cec5SDimitry Andric /// canConvertIf - If the sub-CFG headed by MBB can be if-converted, 1780b57cec5SDimitry Andric /// initialize the internal state, and return true. 1798bcb0991SDimitry Andric /// If predicate is set try to predicate the block otherwise try to 1808bcb0991SDimitry Andric /// speculatively execute it. 1818bcb0991SDimitry Andric bool canConvertIf(MachineBasicBlock *MBB, bool Predicate = false); 1820b57cec5SDimitry Andric 1830b57cec5SDimitry Andric /// convertIf - If-convert the last block passed to canConvertIf(), assuming 1840b57cec5SDimitry Andric /// it is possible. Add any erased blocks to RemovedBlocks. 1858bcb0991SDimitry Andric void convertIf(SmallVectorImpl<MachineBasicBlock *> &RemovedBlocks, 1868bcb0991SDimitry Andric bool Predicate = false); 1870b57cec5SDimitry Andric }; 1880b57cec5SDimitry Andric } // end anonymous namespace 1890b57cec5SDimitry Andric 1900b57cec5SDimitry Andric 1910b57cec5SDimitry Andric /// canSpeculateInstrs - Returns true if all the instructions in MBB can safely 1920b57cec5SDimitry Andric /// be speculated. The terminators are not considered. 1930b57cec5SDimitry Andric /// 1940b57cec5SDimitry Andric /// If instructions use any values that are defined in the head basic block, 1950b57cec5SDimitry Andric /// the defining instructions are added to InsertAfter. 1960b57cec5SDimitry Andric /// 1970b57cec5SDimitry Andric /// Any clobbered regunits are added to ClobberedRegUnits. 1980b57cec5SDimitry Andric /// 1990b57cec5SDimitry Andric bool SSAIfConv::canSpeculateInstrs(MachineBasicBlock *MBB) { 2000b57cec5SDimitry Andric // Reject any live-in physregs. It's probably CPSR/EFLAGS, and very hard to 2010b57cec5SDimitry Andric // get right. 2020b57cec5SDimitry Andric if (!MBB->livein_empty()) { 2030b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << printMBBReference(*MBB) << " has live-ins.\n"); 2040b57cec5SDimitry Andric return false; 2050b57cec5SDimitry Andric } 2060b57cec5SDimitry Andric 2070b57cec5SDimitry Andric unsigned InstrCount = 0; 2080b57cec5SDimitry Andric 2090b57cec5SDimitry Andric // Check all instructions, except the terminators. It is assumed that 2100b57cec5SDimitry Andric // terminators never have side effects or define any used register values. 2110eae32dcSDimitry Andric for (MachineInstr &MI : 2120eae32dcSDimitry Andric llvm::make_range(MBB->begin(), MBB->getFirstTerminator())) { 2130eae32dcSDimitry Andric if (MI.isDebugInstr()) 2140b57cec5SDimitry Andric continue; 2150b57cec5SDimitry Andric 2160b57cec5SDimitry Andric if (++InstrCount > BlockInstrLimit && !Stress) { 2170b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << printMBBReference(*MBB) << " has more than " 2180b57cec5SDimitry Andric << BlockInstrLimit << " instructions.\n"); 2190b57cec5SDimitry Andric return false; 2200b57cec5SDimitry Andric } 2210b57cec5SDimitry Andric 2220b57cec5SDimitry Andric // There shouldn't normally be any phis in a single-predecessor block. 2230eae32dcSDimitry Andric if (MI.isPHI()) { 2240eae32dcSDimitry Andric LLVM_DEBUG(dbgs() << "Can't hoist: " << MI); 2250b57cec5SDimitry Andric return false; 2260b57cec5SDimitry Andric } 2270b57cec5SDimitry Andric 2280b57cec5SDimitry Andric // Don't speculate loads. Note that it may be possible and desirable to 2290b57cec5SDimitry Andric // speculate GOT or constant pool loads that are guaranteed not to trap, 2300b57cec5SDimitry Andric // but we don't support that for now. 2310eae32dcSDimitry Andric if (MI.mayLoad()) { 2320eae32dcSDimitry Andric LLVM_DEBUG(dbgs() << "Won't speculate load: " << MI); 2330b57cec5SDimitry Andric return false; 2340b57cec5SDimitry Andric } 2350b57cec5SDimitry Andric 2360b57cec5SDimitry Andric // We never speculate stores, so an AA pointer isn't necessary. 2370b57cec5SDimitry Andric bool DontMoveAcrossStore = true; 2380eae32dcSDimitry Andric if (!MI.isSafeToMove(nullptr, DontMoveAcrossStore)) { 2390eae32dcSDimitry Andric LLVM_DEBUG(dbgs() << "Can't speculate: " << MI); 2400b57cec5SDimitry Andric return false; 2410b57cec5SDimitry Andric } 2420b57cec5SDimitry Andric 2430b57cec5SDimitry Andric // Check for any dependencies on Head instructions. 2440eae32dcSDimitry Andric if (!InstrDependenciesAllowIfConv(&MI)) 2458bcb0991SDimitry Andric return false; 2468bcb0991SDimitry Andric } 2478bcb0991SDimitry Andric return true; 2488bcb0991SDimitry Andric } 2498bcb0991SDimitry Andric 2508bcb0991SDimitry Andric /// Check that there is no dependencies preventing if conversion. 2518bcb0991SDimitry Andric /// 2528bcb0991SDimitry Andric /// If instruction uses any values that are defined in the head basic block, 2538bcb0991SDimitry Andric /// the defining instructions are added to InsertAfter. 2548bcb0991SDimitry Andric bool SSAIfConv::InstrDependenciesAllowIfConv(MachineInstr *I) { 2550b57cec5SDimitry Andric for (const MachineOperand &MO : I->operands()) { 2560b57cec5SDimitry Andric if (MO.isRegMask()) { 2570b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "Won't speculate regmask: " << *I); 2580b57cec5SDimitry Andric return false; 2590b57cec5SDimitry Andric } 2600b57cec5SDimitry Andric if (!MO.isReg()) 2610b57cec5SDimitry Andric continue; 2628bcb0991SDimitry Andric Register Reg = MO.getReg(); 2630b57cec5SDimitry Andric 2640b57cec5SDimitry Andric // Remember clobbered regunits. 265bdd1243dSDimitry Andric if (MO.isDef() && Reg.isPhysical()) 26606c3fb27SDimitry Andric for (MCRegUnit Unit : TRI->regunits(Reg.asMCReg())) 26706c3fb27SDimitry Andric ClobberedRegUnits.set(Unit); 2680b57cec5SDimitry Andric 269bdd1243dSDimitry Andric if (!MO.readsReg() || !Reg.isVirtual()) 2700b57cec5SDimitry Andric continue; 2710b57cec5SDimitry Andric MachineInstr *DefMI = MRI->getVRegDef(Reg); 2720b57cec5SDimitry Andric if (!DefMI || DefMI->getParent() != Head) 2730b57cec5SDimitry Andric continue; 2740b57cec5SDimitry Andric if (InsertAfter.insert(DefMI).second) 2758bcb0991SDimitry Andric LLVM_DEBUG(dbgs() << printMBBReference(*I->getParent()) << " depends on " 2760b57cec5SDimitry Andric << *DefMI); 2770b57cec5SDimitry Andric if (DefMI->isTerminator()) { 2780b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "Can't insert instructions below terminator.\n"); 2790b57cec5SDimitry Andric return false; 2800b57cec5SDimitry Andric } 2810b57cec5SDimitry Andric } 2828bcb0991SDimitry Andric return true; 2838bcb0991SDimitry Andric } 2848bcb0991SDimitry Andric 2858bcb0991SDimitry Andric /// canPredicateInstrs - Returns true if all the instructions in MBB can safely 2868bcb0991SDimitry Andric /// be predicates. The terminators are not considered. 2878bcb0991SDimitry Andric /// 2888bcb0991SDimitry Andric /// If instructions use any values that are defined in the head basic block, 2898bcb0991SDimitry Andric /// the defining instructions are added to InsertAfter. 2908bcb0991SDimitry Andric /// 2918bcb0991SDimitry Andric /// Any clobbered regunits are added to ClobberedRegUnits. 2928bcb0991SDimitry Andric /// 2938bcb0991SDimitry Andric bool SSAIfConv::canPredicateInstrs(MachineBasicBlock *MBB) { 2948bcb0991SDimitry Andric // Reject any live-in physregs. It's probably CPSR/EFLAGS, and very hard to 2958bcb0991SDimitry Andric // get right. 2968bcb0991SDimitry Andric if (!MBB->livein_empty()) { 2978bcb0991SDimitry Andric LLVM_DEBUG(dbgs() << printMBBReference(*MBB) << " has live-ins.\n"); 2988bcb0991SDimitry Andric return false; 2998bcb0991SDimitry Andric } 3008bcb0991SDimitry Andric 3018bcb0991SDimitry Andric unsigned InstrCount = 0; 3028bcb0991SDimitry Andric 3038bcb0991SDimitry Andric // Check all instructions, except the terminators. It is assumed that 3048bcb0991SDimitry Andric // terminators never have side effects or define any used register values. 3058bcb0991SDimitry Andric for (MachineBasicBlock::iterator I = MBB->begin(), 3068bcb0991SDimitry Andric E = MBB->getFirstTerminator(); 3078bcb0991SDimitry Andric I != E; ++I) { 3088bcb0991SDimitry Andric if (I->isDebugInstr()) 3098bcb0991SDimitry Andric continue; 3108bcb0991SDimitry Andric 3118bcb0991SDimitry Andric if (++InstrCount > BlockInstrLimit && !Stress) { 3128bcb0991SDimitry Andric LLVM_DEBUG(dbgs() << printMBBReference(*MBB) << " has more than " 3138bcb0991SDimitry Andric << BlockInstrLimit << " instructions.\n"); 3148bcb0991SDimitry Andric return false; 3158bcb0991SDimitry Andric } 3168bcb0991SDimitry Andric 3178bcb0991SDimitry Andric // There shouldn't normally be any phis in a single-predecessor block. 3188bcb0991SDimitry Andric if (I->isPHI()) { 3198bcb0991SDimitry Andric LLVM_DEBUG(dbgs() << "Can't predicate: " << *I); 3208bcb0991SDimitry Andric return false; 3218bcb0991SDimitry Andric } 3228bcb0991SDimitry Andric 323bdd1243dSDimitry Andric // Check that instruction is predicable 324bdd1243dSDimitry Andric if (!TII->isPredicable(*I)) { 325bdd1243dSDimitry Andric LLVM_DEBUG(dbgs() << "Isn't predicable: " << *I); 326bdd1243dSDimitry Andric return false; 327bdd1243dSDimitry Andric } 328bdd1243dSDimitry Andric 329bdd1243dSDimitry Andric // Check that instruction is not already predicated. 330bdd1243dSDimitry Andric if (TII->isPredicated(*I) && !TII->canPredicatePredicatedInstr(*I)) { 331bdd1243dSDimitry Andric LLVM_DEBUG(dbgs() << "Is already predicated: " << *I); 3328bcb0991SDimitry Andric return false; 3338bcb0991SDimitry Andric } 3348bcb0991SDimitry Andric 3358bcb0991SDimitry Andric // Check for any dependencies on Head instructions. 3368bcb0991SDimitry Andric if (!InstrDependenciesAllowIfConv(&(*I))) 3378bcb0991SDimitry Andric return false; 3380b57cec5SDimitry Andric } 3390b57cec5SDimitry Andric return true; 3400b57cec5SDimitry Andric } 3410b57cec5SDimitry Andric 3428bcb0991SDimitry Andric // Apply predicate to all instructions in the machine block. 3438bcb0991SDimitry Andric void SSAIfConv::PredicateBlock(MachineBasicBlock *MBB, bool ReversePredicate) { 3448bcb0991SDimitry Andric auto Condition = Cond; 34506c3fb27SDimitry Andric if (ReversePredicate) { 34606c3fb27SDimitry Andric bool CanRevCond = !TII->reverseBranchCondition(Condition); 34706c3fb27SDimitry Andric assert(CanRevCond && "Reversed predicate is not supported"); 34806c3fb27SDimitry Andric (void)CanRevCond; 34906c3fb27SDimitry Andric } 3508bcb0991SDimitry Andric // Terminators don't need to be predicated as they will be removed. 3518bcb0991SDimitry Andric for (MachineBasicBlock::iterator I = MBB->begin(), 3528bcb0991SDimitry Andric E = MBB->getFirstTerminator(); 3538bcb0991SDimitry Andric I != E; ++I) { 3548bcb0991SDimitry Andric if (I->isDebugInstr()) 3558bcb0991SDimitry Andric continue; 3568bcb0991SDimitry Andric TII->PredicateInstruction(*I, Condition); 3578bcb0991SDimitry Andric } 3588bcb0991SDimitry Andric } 3590b57cec5SDimitry Andric 3600b57cec5SDimitry Andric /// Find an insertion point in Head for the speculated instructions. The 3610b57cec5SDimitry Andric /// insertion point must be: 3620b57cec5SDimitry Andric /// 3630b57cec5SDimitry Andric /// 1. Before any terminators. 3640b57cec5SDimitry Andric /// 2. After any instructions in InsertAfter. 3650b57cec5SDimitry Andric /// 3. Not have any clobbered regunits live. 3660b57cec5SDimitry Andric /// 3670b57cec5SDimitry Andric /// This function sets InsertionPoint and returns true when successful, it 3680b57cec5SDimitry Andric /// returns false if no valid insertion point could be found. 3690b57cec5SDimitry Andric /// 3700b57cec5SDimitry Andric bool SSAIfConv::findInsertionPoint() { 3710b57cec5SDimitry Andric // Keep track of live regunits before the current position. 3720b57cec5SDimitry Andric // Only track RegUnits that are also in ClobberedRegUnits. 3730b57cec5SDimitry Andric LiveRegUnits.clear(); 374e8d8bef9SDimitry Andric SmallVector<MCRegister, 8> Reads; 3750b57cec5SDimitry Andric MachineBasicBlock::iterator FirstTerm = Head->getFirstTerminator(); 3760b57cec5SDimitry Andric MachineBasicBlock::iterator I = Head->end(); 3770b57cec5SDimitry Andric MachineBasicBlock::iterator B = Head->begin(); 3780b57cec5SDimitry Andric while (I != B) { 3790b57cec5SDimitry Andric --I; 3800b57cec5SDimitry Andric // Some of the conditional code depends in I. 3810b57cec5SDimitry Andric if (InsertAfter.count(&*I)) { 3820b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "Can't insert code after " << *I); 3830b57cec5SDimitry Andric return false; 3840b57cec5SDimitry Andric } 3850b57cec5SDimitry Andric 3860b57cec5SDimitry Andric // Update live regunits. 3870b57cec5SDimitry Andric for (const MachineOperand &MO : I->operands()) { 3880b57cec5SDimitry Andric // We're ignoring regmask operands. That is conservatively correct. 3890b57cec5SDimitry Andric if (!MO.isReg()) 3900b57cec5SDimitry Andric continue; 3918bcb0991SDimitry Andric Register Reg = MO.getReg(); 392bdd1243dSDimitry Andric if (!Reg.isPhysical()) 3930b57cec5SDimitry Andric continue; 3940b57cec5SDimitry Andric // I clobbers Reg, so it isn't live before I. 3950b57cec5SDimitry Andric if (MO.isDef()) 39606c3fb27SDimitry Andric for (MCRegUnit Unit : TRI->regunits(Reg.asMCReg())) 39706c3fb27SDimitry Andric LiveRegUnits.erase(Unit); 3980b57cec5SDimitry Andric // Unless I reads Reg. 3990b57cec5SDimitry Andric if (MO.readsReg()) 400e8d8bef9SDimitry Andric Reads.push_back(Reg.asMCReg()); 4010b57cec5SDimitry Andric } 4020b57cec5SDimitry Andric // Anything read by I is live before I. 4030b57cec5SDimitry Andric while (!Reads.empty()) 40406c3fb27SDimitry Andric for (MCRegUnit Unit : TRI->regunits(Reads.pop_back_val())) 40506c3fb27SDimitry Andric if (ClobberedRegUnits.test(Unit)) 40606c3fb27SDimitry Andric LiveRegUnits.insert(Unit); 4070b57cec5SDimitry Andric 4080b57cec5SDimitry Andric // We can't insert before a terminator. 4090b57cec5SDimitry Andric if (I != FirstTerm && I->isTerminator()) 4100b57cec5SDimitry Andric continue; 4110b57cec5SDimitry Andric 4120b57cec5SDimitry Andric // Some of the clobbered registers are live before I, not a valid insertion 4130b57cec5SDimitry Andric // point. 4140b57cec5SDimitry Andric if (!LiveRegUnits.empty()) { 4150b57cec5SDimitry Andric LLVM_DEBUG({ 4160b57cec5SDimitry Andric dbgs() << "Would clobber"; 417fe6060f1SDimitry Andric for (unsigned LRU : LiveRegUnits) 418fe6060f1SDimitry Andric dbgs() << ' ' << printRegUnit(LRU, TRI); 4190b57cec5SDimitry Andric dbgs() << " live before " << *I; 4200b57cec5SDimitry Andric }); 4210b57cec5SDimitry Andric continue; 4220b57cec5SDimitry Andric } 4230b57cec5SDimitry Andric 4240b57cec5SDimitry Andric // This is a valid insertion point. 4250b57cec5SDimitry Andric InsertionPoint = I; 4260b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "Can insert before " << *I); 4270b57cec5SDimitry Andric return true; 4280b57cec5SDimitry Andric } 4290b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "No legal insertion point found.\n"); 4300b57cec5SDimitry Andric return false; 4310b57cec5SDimitry Andric } 4320b57cec5SDimitry Andric 4330b57cec5SDimitry Andric 4340b57cec5SDimitry Andric 4350b57cec5SDimitry Andric /// canConvertIf - analyze the sub-cfg rooted in MBB, and return true if it is 4360b57cec5SDimitry Andric /// a potential candidate for if-conversion. Fill out the internal state. 4370b57cec5SDimitry Andric /// 4388bcb0991SDimitry Andric bool SSAIfConv::canConvertIf(MachineBasicBlock *MBB, bool Predicate) { 4390b57cec5SDimitry Andric Head = MBB; 4400b57cec5SDimitry Andric TBB = FBB = Tail = nullptr; 4410b57cec5SDimitry Andric 4420b57cec5SDimitry Andric if (Head->succ_size() != 2) 4430b57cec5SDimitry Andric return false; 4440b57cec5SDimitry Andric MachineBasicBlock *Succ0 = Head->succ_begin()[0]; 4450b57cec5SDimitry Andric MachineBasicBlock *Succ1 = Head->succ_begin()[1]; 4460b57cec5SDimitry Andric 4470b57cec5SDimitry Andric // Canonicalize so Succ0 has MBB as its single predecessor. 4480b57cec5SDimitry Andric if (Succ0->pred_size() != 1) 4490b57cec5SDimitry Andric std::swap(Succ0, Succ1); 4500b57cec5SDimitry Andric 4510b57cec5SDimitry Andric if (Succ0->pred_size() != 1 || Succ0->succ_size() != 1) 4520b57cec5SDimitry Andric return false; 4530b57cec5SDimitry Andric 4540b57cec5SDimitry Andric Tail = Succ0->succ_begin()[0]; 4550b57cec5SDimitry Andric 4560b57cec5SDimitry Andric // This is not a triangle. 4570b57cec5SDimitry Andric if (Tail != Succ1) { 4580b57cec5SDimitry Andric // Check for a diamond. We won't deal with any critical edges. 4590b57cec5SDimitry Andric if (Succ1->pred_size() != 1 || Succ1->succ_size() != 1 || 4600b57cec5SDimitry Andric Succ1->succ_begin()[0] != Tail) 4610b57cec5SDimitry Andric return false; 4620b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "\nDiamond: " << printMBBReference(*Head) << " -> " 4630b57cec5SDimitry Andric << printMBBReference(*Succ0) << "/" 4640b57cec5SDimitry Andric << printMBBReference(*Succ1) << " -> " 4650b57cec5SDimitry Andric << printMBBReference(*Tail) << '\n'); 4660b57cec5SDimitry Andric 4670b57cec5SDimitry Andric // Live-in physregs are tricky to get right when speculating code. 4680b57cec5SDimitry Andric if (!Tail->livein_empty()) { 4690b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "Tail has live-ins.\n"); 4700b57cec5SDimitry Andric return false; 4710b57cec5SDimitry Andric } 4720b57cec5SDimitry Andric } else { 4730b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "\nTriangle: " << printMBBReference(*Head) << " -> " 4740b57cec5SDimitry Andric << printMBBReference(*Succ0) << " -> " 4750b57cec5SDimitry Andric << printMBBReference(*Tail) << '\n'); 4760b57cec5SDimitry Andric } 4770b57cec5SDimitry Andric 4780b57cec5SDimitry Andric // This is a triangle or a diamond. 4798bcb0991SDimitry Andric // Skip if we cannot predicate and there are no phis skip as there must be 4808bcb0991SDimitry Andric // side effects that can only be handled with predication. 4818bcb0991SDimitry Andric if (!Predicate && (Tail->empty() || !Tail->front().isPHI())) { 4820b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "No phis in tail.\n"); 4830b57cec5SDimitry Andric return false; 4840b57cec5SDimitry Andric } 4850b57cec5SDimitry Andric 4860b57cec5SDimitry Andric // The branch we're looking to eliminate must be analyzable. 4870b57cec5SDimitry Andric Cond.clear(); 4880b57cec5SDimitry Andric if (TII->analyzeBranch(*Head, TBB, FBB, Cond)) { 4890b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "Branch not analyzable.\n"); 4900b57cec5SDimitry Andric return false; 4910b57cec5SDimitry Andric } 4920b57cec5SDimitry Andric 4930b57cec5SDimitry Andric // This is weird, probably some sort of degenerate CFG. 4940b57cec5SDimitry Andric if (!TBB) { 4955ffd83dbSDimitry Andric LLVM_DEBUG(dbgs() << "analyzeBranch didn't find conditional branch.\n"); 4960b57cec5SDimitry Andric return false; 4970b57cec5SDimitry Andric } 4980b57cec5SDimitry Andric 4990b57cec5SDimitry Andric // Make sure the analyzed branch is conditional; one of the successors 5000b57cec5SDimitry Andric // could be a landing pad. (Empty landing pads can be generated on Windows.) 5010b57cec5SDimitry Andric if (Cond.empty()) { 5025ffd83dbSDimitry Andric LLVM_DEBUG(dbgs() << "analyzeBranch found an unconditional branch.\n"); 5030b57cec5SDimitry Andric return false; 5040b57cec5SDimitry Andric } 5050b57cec5SDimitry Andric 5065ffd83dbSDimitry Andric // analyzeBranch doesn't set FBB on a fall-through branch. 5070b57cec5SDimitry Andric // Make sure it is always set. 5080b57cec5SDimitry Andric FBB = TBB == Succ0 ? Succ1 : Succ0; 5090b57cec5SDimitry Andric 5100b57cec5SDimitry Andric // Any phis in the tail block must be convertible to selects. 5110b57cec5SDimitry Andric PHIs.clear(); 5120b57cec5SDimitry Andric MachineBasicBlock *TPred = getTPred(); 5130b57cec5SDimitry Andric MachineBasicBlock *FPred = getFPred(); 5140b57cec5SDimitry Andric for (MachineBasicBlock::iterator I = Tail->begin(), E = Tail->end(); 5150b57cec5SDimitry Andric I != E && I->isPHI(); ++I) { 5160b57cec5SDimitry Andric PHIs.push_back(&*I); 5170b57cec5SDimitry Andric PHIInfo &PI = PHIs.back(); 5180b57cec5SDimitry Andric // Find PHI operands corresponding to TPred and FPred. 5190b57cec5SDimitry Andric for (unsigned i = 1; i != PI.PHI->getNumOperands(); i += 2) { 5200b57cec5SDimitry Andric if (PI.PHI->getOperand(i+1).getMBB() == TPred) 5210b57cec5SDimitry Andric PI.TReg = PI.PHI->getOperand(i).getReg(); 5220b57cec5SDimitry Andric if (PI.PHI->getOperand(i+1).getMBB() == FPred) 5230b57cec5SDimitry Andric PI.FReg = PI.PHI->getOperand(i).getReg(); 5240b57cec5SDimitry Andric } 5258bcb0991SDimitry Andric assert(Register::isVirtualRegister(PI.TReg) && "Bad PHI"); 5268bcb0991SDimitry Andric assert(Register::isVirtualRegister(PI.FReg) && "Bad PHI"); 5270b57cec5SDimitry Andric 5280b57cec5SDimitry Andric // Get target information. 5295ffd83dbSDimitry Andric if (!TII->canInsertSelect(*Head, Cond, PI.PHI->getOperand(0).getReg(), 5305ffd83dbSDimitry Andric PI.TReg, PI.FReg, PI.CondCycles, PI.TCycles, 5315ffd83dbSDimitry Andric PI.FCycles)) { 5320b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "Can't convert: " << *PI.PHI); 5330b57cec5SDimitry Andric return false; 5340b57cec5SDimitry Andric } 5350b57cec5SDimitry Andric } 5360b57cec5SDimitry Andric 5370b57cec5SDimitry Andric // Check that the conditional instructions can be speculated. 5380b57cec5SDimitry Andric InsertAfter.clear(); 5390b57cec5SDimitry Andric ClobberedRegUnits.reset(); 5408bcb0991SDimitry Andric if (Predicate) { 5418bcb0991SDimitry Andric if (TBB != Tail && !canPredicateInstrs(TBB)) 5428bcb0991SDimitry Andric return false; 5438bcb0991SDimitry Andric if (FBB != Tail && !canPredicateInstrs(FBB)) 5448bcb0991SDimitry Andric return false; 5458bcb0991SDimitry Andric } else { 5460b57cec5SDimitry Andric if (TBB != Tail && !canSpeculateInstrs(TBB)) 5470b57cec5SDimitry Andric return false; 5480b57cec5SDimitry Andric if (FBB != Tail && !canSpeculateInstrs(FBB)) 5490b57cec5SDimitry Andric return false; 5508bcb0991SDimitry Andric } 5510b57cec5SDimitry Andric 5520b57cec5SDimitry Andric // Try to find a valid insertion point for the speculated instructions in the 5530b57cec5SDimitry Andric // head basic block. 5540b57cec5SDimitry Andric if (!findInsertionPoint()) 5550b57cec5SDimitry Andric return false; 5560b57cec5SDimitry Andric 5570b57cec5SDimitry Andric if (isTriangle()) 5580b57cec5SDimitry Andric ++NumTrianglesSeen; 5590b57cec5SDimitry Andric else 5600b57cec5SDimitry Andric ++NumDiamondsSeen; 5610b57cec5SDimitry Andric return true; 5620b57cec5SDimitry Andric } 5630b57cec5SDimitry Andric 564fe6060f1SDimitry Andric /// \return true iff the two registers are known to have the same value. 565fe6060f1SDimitry Andric static bool hasSameValue(const MachineRegisterInfo &MRI, 566fe6060f1SDimitry Andric const TargetInstrInfo *TII, Register TReg, 567fe6060f1SDimitry Andric Register FReg) { 568fe6060f1SDimitry Andric if (TReg == FReg) 569fe6060f1SDimitry Andric return true; 570fe6060f1SDimitry Andric 571fe6060f1SDimitry Andric if (!TReg.isVirtual() || !FReg.isVirtual()) 572fe6060f1SDimitry Andric return false; 573fe6060f1SDimitry Andric 574fe6060f1SDimitry Andric const MachineInstr *TDef = MRI.getUniqueVRegDef(TReg); 575fe6060f1SDimitry Andric const MachineInstr *FDef = MRI.getUniqueVRegDef(FReg); 576fe6060f1SDimitry Andric if (!TDef || !FDef) 577fe6060f1SDimitry Andric return false; 578fe6060f1SDimitry Andric 579fe6060f1SDimitry Andric // If there are side-effects, all bets are off. 580fe6060f1SDimitry Andric if (TDef->hasUnmodeledSideEffects()) 581fe6060f1SDimitry Andric return false; 582fe6060f1SDimitry Andric 583fe6060f1SDimitry Andric // If the instruction could modify memory, or there may be some intervening 584fe6060f1SDimitry Andric // store between the two, we can't consider them to be equal. 585fcaf7f86SDimitry Andric if (TDef->mayLoadOrStore() && !TDef->isDereferenceableInvariantLoad()) 586fe6060f1SDimitry Andric return false; 587fe6060f1SDimitry Andric 588fe6060f1SDimitry Andric // We also can't guarantee that they are the same if, for example, the 589fe6060f1SDimitry Andric // instructions are both a copy from a physical reg, because some other 590fe6060f1SDimitry Andric // instruction may have modified the value in that reg between the two 591fe6060f1SDimitry Andric // defining insts. 592fe6060f1SDimitry Andric if (any_of(TDef->uses(), [](const MachineOperand &MO) { 593fe6060f1SDimitry Andric return MO.isReg() && MO.getReg().isPhysical(); 594fe6060f1SDimitry Andric })) 595fe6060f1SDimitry Andric return false; 596fe6060f1SDimitry Andric 597fe6060f1SDimitry Andric // Check whether the two defining instructions produce the same value(s). 598fe6060f1SDimitry Andric if (!TII->produceSameValue(*TDef, *FDef, &MRI)) 599fe6060f1SDimitry Andric return false; 600fe6060f1SDimitry Andric 601fe6060f1SDimitry Andric // Further, check that the two defs come from corresponding operands. 602*0fca6ea1SDimitry Andric int TIdx = TDef->findRegisterDefOperandIdx(TReg, /*TRI=*/nullptr); 603*0fca6ea1SDimitry Andric int FIdx = FDef->findRegisterDefOperandIdx(FReg, /*TRI=*/nullptr); 604fe6060f1SDimitry Andric if (TIdx == -1 || FIdx == -1) 605fe6060f1SDimitry Andric return false; 606fe6060f1SDimitry Andric 607fe6060f1SDimitry Andric return TIdx == FIdx; 608fe6060f1SDimitry Andric } 609fe6060f1SDimitry Andric 6100b57cec5SDimitry Andric /// replacePHIInstrs - Completely replace PHI instructions with selects. 6110b57cec5SDimitry Andric /// This is possible when the only Tail predecessors are the if-converted 6120b57cec5SDimitry Andric /// blocks. 6130b57cec5SDimitry Andric void SSAIfConv::replacePHIInstrs() { 6140b57cec5SDimitry Andric assert(Tail->pred_size() == 2 && "Cannot replace PHIs"); 6150b57cec5SDimitry Andric MachineBasicBlock::iterator FirstTerm = Head->getFirstTerminator(); 6160b57cec5SDimitry Andric assert(FirstTerm != Head->end() && "No terminators"); 6170b57cec5SDimitry Andric DebugLoc HeadDL = FirstTerm->getDebugLoc(); 6180b57cec5SDimitry Andric 6190b57cec5SDimitry Andric // Convert all PHIs to select instructions inserted before FirstTerm. 620*0fca6ea1SDimitry Andric for (PHIInfo &PI : PHIs) { 6210b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "If-converting " << *PI.PHI); 6228bcb0991SDimitry Andric Register DstReg = PI.PHI->getOperand(0).getReg(); 623fe6060f1SDimitry Andric if (hasSameValue(*MRI, TII, PI.TReg, PI.FReg)) { 624fe6060f1SDimitry Andric // We do not need the select instruction if both incoming values are 625fe6060f1SDimitry Andric // equal, but we do need a COPY. 626fe6060f1SDimitry Andric BuildMI(*Head, FirstTerm, HeadDL, TII->get(TargetOpcode::COPY), DstReg) 627fe6060f1SDimitry Andric .addReg(PI.TReg); 628fe6060f1SDimitry Andric } else { 629fe6060f1SDimitry Andric TII->insertSelect(*Head, FirstTerm, HeadDL, DstReg, Cond, PI.TReg, 630fe6060f1SDimitry Andric PI.FReg); 631fe6060f1SDimitry Andric } 6320b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << " --> " << *std::prev(FirstTerm)); 6330b57cec5SDimitry Andric PI.PHI->eraseFromParent(); 6340b57cec5SDimitry Andric PI.PHI = nullptr; 6350b57cec5SDimitry Andric } 6360b57cec5SDimitry Andric } 6370b57cec5SDimitry Andric 6380b57cec5SDimitry Andric /// rewritePHIOperands - When there are additional Tail predecessors, insert 6390b57cec5SDimitry Andric /// select instructions in Head and rewrite PHI operands to use the selects. 6400b57cec5SDimitry Andric /// Keep the PHI instructions in Tail to handle the other predecessors. 6410b57cec5SDimitry Andric void SSAIfConv::rewritePHIOperands() { 6420b57cec5SDimitry Andric MachineBasicBlock::iterator FirstTerm = Head->getFirstTerminator(); 6430b57cec5SDimitry Andric assert(FirstTerm != Head->end() && "No terminators"); 6440b57cec5SDimitry Andric DebugLoc HeadDL = FirstTerm->getDebugLoc(); 6450b57cec5SDimitry Andric 6460b57cec5SDimitry Andric // Convert all PHIs to select instructions inserted before FirstTerm. 647*0fca6ea1SDimitry Andric for (PHIInfo &PI : PHIs) { 6480b57cec5SDimitry Andric unsigned DstReg = 0; 6490b57cec5SDimitry Andric 6500b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "If-converting " << *PI.PHI); 651fe6060f1SDimitry Andric if (hasSameValue(*MRI, TII, PI.TReg, PI.FReg)) { 6520b57cec5SDimitry Andric // We do not need the select instruction if both incoming values are 6530b57cec5SDimitry Andric // equal. 6540b57cec5SDimitry Andric DstReg = PI.TReg; 6550b57cec5SDimitry Andric } else { 6568bcb0991SDimitry Andric Register PHIDst = PI.PHI->getOperand(0).getReg(); 6570b57cec5SDimitry Andric DstReg = MRI->createVirtualRegister(MRI->getRegClass(PHIDst)); 6580b57cec5SDimitry Andric TII->insertSelect(*Head, FirstTerm, HeadDL, 6590b57cec5SDimitry Andric DstReg, Cond, PI.TReg, PI.FReg); 6600b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << " --> " << *std::prev(FirstTerm)); 6610b57cec5SDimitry Andric } 6620b57cec5SDimitry Andric 6630b57cec5SDimitry Andric // Rewrite PHI operands TPred -> (DstReg, Head), remove FPred. 6640b57cec5SDimitry Andric for (unsigned i = PI.PHI->getNumOperands(); i != 1; i -= 2) { 6650b57cec5SDimitry Andric MachineBasicBlock *MBB = PI.PHI->getOperand(i-1).getMBB(); 6660b57cec5SDimitry Andric if (MBB == getTPred()) { 6670b57cec5SDimitry Andric PI.PHI->getOperand(i-1).setMBB(Head); 6680b57cec5SDimitry Andric PI.PHI->getOperand(i-2).setReg(DstReg); 6690b57cec5SDimitry Andric } else if (MBB == getFPred()) { 67081ad6265SDimitry Andric PI.PHI->removeOperand(i-1); 67181ad6265SDimitry Andric PI.PHI->removeOperand(i-2); 6720b57cec5SDimitry Andric } 6730b57cec5SDimitry Andric } 6740b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << " --> " << *PI.PHI); 6750b57cec5SDimitry Andric } 6760b57cec5SDimitry Andric } 6770b57cec5SDimitry Andric 6780b57cec5SDimitry Andric /// convertIf - Execute the if conversion after canConvertIf has determined the 6790b57cec5SDimitry Andric /// feasibility. 6800b57cec5SDimitry Andric /// 6810b57cec5SDimitry Andric /// Any basic blocks erased will be added to RemovedBlocks. 6820b57cec5SDimitry Andric /// 6838bcb0991SDimitry Andric void SSAIfConv::convertIf(SmallVectorImpl<MachineBasicBlock *> &RemovedBlocks, 6848bcb0991SDimitry Andric bool Predicate) { 6850b57cec5SDimitry Andric assert(Head && Tail && TBB && FBB && "Call canConvertIf first."); 6860b57cec5SDimitry Andric 6870b57cec5SDimitry Andric // Update statistics. 6880b57cec5SDimitry Andric if (isTriangle()) 6890b57cec5SDimitry Andric ++NumTrianglesConv; 6900b57cec5SDimitry Andric else 6910b57cec5SDimitry Andric ++NumDiamondsConv; 6920b57cec5SDimitry Andric 6930b57cec5SDimitry Andric // Move all instructions into Head, except for the terminators. 6948bcb0991SDimitry Andric if (TBB != Tail) { 6958bcb0991SDimitry Andric if (Predicate) 6968bcb0991SDimitry Andric PredicateBlock(TBB, /*ReversePredicate=*/false); 6970b57cec5SDimitry Andric Head->splice(InsertionPoint, TBB, TBB->begin(), TBB->getFirstTerminator()); 6988bcb0991SDimitry Andric } 6998bcb0991SDimitry Andric if (FBB != Tail) { 7008bcb0991SDimitry Andric if (Predicate) 7018bcb0991SDimitry Andric PredicateBlock(FBB, /*ReversePredicate=*/true); 7020b57cec5SDimitry Andric Head->splice(InsertionPoint, FBB, FBB->begin(), FBB->getFirstTerminator()); 7038bcb0991SDimitry Andric } 7040b57cec5SDimitry Andric // Are there extra Tail predecessors? 7050b57cec5SDimitry Andric bool ExtraPreds = Tail->pred_size() != 2; 7060b57cec5SDimitry Andric if (ExtraPreds) 7070b57cec5SDimitry Andric rewritePHIOperands(); 7080b57cec5SDimitry Andric else 7090b57cec5SDimitry Andric replacePHIInstrs(); 7100b57cec5SDimitry Andric 7110b57cec5SDimitry Andric // Fix up the CFG, temporarily leave Head without any successors. 7120b57cec5SDimitry Andric Head->removeSuccessor(TBB); 7130b57cec5SDimitry Andric Head->removeSuccessor(FBB, true); 7140b57cec5SDimitry Andric if (TBB != Tail) 7150b57cec5SDimitry Andric TBB->removeSuccessor(Tail, true); 7160b57cec5SDimitry Andric if (FBB != Tail) 7170b57cec5SDimitry Andric FBB->removeSuccessor(Tail, true); 7180b57cec5SDimitry Andric 7190b57cec5SDimitry Andric // Fix up Head's terminators. 7200b57cec5SDimitry Andric // It should become a single branch or a fallthrough. 7210b57cec5SDimitry Andric DebugLoc HeadDL = Head->getFirstTerminator()->getDebugLoc(); 7220b57cec5SDimitry Andric TII->removeBranch(*Head); 7230b57cec5SDimitry Andric 7240b57cec5SDimitry Andric // Erase the now empty conditional blocks. It is likely that Head can fall 7250b57cec5SDimitry Andric // through to Tail, and we can join the two blocks. 7260b57cec5SDimitry Andric if (TBB != Tail) { 7270b57cec5SDimitry Andric RemovedBlocks.push_back(TBB); 7280b57cec5SDimitry Andric TBB->eraseFromParent(); 7290b57cec5SDimitry Andric } 7300b57cec5SDimitry Andric if (FBB != Tail) { 7310b57cec5SDimitry Andric RemovedBlocks.push_back(FBB); 7320b57cec5SDimitry Andric FBB->eraseFromParent(); 7330b57cec5SDimitry Andric } 7340b57cec5SDimitry Andric 7350b57cec5SDimitry Andric assert(Head->succ_empty() && "Additional head successors?"); 7360b57cec5SDimitry Andric if (!ExtraPreds && Head->isLayoutSuccessor(Tail)) { 7370b57cec5SDimitry Andric // Splice Tail onto the end of Head. 7380b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "Joining tail " << printMBBReference(*Tail) 7390b57cec5SDimitry Andric << " into head " << printMBBReference(*Head) << '\n'); 7400b57cec5SDimitry Andric Head->splice(Head->end(), Tail, 7410b57cec5SDimitry Andric Tail->begin(), Tail->end()); 7420b57cec5SDimitry Andric Head->transferSuccessorsAndUpdatePHIs(Tail); 7430b57cec5SDimitry Andric RemovedBlocks.push_back(Tail); 7440b57cec5SDimitry Andric Tail->eraseFromParent(); 7450b57cec5SDimitry Andric } else { 7460b57cec5SDimitry Andric // We need a branch to Tail, let code placement work it out later. 7470b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "Converting to unconditional branch.\n"); 7480b57cec5SDimitry Andric SmallVector<MachineOperand, 0> EmptyCond; 7490b57cec5SDimitry Andric TII->insertBranch(*Head, Tail, nullptr, EmptyCond, HeadDL); 7500b57cec5SDimitry Andric Head->addSuccessor(Tail); 7510b57cec5SDimitry Andric } 7520b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << *Head); 7530b57cec5SDimitry Andric } 7540b57cec5SDimitry Andric 7550b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 7560b57cec5SDimitry Andric // EarlyIfConverter Pass 7570b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 7580b57cec5SDimitry Andric 7590b57cec5SDimitry Andric namespace { 7600b57cec5SDimitry Andric class EarlyIfConverter : public MachineFunctionPass { 76106c3fb27SDimitry Andric const TargetInstrInfo *TII = nullptr; 76206c3fb27SDimitry Andric const TargetRegisterInfo *TRI = nullptr; 7630b57cec5SDimitry Andric MCSchedModel SchedModel; 76406c3fb27SDimitry Andric MachineRegisterInfo *MRI = nullptr; 76506c3fb27SDimitry Andric MachineDominatorTree *DomTree = nullptr; 76606c3fb27SDimitry Andric MachineLoopInfo *Loops = nullptr; 76706c3fb27SDimitry Andric MachineTraceMetrics *Traces = nullptr; 76806c3fb27SDimitry Andric MachineTraceMetrics::Ensemble *MinInstr = nullptr; 7690b57cec5SDimitry Andric SSAIfConv IfConv; 7700b57cec5SDimitry Andric 7710b57cec5SDimitry Andric public: 7720b57cec5SDimitry Andric static char ID; 7730b57cec5SDimitry Andric EarlyIfConverter() : MachineFunctionPass(ID) {} 7740b57cec5SDimitry Andric void getAnalysisUsage(AnalysisUsage &AU) const override; 7750b57cec5SDimitry Andric bool runOnMachineFunction(MachineFunction &MF) override; 7760b57cec5SDimitry Andric StringRef getPassName() const override { return "Early If-Conversion"; } 7770b57cec5SDimitry Andric 7780b57cec5SDimitry Andric private: 7790b57cec5SDimitry Andric bool tryConvertIf(MachineBasicBlock*); 7800b57cec5SDimitry Andric void invalidateTraces(); 7810b57cec5SDimitry Andric bool shouldConvertIf(); 7820b57cec5SDimitry Andric }; 7830b57cec5SDimitry Andric } // end anonymous namespace 7840b57cec5SDimitry Andric 7850b57cec5SDimitry Andric char EarlyIfConverter::ID = 0; 7860b57cec5SDimitry Andric char &llvm::EarlyIfConverterID = EarlyIfConverter::ID; 7870b57cec5SDimitry Andric 7880b57cec5SDimitry Andric INITIALIZE_PASS_BEGIN(EarlyIfConverter, DEBUG_TYPE, 7890b57cec5SDimitry Andric "Early If Converter", false, false) 790*0fca6ea1SDimitry Andric INITIALIZE_PASS_DEPENDENCY(MachineBranchProbabilityInfoWrapperPass) 791*0fca6ea1SDimitry Andric INITIALIZE_PASS_DEPENDENCY(MachineDominatorTreeWrapperPass) 7920b57cec5SDimitry Andric INITIALIZE_PASS_DEPENDENCY(MachineTraceMetrics) 7930b57cec5SDimitry Andric INITIALIZE_PASS_END(EarlyIfConverter, DEBUG_TYPE, 7940b57cec5SDimitry Andric "Early If Converter", false, false) 7950b57cec5SDimitry Andric 7960b57cec5SDimitry Andric void EarlyIfConverter::getAnalysisUsage(AnalysisUsage &AU) const { 797*0fca6ea1SDimitry Andric AU.addRequired<MachineBranchProbabilityInfoWrapperPass>(); 798*0fca6ea1SDimitry Andric AU.addRequired<MachineDominatorTreeWrapperPass>(); 799*0fca6ea1SDimitry Andric AU.addPreserved<MachineDominatorTreeWrapperPass>(); 800*0fca6ea1SDimitry Andric AU.addRequired<MachineLoopInfoWrapperPass>(); 801*0fca6ea1SDimitry Andric AU.addPreserved<MachineLoopInfoWrapperPass>(); 8020b57cec5SDimitry Andric AU.addRequired<MachineTraceMetrics>(); 8030b57cec5SDimitry Andric AU.addPreserved<MachineTraceMetrics>(); 8040b57cec5SDimitry Andric MachineFunctionPass::getAnalysisUsage(AU); 8050b57cec5SDimitry Andric } 8060b57cec5SDimitry Andric 8078bcb0991SDimitry Andric namespace { 8080b57cec5SDimitry Andric /// Update the dominator tree after if-conversion erased some blocks. 8098bcb0991SDimitry Andric void updateDomTree(MachineDominatorTree *DomTree, const SSAIfConv &IfConv, 8108bcb0991SDimitry Andric ArrayRef<MachineBasicBlock *> Removed) { 8110b57cec5SDimitry Andric // convertIf can remove TBB, FBB, and Tail can be merged into Head. 8120b57cec5SDimitry Andric // TBB and FBB should not dominate any blocks. 8130b57cec5SDimitry Andric // Tail children should be transferred to Head. 8140b57cec5SDimitry Andric MachineDomTreeNode *HeadNode = DomTree->getNode(IfConv.Head); 815fcaf7f86SDimitry Andric for (auto *B : Removed) { 8168bcb0991SDimitry Andric MachineDomTreeNode *Node = DomTree->getNode(B); 8170b57cec5SDimitry Andric assert(Node != HeadNode && "Cannot erase the head node"); 8180b57cec5SDimitry Andric while (Node->getNumChildren()) { 8190b57cec5SDimitry Andric assert(Node->getBlock() == IfConv.Tail && "Unexpected children"); 8205ffd83dbSDimitry Andric DomTree->changeImmediateDominator(Node->back(), HeadNode); 8210b57cec5SDimitry Andric } 8228bcb0991SDimitry Andric DomTree->eraseNode(B); 8230b57cec5SDimitry Andric } 8240b57cec5SDimitry Andric } 8250b57cec5SDimitry Andric 8260b57cec5SDimitry Andric /// Update LoopInfo after if-conversion. 8278bcb0991SDimitry Andric void updateLoops(MachineLoopInfo *Loops, 8288bcb0991SDimitry Andric ArrayRef<MachineBasicBlock *> Removed) { 8290b57cec5SDimitry Andric // If-conversion doesn't change loop structure, and it doesn't mess with back 8300b57cec5SDimitry Andric // edges, so updating LoopInfo is simply removing the dead blocks. 831fcaf7f86SDimitry Andric for (auto *B : Removed) 8328bcb0991SDimitry Andric Loops->removeBlock(B); 8330b57cec5SDimitry Andric } 8348bcb0991SDimitry Andric } // namespace 8350b57cec5SDimitry Andric 8360b57cec5SDimitry Andric /// Invalidate MachineTraceMetrics before if-conversion. 8370b57cec5SDimitry Andric void EarlyIfConverter::invalidateTraces() { 8380b57cec5SDimitry Andric Traces->verifyAnalysis(); 8390b57cec5SDimitry Andric Traces->invalidate(IfConv.Head); 8400b57cec5SDimitry Andric Traces->invalidate(IfConv.Tail); 8410b57cec5SDimitry Andric Traces->invalidate(IfConv.TBB); 8420b57cec5SDimitry Andric Traces->invalidate(IfConv.FBB); 8430b57cec5SDimitry Andric Traces->verifyAnalysis(); 8440b57cec5SDimitry Andric } 8450b57cec5SDimitry Andric 8460b57cec5SDimitry Andric // Adjust cycles with downward saturation. 8470b57cec5SDimitry Andric static unsigned adjCycles(unsigned Cyc, int Delta) { 8480b57cec5SDimitry Andric if (Delta < 0 && Cyc + Delta > Cyc) 8490b57cec5SDimitry Andric return 0; 8500b57cec5SDimitry Andric return Cyc + Delta; 8510b57cec5SDimitry Andric } 8520b57cec5SDimitry Andric 853e8d8bef9SDimitry Andric namespace { 854e8d8bef9SDimitry Andric /// Helper class to simplify emission of cycle counts into optimization remarks. 855e8d8bef9SDimitry Andric struct Cycles { 856e8d8bef9SDimitry Andric const char *Key; 857e8d8bef9SDimitry Andric unsigned Value; 858e8d8bef9SDimitry Andric }; 859e8d8bef9SDimitry Andric template <typename Remark> Remark &operator<<(Remark &R, Cycles C) { 860e8d8bef9SDimitry Andric return R << ore::NV(C.Key, C.Value) << (C.Value == 1 ? " cycle" : " cycles"); 861e8d8bef9SDimitry Andric } 862e8d8bef9SDimitry Andric } // anonymous namespace 863e8d8bef9SDimitry Andric 8640b57cec5SDimitry Andric /// Apply cost model and heuristics to the if-conversion in IfConv. 8650b57cec5SDimitry Andric /// Return true if the conversion is a good idea. 8660b57cec5SDimitry Andric /// 8670b57cec5SDimitry Andric bool EarlyIfConverter::shouldConvertIf() { 8680b57cec5SDimitry Andric // Stress testing mode disables all cost considerations. 8690b57cec5SDimitry Andric if (Stress) 8700b57cec5SDimitry Andric return true; 8710b57cec5SDimitry Andric 87206c3fb27SDimitry Andric // Do not try to if-convert if the condition has a high chance of being 87306c3fb27SDimitry Andric // predictable. 87406c3fb27SDimitry Andric MachineLoop *CurrentLoop = Loops->getLoopFor(IfConv.Head); 87506c3fb27SDimitry Andric // If the condition is in a loop, consider it predictable if the condition 87606c3fb27SDimitry Andric // itself or all its operands are loop-invariant. E.g. this considers a load 87706c3fb27SDimitry Andric // from a loop-invariant address predictable; we were unable to prove that it 87806c3fb27SDimitry Andric // doesn't alias any of the memory-writes in the loop, but it is likely to 87906c3fb27SDimitry Andric // read to same value multiple times. 88006c3fb27SDimitry Andric if (CurrentLoop && any_of(IfConv.Cond, [&](MachineOperand &MO) { 88106c3fb27SDimitry Andric if (!MO.isReg() || !MO.isUse()) 88206c3fb27SDimitry Andric return false; 88306c3fb27SDimitry Andric Register Reg = MO.getReg(); 88406c3fb27SDimitry Andric if (Register::isPhysicalRegister(Reg)) 88506c3fb27SDimitry Andric return false; 88606c3fb27SDimitry Andric 88706c3fb27SDimitry Andric MachineInstr *Def = MRI->getVRegDef(Reg); 88806c3fb27SDimitry Andric return CurrentLoop->isLoopInvariant(*Def) || 88906c3fb27SDimitry Andric all_of(Def->operands(), [&](MachineOperand &Op) { 89006c3fb27SDimitry Andric if (Op.isImm()) 89106c3fb27SDimitry Andric return true; 89206c3fb27SDimitry Andric if (!MO.isReg() || !MO.isUse()) 89306c3fb27SDimitry Andric return false; 89406c3fb27SDimitry Andric Register Reg = MO.getReg(); 89506c3fb27SDimitry Andric if (Register::isPhysicalRegister(Reg)) 89606c3fb27SDimitry Andric return false; 89706c3fb27SDimitry Andric 89806c3fb27SDimitry Andric MachineInstr *Def = MRI->getVRegDef(Reg); 89906c3fb27SDimitry Andric return CurrentLoop->isLoopInvariant(*Def); 90006c3fb27SDimitry Andric }); 90106c3fb27SDimitry Andric })) 90206c3fb27SDimitry Andric return false; 90306c3fb27SDimitry Andric 9040b57cec5SDimitry Andric if (!MinInstr) 90506c3fb27SDimitry Andric MinInstr = Traces->getEnsemble(MachineTraceStrategy::TS_MinInstrCount); 9060b57cec5SDimitry Andric 9070b57cec5SDimitry Andric MachineTraceMetrics::Trace TBBTrace = MinInstr->getTrace(IfConv.getTPred()); 9080b57cec5SDimitry Andric MachineTraceMetrics::Trace FBBTrace = MinInstr->getTrace(IfConv.getFPred()); 9090b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "TBB: " << TBBTrace << "FBB: " << FBBTrace); 9100b57cec5SDimitry Andric unsigned MinCrit = std::min(TBBTrace.getCriticalPath(), 9110b57cec5SDimitry Andric FBBTrace.getCriticalPath()); 9120b57cec5SDimitry Andric 9130b57cec5SDimitry Andric // Set a somewhat arbitrary limit on the critical path extension we accept. 9140b57cec5SDimitry Andric unsigned CritLimit = SchedModel.MispredictPenalty/2; 9150b57cec5SDimitry Andric 916e8d8bef9SDimitry Andric MachineBasicBlock &MBB = *IfConv.Head; 917e8d8bef9SDimitry Andric MachineOptimizationRemarkEmitter MORE(*MBB.getParent(), nullptr); 918e8d8bef9SDimitry Andric 9190b57cec5SDimitry Andric // If-conversion only makes sense when there is unexploited ILP. Compute the 9200b57cec5SDimitry Andric // maximum-ILP resource length of the trace after if-conversion. Compare it 9210b57cec5SDimitry Andric // to the shortest critical path. 9220b57cec5SDimitry Andric SmallVector<const MachineBasicBlock*, 1> ExtraBlocks; 9230b57cec5SDimitry Andric if (IfConv.TBB != IfConv.Tail) 9240b57cec5SDimitry Andric ExtraBlocks.push_back(IfConv.TBB); 9250b57cec5SDimitry Andric unsigned ResLength = FBBTrace.getResourceLength(ExtraBlocks); 9260b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "Resource length " << ResLength 9270b57cec5SDimitry Andric << ", minimal critical path " << MinCrit << '\n'); 9280b57cec5SDimitry Andric if (ResLength > MinCrit + CritLimit) { 9290b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "Not enough available ILP.\n"); 930e8d8bef9SDimitry Andric MORE.emit([&]() { 931e8d8bef9SDimitry Andric MachineOptimizationRemarkMissed R(DEBUG_TYPE, "IfConversion", 932e8d8bef9SDimitry Andric MBB.findDebugLoc(MBB.back()), &MBB); 933e8d8bef9SDimitry Andric R << "did not if-convert branch: the resulting critical path (" 934e8d8bef9SDimitry Andric << Cycles{"ResLength", ResLength} 935e8d8bef9SDimitry Andric << ") would extend the shorter leg's critical path (" 936e8d8bef9SDimitry Andric << Cycles{"MinCrit", MinCrit} << ") by more than the threshold of " 937e8d8bef9SDimitry Andric << Cycles{"CritLimit", CritLimit} 938e8d8bef9SDimitry Andric << ", which cannot be hidden by available ILP."; 939e8d8bef9SDimitry Andric return R; 940e8d8bef9SDimitry Andric }); 9410b57cec5SDimitry Andric return false; 9420b57cec5SDimitry Andric } 9430b57cec5SDimitry Andric 9440b57cec5SDimitry Andric // Assume that the depth of the first head terminator will also be the depth 9450b57cec5SDimitry Andric // of the select instruction inserted, as determined by the flag dependency. 9460b57cec5SDimitry Andric // TBB / FBB data dependencies may delay the select even more. 9470b57cec5SDimitry Andric MachineTraceMetrics::Trace HeadTrace = MinInstr->getTrace(IfConv.Head); 9480b57cec5SDimitry Andric unsigned BranchDepth = 9490b57cec5SDimitry Andric HeadTrace.getInstrCycles(*IfConv.Head->getFirstTerminator()).Depth; 9500b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "Branch depth: " << BranchDepth << '\n'); 9510b57cec5SDimitry Andric 9520b57cec5SDimitry Andric // Look at all the tail phis, and compute the critical path extension caused 9530b57cec5SDimitry Andric // by inserting select instructions. 9540b57cec5SDimitry Andric MachineTraceMetrics::Trace TailTrace = MinInstr->getTrace(IfConv.Tail); 955e8d8bef9SDimitry Andric struct CriticalPathInfo { 956e8d8bef9SDimitry Andric unsigned Extra; // Count of extra cycles that the component adds. 957e8d8bef9SDimitry Andric unsigned Depth; // Absolute depth of the component in cycles. 958e8d8bef9SDimitry Andric }; 959e8d8bef9SDimitry Andric CriticalPathInfo Cond{}; 960e8d8bef9SDimitry Andric CriticalPathInfo TBlock{}; 961e8d8bef9SDimitry Andric CriticalPathInfo FBlock{}; 962e8d8bef9SDimitry Andric bool ShouldConvert = true; 963*0fca6ea1SDimitry Andric for (SSAIfConv::PHIInfo &PI : IfConv.PHIs) { 9640b57cec5SDimitry Andric unsigned Slack = TailTrace.getInstrSlack(*PI.PHI); 9650b57cec5SDimitry Andric unsigned MaxDepth = Slack + TailTrace.getInstrCycles(*PI.PHI).Depth; 9660b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "Slack " << Slack << ":\t" << *PI.PHI); 9670b57cec5SDimitry Andric 9680b57cec5SDimitry Andric // The condition is pulled into the critical path. 9690b57cec5SDimitry Andric unsigned CondDepth = adjCycles(BranchDepth, PI.CondCycles); 9700b57cec5SDimitry Andric if (CondDepth > MaxDepth) { 9710b57cec5SDimitry Andric unsigned Extra = CondDepth - MaxDepth; 9720b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "Condition adds " << Extra << " cycles.\n"); 973e8d8bef9SDimitry Andric if (Extra > Cond.Extra) 974e8d8bef9SDimitry Andric Cond = {Extra, CondDepth}; 9750b57cec5SDimitry Andric if (Extra > CritLimit) { 9760b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "Exceeds limit of " << CritLimit << '\n'); 977e8d8bef9SDimitry Andric ShouldConvert = false; 9780b57cec5SDimitry Andric } 9790b57cec5SDimitry Andric } 9800b57cec5SDimitry Andric 9810b57cec5SDimitry Andric // The TBB value is pulled into the critical path. 9820b57cec5SDimitry Andric unsigned TDepth = adjCycles(TBBTrace.getPHIDepth(*PI.PHI), PI.TCycles); 9830b57cec5SDimitry Andric if (TDepth > MaxDepth) { 9840b57cec5SDimitry Andric unsigned Extra = TDepth - MaxDepth; 9850b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "TBB data adds " << Extra << " cycles.\n"); 986e8d8bef9SDimitry Andric if (Extra > TBlock.Extra) 987e8d8bef9SDimitry Andric TBlock = {Extra, TDepth}; 9880b57cec5SDimitry Andric if (Extra > CritLimit) { 9890b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "Exceeds limit of " << CritLimit << '\n'); 990e8d8bef9SDimitry Andric ShouldConvert = false; 9910b57cec5SDimitry Andric } 9920b57cec5SDimitry Andric } 9930b57cec5SDimitry Andric 9940b57cec5SDimitry Andric // The FBB value is pulled into the critical path. 9950b57cec5SDimitry Andric unsigned FDepth = adjCycles(FBBTrace.getPHIDepth(*PI.PHI), PI.FCycles); 9960b57cec5SDimitry Andric if (FDepth > MaxDepth) { 9970b57cec5SDimitry Andric unsigned Extra = FDepth - MaxDepth; 9980b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "FBB data adds " << Extra << " cycles.\n"); 999e8d8bef9SDimitry Andric if (Extra > FBlock.Extra) 1000e8d8bef9SDimitry Andric FBlock = {Extra, FDepth}; 10010b57cec5SDimitry Andric if (Extra > CritLimit) { 10020b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "Exceeds limit of " << CritLimit << '\n'); 1003e8d8bef9SDimitry Andric ShouldConvert = false; 10040b57cec5SDimitry Andric } 10050b57cec5SDimitry Andric } 10060b57cec5SDimitry Andric } 1007e8d8bef9SDimitry Andric 1008e8d8bef9SDimitry Andric // Organize by "short" and "long" legs, since the diagnostics get confusing 1009e8d8bef9SDimitry Andric // when referring to the "true" and "false" sides of the branch, given that 1010e8d8bef9SDimitry Andric // those don't always correlate with what the user wrote in source-terms. 1011e8d8bef9SDimitry Andric const CriticalPathInfo Short = TBlock.Extra > FBlock.Extra ? FBlock : TBlock; 1012e8d8bef9SDimitry Andric const CriticalPathInfo Long = TBlock.Extra > FBlock.Extra ? TBlock : FBlock; 1013e8d8bef9SDimitry Andric 1014e8d8bef9SDimitry Andric if (ShouldConvert) { 1015e8d8bef9SDimitry Andric MORE.emit([&]() { 1016e8d8bef9SDimitry Andric MachineOptimizationRemark R(DEBUG_TYPE, "IfConversion", 1017e8d8bef9SDimitry Andric MBB.back().getDebugLoc(), &MBB); 1018e8d8bef9SDimitry Andric R << "performing if-conversion on branch: the condition adds " 1019e8d8bef9SDimitry Andric << Cycles{"CondCycles", Cond.Extra} << " to the critical path"; 1020e8d8bef9SDimitry Andric if (Short.Extra > 0) 1021e8d8bef9SDimitry Andric R << ", and the short leg adds another " 1022e8d8bef9SDimitry Andric << Cycles{"ShortCycles", Short.Extra}; 1023e8d8bef9SDimitry Andric if (Long.Extra > 0) 1024e8d8bef9SDimitry Andric R << ", and the long leg adds another " 1025e8d8bef9SDimitry Andric << Cycles{"LongCycles", Long.Extra}; 1026e8d8bef9SDimitry Andric R << ", each staying under the threshold of " 1027e8d8bef9SDimitry Andric << Cycles{"CritLimit", CritLimit} << "."; 1028e8d8bef9SDimitry Andric return R; 1029e8d8bef9SDimitry Andric }); 1030e8d8bef9SDimitry Andric } else { 1031e8d8bef9SDimitry Andric MORE.emit([&]() { 1032e8d8bef9SDimitry Andric MachineOptimizationRemarkMissed R(DEBUG_TYPE, "IfConversion", 1033e8d8bef9SDimitry Andric MBB.back().getDebugLoc(), &MBB); 1034e8d8bef9SDimitry Andric R << "did not if-convert branch: the condition would add " 1035e8d8bef9SDimitry Andric << Cycles{"CondCycles", Cond.Extra} << " to the critical path"; 1036e8d8bef9SDimitry Andric if (Cond.Extra > CritLimit) 1037e8d8bef9SDimitry Andric R << " exceeding the limit of " << Cycles{"CritLimit", CritLimit}; 1038e8d8bef9SDimitry Andric if (Short.Extra > 0) { 1039e8d8bef9SDimitry Andric R << ", and the short leg would add another " 1040e8d8bef9SDimitry Andric << Cycles{"ShortCycles", Short.Extra}; 1041e8d8bef9SDimitry Andric if (Short.Extra > CritLimit) 1042e8d8bef9SDimitry Andric R << " exceeding the limit of " << Cycles{"CritLimit", CritLimit}; 1043e8d8bef9SDimitry Andric } 1044e8d8bef9SDimitry Andric if (Long.Extra > 0) { 1045e8d8bef9SDimitry Andric R << ", and the long leg would add another " 1046e8d8bef9SDimitry Andric << Cycles{"LongCycles", Long.Extra}; 1047e8d8bef9SDimitry Andric if (Long.Extra > CritLimit) 1048e8d8bef9SDimitry Andric R << " exceeding the limit of " << Cycles{"CritLimit", CritLimit}; 1049e8d8bef9SDimitry Andric } 1050e8d8bef9SDimitry Andric R << "."; 1051e8d8bef9SDimitry Andric return R; 1052e8d8bef9SDimitry Andric }); 1053e8d8bef9SDimitry Andric } 1054e8d8bef9SDimitry Andric 1055e8d8bef9SDimitry Andric return ShouldConvert; 10560b57cec5SDimitry Andric } 10570b57cec5SDimitry Andric 10580b57cec5SDimitry Andric /// Attempt repeated if-conversion on MBB, return true if successful. 10590b57cec5SDimitry Andric /// 10600b57cec5SDimitry Andric bool EarlyIfConverter::tryConvertIf(MachineBasicBlock *MBB) { 10610b57cec5SDimitry Andric bool Changed = false; 10620b57cec5SDimitry Andric while (IfConv.canConvertIf(MBB) && shouldConvertIf()) { 10630b57cec5SDimitry Andric // If-convert MBB and update analyses. 10640b57cec5SDimitry Andric invalidateTraces(); 10650b57cec5SDimitry Andric SmallVector<MachineBasicBlock*, 4> RemovedBlocks; 10660b57cec5SDimitry Andric IfConv.convertIf(RemovedBlocks); 10670b57cec5SDimitry Andric Changed = true; 10688bcb0991SDimitry Andric updateDomTree(DomTree, IfConv, RemovedBlocks); 10698bcb0991SDimitry Andric updateLoops(Loops, RemovedBlocks); 10700b57cec5SDimitry Andric } 10710b57cec5SDimitry Andric return Changed; 10720b57cec5SDimitry Andric } 10730b57cec5SDimitry Andric 10740b57cec5SDimitry Andric bool EarlyIfConverter::runOnMachineFunction(MachineFunction &MF) { 10750b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "********** EARLY IF-CONVERSION **********\n" 10760b57cec5SDimitry Andric << "********** Function: " << MF.getName() << '\n'); 10770b57cec5SDimitry Andric if (skipFunction(MF.getFunction())) 10780b57cec5SDimitry Andric return false; 10790b57cec5SDimitry Andric 10800b57cec5SDimitry Andric // Only run if conversion if the target wants it. 10810b57cec5SDimitry Andric const TargetSubtargetInfo &STI = MF.getSubtarget(); 10820b57cec5SDimitry Andric if (!STI.enableEarlyIfConversion()) 10830b57cec5SDimitry Andric return false; 10840b57cec5SDimitry Andric 10850b57cec5SDimitry Andric TII = STI.getInstrInfo(); 10860b57cec5SDimitry Andric TRI = STI.getRegisterInfo(); 10870b57cec5SDimitry Andric SchedModel = STI.getSchedModel(); 10880b57cec5SDimitry Andric MRI = &MF.getRegInfo(); 1089*0fca6ea1SDimitry Andric DomTree = &getAnalysis<MachineDominatorTreeWrapperPass>().getDomTree(); 1090*0fca6ea1SDimitry Andric Loops = &getAnalysis<MachineLoopInfoWrapperPass>().getLI(); 10910b57cec5SDimitry Andric Traces = &getAnalysis<MachineTraceMetrics>(); 10920b57cec5SDimitry Andric MinInstr = nullptr; 10930b57cec5SDimitry Andric 10940b57cec5SDimitry Andric bool Changed = false; 10950b57cec5SDimitry Andric IfConv.runOnMachineFunction(MF); 10960b57cec5SDimitry Andric 10970b57cec5SDimitry Andric // Visit blocks in dominator tree post-order. The post-order enables nested 10980b57cec5SDimitry Andric // if-conversion in a single pass. The tryConvertIf() function may erase 10990b57cec5SDimitry Andric // blocks, but only blocks dominated by the head block. This makes it safe to 11000b57cec5SDimitry Andric // update the dominator tree while the post-order iterator is still active. 1101fcaf7f86SDimitry Andric for (auto *DomNode : post_order(DomTree)) 11020b57cec5SDimitry Andric if (tryConvertIf(DomNode->getBlock())) 11030b57cec5SDimitry Andric Changed = true; 11040b57cec5SDimitry Andric 11050b57cec5SDimitry Andric return Changed; 11060b57cec5SDimitry Andric } 11078bcb0991SDimitry Andric 11088bcb0991SDimitry Andric //===----------------------------------------------------------------------===// 11098bcb0991SDimitry Andric // EarlyIfPredicator Pass 11108bcb0991SDimitry Andric //===----------------------------------------------------------------------===// 11118bcb0991SDimitry Andric 11128bcb0991SDimitry Andric namespace { 11138bcb0991SDimitry Andric class EarlyIfPredicator : public MachineFunctionPass { 111406c3fb27SDimitry Andric const TargetInstrInfo *TII = nullptr; 111506c3fb27SDimitry Andric const TargetRegisterInfo *TRI = nullptr; 11168bcb0991SDimitry Andric TargetSchedModel SchedModel; 111706c3fb27SDimitry Andric MachineRegisterInfo *MRI = nullptr; 111806c3fb27SDimitry Andric MachineDominatorTree *DomTree = nullptr; 111906c3fb27SDimitry Andric MachineBranchProbabilityInfo *MBPI = nullptr; 112006c3fb27SDimitry Andric MachineLoopInfo *Loops = nullptr; 11218bcb0991SDimitry Andric SSAIfConv IfConv; 11228bcb0991SDimitry Andric 11238bcb0991SDimitry Andric public: 11248bcb0991SDimitry Andric static char ID; 11258bcb0991SDimitry Andric EarlyIfPredicator() : MachineFunctionPass(ID) {} 11268bcb0991SDimitry Andric void getAnalysisUsage(AnalysisUsage &AU) const override; 11278bcb0991SDimitry Andric bool runOnMachineFunction(MachineFunction &MF) override; 11288bcb0991SDimitry Andric StringRef getPassName() const override { return "Early If-predicator"; } 11298bcb0991SDimitry Andric 11308bcb0991SDimitry Andric protected: 11318bcb0991SDimitry Andric bool tryConvertIf(MachineBasicBlock *); 11328bcb0991SDimitry Andric bool shouldConvertIf(); 11338bcb0991SDimitry Andric }; 11348bcb0991SDimitry Andric } // end anonymous namespace 11358bcb0991SDimitry Andric 11368bcb0991SDimitry Andric #undef DEBUG_TYPE 11378bcb0991SDimitry Andric #define DEBUG_TYPE "early-if-predicator" 11388bcb0991SDimitry Andric 11398bcb0991SDimitry Andric char EarlyIfPredicator::ID = 0; 11408bcb0991SDimitry Andric char &llvm::EarlyIfPredicatorID = EarlyIfPredicator::ID; 11418bcb0991SDimitry Andric 11428bcb0991SDimitry Andric INITIALIZE_PASS_BEGIN(EarlyIfPredicator, DEBUG_TYPE, "Early If Predicator", 11438bcb0991SDimitry Andric false, false) 1144*0fca6ea1SDimitry Andric INITIALIZE_PASS_DEPENDENCY(MachineDominatorTreeWrapperPass) 1145*0fca6ea1SDimitry Andric INITIALIZE_PASS_DEPENDENCY(MachineBranchProbabilityInfoWrapperPass) 11468bcb0991SDimitry Andric INITIALIZE_PASS_END(EarlyIfPredicator, DEBUG_TYPE, "Early If Predicator", false, 11478bcb0991SDimitry Andric false) 11488bcb0991SDimitry Andric 11498bcb0991SDimitry Andric void EarlyIfPredicator::getAnalysisUsage(AnalysisUsage &AU) const { 1150*0fca6ea1SDimitry Andric AU.addRequired<MachineBranchProbabilityInfoWrapperPass>(); 1151*0fca6ea1SDimitry Andric AU.addRequired<MachineDominatorTreeWrapperPass>(); 1152*0fca6ea1SDimitry Andric AU.addPreserved<MachineDominatorTreeWrapperPass>(); 1153*0fca6ea1SDimitry Andric AU.addRequired<MachineLoopInfoWrapperPass>(); 1154*0fca6ea1SDimitry Andric AU.addPreserved<MachineLoopInfoWrapperPass>(); 11558bcb0991SDimitry Andric MachineFunctionPass::getAnalysisUsage(AU); 11568bcb0991SDimitry Andric } 11578bcb0991SDimitry Andric 11588bcb0991SDimitry Andric /// Apply the target heuristic to decide if the transformation is profitable. 11598bcb0991SDimitry Andric bool EarlyIfPredicator::shouldConvertIf() { 1160480093f4SDimitry Andric auto TrueProbability = MBPI->getEdgeProbability(IfConv.Head, IfConv.TBB); 11618bcb0991SDimitry Andric if (IfConv.isTriangle()) { 11628bcb0991SDimitry Andric MachineBasicBlock &IfBlock = 11638bcb0991SDimitry Andric (IfConv.TBB == IfConv.Tail) ? *IfConv.FBB : *IfConv.TBB; 11648bcb0991SDimitry Andric 11658bcb0991SDimitry Andric unsigned ExtraPredCost = 0; 11668bcb0991SDimitry Andric unsigned Cycles = 0; 11678bcb0991SDimitry Andric for (MachineInstr &I : IfBlock) { 11688bcb0991SDimitry Andric unsigned NumCycles = SchedModel.computeInstrLatency(&I, false); 11698bcb0991SDimitry Andric if (NumCycles > 1) 11708bcb0991SDimitry Andric Cycles += NumCycles - 1; 11718bcb0991SDimitry Andric ExtraPredCost += TII->getPredicationCost(I); 11728bcb0991SDimitry Andric } 11738bcb0991SDimitry Andric 11748bcb0991SDimitry Andric return TII->isProfitableToIfCvt(IfBlock, Cycles, ExtraPredCost, 1175480093f4SDimitry Andric TrueProbability); 11768bcb0991SDimitry Andric } 11778bcb0991SDimitry Andric unsigned TExtra = 0; 11788bcb0991SDimitry Andric unsigned FExtra = 0; 11798bcb0991SDimitry Andric unsigned TCycle = 0; 11808bcb0991SDimitry Andric unsigned FCycle = 0; 11818bcb0991SDimitry Andric for (MachineInstr &I : *IfConv.TBB) { 11828bcb0991SDimitry Andric unsigned NumCycles = SchedModel.computeInstrLatency(&I, false); 11838bcb0991SDimitry Andric if (NumCycles > 1) 11848bcb0991SDimitry Andric TCycle += NumCycles - 1; 11858bcb0991SDimitry Andric TExtra += TII->getPredicationCost(I); 11868bcb0991SDimitry Andric } 11878bcb0991SDimitry Andric for (MachineInstr &I : *IfConv.FBB) { 11888bcb0991SDimitry Andric unsigned NumCycles = SchedModel.computeInstrLatency(&I, false); 11898bcb0991SDimitry Andric if (NumCycles > 1) 11908bcb0991SDimitry Andric FCycle += NumCycles - 1; 11918bcb0991SDimitry Andric FExtra += TII->getPredicationCost(I); 11928bcb0991SDimitry Andric } 11938bcb0991SDimitry Andric return TII->isProfitableToIfCvt(*IfConv.TBB, TCycle, TExtra, *IfConv.FBB, 1194480093f4SDimitry Andric FCycle, FExtra, TrueProbability); 11958bcb0991SDimitry Andric } 11968bcb0991SDimitry Andric 11978bcb0991SDimitry Andric /// Attempt repeated if-conversion on MBB, return true if successful. 11988bcb0991SDimitry Andric /// 11998bcb0991SDimitry Andric bool EarlyIfPredicator::tryConvertIf(MachineBasicBlock *MBB) { 12008bcb0991SDimitry Andric bool Changed = false; 12018bcb0991SDimitry Andric while (IfConv.canConvertIf(MBB, /*Predicate*/ true) && shouldConvertIf()) { 12028bcb0991SDimitry Andric // If-convert MBB and update analyses. 12038bcb0991SDimitry Andric SmallVector<MachineBasicBlock *, 4> RemovedBlocks; 12048bcb0991SDimitry Andric IfConv.convertIf(RemovedBlocks, /*Predicate*/ true); 12058bcb0991SDimitry Andric Changed = true; 12068bcb0991SDimitry Andric updateDomTree(DomTree, IfConv, RemovedBlocks); 12078bcb0991SDimitry Andric updateLoops(Loops, RemovedBlocks); 12088bcb0991SDimitry Andric } 12098bcb0991SDimitry Andric return Changed; 12108bcb0991SDimitry Andric } 12118bcb0991SDimitry Andric 12128bcb0991SDimitry Andric bool EarlyIfPredicator::runOnMachineFunction(MachineFunction &MF) { 12138bcb0991SDimitry Andric LLVM_DEBUG(dbgs() << "********** EARLY IF-PREDICATOR **********\n" 12148bcb0991SDimitry Andric << "********** Function: " << MF.getName() << '\n'); 12158bcb0991SDimitry Andric if (skipFunction(MF.getFunction())) 12168bcb0991SDimitry Andric return false; 12178bcb0991SDimitry Andric 12188bcb0991SDimitry Andric const TargetSubtargetInfo &STI = MF.getSubtarget(); 12198bcb0991SDimitry Andric TII = STI.getInstrInfo(); 12208bcb0991SDimitry Andric TRI = STI.getRegisterInfo(); 12218bcb0991SDimitry Andric MRI = &MF.getRegInfo(); 12228bcb0991SDimitry Andric SchedModel.init(&STI); 1223*0fca6ea1SDimitry Andric DomTree = &getAnalysis<MachineDominatorTreeWrapperPass>().getDomTree(); 1224*0fca6ea1SDimitry Andric Loops = &getAnalysis<MachineLoopInfoWrapperPass>().getLI(); 1225*0fca6ea1SDimitry Andric MBPI = &getAnalysis<MachineBranchProbabilityInfoWrapperPass>().getMBPI(); 12268bcb0991SDimitry Andric 12278bcb0991SDimitry Andric bool Changed = false; 12288bcb0991SDimitry Andric IfConv.runOnMachineFunction(MF); 12298bcb0991SDimitry Andric 12308bcb0991SDimitry Andric // Visit blocks in dominator tree post-order. The post-order enables nested 12318bcb0991SDimitry Andric // if-conversion in a single pass. The tryConvertIf() function may erase 12328bcb0991SDimitry Andric // blocks, but only blocks dominated by the head block. This makes it safe to 12338bcb0991SDimitry Andric // update the dominator tree while the post-order iterator is still active. 1234fcaf7f86SDimitry Andric for (auto *DomNode : post_order(DomTree)) 12358bcb0991SDimitry Andric if (tryConvertIf(DomNode->getBlock())) 12368bcb0991SDimitry Andric Changed = true; 12378bcb0991SDimitry Andric 12388bcb0991SDimitry Andric return Changed; 12398bcb0991SDimitry Andric } 1240