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

via llvm-commits llvm-commits at lists.llvm.org
Sun Nov 9 06:51:46 PST 2025


================
@@ -640,6 +640,152 @@ 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;
----------------
koachan wrote:

I think this is already handled at the if condition at [line 779](https://github.com/llvm/llvm-project/pull/167140/files#diff-c8dd4e1ebfb7768a44506782d9733cd251508bfd017ccded99cb95ed12989733R779).
@doac can correct me if I'm wrong on this but my reading is that in this sequence:
```
<op> %a, %b, %SrcReg
cmp %SrcReg, 0
```
If the use at the cmp instruction is a kill then it means that SrcReg won't be used in any of the successor blocks, therefore it should be safe to replace it with %g0 during the optimization, folding it into `<op>cc %a, %b, %g0`.

Will add a comment to clarify.

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


More information about the llvm-commits mailing list