[llvm] [Sparc] Optimize compare instruction (PR #167140)

Sergei Barannikov via llvm-commits llvm-commits at lists.llvm.org
Sun Nov 9 07:34:38 PST 2025


================
@@ -640,6 +640,154 @@ unsigned SparcInstrInfo::getInstSizeInBytes(const MachineInstr &MI) const {
   return get(Opcode).getSize();
 }
 
+bool SparcInstrInfo::analyzeCompare(const MachineInstr &MI, Register &SrcReg,
+                                    Register &SrcReg2, int64_t &CmpMask,
+                                    int64_t &CmpValue) const {
+  Register DstReg;
+  switch (MI.getOpcode()) {
+  default:
+    break;
+  case SP::SUBCCri:
+    DstReg = MI.getOperand(0).getReg();
+    SrcReg = MI.getOperand(1).getReg();
+    SrcReg2 = 0;
+    CmpMask = ~0;
+    CmpValue = MI.getOperand(2).getImm();
+    return (DstReg == SP::G0) && (CmpValue == 0);
+  case SP::SUBCCrr:
+    DstReg = MI.getOperand(0).getReg();
+    SrcReg = MI.getOperand(1).getReg();
+    SrcReg2 = MI.getOperand(2).getReg();
+    CmpMask = ~0;
+    CmpValue = 0;
+    return (DstReg == SP::G0) && (SrcReg2 == SP::G0);
+  }
+
+  return false;
+}
+
+bool SparcInstrInfo::optimizeCompareInstr(
+    MachineInstr &CmpInstr, Register SrcReg, Register SrcReg2, int64_t CmpMask,
+    int64_t CmpValue, const MachineRegisterInfo *MRI) const {
+
+  // Get the unique definition of SrcReg.
+  MachineInstr *MI = MRI->getUniqueVRegDef(SrcReg);
+  if (!MI)
+    return false;
+
+  // Only optimize if defining and comparing instruction in same block.
+  if (MI->getParent() != CmpInstr.getParent())
+    return false;
+
+  unsigned NewOpcode;
+  switch (MI->getOpcode()) {
+  case SP::ANDNrr:
+    NewOpcode = SP::ANDNCCrr;
+    break;
+  case SP::ANDNri:
+    NewOpcode = SP::ANDNCCri;
+    break;
+  case SP::ANDrr:
+    NewOpcode = SP::ANDCCrr;
+    break;
+  case SP::ANDri:
+    NewOpcode = SP::ANDCCri;
+    break;
+  case SP::ORrr:
+    NewOpcode = SP::ORCCrr;
+    break;
+  case SP::ORri:
+    NewOpcode = SP::ORCCri;
+    break;
+  case SP::ORNCCrr:
+    NewOpcode = SP::ORNCCrr;
+    break;
+  case SP::ORNri:
+    NewOpcode = SP::ORNCCri;
+    break;
+  case SP::XORrr:
+    NewOpcode = SP::XORCCrr;
+    break;
+  case SP::XNORri:
+    NewOpcode = SP::XNORCCri;
+    break;
+  case SP::XNORrr:
+    NewOpcode = SP::XNORCCrr;
+    break;
+  case SP::ADDrr:
+    NewOpcode = SP::ADDCCrr;
+    break;
+  case SP::ADDri:
+    NewOpcode = SP::ADDCCri;
+    break;
+  case SP::SUBrr:
+    NewOpcode = SP::SUBCCrr;
+    break;
+  case SP::SUBri:
+    NewOpcode = SP::SUBCCri;
+    break;
+  default:
+    return false;
+  }
+
+  bool IsSafe = false;
+  bool IsRegUsed = false;
+  MachineBasicBlock::iterator I = MI;
+  MachineBasicBlock::iterator C = CmpInstr;
+  MachineBasicBlock::iterator E = CmpInstr.getParent()->end();
+  const TargetRegisterInfo *TRI = &getRegisterInfo();
+
+  // If ICC is used or modified between MI and CmpInstr we cannot optimize.
+  while (++I != C) {
+    if (I->modifiesRegister(SP::ICC, TRI) || I->readsRegister(SP::ICC, TRI))
+      return false;
+    if (I->readsRegister(SrcReg, TRI))
+      IsRegUsed = true;
+  }
+
+  while (++I != E) {
+    // Only allow conditionals on equality.
+    if (I->readsRegister(SP::ICC, TRI)) {
+      bool IsICCBranch = (I->getOpcode() == SP::BCOND) ||
+                         (I->getOpcode() == SP::BPICC) ||
+                         (I->getOpcode() == SP::BPXCC);
+      bool IsICCMove = (I->getOpcode() == SP::MOVICCrr) ||
+                       (I->getOpcode() == SP::MOVICCri) ||
+                       (I->getOpcode() == SP::MOVXCCrr) ||
+                       (I->getOpcode() == SP::MOVXCCri);
+      bool IsICCConditional = IsICCBranch || IsICCMove;
+      if (!IsICCConditional ||
+          (I->getOperand(IsICCBranch ? 1 : 3).getImm() != SPCC::ICC_E &&
+           I->getOperand(IsICCBranch ? 1 : 3).getImm() != SPCC::ICC_NE))
+        return false;
+    } else if (I->modifiesRegister(SP::ICC, TRI)) {
+      IsSafe = true;
+      break;
+    }
+  }
+
+  if (!IsSafe) {
+    MachineBasicBlock *MBB = CmpInstr.getParent();
+    for (MachineBasicBlock::succ_iterator SI = MBB->succ_begin(),
+                                          SE = MBB->succ_end();
+         SI != SE; ++SI)
+      if ((*SI)->isLiveIn(SP::ICC))
+        return false;
----------------
s-barannikov wrote:

```suggestion
    if (any_of(MBB->successors(),
               [](MachineBasicBlock *Succ) { return Succ->isLiveIn(SP::ICC); }))
      return false;
```

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


More information about the llvm-commits mailing list