diff options
Diffstat (limited to 'llvm/lib/Target')
-rw-r--r-- | llvm/lib/Target/ARM/ARMBaseInstrInfo.cpp | 97 | ||||
-rw-r--r-- | llvm/lib/Target/ARM/ARMBaseInstrInfo.h | 2 |
2 files changed, 76 insertions, 23 deletions
diff --git a/llvm/lib/Target/ARM/ARMBaseInstrInfo.cpp b/llvm/lib/Target/ARM/ARMBaseInstrInfo.cpp index bd90fe90aab..9981b0586d6 100644 --- a/llvm/lib/Target/ARM/ARMBaseInstrInfo.cpp +++ b/llvm/lib/Target/ARM/ARMBaseInstrInfo.cpp @@ -2534,14 +2534,28 @@ inline static ARMCC::CondCodes getSwappedCondition(ARMCC::CondCodes CC) { } } +/// getCmpToAddCondition - assume the flags are set by CMP(a,b), return +/// the condition code if we modify the instructions such that flags are +/// set by ADD(a,b,X). +inline static ARMCC::CondCodes getCmpToAddCondition(ARMCC::CondCodes CC) { + switch (CC) { + default: return ARMCC::AL; + case ARMCC::HS: return ARMCC::LO; + case ARMCC::LO: return ARMCC::HS; + case ARMCC::VS: return ARMCC::VS; + case ARMCC::VC: return ARMCC::VC; + } +} + /// isRedundantFlagInstr - check whether the first instruction, whose only /// purpose is to update flags, can be made redundant. /// CMPrr can be made redundant by SUBrr if the operands are the same. /// CMPri can be made redundant by SUBri if the operands are the same. +/// CMPrr(r0, r1) can be made redundant by ADDr[ri](r0, r1, X). /// This function can be extended later on. -inline static bool isRedundantFlagInstr(MachineInstr *CmpI, unsigned SrcReg, - unsigned SrcReg2, int ImmValue, - MachineInstr *OI) { +inline static bool isRedundantFlagInstr(const MachineInstr *CmpI, + unsigned SrcReg, unsigned SrcReg2, + int ImmValue, const MachineInstr *OI) { if ((CmpI->getOpcode() == ARM::CMPrr || CmpI->getOpcode() == ARM::t2CMPrr) && (OI->getOpcode() == ARM::SUBrr || @@ -2559,6 +2573,14 @@ inline static bool isRedundantFlagInstr(MachineInstr *CmpI, unsigned SrcReg, OI->getOperand(1).getReg() == SrcReg && OI->getOperand(2).getImm() == ImmValue) 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) + return true; return false; } @@ -2661,17 +2683,18 @@ bool ARMBaseInstrInfo::optimizeCompareInstr( if (I == B) return false; // There are two possible candidates which can be changed to set CPSR: - // One is MI, the other is a SUB instruction. - // For CMPrr(r1,r2), we are looking for SUB(r1,r2) or SUB(r2,r1). + // One is MI, the other is a SUB or ADD instruction. + // For CMPrr(r1,r2), we are looking for SUB(r1,r2), SUB(r2,r1), or + // ADDr[ri](r1, r2, X). // For CMPri(r1, CmpValue), we are looking for SUBri(r1, CmpValue). - MachineInstr *Sub = nullptr; + MachineInstr *SubAdd = nullptr; if (SrcReg2 != 0) // MI is not a candidate for CMPrr. MI = nullptr; else if (MI->getParent() != CmpInstr.getParent() || CmpValue != 0) { // Conservatively refuse to convert an instruction which isn't in the same // BB as the comparison. - // For CMPri w/ CmpValue != 0, a Sub may still be a candidate. + // 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) @@ -2713,38 +2736,43 @@ bool ARMBaseInstrInfo::optimizeCompareInstr( } I = CmpInstr; E = MI; + } else { + // Allow the loop below to search E (which was initially MI). Since MI and + // SubAdd have different tests, even if that instruction could not be MI, it + // could still potentially be SubAdd. + --E; } // Check that CPSR isn't set between the comparison instruction and the one we - // want to change. At the same time, search for Sub. + // want to change. At the same time, search for SubAdd. const TargetRegisterInfo *TRI = &getRegisterInfo(); --I; for (; I != E; --I) { const MachineInstr &Instr = *I; + // Check whether CmpInstr can be made redundant by the current instruction. + if (isRedundantFlagInstr(&CmpInstr, SrcReg, SrcReg2, CmpValue, &*I)) { + SubAdd = &*I; + break; + } + if (Instr.modifiesRegister(ARM::CPSR, TRI) || Instr.readsRegister(ARM::CPSR, TRI)) // This instruction modifies or uses CPSR after the one we want to // change. We can't do this transformation. return false; - // Check whether CmpInstr can be made redundant by the current instruction. - if (isRedundantFlagInstr(&CmpInstr, SrcReg, SrcReg2, CmpValue, &*I)) { - Sub = &*I; - break; - } - if (I == B) // The 'and' is below the comparison instruction. return false; } // Return false if no candidates exist. - if (!MI && !Sub) + if (!MI && !SubAdd) return false; // The single candidate is called MI. - if (!MI) MI = Sub; + if (!MI) MI = SubAdd; // We can't use a predicated instruction - it doesn't always write the flags. if (isPredicated(*MI)) @@ -2802,25 +2830,31 @@ bool ARMBaseInstrInfo::optimizeCompareInstr( break; } - if (Sub) { - ARMCC::CondCodes NewCC = getSwappedCondition(CC); - if (NewCC == ARMCC::AL) - return false; + if (SubAdd) { // If we have SUB(r1, r2) and CMP(r2, r1), the condition code based // on CMP needs to be updated to be based on SUB. + // If we have ADD(r1, r2, X) and CMP(r1, r2), the condition code also + // needs to be modified. // Push the condition code operands to OperandsToUpdate. // If it is safe to remove CmpInstr, the condition code of these // operands will be modified. - if (SrcReg2 != 0 && Sub->getOperand(1).getReg() == SrcReg2 && - Sub->getOperand(2).getReg() == SrcReg) { + 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)) { // VSel doesn't support condition code update. if (IsInstrVSel) return false; + // Ensure we can swap the condition. + ARMCC::CondCodes NewCC = (IsSub ? getSwappedCondition(CC) : getCmpToAddCondition(CC)); + if (NewCC == ARMCC::AL) + return false; OperandsToUpdate.push_back( std::make_pair(&((*I).getOperand(IO - 1)), NewCC)); } } else { - // No Sub, so this is x = <op> y, z; cmp x, 0. + // No SubAdd, so this is x = <op> y, z; cmp x, 0. switch (CC) { case ARMCC::EQ: // Z case ARMCC::NE: // Z @@ -2874,6 +2908,23 @@ bool ARMBaseInstrInfo::optimizeCompareInstr( return true; } +bool ARMBaseInstrInfo::shouldSink(const MachineInstr &MI) const { + // Do not sink MI if it might be used to optimize a redundant compare. + // We heuristically only look at the instruction immediately following MI to + // avoid potentially searching the entire basic block. + if (isPredicated(MI)) + return true; + MachineBasicBlock::const_iterator Next = &MI; + ++Next; + unsigned SrcReg, SrcReg2; + int CmpMask, CmpValue; + if (Next != MI.getParent()->end() && + analyzeCompare(*Next, SrcReg, SrcReg2, CmpMask, CmpValue) && + isRedundantFlagInstr(&*Next, SrcReg, SrcReg2, CmpValue, &MI)) + return false; + return true; +} + bool ARMBaseInstrInfo::FoldImmediate(MachineInstr &UseMI, MachineInstr &DefMI, unsigned Reg, MachineRegisterInfo *MRI) const { diff --git a/llvm/lib/Target/ARM/ARMBaseInstrInfo.h b/llvm/lib/Target/ARM/ARMBaseInstrInfo.h index d375f40d6e1..282a6874910 100644 --- a/llvm/lib/Target/ARM/ARMBaseInstrInfo.h +++ b/llvm/lib/Target/ARM/ARMBaseInstrInfo.h @@ -215,6 +215,8 @@ public: bool expandPostRAPseudo(MachineInstr &MI) const override; + bool shouldSink(const MachineInstr &MI) const override; + void reMaterialize(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, unsigned DestReg, unsigned SubIdx, const MachineInstr &Orig, |