//===-- EarlyIfConversion.cpp - If-conversion on SSA form machine code ----===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // // Early if-conversion is for out-of-order CPUs that don't have a lot of // predicable instructions. The goal is to eliminate conditional branches that // may mispredict. // // Instructions from both sides of the branch are executed specutatively, and a // cmov instruction selects the result. // //===----------------------------------------------------------------------===// #include "llvm/ADT/BitVector.h" #include "llvm/ADT/PostOrderIterator.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SparseSet.h" #include "llvm/ADT/Statistic.h" #include "llvm/Analysis/OptimizationRemarkEmitter.h" #include "llvm/CodeGen/MachineBranchProbabilityInfo.h" #include "llvm/CodeGen/MachineDominators.h" #include "llvm/CodeGen/MachineFunction.h" #include "llvm/CodeGen/MachineFunctionPass.h" #include "llvm/CodeGen/MachineInstr.h" #include "llvm/CodeGen/MachineLoopInfo.h" #include "llvm/CodeGen/MachineOptimizationRemarkEmitter.h" #include "llvm/CodeGen/MachineRegisterInfo.h" #include "llvm/CodeGen/MachineTraceMetrics.h" #include "llvm/CodeGen/TargetInstrInfo.h" #include "llvm/CodeGen/TargetRegisterInfo.h" #include "llvm/CodeGen/TargetSubtargetInfo.h" #include "llvm/InitializePasses.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/Debug.h" #include "llvm/Support/raw_ostream.h" usingnamespacellvm; #define DEBUG_TYPE … // Absolute maximum number of instructions allowed per speculated block. // This bypasses all other heuristics, so it should be set fairly high. static cl::opt<unsigned> BlockInstrLimit("early-ifcvt-limit", cl::init(30), cl::Hidden, cl::desc("Maximum number of instructions per speculated block.")); // Stress testing mode - disable heuristics. static cl::opt<bool> Stress("stress-early-ifcvt", cl::Hidden, cl::desc("Turn all knobs to 11")); STATISTIC(NumDiamondsSeen, "Number of diamonds"); STATISTIC(NumDiamondsConv, "Number of diamonds converted"); STATISTIC(NumTrianglesSeen, "Number of triangles"); STATISTIC(NumTrianglesConv, "Number of triangles converted"); //===----------------------------------------------------------------------===// // SSAIfConv //===----------------------------------------------------------------------===// // // The SSAIfConv class performs if-conversion on SSA form machine code after // determining if it is possible. The class contains no heuristics; external // code should be used to determine when if-conversion is a good idea. // // SSAIfConv can convert both triangles and diamonds: // // Triangle: Head Diamond: Head // | \ / \_ // | \ / | // | [TF]BB FBB TBB // | / \ / // | / \ / // Tail Tail // // Instructions in the conditional blocks TBB and/or FBB are spliced into the // Head block, and phis in the Tail block are converted to select instructions. // namespace { class SSAIfConv { … }; } // end anonymous namespace /// canSpeculateInstrs - Returns true if all the instructions in MBB can safely /// be speculated. The terminators are not considered. /// /// If instructions use any values that are defined in the head basic block, /// the defining instructions are added to InsertAfter. /// /// Any clobbered regunits are added to ClobberedRegUnits. /// bool SSAIfConv::canSpeculateInstrs(MachineBasicBlock *MBB) { … } /// Check that there is no dependencies preventing if conversion. /// /// If instruction uses any values that are defined in the head basic block, /// the defining instructions are added to InsertAfter. bool SSAIfConv::InstrDependenciesAllowIfConv(MachineInstr *I) { … } /// canPredicateInstrs - Returns true if all the instructions in MBB can safely /// be predicates. The terminators are not considered. /// /// If instructions use any values that are defined in the head basic block, /// the defining instructions are added to InsertAfter. /// /// Any clobbered regunits are added to ClobberedRegUnits. /// bool SSAIfConv::canPredicateInstrs(MachineBasicBlock *MBB) { … } // Apply predicate to all instructions in the machine block. void SSAIfConv::PredicateBlock(MachineBasicBlock *MBB, bool ReversePredicate) { … } /// Find an insertion point in Head for the speculated instructions. The /// insertion point must be: /// /// 1. Before any terminators. /// 2. After any instructions in InsertAfter. /// 3. Not have any clobbered regunits live. /// /// This function sets InsertionPoint and returns true when successful, it /// returns false if no valid insertion point could be found. /// bool SSAIfConv::findInsertionPoint() { … } /// canConvertIf - analyze the sub-cfg rooted in MBB, and return true if it is /// a potential candidate for if-conversion. Fill out the internal state. /// bool SSAIfConv::canConvertIf(MachineBasicBlock *MBB, bool Predicate) { … } /// \return true iff the two registers are known to have the same value. static bool hasSameValue(const MachineRegisterInfo &MRI, const TargetInstrInfo *TII, Register TReg, Register FReg) { … } /// replacePHIInstrs - Completely replace PHI instructions with selects. /// This is possible when the only Tail predecessors are the if-converted /// blocks. void SSAIfConv::replacePHIInstrs() { … } /// rewritePHIOperands - When there are additional Tail predecessors, insert /// select instructions in Head and rewrite PHI operands to use the selects. /// Keep the PHI instructions in Tail to handle the other predecessors. void SSAIfConv::rewritePHIOperands() { … } /// convertIf - Execute the if conversion after canConvertIf has determined the /// feasibility. /// /// Any basic blocks that need to be erased will be added to RemoveBlocks. /// void SSAIfConv::convertIf(SmallVectorImpl<MachineBasicBlock *> &RemoveBlocks, bool Predicate) { … } //===----------------------------------------------------------------------===// // EarlyIfConverter Pass //===----------------------------------------------------------------------===// namespace { class EarlyIfConverter : public MachineFunctionPass { … }; } // end anonymous namespace char EarlyIfConverter::ID = …; char &llvm::EarlyIfConverterID = …; INITIALIZE_PASS_BEGIN(EarlyIfConverter, DEBUG_TYPE, "Early If Converter", false, false) INITIALIZE_PASS_DEPENDENCY(MachineBranchProbabilityInfoWrapperPass) INITIALIZE_PASS_DEPENDENCY(MachineDominatorTreeWrapperPass) INITIALIZE_PASS_DEPENDENCY(MachineTraceMetrics) INITIALIZE_PASS_END(EarlyIfConverter, DEBUG_TYPE, "Early If Converter", false, false) void EarlyIfConverter::getAnalysisUsage(AnalysisUsage &AU) const { … } namespace { /// Update the dominator tree after if-conversion erased some blocks. void updateDomTree(MachineDominatorTree *DomTree, const SSAIfConv &IfConv, ArrayRef<MachineBasicBlock *> Removed) { … } /// Update LoopInfo after if-conversion. void updateLoops(MachineLoopInfo *Loops, ArrayRef<MachineBasicBlock *> Removed) { … } } // namespace /// Invalidate MachineTraceMetrics before if-conversion. void EarlyIfConverter::invalidateTraces(SSAIfConv &IfConv) { … } // Adjust cycles with downward saturation. static unsigned adjCycles(unsigned Cyc, int Delta) { … } namespace { /// Helper class to simplify emission of cycle counts into optimization remarks. struct Cycles { … }; template <typename Remark> Remark &operator<<(Remark &R, Cycles C) { … } } // anonymous namespace /// Apply cost model and heuristics to the if-conversion in IfConv. /// Return true if the conversion is a good idea. /// bool EarlyIfConverter::shouldConvertIf(SSAIfConv &IfConv) { … } /// Attempt repeated if-conversion on MBB, return true if successful. /// bool EarlyIfConverter::tryConvertIf(SSAIfConv &IfConv, MachineBasicBlock *MBB) { … } bool EarlyIfConverter::runOnMachineFunction(MachineFunction &MF) { … } //===----------------------------------------------------------------------===// // EarlyIfPredicator Pass //===----------------------------------------------------------------------===// namespace { class EarlyIfPredicator : public MachineFunctionPass { … }; } // end anonymous namespace #undef DEBUG_TYPE #define DEBUG_TYPE … char EarlyIfPredicator::ID = …; char &llvm::EarlyIfPredicatorID = …; INITIALIZE_PASS_BEGIN(EarlyIfPredicator, DEBUG_TYPE, "Early If Predicator", false, false) INITIALIZE_PASS_DEPENDENCY(MachineDominatorTreeWrapperPass) INITIALIZE_PASS_DEPENDENCY(MachineBranchProbabilityInfoWrapperPass) INITIALIZE_PASS_END(EarlyIfPredicator, DEBUG_TYPE, "Early If Predicator", false, false) void EarlyIfPredicator::getAnalysisUsage(AnalysisUsage &AU) const { … } /// Apply the target heuristic to decide if the transformation is profitable. bool EarlyIfPredicator::shouldConvertIf(SSAIfConv &IfConv) { … } /// Attempt repeated if-conversion on MBB, return true if successful. /// bool EarlyIfPredicator::tryConvertIf(SSAIfConv &IfConv, MachineBasicBlock *MBB) { … } bool EarlyIfPredicator::runOnMachineFunction(MachineFunction &MF) { … }