<div dir="ltr">Sorry about that, looks like it got lost in my rebase. Thanks for catching this. <div><br></div><div>I added it back: <a href="https://github.com/llvm/llvm-project/commit/53ab6bef98e7e43a0b5407a24babb837f1317cfa">https://github.com/llvm/llvm-project/commit/53ab6bef98e7e43a0b5407a24babb837f1317cfa</a></div></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Tue, Aug 20, 2019 at 8:55 AM Roman Lebedev <<a href="mailto:lebedev.ri@gmail.com">lebedev.ri@gmail.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">Where did the tests go?<br>
<br>
On Tue, Aug 20, 2019 at 6:53 PM Thomas Raoux via llvm-commits<br>
<<a href="mailto:llvm-commits@lists.llvm.org" target="_blank">llvm-commits@lists.llvm.org</a>> wrote:<br>
><br>
> Author: thomasraoux<br>
> Date: Tue Aug 20 08:54:59 2019<br>
> New Revision: 369395<br>
><br>
> URL: <a href="http://llvm.org/viewvc/llvm-project?rev=369395&view=rev" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project?rev=369395&view=rev</a><br>
> Log:<br>
> [CodeGen] Add a pass to do block predication on SSA machine IR.<br>
><br>
> For targets requiring aggressive scheduling and/or software pipeline we need to<br>
> apply predication before preRA scheduling. This adds a pass re-using the early<br>
> if-cvt infrastructure but generating predicated instructions instead of<br>
> speculatively executing instructions. It allows doing if conversion on blocks<br>
> containing instructions with side-effects. The pass re-use the target hook from<br>
> postRA if-conversion to let the target decide on the heuristic to apply.<br>
><br>
> Differential Revision: <a href="https://reviews.llvm.org/D66190" rel="noreferrer" target="_blank">https://reviews.llvm.org/D66190</a><br>
><br>
> Modified:<br>
> llvm/trunk/include/llvm/CodeGen/Passes.h<br>
> llvm/trunk/include/llvm/InitializePasses.h<br>
> llvm/trunk/lib/CodeGen/CodeGen.cpp<br>
> llvm/trunk/lib/CodeGen/EarlyIfConversion.cpp<br>
><br>
> Modified: llvm/trunk/include/llvm/CodeGen/Passes.h<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CodeGen/Passes.h?rev=369395&r1=369394&r2=369395&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CodeGen/Passes.h?rev=369395&r1=369394&r2=369395&view=diff</a><br>
> ==============================================================================<br>
> --- llvm/trunk/include/llvm/CodeGen/Passes.h (original)<br>
> +++ llvm/trunk/include/llvm/CodeGen/Passes.h Tue Aug 20 08:54:59 2019<br>
> @@ -226,6 +226,10 @@ namespace llvm {<br>
> /// inserting cmov instructions.<br>
> extern char &EarlyIfConverterID;<br>
><br>
> + /// EarlyIfPredicator - This pass performs if-conversion on SSA form by<br>
> + /// predicating if/else block and insert select at the join point.<br>
> + extern char &EarlyIfPredicatorID;<br>
> +<br>
> /// This pass performs instruction combining using trace metrics to estimate<br>
> /// critical-path and resource depth.<br>
> extern char &MachineCombinerID;<br>
><br>
> Modified: llvm/trunk/include/llvm/InitializePasses.h<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/InitializePasses.h?rev=369395&r1=369394&r2=369395&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/InitializePasses.h?rev=369395&r1=369394&r2=369395&view=diff</a><br>
> ==============================================================================<br>
> --- llvm/trunk/include/llvm/InitializePasses.h (original)<br>
> +++ llvm/trunk/include/llvm/InitializePasses.h Tue Aug 20 08:54:59 2019<br>
> @@ -132,6 +132,7 @@ void initializeDwarfEHPreparePass(PassRe<br>
> void initializeEarlyCSELegacyPassPass(PassRegistry&);<br>
> void initializeEarlyCSEMemSSALegacyPassPass(PassRegistry&);<br>
> void initializeEarlyIfConverterPass(PassRegistry&);<br>
> +void initializeEarlyIfPredicatorPass(PassRegistry &);<br>
> void initializeEarlyMachineLICMPass(PassRegistry&);<br>
> void initializeEarlyTailDuplicatePass(PassRegistry&);<br>
> void initializeEdgeBundlesPass(PassRegistry&);<br>
><br>
> Modified: llvm/trunk/lib/CodeGen/CodeGen.cpp<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/CodeGen.cpp?rev=369395&r1=369394&r2=369395&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/CodeGen.cpp?rev=369395&r1=369394&r2=369395&view=diff</a><br>
> ==============================================================================<br>
> --- llvm/trunk/lib/CodeGen/CodeGen.cpp (original)<br>
> +++ llvm/trunk/lib/CodeGen/CodeGen.cpp Tue Aug 20 08:54:59 2019<br>
> @@ -28,6 +28,7 @@ void llvm::initializeCodeGen(PassRegistr<br>
> initializeDetectDeadLanesPass(Registry);<br>
> initializeDwarfEHPreparePass(Registry);<br>
> initializeEarlyIfConverterPass(Registry);<br>
> + initializeEarlyIfPredicatorPass(Registry);<br>
> initializeEarlyMachineLICMPass(Registry);<br>
> initializeEarlyTailDuplicatePass(Registry);<br>
> initializeExpandMemCmpPassPass(Registry);<br>
><br>
> Modified: llvm/trunk/lib/CodeGen/EarlyIfConversion.cpp<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/EarlyIfConversion.cpp?rev=369395&r1=369394&r2=369395&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/EarlyIfConversion.cpp?rev=369395&r1=369394&r2=369395&view=diff</a><br>
> ==============================================================================<br>
> --- llvm/trunk/lib/CodeGen/EarlyIfConversion.cpp (original)<br>
> +++ llvm/trunk/lib/CodeGen/EarlyIfConversion.cpp Tue Aug 20 08:54:59 2019<br>
> @@ -25,6 +25,7 @@<br>
> #include "llvm/CodeGen/MachineDominators.h"<br>
> #include "llvm/CodeGen/MachineFunction.h"<br>
> #include "llvm/CodeGen/MachineFunctionPass.h"<br>
> +#include "llvm/CodeGen/MachineInstr.h"<br>
> #include "llvm/CodeGen/MachineLoopInfo.h"<br>
> #include "llvm/CodeGen/MachineRegisterInfo.h"<br>
> #include "llvm/CodeGen/MachineTraceMetrics.h"<br>
> @@ -140,6 +141,18 @@ private:<br>
> /// speculated.<br>
> bool canSpeculateInstrs(MachineBasicBlock *MBB);<br>
><br>
> + /// Return true if all non-terminator instructions in MBB can be safely<br>
> + /// predicated.<br>
> + bool canPredicateInstrs(MachineBasicBlock *MBB);<br>
> +<br>
> + /// Scan through instruction dependencies and update InsertAfter array.<br>
> + /// Return false if any dependency is incompatible with if conversion.<br>
> + bool InstrDependenciesAllowIfConv(MachineInstr *I);<br>
> +<br>
> + /// Predicate all instructions of the basic block with current condition<br>
> + /// except for terminators. Reverse the condition if ReversePredicate is set.<br>
> + void PredicateBlock(MachineBasicBlock *MBB, bool ReversePredicate);<br>
> +<br>
> /// Find a valid insertion point in Head.<br>
> bool findInsertionPoint();<br>
><br>
> @@ -163,11 +176,14 @@ public:<br>
><br>
> /// canConvertIf - If the sub-CFG headed by MBB can be if-converted,<br>
> /// initialize the internal state, and return true.<br>
> - bool canConvertIf(MachineBasicBlock *MBB);<br>
> + /// If predicate is set try to predicate the block otherwise try to<br>
> + /// speculatively execute it.<br>
> + bool canConvertIf(MachineBasicBlock *MBB, bool Predicate = false);<br>
><br>
> /// convertIf - If-convert the last block passed to canConvertIf(), assuming<br>
> /// it is possible. Add any erased blocks to RemovedBlocks.<br>
> - void convertIf(SmallVectorImpl<MachineBasicBlock*> &RemovedBlocks);<br>
> + void convertIf(SmallVectorImpl<MachineBasicBlock *> &RemovedBlocks,<br>
> + bool Predicate = false);<br>
> };<br>
> } // end anonymous namespace<br>
><br>
> @@ -225,37 +241,112 @@ bool SSAIfConv::canSpeculateInstrs(Machi<br>
> }<br>
><br>
> // Check for any dependencies on Head instructions.<br>
> - for (const MachineOperand &MO : I->operands()) {<br>
> - if (MO.isRegMask()) {<br>
> - LLVM_DEBUG(dbgs() << "Won't speculate regmask: " << *I);<br>
> - return false;<br>
> - }<br>
> - if (!MO.isReg())<br>
> - continue;<br>
> - Register Reg = MO.getReg();<br>
> + if (!InstrDependenciesAllowIfConv(&(*I)))<br>
> + return false;<br>
> + }<br>
> + return true;<br>
> +}<br>
><br>
> - // Remember clobbered regunits.<br>
> - if (MO.isDef() && Register::isPhysicalRegister(Reg))<br>
> - for (MCRegUnitIterator Units(Reg, TRI); Units.isValid(); ++Units)<br>
> - ClobberedRegUnits.set(*Units);<br>
> +/// Check that there is no dependencies preventing if conversion.<br>
> +///<br>
> +/// If instruction uses any values that are defined in the head basic block,<br>
> +/// the defining instructions are added to InsertAfter.<br>
> +bool SSAIfConv::InstrDependenciesAllowIfConv(MachineInstr *I) {<br>
> + for (const MachineOperand &MO : I->operands()) {<br>
> + if (MO.isRegMask()) {<br>
> + LLVM_DEBUG(dbgs() << "Won't speculate regmask: " << *I);<br>
> + return false;<br>
> + }<br>
> + if (!MO.isReg())<br>
> + continue;<br>
> + Register Reg = MO.getReg();<br>
><br>
> - if (!MO.readsReg() || !Register::isVirtualRegister(Reg))<br>
> - continue;<br>
> - MachineInstr *DefMI = MRI->getVRegDef(Reg);<br>
> - if (!DefMI || DefMI->getParent() != Head)<br>
> - continue;<br>
> - if (InsertAfter.insert(DefMI).second)<br>
> - LLVM_DEBUG(dbgs() << printMBBReference(*MBB) << " depends on "<br>
> - << *DefMI);<br>
> - if (DefMI->isTerminator()) {<br>
> - LLVM_DEBUG(dbgs() << "Can't insert instructions below terminator.\n");<br>
> - return false;<br>
> - }<br>
> + // Remember clobbered regunits.<br>
> + if (MO.isDef() && Register::isPhysicalRegister(Reg))<br>
> + for (MCRegUnitIterator Units(Reg, TRI); Units.isValid(); ++Units)<br>
> + ClobberedRegUnits.set(*Units);<br>
> +<br>
> + if (!MO.readsReg() || !Register::isVirtualRegister(Reg))<br>
> + continue;<br>
> + MachineInstr *DefMI = MRI->getVRegDef(Reg);<br>
> + if (!DefMI || DefMI->getParent() != Head)<br>
> + continue;<br>
> + if (InsertAfter.insert(DefMI).second)<br>
> + LLVM_DEBUG(dbgs() << printMBBReference(*I->getParent()) << " depends on "<br>
> + << *DefMI);<br>
> + if (DefMI->isTerminator()) {<br>
> + LLVM_DEBUG(dbgs() << "Can't insert instructions below terminator.\n");<br>
> + return false;<br>
> + }<br>
> + }<br>
> + return true;<br>
> +}<br>
> +<br>
> +/// canPredicateInstrs - Returns true if all the instructions in MBB can safely<br>
> +/// be predicates. The terminators are not considered.<br>
> +///<br>
> +/// If instructions use any values that are defined in the head basic block,<br>
> +/// the defining instructions are added to InsertAfter.<br>
> +///<br>
> +/// Any clobbered regunits are added to ClobberedRegUnits.<br>
> +///<br>
> +bool SSAIfConv::canPredicateInstrs(MachineBasicBlock *MBB) {<br>
> + // Reject any live-in physregs. It's probably CPSR/EFLAGS, and very hard to<br>
> + // get right.<br>
> + if (!MBB->livein_empty()) {<br>
> + LLVM_DEBUG(dbgs() << printMBBReference(*MBB) << " has live-ins.\n");<br>
> + return false;<br>
> + }<br>
> +<br>
> + unsigned InstrCount = 0;<br>
> +<br>
> + // Check all instructions, except the terminators. It is assumed that<br>
> + // terminators never have side effects or define any used register values.<br>
> + for (MachineBasicBlock::iterator I = MBB->begin(),<br>
> + E = MBB->getFirstTerminator();<br>
> + I != E; ++I) {<br>
> + if (I->isDebugInstr())<br>
> + continue;<br>
> +<br>
> + if (++InstrCount > BlockInstrLimit && !Stress) {<br>
> + LLVM_DEBUG(dbgs() << printMBBReference(*MBB) << " has more than "<br>
> + << BlockInstrLimit << " instructions.\n");<br>
> + return false;<br>
> }<br>
> +<br>
> + // There shouldn't normally be any phis in a single-predecessor block.<br>
> + if (I->isPHI()) {<br>
> + LLVM_DEBUG(dbgs() << "Can't predicate: " << *I);<br>
> + return false;<br>
> + }<br>
> +<br>
> + // Check that instruction is predicable and that it is not already<br>
> + // predicated.<br>
> + if (!TII->isPredicable(*I) || TII->isPredicated(*I)) {<br>
> + return false;<br>
> + }<br>
> +<br>
> + // Check for any dependencies on Head instructions.<br>
> + if (!InstrDependenciesAllowIfConv(&(*I)))<br>
> + return false;<br>
> }<br>
> return true;<br>
> }<br>
><br>
> +// Apply predicate to all instructions in the machine block.<br>
> +void SSAIfConv::PredicateBlock(MachineBasicBlock *MBB, bool ReversePredicate) {<br>
> + auto Condition = Cond;<br>
> + if (ReversePredicate)<br>
> + TII->reverseBranchCondition(Condition);<br>
> + // Terminators don't need to be predicated as they will be removed.<br>
> + for (MachineBasicBlock::iterator I = MBB->begin(),<br>
> + E = MBB->getFirstTerminator();<br>
> + I != E; ++I) {<br>
> + if (I->isDebugInstr())<br>
> + continue;<br>
> + TII->PredicateInstruction(*I, Condition);<br>
> + }<br>
> +}<br>
><br>
> /// Find an insertion point in Head for the speculated instructions. The<br>
> /// insertion point must be:<br>
> @@ -337,7 +428,7 @@ bool SSAIfConv::findInsertionPoint() {<br>
> /// canConvertIf - analyze the sub-cfg rooted in MBB, and return true if it is<br>
> /// a potential candidate for if-conversion. Fill out the internal state.<br>
> ///<br>
> -bool SSAIfConv::canConvertIf(MachineBasicBlock *MBB) {<br>
> +bool SSAIfConv::canConvertIf(MachineBasicBlock *MBB, bool Predicate) {<br>
> Head = MBB;<br>
> TBB = FBB = Tail = nullptr;<br>
><br>
> @@ -378,8 +469,9 @@ bool SSAIfConv::canConvertIf(MachineBasi<br>
> }<br>
><br>
> // This is a triangle or a diamond.<br>
> - // If Tail doesn't have any phis, there must be side effects.<br>
> - if (Tail->empty() || !Tail->front().isPHI()) {<br>
> + // Skip if we cannot predicate and there are no phis skip as there must be<br>
> + // side effects that can only be handled with predication.<br>
> + if (!Predicate && (Tail->empty() || !Tail->front().isPHI())) {<br>
> LLVM_DEBUG(dbgs() << "No phis in tail.\n");<br>
> return false;<br>
> }<br>
> @@ -437,10 +529,17 @@ bool SSAIfConv::canConvertIf(MachineBasi<br>
> // Check that the conditional instructions can be speculated.<br>
> InsertAfter.clear();<br>
> ClobberedRegUnits.reset();<br>
> - if (TBB != Tail && !canSpeculateInstrs(TBB))<br>
> - return false;<br>
> - if (FBB != Tail && !canSpeculateInstrs(FBB))<br>
> - return false;<br>
> + if (Predicate) {<br>
> + if (TBB != Tail && !canPredicateInstrs(TBB))<br>
> + return false;<br>
> + if (FBB != Tail && !canPredicateInstrs(FBB))<br>
> + return false;<br>
> + } else {<br>
> + if (TBB != Tail && !canSpeculateInstrs(TBB))<br>
> + return false;<br>
> + if (FBB != Tail && !canSpeculateInstrs(FBB))<br>
> + return false;<br>
> + }<br>
><br>
> // Try to find a valid insertion point for the speculated instructions in the<br>
> // head basic block.<br>
> @@ -521,7 +620,8 @@ void SSAIfConv::rewritePHIOperands() {<br>
> ///<br>
> /// Any basic blocks erased will be added to RemovedBlocks.<br>
> ///<br>
> -void SSAIfConv::convertIf(SmallVectorImpl<MachineBasicBlock*> &RemovedBlocks) {<br>
> +void SSAIfConv::convertIf(SmallVectorImpl<MachineBasicBlock *> &RemovedBlocks,<br>
> + bool Predicate) {<br>
> assert(Head && Tail && TBB && FBB && "Call canConvertIf first.");<br>
><br>
> // Update statistics.<br>
> @@ -531,11 +631,16 @@ void SSAIfConv::convertIf(SmallVectorImp<br>
> ++NumDiamondsConv;<br>
><br>
> // Move all instructions into Head, except for the terminators.<br>
> - if (TBB != Tail)<br>
> + if (TBB != Tail) {<br>
> + if (Predicate)<br>
> + PredicateBlock(TBB, /*ReversePredicate=*/false);<br>
> Head->splice(InsertionPoint, TBB, TBB->begin(), TBB->getFirstTerminator());<br>
> - if (FBB != Tail)<br>
> + }<br>
> + if (FBB != Tail) {<br>
> + if (Predicate)<br>
> + PredicateBlock(FBB, /*ReversePredicate=*/true);<br>
> Head->splice(InsertionPoint, FBB, FBB->begin(), FBB->getFirstTerminator());<br>
> -<br>
> + }<br>
> // Are there extra Tail predecessors?<br>
> bool ExtraPreds = Tail->pred_size() != 2;<br>
> if (ExtraPreds)<br>
> @@ -587,7 +692,6 @@ void SSAIfConv::convertIf(SmallVectorImp<br>
> LLVM_DEBUG(dbgs() << *Head);<br>
> }<br>
><br>
> -<br>
> //===----------------------------------------------------------------------===//<br>
> // EarlyIfConverter Pass<br>
> //===----------------------------------------------------------------------===//<br>
> @@ -613,8 +717,6 @@ public:<br>
><br>
> private:<br>
> bool tryConvertIf(MachineBasicBlock*);<br>
> - void updateDomTree(ArrayRef<MachineBasicBlock*> Removed);<br>
> - void updateLoops(ArrayRef<MachineBasicBlock*> Removed);<br>
> void invalidateTraces();<br>
> bool shouldConvertIf();<br>
> };<br>
> @@ -642,32 +744,36 @@ void EarlyIfConverter::getAnalysisUsage(<br>
> MachineFunctionPass::getAnalysisUsage(AU);<br>
> }<br>
><br>
> +namespace {<br>
> /// Update the dominator tree after if-conversion erased some blocks.<br>
> -void EarlyIfConverter::updateDomTree(ArrayRef<MachineBasicBlock*> Removed) {<br>
> +void updateDomTree(MachineDominatorTree *DomTree, const SSAIfConv &IfConv,<br>
> + ArrayRef<MachineBasicBlock *> Removed) {<br>
> // convertIf can remove TBB, FBB, and Tail can be merged into Head.<br>
> // TBB and FBB should not dominate any blocks.<br>
> // Tail children should be transferred to Head.<br>
> MachineDomTreeNode *HeadNode = DomTree->getNode(IfConv.Head);<br>
> - for (unsigned i = 0, e = Removed.size(); i != e; ++i) {<br>
> - MachineDomTreeNode *Node = DomTree->getNode(Removed[i]);<br>
> + for (auto B : Removed) {<br>
> + MachineDomTreeNode *Node = DomTree->getNode(B);<br>
> assert(Node != HeadNode && "Cannot erase the head node");<br>
> while (Node->getNumChildren()) {<br>
> assert(Node->getBlock() == IfConv.Tail && "Unexpected children");<br>
> DomTree->changeImmediateDominator(Node->getChildren().back(), HeadNode);<br>
> }<br>
> - DomTree->eraseNode(Removed[i]);<br>
> + DomTree->eraseNode(B);<br>
> }<br>
> }<br>
><br>
> /// Update LoopInfo after if-conversion.<br>
> -void EarlyIfConverter::updateLoops(ArrayRef<MachineBasicBlock*> Removed) {<br>
> +void updateLoops(MachineLoopInfo *Loops,<br>
> + ArrayRef<MachineBasicBlock *> Removed) {<br>
> if (!Loops)<br>
> return;<br>
> // If-conversion doesn't change loop structure, and it doesn't mess with back<br>
> // edges, so updating LoopInfo is simply removing the dead blocks.<br>
> - for (unsigned i = 0, e = Removed.size(); i != e; ++i)<br>
> - Loops->removeBlock(Removed[i]);<br>
> + for (auto B : Removed)<br>
> + Loops->removeBlock(B);<br>
> }<br>
> +} // namespace<br>
><br>
> /// Invalidate MachineTraceMetrics before if-conversion.<br>
> void EarlyIfConverter::invalidateTraces() {<br>
> @@ -783,8 +889,8 @@ bool EarlyIfConverter::tryConvertIf(Mach<br>
> SmallVector<MachineBasicBlock*, 4> RemovedBlocks;<br>
> IfConv.convertIf(RemovedBlocks);<br>
> Changed = true;<br>
> - updateDomTree(RemovedBlocks);<br>
> - updateLoops(RemovedBlocks);<br>
> + updateDomTree(DomTree, IfConv, RemovedBlocks);<br>
> + updateLoops(Loops, RemovedBlocks);<br>
> }<br>
> return Changed;<br>
> }<br>
> @@ -811,6 +917,135 @@ bool EarlyIfConverter::runOnMachineFunct<br>
><br>
> bool Changed = false;<br>
> IfConv.runOnMachineFunction(MF);<br>
> +<br>
> + // Visit blocks in dominator tree post-order. The post-order enables nested<br>
> + // if-conversion in a single pass. The tryConvertIf() function may erase<br>
> + // blocks, but only blocks dominated by the head block. This makes it safe to<br>
> + // update the dominator tree while the post-order iterator is still active.<br>
> + for (auto DomNode : post_order(DomTree))<br>
> + if (tryConvertIf(DomNode->getBlock()))<br>
> + Changed = true;<br>
> +<br>
> + return Changed;<br>
> +}<br>
> +<br>
> +//===----------------------------------------------------------------------===//<br>
> +// EarlyIfPredicator Pass<br>
> +//===----------------------------------------------------------------------===//<br>
> +<br>
> +namespace {<br>
> +class EarlyIfPredicator : public MachineFunctionPass {<br>
> + const TargetInstrInfo *TII;<br>
> + const TargetRegisterInfo *TRI;<br>
> + TargetSchedModel SchedModel;<br>
> + MachineRegisterInfo *MRI;<br>
> + MachineDominatorTree *DomTree;<br>
> + MachineLoopInfo *Loops;<br>
> + SSAIfConv IfConv;<br>
> +<br>
> +public:<br>
> + static char ID;<br>
> + EarlyIfPredicator() : MachineFunctionPass(ID) {}<br>
> + void getAnalysisUsage(AnalysisUsage &AU) const override;<br>
> + bool runOnMachineFunction(MachineFunction &MF) override;<br>
> + StringRef getPassName() const override { return "Early If-predicator"; }<br>
> +<br>
> +protected:<br>
> + bool tryConvertIf(MachineBasicBlock *);<br>
> + bool shouldConvertIf();<br>
> +};<br>
> +} // end anonymous namespace<br>
> +<br>
> +#undef DEBUG_TYPE<br>
> +#define DEBUG_TYPE "early-if-predicator"<br>
> +<br>
> +char EarlyIfPredicator::ID = 0;<br>
> +char &llvm::EarlyIfPredicatorID = EarlyIfPredicator::ID;<br>
> +<br>
> +INITIALIZE_PASS_BEGIN(EarlyIfPredicator, DEBUG_TYPE, "Early If Predicator",<br>
> + false, false)<br>
> +INITIALIZE_PASS_DEPENDENCY(MachineDominatorTree)<br>
> +INITIALIZE_PASS_END(EarlyIfPredicator, DEBUG_TYPE, "Early If Predicator", false,<br>
> + false)<br>
> +<br>
> +void EarlyIfPredicator::getAnalysisUsage(AnalysisUsage &AU) const {<br>
> + AU.addRequired<MachineDominatorTree>();<br>
> + AU.addPreserved<MachineDominatorTree>();<br>
> + AU.addRequired<MachineLoopInfo>();<br>
> + AU.addPreserved<MachineLoopInfo>();<br>
> + MachineFunctionPass::getAnalysisUsage(AU);<br>
> +}<br>
> +<br>
> +/// Apply the target heuristic to decide if the transformation is profitable.<br>
> +bool EarlyIfPredicator::shouldConvertIf() {<br>
> + if (IfConv.isTriangle()) {<br>
> + MachineBasicBlock &IfBlock =<br>
> + (IfConv.TBB == IfConv.Tail) ? *IfConv.FBB : *IfConv.TBB;<br>
> +<br>
> + unsigned ExtraPredCost = 0;<br>
> + unsigned Cycles = 0;<br>
> + for (MachineInstr &I : IfBlock) {<br>
> + unsigned NumCycles = SchedModel.computeInstrLatency(&I, false);<br>
> + if (NumCycles > 1)<br>
> + Cycles += NumCycles - 1;<br>
> + ExtraPredCost += TII->getPredicationCost(I);<br>
> + }<br>
> +<br>
> + return TII->isProfitableToIfCvt(IfBlock, Cycles, ExtraPredCost,<br>
> + BranchProbability::getUnknown());<br>
> + }<br>
> + unsigned TExtra = 0;<br>
> + unsigned FExtra = 0;<br>
> + unsigned TCycle = 0;<br>
> + unsigned FCycle = 0;<br>
> + for (MachineInstr &I : *IfConv.TBB) {<br>
> + unsigned NumCycles = SchedModel.computeInstrLatency(&I, false);<br>
> + if (NumCycles > 1)<br>
> + TCycle += NumCycles - 1;<br>
> + TExtra += TII->getPredicationCost(I);<br>
> + }<br>
> + for (MachineInstr &I : *IfConv.FBB) {<br>
> + unsigned NumCycles = SchedModel.computeInstrLatency(&I, false);<br>
> + if (NumCycles > 1)<br>
> + FCycle += NumCycles - 1;<br>
> + FExtra += TII->getPredicationCost(I);<br>
> + }<br>
> + return TII->isProfitableToIfCvt(*IfConv.TBB, TCycle, TExtra, *IfConv.FBB,<br>
> + FCycle, FExtra,<br>
> + BranchProbability::getUnknown());<br>
> +}<br>
> +<br>
> +/// Attempt repeated if-conversion on MBB, return true if successful.<br>
> +///<br>
> +bool EarlyIfPredicator::tryConvertIf(MachineBasicBlock *MBB) {<br>
> + bool Changed = false;<br>
> + while (IfConv.canConvertIf(MBB, /*Predicate*/ true) && shouldConvertIf()) {<br>
> + // If-convert MBB and update analyses.<br>
> + SmallVector<MachineBasicBlock *, 4> RemovedBlocks;<br>
> + IfConv.convertIf(RemovedBlocks, /*Predicate*/ true);<br>
> + Changed = true;<br>
> + updateDomTree(DomTree, IfConv, RemovedBlocks);<br>
> + updateLoops(Loops, RemovedBlocks);<br>
> + }<br>
> + return Changed;<br>
> +}<br>
> +<br>
> +bool EarlyIfPredicator::runOnMachineFunction(MachineFunction &MF) {<br>
> + LLVM_DEBUG(dbgs() << "********** EARLY IF-PREDICATOR **********\n"<br>
> + << "********** Function: " << MF.getName() << '\n');<br>
> + if (skipFunction(MF.getFunction()))<br>
> + return false;<br>
> +<br>
> + const TargetSubtargetInfo &STI = MF.getSubtarget();<br>
> + TII = STI.getInstrInfo();<br>
> + TRI = STI.getRegisterInfo();<br>
> + MRI = &MF.getRegInfo();<br>
> + SchedModel.init(&STI);<br>
> + DomTree = &getAnalysis<MachineDominatorTree>();<br>
> + Loops = getAnalysisIfAvailable<MachineLoopInfo>();<br>
> +<br>
> + bool Changed = false;<br>
> + IfConv.runOnMachineFunction(MF);<br>
><br>
> // Visit blocks in dominator tree post-order. The post-order enables nested<br>
> // if-conversion in a single pass. The tryConvertIf() function may erase<br>
><br>
><br>
> _______________________________________________<br>
> llvm-commits mailing list<br>
> <a href="mailto:llvm-commits@lists.llvm.org" target="_blank">llvm-commits@lists.llvm.org</a><br>
> <a href="https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits" rel="noreferrer" target="_blank">https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits</a><br>
</blockquote></div>