From: Tim Northover Date: Wed, 8 May 2019 10:59:08 +0000 (+0000) Subject: ARM: disallow SP as Rn for Thumb2 TST & TEQ instructions X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=a837f1edd83b96b35c10bd5429e5c3811e8bf29f;p=llvm ARM: disallow SP as Rn for Thumb2 TST & TEQ instructions Using SP in this position is unpredictable in ARMv7. CMP and CMN are not affected, and of course v8 relaxes this requirement, but that's handled elsewhere. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@360242 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Target/ARM/ARMInstrThumb2.td b/lib/Target/ARM/ARMInstrThumb2.td index a38980cc796..2909d03cca0 100644 --- a/lib/Target/ARM/ARMInstrThumb2.td +++ b/lib/Target/ARM/ARMInstrThumb2.td @@ -922,15 +922,15 @@ multiclass T2I_sh_ir opcod, string opc, Operand ty, SDNode opnode> { /// T2I_cmp_irs - Defines a set of (op r, {so_imm|r|so_reg}) cmp / test /// patterns. Similar to T2I_bin_irs except the instruction does not produce /// a explicit result, only implicitly set CPSR. -multiclass T2I_cmp_irs opcod, string opc, +multiclass T2I_cmp_irs opcod, string opc, RegisterClass LHSGPR, InstrItinClass iii, InstrItinClass iir, InstrItinClass iis, SDPatternOperator opnode> { let isCompare = 1, Defs = [CPSR] in { // shifted imm def ri : T2OneRegCmpImm< - (outs), (ins GPRnopc:$Rn, t2_so_imm:$imm), iii, + (outs), (ins LHSGPR:$Rn, t2_so_imm:$imm), iii, opc, ".w\t$Rn, $imm", - [(opnode GPRnopc:$Rn, t2_so_imm:$imm)]>, Sched<[WriteCMP]> { + [(opnode LHSGPR:$Rn, t2_so_imm:$imm)]>, Sched<[WriteCMP]> { let Inst{31-27} = 0b11110; let Inst{25} = 0; let Inst{24-21} = opcod; @@ -940,9 +940,9 @@ let isCompare = 1, Defs = [CPSR] in { } // register def rr : T2TwoRegCmp< - (outs), (ins GPRnopc:$Rn, rGPR:$Rm), iir, + (outs), (ins LHSGPR:$Rn, rGPR:$Rm), iir, opc, ".w\t$Rn, $Rm", - [(opnode GPRnopc:$Rn, rGPR:$Rm)]>, Sched<[WriteCMP]> { + [(opnode LHSGPR:$Rn, rGPR:$Rm)]>, Sched<[WriteCMP]> { let Inst{31-27} = 0b11101; let Inst{26-25} = 0b01; let Inst{24-21} = opcod; @@ -954,9 +954,9 @@ let isCompare = 1, Defs = [CPSR] in { } // shifted register def rs : T2OneRegCmpShiftedReg< - (outs), (ins GPRnopc:$Rn, t2_so_reg:$ShiftedRm), iis, + (outs), (ins LHSGPR:$Rn, t2_so_reg:$ShiftedRm), iis, opc, ".w\t$Rn, $ShiftedRm", - [(opnode GPRnopc:$Rn, t2_so_reg:$ShiftedRm)]>, + [(opnode LHSGPR:$Rn, t2_so_reg:$ShiftedRm)]>, Sched<[WriteCMPsi]> { let Inst{31-27} = 0b11101; let Inst{26-25} = 0b01; @@ -970,9 +970,9 @@ let isCompare = 1, Defs = [CPSR] in { // No alias here for 'rr' version as not all instantiations of this // multiclass want one (CMP in particular, does not). def : t2InstAlias(NAME#"ri") GPRnopc:$Rn, t2_so_imm:$imm, pred:$p)>; + (!cast(NAME#"ri") LHSGPR:$Rn, t2_so_imm:$imm, pred:$p)>; def : t2InstAlias(NAME#"rs") GPRnopc:$Rn, t2_so_reg:$shift, pred:$p)>; + (!cast(NAME#"rs") LHSGPR:$Rn, t2_so_reg:$shift, pred:$p)>; } /// T2I_ld - Defines a set of (op r, {imm12|imm8|so_reg}) load patterns. @@ -3058,7 +3058,7 @@ def t2CRC32CW : T2I_crc32<1, 0b10, "cw", int_arm_crc32cw>; //===----------------------------------------------------------------------===// // Comparison Instructions... // -defm t2CMP : T2I_cmp_irs<0b1101, "cmp", +defm t2CMP : T2I_cmp_irs<0b1101, "cmp", GPRnopc, IIC_iCMPi, IIC_iCMPr, IIC_iCMPsi, ARMcmp>; def : T2Pat<(ARMcmpZ GPRnopc:$lhs, t2_so_imm:$imm), @@ -3126,10 +3126,10 @@ def : T2Pat<(ARMcmp GPR:$src, t2_so_imm_neg:$imm), def : T2Pat<(ARMcmpZ GPRnopc:$src, t2_so_imm_neg:$imm), (t2CMNri GPRnopc:$src, t2_so_imm_neg:$imm)>; -defm t2TST : T2I_cmp_irs<0b0000, "tst", +defm t2TST : T2I_cmp_irs<0b0000, "tst", rGPR, IIC_iTSTi, IIC_iTSTr, IIC_iTSTsi, BinOpFrag<(ARMcmpZ (and_su node:$LHS, node:$RHS), 0)>>; -defm t2TEQ : T2I_cmp_irs<0b0100, "teq", +defm t2TEQ : T2I_cmp_irs<0b0100, "teq", rGPR, IIC_iTSTi, IIC_iTSTr, IIC_iTSTsi, BinOpFrag<(ARMcmpZ (xor_su node:$LHS, node:$RHS), 0)>>; @@ -4551,9 +4551,9 @@ def : t2InstAlias<"sub${s}${p} $Rdn, $ShiftedRm", def : t2InstAlias<"cmn${p} $Rn, $Rm", (t2CMNzrr GPRnopc:$Rn, rGPR:$Rm, pred:$p)>; def : t2InstAlias<"teq${p} $Rn, $Rm", - (t2TEQrr GPRnopc:$Rn, rGPR:$Rm, pred:$p)>; + (t2TEQrr rGPR:$Rn, rGPR:$Rm, pred:$p)>; def : t2InstAlias<"tst${p} $Rn, $Rm", - (t2TSTrr GPRnopc:$Rn, rGPR:$Rm, pred:$p)>; + (t2TSTrr rGPR:$Rn, rGPR:$Rm, pred:$p)>; // Memory barriers def : InstAlias<"dmb${p}", (t2DMB 0xf, pred:$p), 0>, Requires<[HasDB]>; diff --git a/test/CodeGen/ARM/GlobalISel/thumb-select-br.mir b/test/CodeGen/ARM/GlobalISel/thumb-select-br.mir index e7cec0260e0..6c5719d0930 100644 --- a/test/CodeGen/ARM/GlobalISel/thumb-select-br.mir +++ b/test/CodeGen/ARM/GlobalISel/thumb-select-br.mir @@ -21,7 +21,7 @@ body: | %0(s32) = COPY $r0 ; CHECK: [[COND32:%[0-9]+]]:gpr = COPY $r0 %1(s1) = G_TRUNC %0(s32) - ; CHECK: [[COND:%[0-9]+]]:gprnopc = COPY [[COND32]] + ; CHECK: [[COND:%[0-9]+]]:rgpr = COPY [[COND32]] G_BRCOND %1(s1), %bb.1 ; CHECK: t2TSTri [[COND]], 1, 14, $noreg, implicit-def $cpsr diff --git a/test/CodeGen/ARM/GlobalISel/thumb-select-select.mir b/test/CodeGen/ARM/GlobalISel/thumb-select-select.mir index 290ce548a3b..42e20cb32c5 100644 --- a/test/CodeGen/ARM/GlobalISel/thumb-select-select.mir +++ b/test/CodeGen/ARM/GlobalISel/thumb-select-select.mir @@ -26,10 +26,9 @@ body: | ; CHECK: [[VREGY:%[0-9]+]]:rgpr = COPY $r1 %2(s1) = G_TRUNC %1(s32) - ; CHECK: [[VREGC:%[0-9]+]]:gprnopc = COPY [[VREGY]] %3(s32) = G_SELECT %2(s1), %0, %1 - ; CHECK: t2TSTri [[VREGC]], 1, 14, $noreg, implicit-def $cpsr + ; CHECK: t2TSTri [[VREGY]], 1, 14, $noreg, implicit-def $cpsr ; CHECK: [[RES:%[0-9]+]]:rgpr = t2MOVCCr [[VREGX]], [[VREGY]], 0, $cpsr $r0 = COPY %3(s32) @@ -65,7 +64,7 @@ body: | ; CHECK: [[VREGC32:%[0-9]+]]:gpr = COPY $r2 %3(s1) = G_TRUNC %2(s32) - ; CHECK: [[VREGC:%[0-9]+]]:gprnopc = COPY [[VREGC32]] + ; CHECK: [[VREGC:%[0-9]+]]:rgpr = COPY [[VREGC32]] %4(p0) = G_SELECT %3(s1), %0, %1 ; CHECK: t2TSTri [[VREGC]], 1, 14, $noreg, implicit-def $cpsr diff --git a/test/MC/ARM/thumb2-diagnostics.s b/test/MC/ARM/thumb2-diagnostics.s index b784d79fa43..fdbcd11b481 100644 --- a/test/MC/ARM/thumb2-diagnostics.s +++ b/test/MC/ARM/thumb2-diagnostics.s @@ -151,3 +151,17 @@ foo2: adds r0 @ CHECK-ERRORS: error: too few operands for instruction @ CHECK-ERRORS: error: too few operands for instruction + + tst sp, #3 + tst sp, r5 + tst sp, r5, lsl #3 +@ CHECK-ERRORS-V7: error: operand must be a register in range [r0, r12] or r14 +@ CHECK-ERRORS-V7: operand must be a register in range [r0, r12] or r14 +@ CHECK-ERRORS-V7: operand must be a register in range [r0, r12] or r14 + + teq sp, #5 + teq sp, r7 + teq sp, r9, lsl #2 +@ CHECK-ERRORS-V7: error: operand must be a register in range [r0, r12] or r14 +@ CHECK-ERRORS-V7: operand must be a register in range [r0, r12] or r14 +@ CHECK-ERRORS-V7: operand must be a register in range [r0, r12] or r14