aboutsummaryrefslogtreecommitdiffstats
path: root/lib/Target/ARM
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Target/ARM')
-rw-r--r--lib/Target/ARM/ARMBaseInstrInfo.cpp49
-rw-r--r--lib/Target/ARM/ARMBaseInstrInfo.h5
-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, 104 insertions, 2 deletions
diff --git a/lib/Target/ARM/ARMBaseInstrInfo.cpp b/lib/Target/ARM/ARMBaseInstrInfo.cpp
index 057fd71..aa45253 100644
--- a/lib/Target/ARM/ARMBaseInstrInfo.cpp
+++ b/lib/Target/ARM/ARMBaseInstrInfo.cpp
@@ -1568,6 +1568,55 @@ ARMBaseInstrInfo::commuteInstruction(MachineInstr *MI, bool NewMI) const {
return TargetInstrInfoImpl::commuteInstruction(MI, NewMI);
}
+/// 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) {
+ if (!TargetRegisterInfo::isVirtualRegister(Reg))
+ return 0;
+ if (!MRI.hasOneNonDBGUse(Reg))
+ return 0;
+ MI = MRI.getVRegDef(Reg);
+ if (!MI)
+ return 0;
+ // Check if MI has any non-dead defs or physreg uses. This also detects
+ // predicated instructions which will be reading CPSR.
+ for (unsigned i = 1, e = MI->getNumOperands(); i != e; ++i) {
+ const MachineOperand &MO = MI->getOperand(i);
+ if (!MO.isReg())
+ continue;
+ if (TargetRegisterInfo::isPhysicalRegister(MO.getReg()))
+ return 0;
+ if (MO.isDef() && !MO.isDead())
+ return 0;
+ }
+ switch (MI->getOpcode()) {
+ default: return 0;
+ case ARM::ANDri: return ARM::ANDCCri;
+ case ARM::ANDrr: return ARM::ANDCCrr;
+ case ARM::ANDrsi: return ARM::ANDCCrsi;
+ case ARM::ANDrsr: return ARM::ANDCCrsr;
+ case ARM::t2ANDri: return ARM::t2ANDCCri;
+ case ARM::t2ANDrr: return ARM::t2ANDCCrr;
+ case ARM::t2ANDrs: return ARM::t2ANDCCrs;
+ case ARM::EORri: return ARM::EORCCri;
+ case ARM::EORrr: return ARM::EORCCrr;
+ case ARM::EORrsi: return ARM::EORCCrsi;
+ case ARM::EORrsr: return ARM::EORCCrsr;
+ case ARM::t2EORri: return ARM::t2EORCCri;
+ case ARM::t2EORrr: return ARM::t2EORCCrr;
+ case ARM::t2EORrs: return ARM::t2EORCCrs;
+ case ARM::ORRri: return ARM::ORRCCri;
+ case ARM::ORRrr: return ARM::ORRCCrr;
+ case ARM::ORRrsi: return ARM::ORRCCrsi;
+ case ARM::ORRrsr: return ARM::ORRCCrsr;
+ case ARM::t2ORRri: return ARM::t2ORRCCri;
+ case ARM::t2ORRrr: return ARM::t2ORRCCrr;
+ case ARM::t2ORRrs: return ARM::t2ORRCCrs;
+ }
+}
+
/// 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 1a10a4a..7a69b86 100644
--- a/lib/Target/ARM/ARMBaseInstrInfo.h
+++ b/lib/Target/ARM/ARMBaseInstrInfo.h
@@ -352,6 +352,11 @@ ARMCC::CondCodes getInstrPredicate(const MachineInstr *MI, unsigned &PredReg);
int getMatchingCondBranchOpcode(int Opc);
+/// Determine if MI can be folded into an ARM MOVCC instruction, and return the
+/// opcode of the SSA instruction representing the conditional MI.
+unsigned canFoldARMInstrIntoMOVCC(unsigned Reg,
+ MachineInstr *&MI,
+ const MachineRegisterInfo &MRI);
/// 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
diff --git a/lib/Target/ARM/ARMISelLowering.cpp b/lib/Target/ARM/ARMISelLowering.cpp
index 77181cf..a0284e6 100644
--- a/lib/Target/ARM/ARMISelLowering.cpp
+++ b/lib/Target/ARM/ARMISelLowering.cpp
@@ -6762,6 +6762,54 @@ 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 76c897c..9da8f1c 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 in
+let isCommutable = 1, usesCustomInserter = 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 d2d24c8..79dc509 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 in
+let isCommutable = 1, usesCustomInserter = 1 in
def t2MOVCCr : t2PseudoInst<(outs rGPR:$Rd),
(ins rGPR:$false, rGPR:$Rm, pred:$p),
4, IIC_iCMOVr,