forked from OSchip/llvm-project
				
			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. llvm-svn: 360242
This commit is contained in:
		
							parent
							
								
									cced3ecc35
								
							
						
					
					
						commit
						18adcf331b
					
				| 
						 | 
					@ -922,15 +922,15 @@ multiclass T2I_sh_ir<bits<2> opcod, string opc, Operand ty, SDNode opnode> {
 | 
				
			||||||
/// T2I_cmp_irs - Defines a set of (op r, {so_imm|r|so_reg}) cmp / test
 | 
					/// 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
 | 
					/// patterns. Similar to T2I_bin_irs except the instruction does not produce
 | 
				
			||||||
/// a explicit result, only implicitly set CPSR.
 | 
					/// a explicit result, only implicitly set CPSR.
 | 
				
			||||||
multiclass T2I_cmp_irs<bits<4> opcod, string opc,
 | 
					multiclass T2I_cmp_irs<bits<4> opcod, string opc, RegisterClass LHSGPR,
 | 
				
			||||||
                     InstrItinClass iii, InstrItinClass iir, InstrItinClass iis,
 | 
					                     InstrItinClass iii, InstrItinClass iir, InstrItinClass iis,
 | 
				
			||||||
                     SDPatternOperator opnode> {
 | 
					                     SDPatternOperator opnode> {
 | 
				
			||||||
let isCompare = 1, Defs = [CPSR] in {
 | 
					let isCompare = 1, Defs = [CPSR] in {
 | 
				
			||||||
   // shifted imm
 | 
					   // shifted imm
 | 
				
			||||||
   def ri : T2OneRegCmpImm<
 | 
					   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",
 | 
					                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{31-27} = 0b11110;
 | 
				
			||||||
     let Inst{25} = 0;
 | 
					     let Inst{25} = 0;
 | 
				
			||||||
     let Inst{24-21} = opcod;
 | 
					     let Inst{24-21} = opcod;
 | 
				
			||||||
| 
						 | 
					@ -940,9 +940,9 @@ let isCompare = 1, Defs = [CPSR] in {
 | 
				
			||||||
   }
 | 
					   }
 | 
				
			||||||
   // register
 | 
					   // register
 | 
				
			||||||
   def rr : T2TwoRegCmp<
 | 
					   def rr : T2TwoRegCmp<
 | 
				
			||||||
                (outs), (ins GPRnopc:$Rn, rGPR:$Rm), iir,
 | 
					                (outs), (ins LHSGPR:$Rn, rGPR:$Rm), iir,
 | 
				
			||||||
                opc, ".w\t$Rn, $Rm",
 | 
					                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{31-27} = 0b11101;
 | 
				
			||||||
     let Inst{26-25} = 0b01;
 | 
					     let Inst{26-25} = 0b01;
 | 
				
			||||||
     let Inst{24-21} = opcod;
 | 
					     let Inst{24-21} = opcod;
 | 
				
			||||||
| 
						 | 
					@ -954,9 +954,9 @@ let isCompare = 1, Defs = [CPSR] in {
 | 
				
			||||||
   }
 | 
					   }
 | 
				
			||||||
   // shifted register
 | 
					   // shifted register
 | 
				
			||||||
   def rs : T2OneRegCmpShiftedReg<
 | 
					   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",
 | 
					                opc, ".w\t$Rn, $ShiftedRm",
 | 
				
			||||||
                [(opnode GPRnopc:$Rn, t2_so_reg:$ShiftedRm)]>,
 | 
					                [(opnode LHSGPR:$Rn, t2_so_reg:$ShiftedRm)]>,
 | 
				
			||||||
                Sched<[WriteCMPsi]> {
 | 
					                Sched<[WriteCMPsi]> {
 | 
				
			||||||
     let Inst{31-27} = 0b11101;
 | 
					     let Inst{31-27} = 0b11101;
 | 
				
			||||||
     let Inst{26-25} = 0b01;
 | 
					     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
 | 
					  // No alias here for 'rr' version as not all instantiations of this
 | 
				
			||||||
  // multiclass want one (CMP in particular, does not).
 | 
					  // multiclass want one (CMP in particular, does not).
 | 
				
			||||||
  def : t2InstAlias<!strconcat(opc, "${p}", " $Rn, $imm"),
 | 
					  def : t2InstAlias<!strconcat(opc, "${p}", " $Rn, $imm"),
 | 
				
			||||||
     (!cast<Instruction>(NAME#"ri") GPRnopc:$Rn, t2_so_imm:$imm, pred:$p)>;
 | 
					     (!cast<Instruction>(NAME#"ri") LHSGPR:$Rn, t2_so_imm:$imm, pred:$p)>;
 | 
				
			||||||
  def : t2InstAlias<!strconcat(opc, "${p}", " $Rn, $shift"),
 | 
					  def : t2InstAlias<!strconcat(opc, "${p}", " $Rn, $shift"),
 | 
				
			||||||
     (!cast<Instruction>(NAME#"rs") GPRnopc:$Rn, t2_so_reg:$shift, pred:$p)>;
 | 
					     (!cast<Instruction>(NAME#"rs") LHSGPR:$Rn, t2_so_reg:$shift, pred:$p)>;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/// T2I_ld - Defines a set of (op r, {imm12|imm8|so_reg}) load patterns.
 | 
					/// 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...
 | 
					//  Comparison Instructions...
 | 
				
			||||||
//
 | 
					//
 | 
				
			||||||
defm t2CMP  : T2I_cmp_irs<0b1101, "cmp",
 | 
					defm t2CMP  : T2I_cmp_irs<0b1101, "cmp", GPRnopc,
 | 
				
			||||||
                          IIC_iCMPi, IIC_iCMPr, IIC_iCMPsi, ARMcmp>;
 | 
					                          IIC_iCMPi, IIC_iCMPr, IIC_iCMPsi, ARMcmp>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def : T2Pat<(ARMcmpZ  GPRnopc:$lhs, t2_so_imm:$imm),
 | 
					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),
 | 
					def : T2Pat<(ARMcmpZ GPRnopc:$src, t2_so_imm_neg:$imm),
 | 
				
			||||||
            (t2CMNri 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,
 | 
					                          IIC_iTSTi, IIC_iTSTr, IIC_iTSTsi,
 | 
				
			||||||
                         BinOpFrag<(ARMcmpZ (and_su node:$LHS, node:$RHS), 0)>>;
 | 
					                         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,
 | 
					                          IIC_iTSTi, IIC_iTSTr, IIC_iTSTsi,
 | 
				
			||||||
                         BinOpFrag<(ARMcmpZ (xor_su node:$LHS, node:$RHS), 0)>>;
 | 
					                         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",
 | 
					def : t2InstAlias<"cmn${p} $Rn, $Rm",
 | 
				
			||||||
                  (t2CMNzrr GPRnopc:$Rn, rGPR:$Rm, pred:$p)>;
 | 
					                  (t2CMNzrr GPRnopc:$Rn, rGPR:$Rm, pred:$p)>;
 | 
				
			||||||
def : t2InstAlias<"teq${p} $Rn, $Rm",
 | 
					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",
 | 
					def : t2InstAlias<"tst${p} $Rn, $Rm",
 | 
				
			||||||
                  (t2TSTrr GPRnopc:$Rn, rGPR:$Rm, pred:$p)>;
 | 
					                  (t2TSTrr rGPR:$Rn, rGPR:$Rm, pred:$p)>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Memory barriers
 | 
					// Memory barriers
 | 
				
			||||||
def : InstAlias<"dmb${p}", (t2DMB 0xf, pred:$p), 0>, Requires<[HasDB]>;
 | 
					def : InstAlias<"dmb${p}", (t2DMB 0xf, pred:$p), 0>, Requires<[HasDB]>;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -21,7 +21,7 @@ body:             |
 | 
				
			||||||
    %0(s32) = COPY $r0
 | 
					    %0(s32) = COPY $r0
 | 
				
			||||||
    ; CHECK: [[COND32:%[0-9]+]]:gpr = COPY $r0
 | 
					    ; CHECK: [[COND32:%[0-9]+]]:gpr = COPY $r0
 | 
				
			||||||
    %1(s1) = G_TRUNC %0(s32)
 | 
					    %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
 | 
					    G_BRCOND %1(s1), %bb.1
 | 
				
			||||||
    ; CHECK: t2TSTri [[COND]], 1, 14, $noreg, implicit-def $cpsr
 | 
					    ; CHECK: t2TSTri [[COND]], 1, 14, $noreg, implicit-def $cpsr
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -26,10 +26,9 @@ body:             |
 | 
				
			||||||
    ; CHECK: [[VREGY:%[0-9]+]]:rgpr = COPY $r1
 | 
					    ; CHECK: [[VREGY:%[0-9]+]]:rgpr = COPY $r1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    %2(s1) = G_TRUNC %1(s32)
 | 
					    %2(s1) = G_TRUNC %1(s32)
 | 
				
			||||||
    ; CHECK: [[VREGC:%[0-9]+]]:gprnopc = COPY [[VREGY]]
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    %3(s32) = G_SELECT %2(s1),  %0, %1
 | 
					    %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
 | 
					    ; CHECK: [[RES:%[0-9]+]]:rgpr = t2MOVCCr [[VREGX]], [[VREGY]], 0, $cpsr
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    $r0 = COPY %3(s32)
 | 
					    $r0 = COPY %3(s32)
 | 
				
			||||||
| 
						 | 
					@ -65,7 +64,7 @@ body:             |
 | 
				
			||||||
    ; CHECK: [[VREGC32:%[0-9]+]]:gpr = COPY $r2
 | 
					    ; CHECK: [[VREGC32:%[0-9]+]]:gpr = COPY $r2
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    %3(s1) = G_TRUNC %2(s32)
 | 
					    %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
 | 
					    %4(p0) = G_SELECT %3(s1),  %0, %1
 | 
				
			||||||
    ; CHECK: t2TSTri [[VREGC]], 1, 14, $noreg, implicit-def $cpsr
 | 
					    ; CHECK: t2TSTri [[VREGC]], 1, 14, $noreg, implicit-def $cpsr
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -151,3 +151,17 @@ foo2:
 | 
				
			||||||
        adds r0
 | 
					        adds r0
 | 
				
			||||||
@ CHECK-ERRORS: error: too few operands for instruction
 | 
					@ CHECK-ERRORS: error: too few operands for instruction
 | 
				
			||||||
@ 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
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue