[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