Skip to content

Commit 7e4dcb1

Browse files
doackoachan
authored andcommitted
[Sparc] Optimize compare instruction
If we need to compare the result of a computation with 0, we can sometimes replace the last instruction in the computation with one that sets the integer condition codes. We can then branch immediately based on the zero-flag instead of having to use an extra compare instruction (a SUBcc instruction). This is only possible if the result of the compare is not used anywhere else and that no other instruction modifies the integer condition codes between the time the result of the computation is defined and the time it is used.
1 parent d07a4fe commit 7e4dcb1

File tree

10 files changed

+428
-29
lines changed

10 files changed

+428
-29
lines changed

llvm/lib/Target/Sparc/SparcInstrInfo.cpp

Lines changed: 143 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -640,6 +640,149 @@ unsigned SparcInstrInfo::getInstSizeInBytes(const MachineInstr &MI) const {
640640
return get(Opcode).getSize();
641641
}
642642

643+
bool SparcInstrInfo::analyzeCompare(const MachineInstr &MI, Register &SrcReg,
644+
Register &SrcReg2, int64_t &CmpMask,
645+
int64_t &CmpValue) const {
646+
switch (MI.getOpcode()) {
647+
default:
648+
break;
649+
case SP::CMPri:
650+
SrcReg = MI.getOperand(0).getReg();
651+
SrcReg2 = 0;
652+
CmpMask = ~0;
653+
CmpValue = MI.getOperand(1).getImm();
654+
return (CmpValue == 0);
655+
case SP::CMPrr:
656+
SrcReg = MI.getOperand(0).getReg();
657+
SrcReg2 = MI.getOperand(1).getReg();
658+
CmpMask = ~0;
659+
CmpValue = 0;
660+
return SrcReg2 == SP::G0;
661+
}
662+
663+
return false;
664+
}
665+
666+
bool SparcInstrInfo::optimizeCompareInstr(
667+
MachineInstr &CmpInstr, Register SrcReg, Register SrcReg2, int64_t CmpMask,
668+
int64_t CmpValue, const MachineRegisterInfo *MRI) const {
669+
670+
// Get the unique definition of SrcReg.
671+
MachineInstr *MI = MRI->getUniqueVRegDef(SrcReg);
672+
if (!MI)
673+
return false;
674+
675+
// Only optimize if defining and comparing instruction in same block.
676+
if (MI->getParent() != CmpInstr.getParent())
677+
return false;
678+
679+
unsigned newOpcode;
680+
switch (MI->getOpcode()) {
681+
case SP::ANDNrr:
682+
newOpcode = SP::ANDNCCrr;
683+
break;
684+
case SP::ANDNri:
685+
newOpcode = SP::ANDNCCri;
686+
break;
687+
case SP::ANDrr:
688+
newOpcode = SP::ANDCCrr;
689+
break;
690+
case SP::ANDri:
691+
newOpcode = SP::ANDCCri;
692+
break;
693+
case SP::ORrr:
694+
newOpcode = SP::ORCCrr;
695+
break;
696+
case SP::ORri:
697+
newOpcode = SP::ORCCri;
698+
break;
699+
case SP::ORNCCrr:
700+
newOpcode = SP::ORNCCrr;
701+
break;
702+
case SP::ORNri:
703+
newOpcode = SP::ORNCCri;
704+
break;
705+
case SP::XORrr:
706+
newOpcode = SP::XORCCrr;
707+
break;
708+
case SP::XNORri:
709+
newOpcode = SP::XNORCCri;
710+
break;
711+
case SP::XNORrr:
712+
newOpcode = SP::XNORCCrr;
713+
break;
714+
case SP::ADDrr:
715+
newOpcode = SP::ADDCCrr;
716+
break;
717+
case SP::ADDri:
718+
newOpcode = SP::ADDCCri;
719+
break;
720+
case SP::SUBrr:
721+
newOpcode = SP::SUBCCrr;
722+
break;
723+
case SP::SUBri:
724+
newOpcode = SP::SUBCCri;
725+
break;
726+
default:
727+
return false;
728+
}
729+
730+
bool isSafe = false;
731+
bool isRegUsed = false;
732+
MachineBasicBlock::iterator I = MI;
733+
MachineBasicBlock::iterator C = CmpInstr;
734+
MachineBasicBlock::iterator E = CmpInstr.getParent()->end();
735+
const TargetRegisterInfo *TRI = &getRegisterInfo();
736+
737+
// If ICC is used or modified between MI and CmpInstr we cannot optimize.
738+
while (++I != C) {
739+
if (I->modifiesRegister(SP::ICC, TRI) || I->readsRegister(SP::ICC, TRI))
740+
return false;
741+
if (I->readsRegister(SrcReg, TRI))
742+
isRegUsed = true;
743+
}
744+
745+
while (++I != E) {
746+
// Only allow conditionals on equality.
747+
if (I->readsRegister(SP::ICC, TRI)) {
748+
bool IsICCBranch = (I->getOpcode() == SP::BCOND) ||
749+
(I->getOpcode() == SP::BPICC) ||
750+
(I->getOpcode() == SP::BPXCC);
751+
bool IsICCMove = (I->getOpcode() == SP::MOVICCrr) ||
752+
(I->getOpcode() == SP::MOVICCri) ||
753+
(I->getOpcode() == SP::MOVXCCrr) ||
754+
(I->getOpcode() == SP::MOVXCCri);
755+
bool IsICCConditional = IsICCBranch || IsICCMove;
756+
if (!IsICCConditional ||
757+
(I->getOperand(IsICCBranch ? 1 : 3).getImm() != SPCC::ICC_E &&
758+
I->getOperand(IsICCBranch ? 1 : 3).getImm() != SPCC::ICC_NE))
759+
return false;
760+
} else if (I->modifiesRegister(SP::ICC, TRI)) {
761+
isSafe = true;
762+
break;
763+
}
764+
}
765+
766+
if (!isSafe) {
767+
MachineBasicBlock *MBB = CmpInstr.getParent();
768+
for (MachineBasicBlock::succ_iterator SI = MBB->succ_begin(),
769+
SE = MBB->succ_end();
770+
SI != SE; ++SI)
771+
if ((*SI)->isLiveIn(SP::ICC))
772+
return false;
773+
}
774+
775+
// If the result is not needed use the %g0 register.
776+
if (!isRegUsed && CmpInstr.getOperand(0).isKill())
777+
MI->getOperand(0).setReg(SP::G0);
778+
779+
MI->setDesc(get(newOpcode));
780+
MI->addRegisterDefined(SP::ICC);
781+
CmpInstr.eraseFromParent();
782+
783+
return true;
784+
}
785+
643786
bool SparcInstrInfo::expandPostRAPseudo(MachineInstr &MI) const {
644787
switch (MI.getOpcode()) {
645788
case TargetOpcode::LOAD_STACK_GUARD: {

llvm/lib/Target/Sparc/SparcInstrInfo.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,14 @@ class SparcInstrInfo : public SparcGenInstrInfo {
108108
/// instruction may be. This returns the maximum number of bytes.
109109
unsigned getInstSizeInBytes(const MachineInstr &MI) const override;
110110

111+
bool analyzeCompare(const MachineInstr &MI, Register &SrcReg,
112+
Register &SrcReg2, int64_t &CmpMask,
113+
int64_t &CmpValue) const override;
114+
115+
bool optimizeCompareInstr(MachineInstr &CmpInstr, Register SrcReg,
116+
Register SrcReg2, int64_t CmpMask, int64_t CmpValue,
117+
const MachineRegisterInfo *MRI) const override;
118+
111119
// Lower pseudo instructions after register allocation.
112120
bool expandPostRAPseudo(MachineInstr &MI) const override;
113121
};

llvm/lib/Target/Sparc/SparcInstrInfo.td

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -914,8 +914,17 @@ let Defs = [ICC], hasPostISelHook = true in
914914
let Uses = [ICC] in
915915
defm SUBC : F3_12np <"subx", 0b001100>;
916916

917-
def : Pat<(SPcmpicc i32:$lhs, i32:$rhs), (SUBCCrr $lhs, $rhs)>;
918-
def : Pat<(SPcmpicc i32:$lhs, (i32 simm13:$rhs)), (SUBCCri $lhs, imm:$rhs)>;
917+
// cmp (from Section A.3) is a specialized alias for subcc
918+
let Defs = [ICC], rd = 0, isCompare = 1 in {
919+
def CMPrr : F3_1<2, 0b010100,
920+
(outs), (ins IntRegs:$rs1, IntRegs:$rs2),
921+
"cmp $rs1, $rs2",
922+
[(SPcmpicc i32:$rs1, i32:$rs2)]>;
923+
def CMPri : F3_2<2, 0b010100,
924+
(outs), (ins IntRegs:$rs1, simm13Op:$simm13),
925+
"cmp $rs1, $simm13",
926+
[(SPcmpicc i32:$rs1, (i32 simm13:$simm13))]>;
927+
}
919928

920929
// Section B.18 - Multiply Instructions, p. 113
921930
let Defs = [Y] in {

llvm/test/CodeGen/SPARC/2011-01-11-CC.ll

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,15 +25,13 @@ define i32 @test_addx(i64 %a, i64 %b, i64 %c) nounwind {
2525
; V8-NEXT: retl
2626
; V8-NEXT: nop
2727
; V8-NEXT: .LBB0_4: ! %entry
28-
; V8-NEXT: mov %g0, %o2
2928
; V8-NEXT: cmp %o3, %o5
3029
; V8-NEXT: bgu .LBB0_2
31-
; V8-NEXT: nop
30+
; V8-NEXT: mov %g0, %o2
3231
; V8-NEXT: .LBB0_5: ! %entry
33-
; V8-NEXT: mov %g0, %o0
3432
; V8-NEXT: cmp %o1, %o4
3533
; V8-NEXT: be .LBB0_3
36-
; V8-NEXT: nop
34+
; V8-NEXT: mov %g0, %o0
3735
; V8-NEXT: .LBB0_6: ! %entry
3836
; V8-NEXT: retl
3937
; V8-NEXT: mov %o2, %o0

llvm/test/CodeGen/SPARC/atomicrmw-uinc-udec-wrap.ll

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -292,17 +292,15 @@ define i64 @atomicrmw_udec_wrap_i64(ptr %ptr, i64 %val) {
292292
; CHECK-NEXT: mov %g0, %l0
293293
; CHECK-NEXT: addcc %g3, -1, %o3
294294
; CHECK-NEXT: addxcc %g2, -1, %o2
295-
; CHECK-NEXT: or %g3, %g2, %l1
296-
; CHECK-NEXT: cmp %l1, 0
295+
; CHECK-NEXT: orcc %g3, %g2, %g0
297296
; CHECK-NEXT: move %icc, 1, %i5
298297
; CHECK-NEXT: cmp %g2, %i1
299298
; CHECK-NEXT: movgu %icc, 1, %g4
300299
; CHECK-NEXT: cmp %g3, %i2
301300
; CHECK-NEXT: movgu %icc, 1, %l0
302301
; CHECK-NEXT: cmp %g2, %i1
303302
; CHECK-NEXT: move %icc, %l0, %g4
304-
; CHECK-NEXT: or %i5, %g4, %i5
305-
; CHECK-NEXT: cmp %i5, 0
303+
; CHECK-NEXT: orcc %i5, %g4, %i5
306304
; CHECK-NEXT: movne %icc, %i1, %o2
307305
; CHECK-NEXT: movne %icc, %i2, %o3
308306
; CHECK-NEXT: std %g2, [%fp+-8]

llvm/test/CodeGen/SPARC/ctlz.ll

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -156,8 +156,7 @@ define i64 @i64_nopoison(i64 %x) nounwind {
156156
; SPARC-LABEL: i64_nopoison:
157157
; SPARC: ! %bb.0:
158158
; SPARC-NEXT: save %sp, -96, %sp
159-
; SPARC-NEXT: or %i1, %i0, %i2
160-
; SPARC-NEXT: cmp %i2, 0
159+
; SPARC-NEXT: orcc %i1, %i0, %g0
161160
; SPARC-NEXT: be .LBB2_4
162161
; SPARC-NEXT: nop
163162
; SPARC-NEXT: ! %bb.1: ! %cond.false
@@ -182,8 +181,7 @@ define i64 @i64_nopoison(i64 %x) nounwind {
182181
; SPARC-POPC-LABEL: i64_nopoison:
183182
; SPARC-POPC: ! %bb.0:
184183
; SPARC-POPC-NEXT: save %sp, -96, %sp
185-
; SPARC-POPC-NEXT: or %i1, %i0, %i2
186-
; SPARC-POPC-NEXT: cmp %i2, 0
184+
; SPARC-POPC-NEXT: orcc %i1, %i0, %g0
187185
; SPARC-POPC-NEXT: be .LBB2_4
188186
; SPARC-POPC-NEXT: nop
189187
; SPARC-POPC-NEXT: ! %bb.1: ! %cond.false

llvm/test/CodeGen/SPARC/cttz.ll

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -184,8 +184,7 @@ define i32 @i32_poison(i32 %x) nounwind {
184184
define i64 @i64_nopoison(i64 %x) nounwind {
185185
; SPARC-LABEL: i64_nopoison:
186186
; SPARC: ! %bb.0:
187-
; SPARC-NEXT: or %o1, %o0, %o2
188-
; SPARC-NEXT: cmp %o2, 0
187+
; SPARC-NEXT: orcc %o1, %o0, %g0
189188
; SPARC-NEXT: be .LBB2_3
190189
; SPARC-NEXT: nop
191190
; SPARC-NEXT: ! %bb.1: ! %cond.false
@@ -219,8 +218,7 @@ define i64 @i64_nopoison(i64 %x) nounwind {
219218
;
220219
; SPARC-POPC-LABEL: i64_nopoison:
221220
; SPARC-POPC: ! %bb.0:
222-
; SPARC-POPC-NEXT: or %o1, %o0, %o2
223-
; SPARC-POPC-NEXT: cmp %o2, 0
221+
; SPARC-POPC-NEXT: orcc %o1, %o0, %g0
224222
; SPARC-POPC-NEXT: be .LBB2_3
225223
; SPARC-POPC-NEXT: nop
226224
; SPARC-POPC-NEXT: ! %bb.1: ! %cond.false

0 commit comments

Comments
 (0)