[ARM] Add some missing thumb1 opcodes to enable peephole optimisation of CMPs
This adds a number of missing Thumb1 opcodes so that the peephole optimiser can
remove redundant CMP instructions.
Reapplying this after the first attempt broke non-thumb1 code as the t2ADDri
instruction can be used with frame indices. In thumb1 we use tADDframe.
Differential Revision: https://reviews.llvm.org/D57833
llvm-svn: 354667
diff --git a/llvm/lib/Target/ARM/ARMBaseInstrInfo.cpp b/llvm/lib/Target/ARM/ARMBaseInstrInfo.cpp
index a23ae20..365030f 100644
--- a/llvm/lib/Target/ARM/ARMBaseInstrInfo.cpp
+++ b/llvm/lib/Target/ARM/ARMBaseInstrInfo.cpp
@@ -2542,6 +2542,7 @@
return true;
case ARM::CMPrr:
case ARM::t2CMPrr:
+ case ARM::tCMPr:
SrcReg = MI.getOperand(0).getReg();
SrcReg2 = MI.getOperand(1).getReg();
CmpMask = ~0;
@@ -2618,28 +2619,62 @@
/// This function can be extended later on.
inline static bool isRedundantFlagInstr(const MachineInstr *CmpI,
unsigned SrcReg, unsigned SrcReg2,
- int ImmValue, const MachineInstr *OI) {
+ int ImmValue, const MachineInstr *OI,
+ bool &IsThumb1) {
if ((CmpI->getOpcode() == ARM::CMPrr || CmpI->getOpcode() == ARM::t2CMPrr) &&
(OI->getOpcode() == ARM::SUBrr || OI->getOpcode() == ARM::t2SUBrr) &&
((OI->getOperand(1).getReg() == SrcReg &&
OI->getOperand(2).getReg() == SrcReg2) ||
(OI->getOperand(1).getReg() == SrcReg2 &&
- OI->getOperand(2).getReg() == SrcReg)))
+ OI->getOperand(2).getReg() == SrcReg))) {
+ IsThumb1 = false;
return true;
+ }
+
+ if (CmpI->getOpcode() == ARM::tCMPr && OI->getOpcode() == ARM::tSUBrr &&
+ ((OI->getOperand(2).getReg() == SrcReg &&
+ OI->getOperand(3).getReg() == SrcReg2) ||
+ (OI->getOperand(2).getReg() == SrcReg2 &&
+ OI->getOperand(3).getReg() == SrcReg))) {
+ IsThumb1 = true;
+ return true;
+ }
if ((CmpI->getOpcode() == ARM::CMPri || CmpI->getOpcode() == ARM::t2CMPri) &&
(OI->getOpcode() == ARM::SUBri || OI->getOpcode() == ARM::t2SUBri) &&
OI->getOperand(1).getReg() == SrcReg &&
- OI->getOperand(2).getImm() == ImmValue)
+ OI->getOperand(2).getImm() == ImmValue) {
+ IsThumb1 = false;
return true;
+ }
+
+ if (CmpI->getOpcode() == ARM::tCMPi8 &&
+ (OI->getOpcode() == ARM::tSUBi8 || OI->getOpcode() == ARM::tSUBi3) &&
+ OI->getOperand(2).getReg() == SrcReg &&
+ OI->getOperand(3).getImm() == ImmValue) {
+ IsThumb1 = true;
+ return true;
+ }
if ((CmpI->getOpcode() == ARM::CMPrr || CmpI->getOpcode() == ARM::t2CMPrr) &&
(OI->getOpcode() == ARM::ADDrr || OI->getOpcode() == ARM::t2ADDrr ||
OI->getOpcode() == ARM::ADDri || OI->getOpcode() == ARM::t2ADDri) &&
OI->getOperand(0).isReg() && OI->getOperand(1).isReg() &&
OI->getOperand(0).getReg() == SrcReg &&
- OI->getOperand(1).getReg() == SrcReg2)
+ OI->getOperand(1).getReg() == SrcReg2) {
+ IsThumb1 = false;
return true;
+ }
+
+ if (CmpI->getOpcode() == ARM::tCMPr &&
+ (OI->getOpcode() == ARM::tADDi3 || OI->getOpcode() == ARM::tADDi8 ||
+ OI->getOpcode() == ARM::tADDrr) &&
+ OI->getOperand(0).getReg() == SrcReg &&
+ OI->getOperand(2).getReg() == SrcReg2) {
+ IsThumb1 = true;
+ return true;
+ }
+
return false;
}
@@ -2756,7 +2791,8 @@
// For CMPri w/ CmpValue != 0, a SubAdd may still be a candidate.
// Thus we cannot return here.
if (CmpInstr.getOpcode() == ARM::CMPri ||
- CmpInstr.getOpcode() == ARM::t2CMPri)
+ CmpInstr.getOpcode() == ARM::t2CMPri ||
+ CmpInstr.getOpcode() == ARM::tCMPi8)
MI = nullptr;
else
return false;
@@ -2800,11 +2836,13 @@
// Check that CPSR isn't set between the comparison instruction and the one we
// want to change. At the same time, search for SubAdd.
const TargetRegisterInfo *TRI = &getRegisterInfo();
+ bool SubAddIsThumb1 = false;
do {
const MachineInstr &Instr = *--I;
// Check whether CmpInstr can be made redundant by the current instruction.
- if (isRedundantFlagInstr(&CmpInstr, SrcReg, SrcReg2, CmpValue, &Instr)) {
+ if (isRedundantFlagInstr(&CmpInstr, SrcReg, SrcReg2, CmpValue, &Instr,
+ SubAddIsThumb1)) {
SubAdd = &*I;
break;
}
@@ -2828,7 +2866,7 @@
// If we found a SubAdd, use it as it will be closer to the CMP
if (SubAdd) {
MI = SubAdd;
- IsThumb1 = false;
+ IsThumb1 = SubAddIsThumb1;
}
// We can't use a predicated instruction - it doesn't always write the flags.
@@ -2897,9 +2935,13 @@
// operands will be modified.
unsigned Opc = SubAdd->getOpcode();
bool IsSub = Opc == ARM::SUBrr || Opc == ARM::t2SUBrr ||
- Opc == ARM::SUBri || Opc == ARM::t2SUBri;
- if (!IsSub || (SrcReg2 != 0 && SubAdd->getOperand(1).getReg() == SrcReg2 &&
- SubAdd->getOperand(2).getReg() == SrcReg)) {
+ Opc == ARM::SUBri || Opc == ARM::t2SUBri ||
+ Opc == ARM::tSUBrr || Opc == ARM::tSUBi3 ||
+ Opc == ARM::tSUBi8;
+ unsigned OpI = Opc != ARM::tSUBrr ? 1 : 2;
+ if (!IsSub ||
+ (SrcReg2 != 0 && SubAdd->getOperand(OpI).getReg() == SrcReg2 &&
+ SubAdd->getOperand(OpI + 1).getReg() == SrcReg)) {
// VSel doesn't support condition code update.
if (IsInstrVSel)
return false;
@@ -2977,9 +3019,10 @@
++Next;
unsigned SrcReg, SrcReg2;
int CmpMask, CmpValue;
+ bool IsThumb1;
if (Next != MI.getParent()->end() &&
analyzeCompare(*Next, SrcReg, SrcReg2, CmpMask, CmpValue) &&
- isRedundantFlagInstr(&*Next, SrcReg, SrcReg2, CmpValue, &MI))
+ isRedundantFlagInstr(&*Next, SrcReg, SrcReg2, CmpValue, &MI, IsThumb1))
return false;
return true;
}