summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJohn Brawn <john.brawn@arm.com>2017-02-21 16:41:29 +0000
committerJohn Brawn <john.brawn@arm.com>2017-02-21 16:41:29 +0000
commita6e95e1652bf42239562f86a665898530becd83f (patch)
treeb5b0f2f7c4add9ee08b55d755307698e6e47139b
parentf98a32fa7fbeb4599a341785f1c190346cee001c (diff)
downloadbcm5719-llvm-a6e95e1652bf42239562f86a665898530becd83f.tar.gz
bcm5719-llvm-a6e95e1652bf42239562f86a665898530becd83f.zip
[ARM] Correct SP/PC handling in t2MOVr
PC isn't allowed in the source operand of t2MOVr, so change the register class to one without PC. SP handling is slightly trickier and changes depending on if we're in ARMv8, so do that in checkTargetMatchPredicate. Differential Revision: https://reviews.llvm.org/D30199 llvm-svn: 295732
-rw-r--r--llvm/lib/Target/ARM/ARMInstrThumb2.td8
-rw-r--r--llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp16
2 files changed, 20 insertions, 4 deletions
diff --git a/llvm/lib/Target/ARM/ARMInstrThumb2.td b/llvm/lib/Target/ARM/ARMInstrThumb2.td
index eb67059b209..fdf718db09d 100644
--- a/llvm/lib/Target/ARM/ARMInstrThumb2.td
+++ b/llvm/lib/Target/ARM/ARMInstrThumb2.td
@@ -1828,7 +1828,7 @@ defm t2STM : thumb2_st_mult<"stm", IIC_iStore_m, IIC_iStore_mu, 0>;
//
let hasSideEffects = 0 in
-def t2MOVr : T2sTwoReg<(outs GPRnopc:$Rd), (ins GPR:$Rm), IIC_iMOVr,
+def t2MOVr : T2sTwoReg<(outs GPRnopc:$Rd), (ins GPRnopc:$Rm), IIC_iMOVr,
"mov", ".w\t$Rd, $Rm", []>, Sched<[WriteALU]> {
let Inst{31-27} = 0b11101;
let Inst{26-25} = 0b01;
@@ -1837,11 +1837,11 @@ def t2MOVr : T2sTwoReg<(outs GPRnopc:$Rd), (ins GPR:$Rm), IIC_iMOVr,
let Inst{14-12} = 0b000;
let Inst{7-4} = 0b0000;
}
-def : t2InstAlias<"mov${p}.w $Rd, $Rm", (t2MOVr GPRnopc:$Rd, GPR:$Rm,
+def : t2InstAlias<"mov${p}.w $Rd, $Rm", (t2MOVr GPRnopc:$Rd, GPRnopc:$Rm,
pred:$p, zero_reg)>;
-def : t2InstAlias<"movs${p}.w $Rd, $Rm", (t2MOVr GPRnopc:$Rd, GPR:$Rm,
+def : t2InstAlias<"movs${p}.w $Rd, $Rm", (t2MOVr GPRnopc:$Rd, GPRnopc:$Rm,
pred:$p, CPSR)>;
-def : t2InstAlias<"movs${p} $Rd, $Rm", (t2MOVr GPRnopc:$Rd, GPR:$Rm,
+def : t2InstAlias<"movs${p} $Rd, $Rm", (t2MOVr GPRnopc:$Rd, GPRnopc:$Rm,
pred:$p, CPSR)>;
// AddedComplexity to ensure isel tries t2MOVi before t2MOVi16.
diff --git a/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp b/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp
index c243a2d3597..2493e71d5e8 100644
--- a/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp
+++ b/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp
@@ -8932,6 +8932,22 @@ unsigned ARMAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
return Match_RequiresV6;
}
+ // Before ARMv8 the rules for when SP is allowed in t2MOVr are more complex
+ // than the loop below can handle, so it uses the GPRnopc register class and
+ // we do SP handling here.
+ if (Opc == ARM::t2MOVr && !hasV8Ops())
+ {
+ // SP as both source and destination is not allowed
+ if (Inst.getOperand(0).getReg() == ARM::SP &&
+ Inst.getOperand(1).getReg() == ARM::SP)
+ return Match_RequiresV8;
+ // When flags-setting SP as either source or destination is not allowed
+ if (Inst.getOperand(4).getReg() == ARM::CPSR &&
+ (Inst.getOperand(0).getReg() == ARM::SP ||
+ Inst.getOperand(1).getReg() == ARM::SP))
+ return Match_RequiresV8;
+ }
+
for (unsigned I = 0; I < MCID.NumOperands; ++I)
if (MCID.OpInfo[I].RegClass == ARM::rGPRRegClassID) {
// rGPRRegClass excludes PC, and also excluded SP before ARMv8
OpenPOWER on IntegriCloud