[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