[llvm] [NFC][EarlyIfConverter] Replace boolean Preadicate for a class (PR #108519)

via llvm-commits llvm-commits at lists.llvm.org
Fri Sep 13 01:59:42 PDT 2024


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-backend-x86

Author: Juan Manuel Martinez CaamaƱo (jmmartinez)

<details>
<summary>Changes</summary>

Currently SSAIfConv is used in 2 scenarios. Generalize them to support more scenarios.

---
Full diff: https://github.com/llvm/llvm-project/pull/108519.diff


1 Files Affected:

- (modified) llvm/lib/CodeGen/EarlyIfConversion.cpp (+117-137) 


``````````diff
diff --git a/llvm/lib/CodeGen/EarlyIfConversion.cpp b/llvm/lib/CodeGen/EarlyIfConversion.cpp
index 99ffc01ca4ebb9..ae3b367b09308a 100644
--- a/llvm/lib/CodeGen/EarlyIfConversion.cpp
+++ b/llvm/lib/CodeGen/EarlyIfConversion.cpp
@@ -122,6 +122,17 @@ class SSAIfConv {
   /// The branch condition determined by analyzeBranch.
   SmallVector<MachineOperand, 4> Cond;
 
+  struct PredicationStrategyBase {
+    virtual bool canConvertIf(MachineBasicBlock *Tail) { return true; }
+    virtual bool canPredicateInstr(const MachineInstr &I) = 0;
+    virtual void predicateBlock(MachineBasicBlock *MBB,
+                                ArrayRef<MachineOperand> Cond,
+                                bool Reverse) = 0;
+    virtual ~PredicationStrategyBase() = default;
+  };
+
+  PredicationStrategyBase &Predicate;
+
 private:
   /// Instructions in Head that define values used by the conditional blocks.
   /// The hoisted instructions must be inserted after these instructions.
@@ -137,10 +148,6 @@ class SSAIfConv {
   /// and FBB.
   MachineBasicBlock::iterator InsertionPoint;
 
-  /// Return true if all non-terminator instructions in MBB can be safely
-  /// speculated.
-  bool canSpeculateInstrs(MachineBasicBlock *MBB);
-
   /// Return true if all non-terminator instructions in MBB can be safely
   /// predicated.
   bool canPredicateInstrs(MachineBasicBlock *MBB);
@@ -149,10 +156,6 @@ class SSAIfConv {
   /// Return false if any dependency is incompatible with if conversion.
   bool InstrDependenciesAllowIfConv(MachineInstr *I);
 
-  /// Predicate all instructions of the basic block with current condition
-  /// except for terminators. Reverse the condition if ReversePredicate is set.
-  void PredicateBlock(MachineBasicBlock *MBB, bool ReversePredicate);
-
   /// Find a valid insertion point in Head.
   bool findInsertionPoint();
 
@@ -163,7 +166,8 @@ class SSAIfConv {
   void rewritePHIOperands();
 
 public:
-  SSAIfConv(MachineFunction &MF) {
+  SSAIfConv(PredicationStrategyBase &Predicate, MachineFunction &MF)
+      : Predicate(Predicate) {
     TII = MF.getSubtarget().getInstrInfo();
     TRI = MF.getSubtarget().getRegisterInfo();
     MRI = &MF.getRegInfo();
@@ -175,77 +179,14 @@ class SSAIfConv {
 
   /// canConvertIf - If the sub-CFG headed by MBB can be if-converted,
   /// initialize the internal state, and return true.
-  /// If predicate is set try to predicate the block otherwise try to
-  /// speculatively execute it.
-  bool canConvertIf(MachineBasicBlock *MBB, bool Predicate = false);
+  bool canConvertIf(MachineBasicBlock *MBB);
 
   /// convertIf - If-convert the last block passed to canConvertIf(), assuming
   /// it is possible. Add any blocks that are to be erased to RemoveBlocks.
-  void convertIf(SmallVectorImpl<MachineBasicBlock *> &RemoveBlocks,
-                 bool Predicate = false);
+  void convertIf(SmallVectorImpl<MachineBasicBlock *> &RemoveBlocks);
 };
 } // 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) {
-  // Reject any live-in physregs. It's probably CPSR/EFLAGS, and very hard to
-  // get right.
-  if (!MBB->livein_empty()) {
-    LLVM_DEBUG(dbgs() << printMBBReference(*MBB) << " has live-ins.\n");
-    return false;
-  }
-
-  unsigned InstrCount = 0;
-
-  // Check all instructions, except the terminators. It is assumed that
-  // terminators never have side effects or define any used register values.
-  for (MachineInstr &MI :
-       llvm::make_range(MBB->begin(), MBB->getFirstTerminator())) {
-    if (MI.isDebugInstr())
-      continue;
-
-    if (++InstrCount > BlockInstrLimit && !Stress) {
-      LLVM_DEBUG(dbgs() << printMBBReference(*MBB) << " has more than "
-                        << BlockInstrLimit << " instructions.\n");
-      return false;
-    }
-
-    // There shouldn't normally be any phis in a single-predecessor block.
-    if (MI.isPHI()) {
-      LLVM_DEBUG(dbgs() << "Can't hoist: " << MI);
-      return false;
-    }
-
-    // Don't speculate loads. Note that it may be possible and desirable to
-    // speculate GOT or constant pool loads that are guaranteed not to trap,
-    // but we don't support that for now.
-    if (MI.mayLoad()) {
-      LLVM_DEBUG(dbgs() << "Won't speculate load: " << MI);
-      return false;
-    }
-
-    // We never speculate stores, so an AA pointer isn't necessary.
-    bool DontMoveAcrossStore = true;
-    if (!MI.isSafeToMove(DontMoveAcrossStore)) {
-      LLVM_DEBUG(dbgs() << "Can't speculate: " << MI);
-      return false;
-    }
-
-    // Check for any dependencies on Head instructions.
-    if (!InstrDependenciesAllowIfConv(&MI))
-      return false;
-  }
-  return true;
-}
-
 /// Check that there is no dependencies preventing if conversion.
 ///
 /// If instruction uses any values that are defined in the head basic block,
@@ -319,17 +260,8 @@ bool SSAIfConv::canPredicateInstrs(MachineBasicBlock *MBB) {
       return false;
     }
 
-    // Check that instruction is predicable
-    if (!TII->isPredicable(*I)) {
-      LLVM_DEBUG(dbgs() << "Isn't predicable: " << *I);
-      return false;
-    }
-
-    // Check that instruction is not already predicated.
-    if (TII->isPredicated(*I) && !TII->canPredicatePredicatedInstr(*I)) {
-      LLVM_DEBUG(dbgs() << "Is already predicated: " << *I);
+    if (!Predicate.canPredicateInstr(*I))
       return false;
-    }
 
     // Check for any dependencies on Head instructions.
     if (!InstrDependenciesAllowIfConv(&(*I)))
@@ -338,24 +270,6 @@ bool SSAIfConv::canPredicateInstrs(MachineBasicBlock *MBB) {
   return true;
 }
 
-// Apply predicate to all instructions in the machine block.
-void SSAIfConv::PredicateBlock(MachineBasicBlock *MBB, bool ReversePredicate) {
-  auto Condition = Cond;
-  if (ReversePredicate) {
-    bool CanRevCond = !TII->reverseBranchCondition(Condition);
-    assert(CanRevCond && "Reversed predicate is not supported");
-    (void)CanRevCond;
-  }
-  // Terminators don't need to be predicated as they will be removed.
-  for (MachineBasicBlock::iterator I = MBB->begin(),
-                                   E = MBB->getFirstTerminator();
-       I != E; ++I) {
-    if (I->isDebugInstr())
-      continue;
-    TII->PredicateInstruction(*I, Condition);
-  }
-}
-
 /// Find an insertion point in Head for the speculated instructions. The
 /// insertion point must be:
 ///
@@ -434,7 +348,7 @@ 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) {
+bool SSAIfConv::canConvertIf(MachineBasicBlock *MBB) {
   Head = MBB;
   TBB = FBB = Tail = nullptr;
 
@@ -474,14 +388,6 @@ bool SSAIfConv::canConvertIf(MachineBasicBlock *MBB, bool Predicate) {
                       << printMBBReference(*Tail) << '\n');
   }
 
-  // This is a triangle or a diamond.
-  // Skip if we cannot predicate and there are no phis skip as there must be
-  // side effects that can only be handled with predication.
-  if (!Predicate && (Tail->empty() || !Tail->front().isPHI())) {
-    LLVM_DEBUG(dbgs() << "No phis in tail.\n");
-    return false;
-  }
-
   // The branch we're looking to eliminate must be analyzable.
   Cond.clear();
   if (TII->analyzeBranch(*Head, TBB, FBB, Cond)) {
@@ -489,6 +395,10 @@ bool SSAIfConv::canConvertIf(MachineBasicBlock *MBB, bool Predicate) {
     return false;
   }
 
+  if (!Predicate.canConvertIf(Tail)) {
+    return false;
+  }
+
   // This is weird, probably some sort of degenerate CFG.
   if (!TBB) {
     LLVM_DEBUG(dbgs() << "analyzeBranch didn't find conditional branch.\n");
@@ -536,17 +446,9 @@ bool SSAIfConv::canConvertIf(MachineBasicBlock *MBB, bool Predicate) {
   // Check that the conditional instructions can be speculated.
   InsertAfter.clear();
   ClobberedRegUnits.reset();
-  if (Predicate) {
-    if (TBB != Tail && !canPredicateInstrs(TBB))
-      return false;
-    if (FBB != Tail && !canPredicateInstrs(FBB))
-      return false;
-  } else {
-    if (TBB != Tail && !canSpeculateInstrs(TBB))
-      return false;
-    if (FBB != Tail && !canSpeculateInstrs(FBB))
+  for (MachineBasicBlock *MBB : {TBB, FBB})
+    if (MBB != Tail && !canPredicateInstrs(MBB))
       return false;
-  }
 
   // Try to find a valid insertion point for the speculated instructions in the
   // head basic block.
@@ -679,8 +581,7 @@ void SSAIfConv::rewritePHIOperands() {
 ///
 /// Any basic blocks that need to be erased will be added to RemoveBlocks.
 ///
-void SSAIfConv::convertIf(SmallVectorImpl<MachineBasicBlock *> &RemoveBlocks,
-                          bool Predicate) {
+void SSAIfConv::convertIf(SmallVectorImpl<MachineBasicBlock *> &RemoveBlocks) {
   assert(Head && Tail && TBB && FBB && "Call canConvertIf first.");
 
   // Update statistics.
@@ -690,16 +591,15 @@ void SSAIfConv::convertIf(SmallVectorImpl<MachineBasicBlock *> &RemoveBlocks,
     ++NumDiamondsConv;
 
   // Move all instructions into Head, except for the terminators.
-  if (TBB != Tail) {
-    if (Predicate)
-      PredicateBlock(TBB, /*ReversePredicate=*/false);
-    Head->splice(InsertionPoint, TBB, TBB->begin(), TBB->getFirstTerminator());
-  }
-  if (FBB != Tail) {
-    if (Predicate)
-      PredicateBlock(FBB, /*ReversePredicate=*/true);
-    Head->splice(InsertionPoint, FBB, FBB->begin(), FBB->getFirstTerminator());
+  for (MachineBasicBlock *MBB : {TBB, FBB}) {
+    if (MBB != Tail) {
+      // reverse the condition for the false bb
+      Predicate.predicateBlock(MBB, Cond, MBB == FBB);
+      Head->splice(InsertionPoint, MBB, MBB->begin(),
+                   MBB->getFirstTerminator());
+    }
   }
+
   // Are there extra Tail predecessors?
   bool ExtraPreds = Tail->pred_size() != 2;
   if (ExtraPreds)
@@ -863,6 +763,45 @@ template <typename Remark> Remark &operator<<(Remark &R, Cycles C) {
 }
 } // anonymous namespace
 
+struct SpeculateStrategy : SSAIfConv::PredicationStrategyBase {
+  bool canConvertIf(MachineBasicBlock *Tail) override {
+    // This is a triangle or a diamond.
+    // Skip if we cannot predicate and there are no phis skip as there must
+    // be side effects that can only be handled with predication.
+    if (Tail->empty() || !Tail->front().isPHI()) {
+      LLVM_DEBUG(dbgs() << "No phis in tail.\n");
+      return false;
+    }
+    return true;
+  }
+
+  bool canPredicateInstr(const MachineInstr &I) override {
+    // Don't speculate loads. Note that it may be possible and desirable to
+    // speculate GOT or constant pool loads that are guaranteed not to trap,
+    // but we don't support that for now.
+    if (I.mayLoad()) {
+      LLVM_DEBUG(dbgs() << "Won't speculate load: " << I);
+      return false;
+    }
+
+    // We never speculate stores, so an AA pointer isn't necessary.
+    bool DontMoveAcrossStore = true;
+    if (!I.isSafeToMove(DontMoveAcrossStore)) {
+      LLVM_DEBUG(dbgs() << "Can't speculate: " << I);
+      return false;
+    }
+    return true;
+  }
+
+  void predicateBlock(MachineBasicBlock *MBB, ArrayRef<MachineOperand> Cond,
+                      bool Reverse)
+      override { /* do nothing, everything is speculatable and it's valid to
+                    move the instructions into the head */
+  }
+
+  ~SpeculateStrategy() override = default;
+};
+
 /// Apply cost model and heuristics to the if-conversion in IfConv.
 /// Return true if the conversion is a good idea.
 ///
@@ -1096,7 +1035,8 @@ bool EarlyIfConverter::runOnMachineFunction(MachineFunction &MF) {
   MinInstr = nullptr;
 
   bool Changed = false;
-  SSAIfConv IfConv(MF);
+  SpeculateStrategy Speculate;
+  SSAIfConv IfConv(Speculate, MF);
 
   // Visit blocks in dominator tree post-order. The post-order enables nested
   // if-conversion in a single pass. The tryConvertIf() function may erase
@@ -1158,6 +1098,46 @@ void EarlyIfPredicator::getAnalysisUsage(AnalysisUsage &AU) const {
   MachineFunctionPass::getAnalysisUsage(AU);
 }
 
+struct PredicatorStrategy : SSAIfConv::PredicationStrategyBase {
+  const TargetInstrInfo *TII = nullptr;
+  PredicatorStrategy(const TargetInstrInfo *TII) : TII(TII) {}
+
+  bool canPredicateInstr(const MachineInstr &I) override {
+    // Check that instruction is predicable
+    if (!TII->isPredicable(I)) {
+      LLVM_DEBUG(dbgs() << "Isn't predicable: " << I);
+      return false;
+    }
+
+    // Check that instruction is not already predicated.
+    if (TII->isPredicated(I) && !TII->canPredicatePredicatedInstr(I)) {
+      LLVM_DEBUG(dbgs() << "Is already predicated: " << I);
+      return false;
+    }
+    return true;
+  }
+
+  void predicateBlock(MachineBasicBlock *MBB, ArrayRef<MachineOperand> Cond,
+                      bool Reverse) override {
+    SmallVector<MachineOperand> Condition(Cond.begin(), Cond.end());
+    if (Reverse) {
+      bool CanRevCond = !TII->reverseBranchCondition(Condition);
+      assert(CanRevCond && "Reversed predicate is not supported");
+      (void)CanRevCond;
+    }
+    // Terminators don't need to be predicated as they will be removed.
+    for (MachineBasicBlock::iterator I = MBB->begin(),
+                                     E = MBB->getFirstTerminator();
+         I != E; ++I) {
+      if (I->isDebugInstr())
+        continue;
+      TII->PredicateInstruction(*I, Condition);
+    }
+  }
+
+  ~PredicatorStrategy() override = default;
+};
+
 /// Apply the target heuristic to decide if the transformation is profitable.
 bool EarlyIfPredicator::shouldConvertIf(SSAIfConv &IfConv) {
   auto TrueProbability = MBPI->getEdgeProbability(IfConv.Head, IfConv.TBB);
@@ -1202,11 +1182,10 @@ bool EarlyIfPredicator::shouldConvertIf(SSAIfConv &IfConv) {
 bool EarlyIfPredicator::tryConvertIf(SSAIfConv &IfConv,
                                      MachineBasicBlock *MBB) {
   bool Changed = false;
-  while (IfConv.canConvertIf(MBB, /*Predicate=*/true) &&
-         shouldConvertIf(IfConv)) {
+  while (IfConv.canConvertIf(MBB) && shouldConvertIf(IfConv)) {
     // If-convert MBB and update analyses.
     SmallVector<MachineBasicBlock *, 4> RemoveBlocks;
-    IfConv.convertIf(RemoveBlocks, /*Predicate=*/true);
+    IfConv.convertIf(RemoveBlocks);
     Changed = true;
     updateDomTree(DomTree, IfConv, RemoveBlocks);
     for (MachineBasicBlock *MBB : RemoveBlocks)
@@ -1232,7 +1211,8 @@ bool EarlyIfPredicator::runOnMachineFunction(MachineFunction &MF) {
   MBPI = &getAnalysis<MachineBranchProbabilityInfoWrapperPass>().getMBPI();
 
   bool Changed = false;
-  SSAIfConv IfConv(MF);
+  PredicatorStrategy Predicate(TII);
+  SSAIfConv IfConv(Predicate, MF);
 
   // Visit blocks in dominator tree post-order. The post-order enables nested
   // if-conversion in a single pass. The tryConvertIf() function may erase

``````````

</details>


https://github.com/llvm/llvm-project/pull/108519


More information about the llvm-commits mailing list