aboutsummaryrefslogtreecommitdiff
path: root/lib/Target
diff options
context:
space:
mode:
authorJakob Stoklund Olesen <stoklund@2pi.dk>2012-08-16 23:14:20 +0000
committerJakob Stoklund Olesen <stoklund@2pi.dk>2012-08-16 23:14:20 +0000
commit053b5b0b3c34d4763511b6dcd8e0150f8e9dd083 (patch)
tree989c3c0d1eedf009f110607eff9e4d972799fa01 /lib/Target
parentf2c64ef519b38a4328809b27b4a3a8e0c26e9709 (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.cpp67
-rw-r--r--lib/Target/ARM/ARMBaseInstrInfo.h7
-rw-r--r--lib/Target/ARM/ARMISelLowering.cpp48
-rw-r--r--lib/Target/ARM/ARMInstrInfo.td2
-rw-r--r--lib/Target/ARM/ARMInstrThumb2.td2
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,