[llvm] 70e49d8 - [NFC][AArch64] Improve semantics of findSuitableCompare in ConditionOptimizer (#183532)

via llvm-commits llvm-commits at lists.llvm.org
Mon Mar 9 06:04:35 PDT 2026


Author: Hussam Alhassan
Date: 2026-03-09T13:04:31Z
New Revision: 70e49d87b0fe9b139e6976a48379810dc22ab567

URL: https://github.com/llvm/llvm-project/commit/70e49d87b0fe9b139e6976a48379810dc22ab567
DIFF: https://github.com/llvm/llvm-project/commit/70e49d87b0fe9b139e6976a48379810dc22ab567.diff

LOG: [NFC][AArch64] Improve semantics of findSuitableCompare in ConditionOptimizer (#183532)

Improve the semantics of the "findSuitableCompare" method and improve
logic sharing between the cross- and intra-block paths.

Add the "getBccTerminator" helper and rename the above function to
"findAdjustableCmp" which now takes a conditional instruction and
returns its controlling compare.

Added: 
    

Modified: 
    llvm/lib/Target/AArch64/AArch64ConditionOptimizer.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Target/AArch64/AArch64ConditionOptimizer.cpp b/llvm/lib/Target/AArch64/AArch64ConditionOptimizer.cpp
index 15e3657e8f549..ef86f1b431418 100644
--- a/llvm/lib/Target/AArch64/AArch64ConditionOptimizer.cpp
+++ b/llvm/lib/Target/AArch64/AArch64ConditionOptimizer.cpp
@@ -118,7 +118,8 @@ class AArch64ConditionOptimizer : public MachineFunctionPass {
   bool canAdjustCmp(MachineInstr &CmpMI);
   bool registersMatch(MachineInstr *FirstMI, MachineInstr *SecondMI);
   bool nzcvLivesOut(MachineBasicBlock *MBB);
-  MachineInstr *findSuitableCompare(MachineBasicBlock *MBB);
+  MachineInstr *getBccTerminator(MachineBasicBlock *MBB);
+  MachineInstr *findAdjustableCmp(MachineInstr *CondMI);
   CmpInfo adjustCmp(MachineInstr *CmpMI, AArch64CC::CondCode Cmp);
   void modifyCmp(MachineInstr *CmpMI, const CmpInfo &Info);
   bool adjustTo(MachineInstr *CmpMI, AArch64CC::CondCode Cmp, MachineInstr *To,
@@ -220,28 +221,43 @@ static bool isCSINCInstruction(unsigned Opc) {
   return Opc == AArch64::CSINCWr || Opc == AArch64::CSINCXr;
 }
 
-// Finds compare instruction that corresponds to supported types of branching.
-// Returns the instruction or nullptr on failures or detecting unsupported
-// instructions.
-MachineInstr *AArch64ConditionOptimizer::findSuitableCompare(
-    MachineBasicBlock *MBB) {
+// Returns the Bcc terminator if present, otherwise nullptr.
+MachineInstr *
+AArch64ConditionOptimizer::getBccTerminator(MachineBasicBlock *MBB) {
   MachineBasicBlock::iterator Term = MBB->getFirstTerminator();
-  if (Term == MBB->end())
+  if (Term == MBB->end()) {
+    LLVM_DEBUG(dbgs() << "No terminator in " << printMBBReference(*MBB)
+                      << '\n');
     return nullptr;
+  }
 
-  if (Term->getOpcode() != AArch64::Bcc)
+  if (Term->getOpcode() != AArch64::Bcc) {
+    LLVM_DEBUG(dbgs() << "Non-Bcc terminator in " << printMBBReference(*MBB)
+                      << ": " << *Term);
     return nullptr;
+  }
 
-  // Since we may modify cmp of this MBB, make sure NZCV does not live out.
-  if (nzcvLivesOut(MBB))
-    return nullptr;
+  return &*Term;
+}
 
-  // Now find the instruction controlling the terminator.
-  for (MachineBasicBlock::iterator B = MBB->begin(), It = Term; It != B;) {
+// Find the CMP instruction controlling the given conditional instruction and
+// ensure it can be adjusted for CSE optimization. Searches backward from
+// CondMI, ensuring no NZCV interference. Returns nullptr if no suitable CMP
+// is found or if adjustments are not safe.
+MachineInstr *
+AArch64ConditionOptimizer::findAdjustableCmp(MachineInstr *CondMI) {
+  assert(CondMI && "CondMI cannot be null");
+  MachineBasicBlock *MBB = CondMI->getParent();
+
+  // Search backward from the conditional to find the instruction controlling
+  // it.
+  for (MachineBasicBlock::iterator B = MBB->begin(),
+                                   It = MachineBasicBlock::iterator(CondMI);
+       It != B;) {
     It = prev_nodbg(It, B);
     MachineInstr &I = *It;
     assert(!I.isTerminator() && "Spurious terminator");
-    // Check if there is any use of NZCV between CMP and Bcc.
+    // Ensure there is no use of NZCV between CMP and conditional.
     if (I.readsRegister(AArch64::NZCV, /*TRI=*/nullptr))
       return nullptr;
 
@@ -421,37 +437,22 @@ static bool isLessThan(AArch64CC::CondCode Cmp) {
 // The second CMP is eliminated, enabling CSE to remove the redundant
 // comparison.
 bool AArch64ConditionOptimizer::optimizeIntraBlock(MachineBasicBlock &MBB) {
-  MachineInstr *FirstCmp = nullptr;
   MachineInstr *FirstCSINC = nullptr;
-  MachineInstr *SecondCmp = nullptr;
   MachineInstr *SecondCSINC = nullptr;
 
-  // Find two CMP + CSINC pairs
+  // Find two CSINC instructions
   for (MachineInstr &MI : MBB) {
-    if (isCmpInstruction(MI.getOpcode())) {
-      if (!FirstCmp) {
-        FirstCmp = &MI;
-      } else if (FirstCSINC && !SecondCmp) {
-        SecondCmp = &MI;
-      }
-      continue;
-    }
-
     if (isCSINCInstruction(MI.getOpcode())) {
-      // Found a CSINC, ensure it comes after the corresponding comparison
-      if (FirstCmp && !FirstCSINC) {
+      if (!FirstCSINC) {
         FirstCSINC = &MI;
-      } else if (SecondCmp && !SecondCSINC) {
+      } else if (!SecondCSINC) {
         SecondCSINC = &MI;
+        break; // Found both
       }
     }
-
-    if (SecondCSINC)
-      break;
   }
 
-  if (!SecondCmp || !SecondCSINC) {
-    LLVM_DEBUG(dbgs() << "Didn't find two CMP+CSINC pairs\n");
+  if (!FirstCSINC || !SecondCSINC) {
     return false;
   }
 
@@ -459,19 +460,26 @@ bool AArch64ConditionOptimizer::optimizeIntraBlock(MachineBasicBlock &MBB) {
   if (nzcvLivesOut(&MBB))
     return false;
 
-  if (!registersMatch(FirstCmp, SecondCmp))
+  // Find the CMPs controlling each CSINC
+  MachineInstr *FirstCmpMI = findAdjustableCmp(FirstCSINC);
+  MachineInstr *SecondCmpMI = findAdjustableCmp(SecondCSINC);
+  if (!FirstCmpMI || !SecondCmpMI)
     return false;
 
-  if (!canAdjustCmp(*FirstCmp) || !canAdjustCmp(*SecondCmp)) {
-    LLVM_DEBUG(dbgs() << "One or both CMPs are not pure\n");
+  // Ensure we have two distinct CMPs
+  if (FirstCmpMI == SecondCmpMI) {
+    LLVM_DEBUG(dbgs() << "Both CSINCs already controlled by same CMP\n");
     return false;
   }
 
+  if (!registersMatch(FirstCmpMI, SecondCmpMI))
+    return false;
+
   // Check that nothing else modifies the flags between the first CMP and second
   // conditional
-  for (auto It = std::next(MachineBasicBlock::iterator(FirstCmp));
+  for (auto It = std::next(MachineBasicBlock::iterator(FirstCmpMI));
        It != std::next(MachineBasicBlock::iterator(SecondCSINC)); ++It) {
-    if (&*It != SecondCmp &&
+    if (&*It != SecondCmpMI &&
         It->modifiesRegister(AArch64::NZCV, /*TRI=*/nullptr)) {
       LLVM_DEBUG(dbgs() << "Flags modified between CMPs by: " << *It << '\n');
       return false;
@@ -493,8 +501,8 @@ bool AArch64ConditionOptimizer::optimizeIntraBlock(MachineBasicBlock &MBB) {
   AArch64CC::CondCode SecondCond =
       (AArch64CC::CondCode)(int)SecondCSINC->getOperand(3).getImm();
 
-  const int FirstImm = (int)FirstCmp->getOperand(2).getImm();
-  const int SecondImm = (int)SecondCmp->getOperand(2).getImm();
+  const int FirstImm = (int)FirstCmpMI->getOperand(2).getImm();
+  const int SecondImm = (int)SecondCmpMI->getOperand(2).getImm();
 
   LLVM_DEBUG(dbgs() << "Comparing intra-block CSINCs: "
                     << AArch64CC::getCondCodeName(FirstCond) << " #" << FirstImm
@@ -514,7 +522,7 @@ bool AArch64ConditionOptimizer::optimizeIntraBlock(MachineBasicBlock &MBB) {
       adjustFirst = !adjustFirst;
     }
 
-    MachineInstr *CmpToAdjust = adjustFirst ? FirstCmp : SecondCmp;
+    MachineInstr *CmpToAdjust = adjustFirst ? FirstCmpMI : SecondCmpMI;
     MachineInstr *CSINCToAdjust = adjustFirst ? FirstCSINC : SecondCSINC;
     AArch64CC::CondCode CondToAdjust = adjustFirst ? FirstCond : SecondCond;
     int TargetImm = adjustFirst ? SecondImm : FirstImm;
@@ -523,7 +531,7 @@ bool AArch64ConditionOptimizer::optimizeIntraBlock(MachineBasicBlock &MBB) {
 
     if (std::get<0>(AdjustedInfo) == TargetImm &&
         std::get<1>(AdjustedInfo) ==
-            (adjustFirst ? SecondCmp : FirstCmp)->getOpcode()) {
+            (adjustFirst ? SecondCmpMI : FirstCmpMI)->getOpcode()) {
       LLVM_DEBUG(dbgs() << "Successfully optimizing intra-block CSINC pair\n");
 
       // Modify the selected CMP and CSINC
@@ -557,19 +565,22 @@ bool AArch64ConditionOptimizer::optimizeCrossBlock(MachineBasicBlock &HBB) {
     return false;
   }
 
-  MachineInstr *HeadCmpMI = findSuitableCompare(&HBB);
-  if (!HeadCmpMI) {
+  MachineInstr *HeadBrMI = getBccTerminator(&HBB);
+  MachineInstr *TrueBrMI = getBccTerminator(TBB);
+  if (!HeadBrMI || !TrueBrMI)
     return false;
-  }
 
-  MachineInstr *TrueCmpMI = findSuitableCompare(TBB);
-  if (!TrueCmpMI) {
+  // Since we may modify cmps in these blocks, make sure NZCV does not live out.
+  if (nzcvLivesOut(&HBB) || nzcvLivesOut(TBB))
     return false;
-  }
 
-  if (!registersMatch(HeadCmpMI, TrueCmpMI)) {
+  MachineInstr *HeadCmpMI = findAdjustableCmp(HeadBrMI);
+  MachineInstr *TrueCmpMI = findAdjustableCmp(TrueBrMI);
+  if (!HeadCmpMI || !TrueCmpMI)
+    return false;
+
+  if (!registersMatch(HeadCmpMI, TrueCmpMI))
     return false;
-  }
 
   AArch64CC::CondCode HeadCmp;
   if (HeadCond.empty() || !parseCond(HeadCond, HeadCmp)) {


        


More information about the llvm-commits mailing list