diff options
author | Jakob Stoklund Olesen <stoklund@2pi.dk> | 2012-08-16 23:14:20 +0000 |
---|---|---|
committer | Jakob Stoklund Olesen <stoklund@2pi.dk> | 2012-08-16 23:14:20 +0000 |
commit | 053b5b0b3c34d4763511b6dcd8e0150f8e9dd083 (patch) | |
tree | 989c3c0d1eedf009f110607eff9e4d972799fa01 /lib/Target | |
parent | f2c64ef519b38a4328809b27b4a3a8e0c26e9709 (diff) |
Handle ARM MOVCC optimization in PeepholeOptimizer.
Use the target independent select analysis hooks.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@162060 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Target')
-rw-r--r-- | lib/Target/ARM/ARMBaseInstrInfo.cpp | 67 | ||||
-rw-r--r-- | lib/Target/ARM/ARMBaseInstrInfo.h | 7 | ||||
-rw-r--r-- | lib/Target/ARM/ARMISelLowering.cpp | 48 | ||||
-rw-r--r-- | lib/Target/ARM/ARMInstrInfo.td | 2 | ||||
-rw-r--r-- | lib/Target/ARM/ARMInstrThumb2.td | 2 |
5 files changed, 73 insertions, 53 deletions
diff --git a/lib/Target/ARM/ARMBaseInstrInfo.cpp b/lib/Target/ARM/ARMBaseInstrInfo.cpp index aa452538a8..f5a3bcd11f 100644 --- a/lib/Target/ARM/ARMBaseInstrInfo.cpp +++ b/lib/Target/ARM/ARMBaseInstrInfo.cpp @@ -1570,9 +1570,8 @@ ARMBaseInstrInfo::commuteInstruction(MachineInstr *MI, bool NewMI) const { /// Identify instructions that can be folded into a MOVCC instruction, and /// return the corresponding opcode for the predicated pseudo-instruction. -unsigned llvm::canFoldARMInstrIntoMOVCC(unsigned Reg, - MachineInstr *&MI, - const MachineRegisterInfo &MRI) { +static unsigned canFoldIntoMOVCC(unsigned Reg, MachineInstr *&MI, + const MachineRegisterInfo &MRI) { if (!TargetRegisterInfo::isVirtualRegister(Reg)) return 0; if (!MRI.hasOneNonDBGUse(Reg)) @@ -1617,6 +1616,68 @@ unsigned llvm::canFoldARMInstrIntoMOVCC(unsigned Reg, } } +bool ARMBaseInstrInfo::analyzeSelect(const MachineInstr *MI, + SmallVectorImpl<MachineOperand> &Cond, + unsigned &TrueOp, unsigned &FalseOp, + bool &Optimizable) const { + assert((MI->getOpcode() == ARM::MOVCCr || MI->getOpcode() == ARM::t2MOVCCr) && + "Unknown select instruction"); + // MOVCC operands: + // 0: Def. + // 1: True use. + // 2: False use. + // 3: Condition code. + // 4: CPSR use. + TrueOp = 1; + FalseOp = 2; + Cond.push_back(MI->getOperand(3)); + Cond.push_back(MI->getOperand(4)); + // We can always fold a def. + Optimizable = true; + return false; +} + +MachineInstr *ARMBaseInstrInfo::optimizeSelect(MachineInstr *MI, + bool PreferFalse) const { + assert((MI->getOpcode() == ARM::MOVCCr || MI->getOpcode() == ARM::t2MOVCCr) && + "Unknown select instruction"); + const MachineRegisterInfo &MRI = MI->getParent()->getParent()->getRegInfo(); + MachineInstr *DefMI = 0; + unsigned Opc = canFoldIntoMOVCC(MI->getOperand(2).getReg(), DefMI, MRI); + bool Invert = !Opc; + if (!Opc) + Opc = canFoldIntoMOVCC(MI->getOperand(1).getReg(), DefMI, MRI); + if (!Opc) + return 0; + + // Create a new predicated version of DefMI. + // Rfalse is the first use. + MachineInstrBuilder NewMI = BuildMI(*MI->getParent(), MI, MI->getDebugLoc(), + get(Opc), MI->getOperand(0).getReg()) + .addOperand(MI->getOperand(Invert ? 2 : 1)); + + // Copy all the DefMI operands, excluding its (null) predicate. + const MCInstrDesc &DefDesc = DefMI->getDesc(); + for (unsigned i = 1, e = DefDesc.getNumOperands(); + i != e && !DefDesc.OpInfo[i].isPredicate(); ++i) + NewMI.addOperand(DefMI->getOperand(i)); + + unsigned CondCode = MI->getOperand(3).getImm(); + if (Invert) + NewMI.addImm(ARMCC::getOppositeCondition(ARMCC::CondCodes(CondCode))); + else + NewMI.addImm(CondCode); + NewMI.addOperand(MI->getOperand(4)); + + // DefMI is not the -S version that sets CPSR, so add an optional %noreg. + if (NewMI->hasOptionalDef()) + AddDefaultCC(NewMI); + + // The caller will erase MI, but not DefMI. + DefMI->eraseFromParent(); + return NewMI; +} + /// Map pseudo instructions that imply an 'S' bit onto real opcodes. Whether the /// instruction is encoded with an 'S' bit is determined by the optional CPSR /// def operand. diff --git a/lib/Target/ARM/ARMBaseInstrInfo.h b/lib/Target/ARM/ARMBaseInstrInfo.h index 7a69b868c0..92e5ee8dcb 100644 --- a/lib/Target/ARM/ARMBaseInstrInfo.h +++ b/lib/Target/ARM/ARMBaseInstrInfo.h @@ -202,6 +202,13 @@ public: unsigned SrcReg2, int CmpMask, int CmpValue, const MachineRegisterInfo *MRI) const; + virtual bool analyzeSelect(const MachineInstr *MI, + SmallVectorImpl<MachineOperand> &Cond, + unsigned &TrueOp, unsigned &FalseOp, + bool &Optimizable) const; + + virtual MachineInstr *optimizeSelect(MachineInstr *MI, bool) const; + /// FoldImmediate - 'Reg' is known to be defined by a move immediate /// instruction, try to fold the immediate into the use instruction. virtual bool FoldImmediate(MachineInstr *UseMI, MachineInstr *DefMI, diff --git a/lib/Target/ARM/ARMISelLowering.cpp b/lib/Target/ARM/ARMISelLowering.cpp index a0284e6e15..77181cfcac 100644 --- a/lib/Target/ARM/ARMISelLowering.cpp +++ b/lib/Target/ARM/ARMISelLowering.cpp @@ -6762,54 +6762,6 @@ ARMTargetLowering::EmitInstrWithCustomInserter(MachineInstr *MI, return BB; } - case ARM::MOVCCr: - case ARM::t2MOVCCr: { - // MOVCCr instructions can fold one of its operands as a predicated - // instruction: - // - // %v1 = AND %v2, %v3 - // %v4 = MOVCCr %v5, %v1, CC - // - // Becomes: - // - // %v4 = ANDCCrr %v5, %v2, %v3, CC - // - const MachineRegisterInfo &MRI = MI->getParent()->getParent()->getRegInfo(); - MachineInstr *DefMI = 0; - unsigned Opc = canFoldARMInstrIntoMOVCC(MI->getOperand(2).getReg(), - DefMI, MRI); - bool Invert = !Opc; - if (!Opc) - Opc = canFoldARMInstrIntoMOVCC(MI->getOperand(1).getReg(), DefMI, MRI); - if (!Opc) - return BB; - - // Create a new predicated version of DefMI. - // Rfalse is the first use. - MachineInstrBuilder NewMI = BuildMI(*BB, MI, dl, TII->get(Opc), - MI->getOperand(0).getReg()) - .addOperand(MI->getOperand(Invert ? 2 : 1)); - - // Copy all the DefMI operands, excluding its (null) predicate. - const MCInstrDesc &DefDesc = DefMI->getDesc(); - for (unsigned i = 1, e = DefDesc.getNumOperands(); - i != e && !DefDesc.OpInfo[i].isPredicate(); ++i) - NewMI.addOperand(DefMI->getOperand(i)); - - unsigned CondCode = MI->getOperand(3).getImm(); - if (Invert) - NewMI.addImm(ARMCC::getOppositeCondition(ARMCC::CondCodes(CondCode))); - else - NewMI.addImm(CondCode); - NewMI.addOperand(MI->getOperand(4)); - - AddDefaultCC(NewMI); - - DefMI->eraseFromParent(); - MI->eraseFromParent(); - return BB; - } - case ARM::BCCi64: case ARM::BCCZi64: { // If there is an unconditional branch to the other successor, remove it. diff --git a/lib/Target/ARM/ARMInstrInfo.td b/lib/Target/ARM/ARMInstrInfo.td index 9da8f1c3e3..db83a9feb6 100644 --- a/lib/Target/ARM/ARMInstrInfo.td +++ b/lib/Target/ARM/ARMInstrInfo.td @@ -3939,7 +3939,7 @@ def BCCZi64 : PseudoInst<(outs), // a two-value operand where a dag node expects two operands. :( let neverHasSideEffects = 1 in { -let isCommutable = 1, usesCustomInserter = 1 in +let isCommutable = 1, isSelect = 1 in def MOVCCr : ARMPseudoInst<(outs GPR:$Rd), (ins GPR:$false, GPR:$Rm, pred:$p), 4, IIC_iCMOVr, [/*(set GPR:$Rd, (ARMcmov GPR:$false, GPR:$Rm, imm:$cc, CCR:$ccr))*/]>, diff --git a/lib/Target/ARM/ARMInstrThumb2.td b/lib/Target/ARM/ARMInstrThumb2.td index 79dc509fd5..2761b50f44 100644 --- a/lib/Target/ARM/ARMInstrThumb2.td +++ b/lib/Target/ARM/ARMInstrThumb2.td @@ -2938,7 +2938,7 @@ defm t2TEQ : T2I_cmp_irs<0b0100, "teq", // a two-value operand where a dag node expects two operands. :( let neverHasSideEffects = 1 in { -let isCommutable = 1, usesCustomInserter = 1 in +let isCommutable = 1, isSelect = 1 in def t2MOVCCr : t2PseudoInst<(outs rGPR:$Rd), (ins rGPR:$false, rGPR:$Rm, pred:$p), 4, IIC_iCMOVr, |