diff --git a/llvm/lib/Target/ARM/ARMAsmPrinter.cpp b/llvm/lib/Target/ARM/ARMAsmPrinter.cpp --- a/llvm/lib/Target/ARM/ARMAsmPrinter.cpp +++ b/llvm/lib/Target/ARM/ARMAsmPrinter.cpp @@ -1170,10 +1170,16 @@ break; case ARM::ADDri: case ARM::t2ADDri: + case ARM::t2ADDri12: + case ARM::t2ADDspImm: + case ARM::t2ADDspImm12: Offset = -MI->getOperand(2).getImm(); break; case ARM::SUBri: case ARM::t2SUBri: + case ARM::t2SUBri12: + case ARM::t2SUBspImm: + case ARM::t2SUBspImm12: Offset = MI->getOperand(2).getImm(); break; case ARM::tSUBspi: diff --git a/llvm/lib/Target/ARM/ARMBaseInstrInfo.cpp b/llvm/lib/Target/ARM/ARMBaseInstrInfo.cpp --- a/llvm/lib/Target/ARM/ARMBaseInstrInfo.cpp +++ b/llvm/lib/Target/ARM/ARMBaseInstrInfo.cpp @@ -2864,10 +2864,14 @@ case ARM::t2RSBri: case ARM::t2ADDrr: case ARM::t2ADDri: + case ARM::t2ADDspImm: + case ARM::t2ADDspImm12: case ARM::t2ADCrr: case ARM::t2ADCri: case ARM::t2SUBrr: case ARM::t2SUBri: + case ARM::t2SUBspImm: + case ARM::t2SUBspImm12: case ARM::t2SBCrr: case ARM::t2SBCri: case ARM::ANDrr: @@ -3276,22 +3280,26 @@ } break; case ARM::t2ADDrr: - case ARM::t2SUBrr: + case ARM::t2SUBrr: { if (UseOpc == ARM::t2SUBrr && Commute) return false; // ADD/SUB are special because they're essentially the same operation, so // we can handle a larger range of immediates. + const bool ToSP = DefMI.getOperand(0).getReg() == ARM::SP; + const unsigned t2ADD = ToSP ? ARM::t2ADDspImm : ARM::t2ADDri; + const unsigned t2SUB = ToSP ? ARM::t2SUBspImm : ARM::t2SUBri; if (ARM_AM::isT2SOImmTwoPartVal(ImmVal)) - NewUseOpc = UseOpc == ARM::t2ADDrr ? ARM::t2ADDri : ARM::t2SUBri; + NewUseOpc = UseOpc == ARM::t2ADDrr ? t2ADD : t2SUB; else if (ARM_AM::isT2SOImmTwoPartVal(-ImmVal)) { ImmVal = -ImmVal; - NewUseOpc = UseOpc == ARM::t2ADDrr ? ARM::t2SUBri : ARM::t2ADDri; + NewUseOpc = UseOpc == ARM::t2ADDrr ? t2SUB : t2ADD; } else return false; SOImmValV1 = (uint32_t)ARM_AM::getT2SOImmTwoPartFirst(ImmVal); SOImmValV2 = (uint32_t)ARM_AM::getT2SOImmTwoPartSecond(ImmVal); break; + } case ARM::t2ORRrr: case ARM::t2EORrr: if (!ARM_AM::isT2SOImmTwoPartVal(ImmVal)) diff --git a/llvm/lib/Target/ARM/ARMFrameLowering.cpp b/llvm/lib/Target/ARM/ARMFrameLowering.cpp --- a/llvm/lib/Target/ARM/ARMFrameLowering.cpp +++ b/llvm/lib/Target/ARM/ARMFrameLowering.cpp @@ -1526,7 +1526,10 @@ } // t2ADDri will not require an extra register, it can reuse the // destination. - if (MI.getOpcode() == ARM::t2ADDri || MI.getOpcode() == ARM::t2ADDri12) + if (MI.getOpcode() == ARM::t2ADDri || + MI.getOpcode() == ARM::t2ADDri12 || + MI.getOpcode() == ARM::t2ADDspImm || + MI.getOpcode() == ARM::t2ADDspImm12) break; const MCInstrDesc &MCID = MI.getDesc(); diff --git a/llvm/lib/Target/ARM/ARMInstrThumb2.td b/llvm/lib/Target/ARM/ARMInstrThumb2.td --- a/llvm/lib/Target/ARM/ARMInstrThumb2.td +++ b/llvm/lib/Target/ARM/ARMInstrThumb2.td @@ -917,10 +917,33 @@ // The register-immediate version is re-materializable. This is useful // in particular for taking the address of a local. let isReMaterializable = 1 in { + def spImm : T2sTwoRegImm< + (outs GPRsp:$Rd), (ins GPRsp:$Rn, t2_so_imm:$imm), IIC_iALUi, + opc, ".w\t$Rd, $Rn, $imm", + []>, + Sched<[WriteALU, ReadALU]> { + bits<4> Rn = 13; + bits<4> Rd = 13; + bits<12> imm; + + let Inst{31-27} = 0b11110; + let Inst{26} = imm{11}; + let Inst{25-24} = 0b01; + let Inst{23-21} = op23_21; + let Inst{20} = 0; + let Inst{19-16} = Rn; + let Inst{15} = 0; + let Inst{14-12} = imm{10-8}; + let Inst{11-8} = Rd; + let Inst{7-0} = imm{7-0}; + + let DecoderMethod = "DecodeT2AddSubSPImm"; + } + def ri : T2sTwoRegImm< - (outs GPRnopc:$Rd), (ins GPRnopc:$Rn, t2_so_imm:$imm), IIC_iALUi, + (outs rGPR:$Rd), (ins GPRnopc:$Rn, t2_so_imm:$imm), IIC_iALUi, opc, ".w\t$Rd, $Rn, $imm", - [(set GPRnopc:$Rd, (opnode GPRnopc:$Rn, t2_so_imm:$imm))]>, + [(set rGPR:$Rd, (opnode GPRnopc:$Rn, t2_so_imm:$imm))]>, Sched<[WriteALU, ReadALU]> { let Inst{31-27} = 0b11110; let Inst{25} = 0; @@ -931,9 +954,9 @@ } // 12-bit imm def ri12 : T2I< - (outs GPRnopc:$Rd), (ins GPR:$Rn, imm0_4095:$imm), IIC_iALUi, + (outs rGPR:$Rd), (ins GPR:$Rn, imm0_4095:$imm), IIC_iALUi, !strconcat(opc, "w"), "\t$Rd, $Rn, $imm", - [(set GPRnopc:$Rd, (opnode GPR:$Rn, imm0_4095:$imm))]>, + [(set rGPR:$Rd, (opnode GPR:$Rn, imm0_4095:$imm))]>, Sched<[WriteALU, ReadALU]> { bits<4> Rd; bits<4> Rn; @@ -949,6 +972,26 @@ let Inst{11-8} = Rd; let Inst{7-0} = imm{7-0}; } + def spImm12 : T2I< + (outs GPRsp:$Rd), (ins GPRsp:$Rn, imm0_4095:$imm), IIC_iALUi, + !strconcat(opc, "w"), "\t$Rd, $Rn, $imm", + []>, + Sched<[WriteALU, ReadALU]> { + bits<4> Rd = 13; + bits<4> Rn = 13; + bits<12> imm; + let Inst{31-27} = 0b11110; + let Inst{26} = imm{11}; + let Inst{25-24} = 0b10; + let Inst{23-21} = op23_21; + let Inst{20} = 0; + let Inst{19-16} = Rn; + let Inst{15} = 0; + let Inst{14-12} = imm{10-8}; + let Inst{11-8} = Rd; + let Inst{7-0} = imm{7-0}; + let DecoderMethod = "DecodeT2AddSubSPImm"; + } // register def rr : T2sThreeReg<(outs GPRnopc:$Rd), (ins GPRnopc:$Rn, rGPR:$Rm), IIC_iALUr, opc, ".w\t$Rd, $Rn, $Rm", @@ -2264,19 +2307,37 @@ (t2ADCri rGPR:$rd, rGPR:$rn, t2_so_imm_not:$imm, pred:$p, s_cc_out:$s)>; def : t2InstSubst<"add${s}${p}.w $rd, $rn, $imm", - (t2SUBri GPRnopc:$rd, GPRnopc:$rn, t2_so_imm_neg:$imm, pred:$p, s_cc_out:$s)>; + (t2SUBri rGPR:$rd, GPRnopc:$rn, t2_so_imm_neg:$imm, pred:$p, s_cc_out:$s)>; +def : t2InstSubst<"addw${p} $rd, $rn, $imm", + (t2SUBri12 rGPR:$rd, GPR:$rn, t2_so_imm_neg:$imm, pred:$p)>; +def : t2InstSubst<"sub${s}${p}.w $rd, $rn, $imm", + (t2ADDri rGPR:$rd, GPRnopc:$rn, t2_so_imm_neg:$imm, pred:$p, s_cc_out:$s)>; +def : t2InstSubst<"subw${p} $rd, $rn, $imm", + (t2ADDri12 rGPR:$rd, GPR:$rn, t2_so_imm_neg:$imm, pred:$p)>; +def : t2InstSubst<"subw${p} $Rd, $Rn, $imm", + (t2ADDri12 rGPR:$Rd, GPR:$Rn, imm0_4095_neg:$imm, pred:$p)>; +def : t2InstSubst<"sub${s}${p} $rd, $rn, $imm", + (t2ADDri rGPR:$rd, GPRnopc:$rn, t2_so_imm_neg:$imm, pred:$p, s_cc_out:$s)>; +def : t2InstSubst<"sub${p} $rd, $rn, $imm", + (t2ADDri12 rGPR:$rd, GPR:$rn, t2_so_imm_neg:$imm, pred:$p)>; + +// SP to SP alike +def : t2InstSubst<"add${s}${p}.w $rd, $rn, $imm", + (t2SUBspImm GPRsp:$rd, GPRsp:$rn, t2_so_imm_neg:$imm, pred:$p, s_cc_out:$s)>; def : t2InstSubst<"addw${p} $rd, $rn, $imm", - (t2SUBri12 GPRnopc:$rd, GPR:$rn, t2_so_imm_neg:$imm, pred:$p)>; + (t2SUBspImm12 GPRsp:$rd, GPRsp:$rn, t2_so_imm_neg:$imm, pred:$p)>; def : t2InstSubst<"sub${s}${p}.w $rd, $rn, $imm", - (t2ADDri GPRnopc:$rd, GPRnopc:$rn, t2_so_imm_neg:$imm, pred:$p, s_cc_out:$s)>; + (t2ADDspImm GPRsp:$rd, GPRsp:$rn, t2_so_imm_neg:$imm, pred:$p, s_cc_out:$s)>; def : t2InstSubst<"subw${p} $rd, $rn, $imm", - (t2ADDri12 GPRnopc:$rd, GPR:$rn, t2_so_imm_neg:$imm, pred:$p)>; + (t2ADDspImm12 GPRsp:$rd, GPRsp:$rn, t2_so_imm_neg:$imm, pred:$p)>; def : t2InstSubst<"subw${p} $Rd, $Rn, $imm", - (t2ADDri12 GPRnopc:$Rd, GPR:$Rn, imm0_4095_neg:$imm, pred:$p)>; + (t2ADDspImm12 GPRsp:$Rd, GPRsp:$Rn, imm0_4095_neg:$imm, pred:$p)>; def : t2InstSubst<"sub${s}${p} $rd, $rn, $imm", - (t2ADDri GPRnopc:$rd, GPRnopc:$rn, t2_so_imm_neg:$imm, pred:$p, s_cc_out:$s)>; + (t2ADDspImm GPRsp:$rd, GPRsp:$rn, t2_so_imm_neg:$imm, pred:$p, s_cc_out:$s)>; def : t2InstSubst<"sub${p} $rd, $rn, $imm", - (t2ADDri12 GPRnopc:$rd, GPR:$rn, t2_so_imm_neg:$imm, pred:$p)>; + (t2ADDspImm12 GPRsp:$rd, GPRsp:$rn, t2_so_imm_neg:$imm, pred:$p)>; + + // RSB defm t2RSB : T2I_rbin_irs <0b1110, "rsb", sub>; @@ -2292,12 +2353,19 @@ // The AddedComplexity preferences the first variant over the others since // it can be shrunk to a 16-bit wide encoding, while the others cannot. let AddedComplexity = 1 in -def : T2Pat<(add GPR:$src, imm1_255_neg:$imm), - (t2SUBri GPR:$src, imm1_255_neg:$imm)>; -def : T2Pat<(add GPR:$src, t2_so_imm_neg:$imm), - (t2SUBri GPR:$src, t2_so_imm_neg:$imm)>; -def : T2Pat<(add GPR:$src, imm0_4095_neg:$imm), - (t2SUBri12 GPR:$src, imm0_4095_neg:$imm)>; +def : T2Pat<(add rGPR:$src, imm1_255_neg:$imm), + (t2SUBri rGPR:$src, imm1_255_neg:$imm)>; +def : T2Pat<(add rGPR:$src, t2_so_imm_neg:$imm), + (t2SUBri rGPR:$src, t2_so_imm_neg:$imm)>; +def : T2Pat<(add rGPR:$src, imm0_4095_neg:$imm), + (t2SUBri12 rGPR:$src, imm0_4095_neg:$imm)>; +// SP to SP alike +def : T2Pat<(add GPRsp:$src, imm1_255_neg:$imm), + (t2SUBspImm GPRsp:$src, imm1_255_neg:$imm)>; +def : T2Pat<(add GPRsp:$src, t2_so_imm_neg:$imm), + (t2SUBspImm GPRsp:$src, t2_so_imm_neg:$imm)>; +def : T2Pat<(add GPRsp:$src, imm0_4095_neg:$imm), + (t2SUBspImm12 GPRsp:$src, imm0_4095_neg:$imm)>; def : T2Pat<(add GPR:$src, imm0_65535_neg:$imm), (t2SUBrr GPR:$src, (t2MOVi16 (imm_neg_XFORM imm:$imm)))>; @@ -2796,10 +2864,16 @@ // Thumb2SizeReduction's chances later on we select a t2ADD for an or where // possible. def : T2Pat<(or AddLikeOrOp:$Rn, t2_so_imm:$imm), - (t2ADDri $Rn, t2_so_imm:$imm)>; + (t2ADDri rGPR:$Rn, t2_so_imm:$imm)>; + +def : T2Pat<(or AddLikeOrOp:$Rn, t2_so_imm:$imm), + (t2ADDspImm GPRsp:$Rn, t2_so_imm:$imm)>; def : T2Pat<(or AddLikeOrOp:$Rn, imm0_4095:$Rm), - (t2ADDri12 $Rn, imm0_4095:$Rm)>; + (t2ADDri12 rGPR:$Rn, imm0_4095:$Rm)>; + +def : T2Pat<(or AddLikeOrOp:$Rn, imm0_4095:$Rm), + (t2ADDspImm12 GPRsp:$Rn, imm0_4095:$Rm)>; def : T2Pat<(or AddLikeOrOp:$Rn, non_imm32:$Rm), (t2ADDrr $Rn, $Rm)>; @@ -4655,10 +4729,10 @@ // Aliases for ADD without the ".w" optional width specifier. def : t2InstAlias<"add${s}${p} $Rd, $Rn, $imm", - (t2ADDri GPRnopc:$Rd, GPRnopc:$Rn, t2_so_imm:$imm, pred:$p, + (t2ADDri rGPR:$Rd, GPRnopc:$Rn, t2_so_imm:$imm, pred:$p, cc_out:$s)>; def : t2InstAlias<"add${p} $Rd, $Rn, $imm", - (t2ADDri12 GPRnopc:$Rd, GPR:$Rn, imm0_4095:$imm, pred:$p)>; + (t2ADDri12 rGPR:$Rd, GPR:$Rn, imm0_4095:$imm, pred:$p)>; def : t2InstAlias<"add${s}${p} $Rd, $Rn, $Rm", (t2ADDrr GPRnopc:$Rd, GPRnopc:$Rn, rGPR:$Rm, pred:$p, cc_out:$s)>; def : t2InstAlias<"add${s}${p} $Rd, $Rn, $ShiftedRm", @@ -4666,9 +4740,9 @@ pred:$p, cc_out:$s)>; // ... and with the destination and source register combined. def : t2InstAlias<"add${s}${p} $Rdn, $imm", - (t2ADDri GPRnopc:$Rdn, GPRnopc:$Rdn, t2_so_imm:$imm, pred:$p, cc_out:$s)>; + (t2ADDri rGPR:$Rdn, rGPR:$Rdn, t2_so_imm:$imm, pred:$p, cc_out:$s)>; def : t2InstAlias<"add${p} $Rdn, $imm", - (t2ADDri12 GPRnopc:$Rdn, GPRnopc:$Rdn, imm0_4095:$imm, pred:$p)>; + (t2ADDri12 rGPR:$Rdn, rGPR:$Rdn, imm0_4095:$imm, pred:$p)>; def : t2InstAlias<"add${s}${p} $Rdn, $Rm", (t2ADDrr GPRnopc:$Rdn, GPRnopc:$Rdn, rGPR:$Rm, pred:$p, cc_out:$s)>; def : t2InstAlias<"add${s}${p} $Rdn, $ShiftedRm", @@ -4677,33 +4751,33 @@ // add w/ negative immediates is just a sub. def : t2InstSubst<"add${s}${p} $Rd, $Rn, $imm", - (t2SUBri GPRnopc:$Rd, GPRnopc:$Rn, t2_so_imm_neg:$imm, pred:$p, + (t2SUBri rGPR:$Rd, GPRnopc:$Rn, t2_so_imm_neg:$imm, pred:$p, cc_out:$s)>; def : t2InstSubst<"add${p} $Rd, $Rn, $imm", - (t2SUBri12 GPRnopc:$Rd, GPR:$Rn, imm0_4095_neg:$imm, pred:$p)>; + (t2SUBri12 rGPR:$Rd, GPR:$Rn, imm0_4095_neg:$imm, pred:$p)>; def : t2InstSubst<"add${s}${p} $Rdn, $imm", - (t2SUBri GPRnopc:$Rdn, GPRnopc:$Rdn, t2_so_imm_neg:$imm, pred:$p, + (t2SUBri rGPR:$Rdn, rGPR:$Rdn, t2_so_imm_neg:$imm, pred:$p, cc_out:$s)>; def : t2InstSubst<"add${p} $Rdn, $imm", - (t2SUBri12 GPRnopc:$Rdn, GPRnopc:$Rdn, imm0_4095_neg:$imm, pred:$p)>; + (t2SUBri12 rGPR:$Rdn, rGPR:$Rdn, imm0_4095_neg:$imm, pred:$p)>; def : t2InstSubst<"add${s}${p}.w $Rd, $Rn, $imm", - (t2SUBri GPRnopc:$Rd, GPRnopc:$Rn, t2_so_imm_neg:$imm, pred:$p, + (t2SUBri rGPR:$Rd, GPRnopc:$Rn, t2_so_imm_neg:$imm, pred:$p, cc_out:$s)>; def : t2InstSubst<"addw${p} $Rd, $Rn, $imm", - (t2SUBri12 GPRnopc:$Rd, GPR:$Rn, imm0_4095_neg:$imm, pred:$p)>; + (t2SUBri12 rGPR:$Rd, rGPR:$Rn, imm0_4095_neg:$imm, pred:$p)>; def : t2InstSubst<"add${s}${p}.w $Rdn, $imm", - (t2SUBri GPRnopc:$Rdn, GPRnopc:$Rdn, t2_so_imm_neg:$imm, pred:$p, + (t2SUBri rGPR:$Rdn, rGPR:$Rdn, t2_so_imm_neg:$imm, pred:$p, cc_out:$s)>; def : t2InstSubst<"addw${p} $Rdn, $imm", - (t2SUBri12 GPRnopc:$Rdn, GPRnopc:$Rdn, imm0_4095_neg:$imm, pred:$p)>; + (t2SUBri12 rGPR:$Rdn, rGPR:$Rdn, imm0_4095_neg:$imm, pred:$p)>; // Aliases for SUB without the ".w" optional width specifier. def : t2InstAlias<"sub${s}${p} $Rd, $Rn, $imm", - (t2SUBri GPRnopc:$Rd, GPRnopc:$Rn, t2_so_imm:$imm, pred:$p, cc_out:$s)>; + (t2SUBri rGPR:$Rd, GPRnopc:$Rn, t2_so_imm:$imm, pred:$p, cc_out:$s)>; def : t2InstAlias<"sub${p} $Rd, $Rn, $imm", - (t2SUBri12 GPRnopc:$Rd, GPR:$Rn, imm0_4095:$imm, pred:$p)>; + (t2SUBri12 rGPR:$Rd, rGPR:$Rn, imm0_4095:$imm, pred:$p)>; def : t2InstAlias<"sub${s}${p} $Rd, $Rn, $Rm", (t2SUBrr GPRnopc:$Rd, GPRnopc:$Rn, rGPR:$Rm, pred:$p, cc_out:$s)>; def : t2InstAlias<"sub${s}${p} $Rd, $Rn, $ShiftedRm", @@ -4711,9 +4785,9 @@ pred:$p, cc_out:$s)>; // ... and with the destination and source register combined. def : t2InstAlias<"sub${s}${p} $Rdn, $imm", - (t2SUBri GPRnopc:$Rdn, GPRnopc:$Rdn, t2_so_imm:$imm, pred:$p, cc_out:$s)>; + (t2SUBri rGPR:$Rdn, rGPR:$Rdn, t2_so_imm:$imm, pred:$p, cc_out:$s)>; def : t2InstAlias<"sub${p} $Rdn, $imm", - (t2SUBri12 GPRnopc:$Rdn, GPRnopc:$Rdn, imm0_4095:$imm, pred:$p)>; + (t2SUBri12 rGPR:$Rdn, rGPR:$Rdn, imm0_4095:$imm, pred:$p)>; def : t2InstAlias<"sub${s}${p}.w $Rdn, $Rm", (t2SUBrr GPRnopc:$Rdn, GPRnopc:$Rdn, rGPR:$Rm, pred:$p, cc_out:$s)>; def : t2InstAlias<"sub${s}${p} $Rdn, $Rm", @@ -4722,6 +4796,60 @@ (t2SUBrs GPRnopc:$Rdn, GPRnopc:$Rdn, t2_so_reg:$ShiftedRm, pred:$p, cc_out:$s)>; +// SP to SP alike aliases +// Aliases for ADD without the ".w" optional width specifier. +def : t2InstAlias<"add${s}${p} $Rd, $Rn, $imm", + (t2ADDspImm GPRsp:$Rd, GPRsp:$Rn, t2_so_imm:$imm, pred:$p, + cc_out:$s)>; +def : t2InstAlias<"add${p} $Rd, $Rn, $imm", + (t2ADDspImm12 GPRsp:$Rd, GPRsp:$Rn, imm0_4095:$imm, pred:$p)>; +def : t2InstAlias<"add${s}${p} $Rd, $Rn, $ShiftedRm", + (t2ADDrs GPRsp:$Rd, GPRsp:$Rn, t2_so_reg:$ShiftedRm, + pred:$p, cc_out:$s)>; +// ... and with the destination and source register combined. +def : t2InstAlias<"add${s}${p} $Rdn, $imm", + (t2ADDspImm GPRsp:$Rdn, GPRsp:$Rdn, t2_so_imm:$imm, pred:$p, cc_out:$s)>; +def : t2InstAlias<"add${p} $Rdn, $imm", + (t2ADDspImm12 GPRsp:$Rdn, GPRsp:$Rdn, imm0_4095:$imm, pred:$p)>; +def : t2InstAlias<"add${s}${p} $Rdn, $ShiftedRm", + (t2ADDrs GPRsp:$Rdn, GPRsp:$Rdn, t2_so_reg:$ShiftedRm, + pred:$p, cc_out:$s)>; + +// add w/ negative immediates is just a sub. +def : t2InstSubst<"add${s}${p} $Rd, $Rn, $imm", + (t2SUBspImm GPRsp:$Rd, GPRsp:$Rn, t2_so_imm_neg:$imm, pred:$p, + cc_out:$s)>; +def : t2InstSubst<"add${p} $Rd, $Rn, $imm", + (t2SUBspImm12 GPRsp:$Rd, GPRsp:$Rn, imm0_4095_neg:$imm, pred:$p)>; +def : t2InstSubst<"add${s}${p} $Rdn, $imm", + (t2SUBspImm GPRsp:$Rdn, GPRsp:$Rdn, t2_so_imm_neg:$imm, pred:$p, + cc_out:$s)>; +def : t2InstSubst<"add${p} $Rdn, $imm", + (t2SUBspImm12 GPRsp:$Rdn, GPRsp:$Rdn, imm0_4095_neg:$imm, pred:$p)>; + +def : t2InstSubst<"add${s}${p}.w $Rd, $Rn, $imm", + (t2SUBspImm GPRsp:$Rd, GPRsp:$Rn, t2_so_imm_neg:$imm, pred:$p, + cc_out:$s)>; +def : t2InstSubst<"addw${p} $Rd, $Rn, $imm", + (t2SUBspImm12 GPRsp:$Rd, GPRsp:$Rn, imm0_4095_neg:$imm, pred:$p)>; +def : t2InstSubst<"add${s}${p}.w $Rdn, $imm", + (t2SUBspImm GPRsp:$Rdn, GPRsp:$Rdn, t2_so_imm_neg:$imm, pred:$p, + cc_out:$s)>; +def : t2InstSubst<"addw${p} $Rdn, $imm", + (t2SUBspImm12 GPRsp:$Rdn, GPRsp:$Rdn, imm0_4095_neg:$imm, pred:$p)>; + + +// Aliases for SUB without the ".w" optional width specifier. +def : t2InstAlias<"sub${s}${p} $Rd, $Rn, $imm", + (t2SUBspImm GPRsp:$Rd, GPRsp:$Rn, t2_so_imm:$imm, pred:$p, cc_out:$s)>; +def : t2InstAlias<"sub${p} $Rd, $Rn, $imm", + (t2SUBspImm12 GPRsp:$Rd, GPRsp:$Rn, imm0_4095:$imm, pred:$p)>; +// ... and with the destination and source register combined. +def : t2InstAlias<"sub${s}${p} $Rdn, $imm", + (t2SUBspImm GPRsp:$Rdn, GPRsp:$Rdn, t2_so_imm:$imm, pred:$p, cc_out:$s)>; +def : t2InstAlias<"sub${p} $Rdn, $imm", + (t2SUBspImm12 GPRsp:$Rdn, GPRsp:$Rdn, imm0_4095:$imm, pred:$p)>; + // Alias for compares without the ".w" optional width specifier. def : t2InstAlias<"cmn${p} $Rn, $Rm", (t2CMNzrr GPRnopc:$Rn, rGPR:$Rm, pred:$p)>; @@ -4978,10 +5106,16 @@ pred:$p, cc_out:$s)>; // Likewise, "add Rd, t2_so_imm_neg" -> sub def : t2InstSubst<"add${s}${p} $Rd, $Rn, $imm", - (t2SUBri GPRnopc:$Rd, GPRnopc:$Rn, t2_so_imm_neg:$imm, + (t2SUBri rGPR:$Rd, GPRnopc:$Rn, t2_so_imm_neg:$imm, + pred:$p, cc_out:$s)>; +def : t2InstSubst<"add${s}${p} $Rd, $Rn, $imm", + (t2SUBspImm GPRsp:$Rd, GPRsp:$Rn, t2_so_imm_neg:$imm, + pred:$p, cc_out:$s)>; +def : t2InstSubst<"add${s}${p} $Rd, $imm", + (t2SUBri rGPR:$Rd, rGPR:$Rd, t2_so_imm_neg:$imm, pred:$p, cc_out:$s)>; def : t2InstSubst<"add${s}${p} $Rd, $imm", - (t2SUBri GPRnopc:$Rd, GPRnopc:$Rd, t2_so_imm_neg:$imm, + (t2SUBspImm GPRsp:$Rd, GPRsp:$Rd, t2_so_imm_neg:$imm, pred:$p, cc_out:$s)>; // Same for CMP <--> CMN via t2_so_imm_neg def : t2InstSubst<"cmp${p} $Rd, $imm", diff --git a/llvm/lib/Target/ARM/ARMLoadStoreOptimizer.cpp b/llvm/lib/Target/ARM/ARMLoadStoreOptimizer.cpp --- a/llvm/lib/Target/ARM/ARMLoadStoreOptimizer.cpp +++ b/llvm/lib/Target/ARM/ARMLoadStoreOptimizer.cpp @@ -696,18 +696,21 @@ return nullptr; } - int BaseOpc = - isThumb2 ? ARM::t2ADDri : - (isThumb1 && Base == ARM::SP) ? ARM::tADDrSPi : - (isThumb1 && Offset < 8) ? ARM::tADDi3 : - isThumb1 ? ARM::tADDi8 : ARM::ADDri; + int BaseOpc = isThumb2 ? (BaseKill && Base == ARM::SP ? ARM::t2ADDspImm + : ARM::t2ADDri) + : (isThumb1 && Base == ARM::SP) + ? ARM::tADDrSPi + : (isThumb1 && Offset < 8) + ? ARM::tADDi3 + : isThumb1 ? ARM::tADDi8 : ARM::ADDri; if (Offset < 0) { - Offset = - Offset; - BaseOpc = - isThumb2 ? ARM::t2SUBri : - (isThumb1 && Offset < 8 && Base != ARM::SP) ? ARM::tSUBi3 : - isThumb1 ? ARM::tSUBi8 : ARM::SUBri; + Offset = -Offset; + BaseOpc = isThumb2 ? (BaseKill && Base == ARM::SP ? ARM::t2SUBspImm + : ARM::t2SUBri) + : (isThumb1 && Offset < 8 && Base != ARM::SP) + ? ARM::tSUBi3 + : isThumb1 ? ARM::tSUBi8 : ARM::SUBri; } if (!TL->isLegalAddImmediate(Offset)) @@ -1183,15 +1186,36 @@ bool CheckCPSRDef; int Scale; switch (MI.getOpcode()) { - case ARM::tADDi8: Scale = 4; CheckCPSRDef = true; break; - case ARM::tSUBi8: Scale = -4; CheckCPSRDef = true; break; + case ARM::tADDi8: + Scale = 4; + CheckCPSRDef = true; + break; + case ARM::tSUBi8: + Scale = -4; + CheckCPSRDef = true; + break; case ARM::t2SUBri: - case ARM::SUBri: Scale = -1; CheckCPSRDef = true; break; + case ARM::t2SUBspImm: + case ARM::SUBri: + Scale = -1; + CheckCPSRDef = true; + break; case ARM::t2ADDri: - case ARM::ADDri: Scale = 1; CheckCPSRDef = true; break; - case ARM::tADDspi: Scale = 4; CheckCPSRDef = false; break; - case ARM::tSUBspi: Scale = -4; CheckCPSRDef = false; break; - default: return 0; + case ARM::t2ADDspImm: + case ARM::ADDri: + Scale = 1; + CheckCPSRDef = true; + break; + case ARM::tADDspi: + Scale = 4; + CheckCPSRDef = false; + break; + case ARM::tSUBspi: + Scale = -4; + CheckCPSRDef = false; + break; + default: + return 0; } unsigned MIPredReg; diff --git a/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp b/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp --- a/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp +++ b/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp @@ -7720,6 +7720,13 @@ return Error(Operands[4]->getStartLoc(), "source register must be sp if destination is sp"); break; + case ARM::t2ADDspImm: + case ARM::t2ADDspImm12: + if (Inst.getOperand(0).getReg() != ARM::SP || + Inst.getOperand(1).getReg() != ARM::SP) + return Error(Operands[4]->getStartLoc(), + "source and destination registers must be sp"); + break; // Final range checking for Thumb unconditional branch instructions. case ARM::tB: @@ -9758,13 +9765,22 @@ Inst.setOpcode(ARM::t2ADDri); Inst.addOperand(MCOperand::createReg(0)); // cc_out break; - case ARM::t2SUBri12: + case ARM::t2ADDspImm12: + // If the immediate fits for encoding T3 (t2ADDspImm) and the generic "add" + // mnemonic was used (not "addw"), encoding T3 is preferred. + if (static_cast(*Operands[0]).getToken() != "add" || + ARM_AM::getT2SOImmVal(Inst.getOperand(2).getImm()) == -1) + break; + Inst.setOpcode(ARM::t2ADDspImm); + Inst.addOperand(MCOperand::createReg(0)); // cc_out + break; + case ARM::t2SUBspImm12: // If the immediate fits for encoding T3 (t2SUBri) and the generic "sub" // mnemonic was used (not "subw"), encoding T3 is preferred. if (static_cast(*Operands[0]).getToken() != "sub" || ARM_AM::getT2SOImmVal(Inst.getOperand(2).getImm()) == -1) break; - Inst.setOpcode(ARM::t2SUBri); + Inst.setOpcode(ARM::t2SUBspImm); Inst.addOperand(MCOperand::createReg(0)); // cc_out break; case ARM::tADDi8: @@ -9788,7 +9804,9 @@ } break; case ARM::t2ADDri: - case ARM::t2SUBri: { + case ARM::t2SUBri: + case ARM::t2ADDspImm: + case ARM::t2SUBspImm: { // If the destination and first source operand are the same, and // the flags are compatible with the current IT status, use encoding T2 // instead of T3. For compatibility with the system 'as'. Make sure the @@ -9801,8 +9819,9 @@ HasWideQualifier) break; MCInst TmpInst; - TmpInst.setOpcode(Inst.getOpcode() == ARM::t2ADDri ? - ARM::tADDi8 : ARM::tSUBi8); + const bool IsAdd = + Inst.getOpcode() == ARM::t2ADDri || Inst.getOpcode() == ARM::t2ADDspImm; + TmpInst.setOpcode(IsAdd ? ARM::tADDi8 : ARM::tSUBi8); TmpInst.addOperand(Inst.getOperand(0)); TmpInst.addOperand(Inst.getOperand(5)); TmpInst.addOperand(Inst.getOperand(0)); diff --git a/llvm/lib/Target/ARM/Disassembler/ARMDisassembler.cpp b/llvm/lib/Target/ARM/Disassembler/ARMDisassembler.cpp --- a/llvm/lib/Target/ARM/Disassembler/ARMDisassembler.cpp +++ b/llvm/lib/Target/ARM/Disassembler/ARMDisassembler.cpp @@ -204,6 +204,9 @@ uint64_t Address, const void *Decoder); static DecodeStatus DecodeGPRPairRegisterClass(MCInst &Inst, unsigned RegNo, uint64_t Address, const void *Decoder); +static DecodeStatus DecodeGPRspRegisterClass(MCInst &Inst, unsigned RegNo, + uint64_t Address, + const void *Decoder); static DecodeStatus DecodeHPRRegisterClass(MCInst &Inst, unsigned RegNo, uint64_t Address, const void *Decoder); static DecodeStatus DecodeSPRRegisterClass(MCInst &Inst, unsigned RegNo, @@ -566,6 +569,9 @@ static DecodeStatus DecodeMVEOverlappingLongShift(MCInst &Inst, unsigned Insn, uint64_t Address, const void *Decoder); +static DecodeStatus DecodeT2AddSubSPImm(MCInst &Inst, unsigned Insn, + uint64_t Address, const void *Decoder); + #include "ARMGenDisassemblerTables.inc" static MCDisassembler *createARMDisassembler(const Target &T, @@ -1231,6 +1237,17 @@ return S; } +static DecodeStatus DecodeGPRspRegisterClass(MCInst &Inst, unsigned RegNo, + uint64_t Address, + const void *Decoder) { + if (RegNo != 13) + return MCDisassembler::Fail; + + unsigned Register = GPRDecoderTable[RegNo]; + Inst.addOperand(MCOperand::createReg(Register)); + return MCDisassembler::Success; +} + static DecodeStatus DecodetcGPRRegisterClass(MCInst &Inst, unsigned RegNo, uint64_t Address, const void *Decoder) { unsigned Register = 0; @@ -6595,3 +6612,42 @@ Inst.addOperand(MCOperand::createReg(ARM::VPR)); return S; } + +static DecodeStatus DecodeT2AddSubSPImm(MCInst &Inst, unsigned Insn, + uint64_t Address, const void *Decoder) { + const unsigned Rd = fieldFromInstruction(Insn, 8, 4); + const unsigned Rn = fieldFromInstruction(Insn, 16, 4); + const unsigned Imm12 = fieldFromInstruction(Insn, 26, 1) << 11 | + fieldFromInstruction(Insn, 12, 3) << 8 | + fieldFromInstruction(Insn, 0, 8); + const unsigned TypeT3 = fieldFromInstruction(Insn, 25, 1); + // T3 does a zext of imm12, where T2 does a ThumbExpandImm (T2SOImm) + DecodeStatus DS = MCDisassembler::Success; + if (TypeT3) { + Inst.setOpcode(ARM::t2ADDspImm12); + if ((!Check(DS, + DecodeGPRspRegisterClass(Inst, Rd, Address, Decoder))) || // dst + (!Check(DS, DecodeGPRspRegisterClass(Inst, Rn, Address, Decoder)))) + return MCDisassembler::Fail; + + Inst.addOperand(MCOperand::createImm(Imm12)); // zext imm12 + + if (!Check(DS, DecodeCCOutOperand(Inst, 0, Address, Decoder))) // cc_out + return MCDisassembler::Fail; + + } else { + Inst.setOpcode(ARM::t2ADDspImm); + const unsigned S = fieldFromInstruction(Insn, 20, 1); + if ((!Check(DS, + DecodeGPRspRegisterClass(Inst, Rd, Address, Decoder))) || // dst + (!Check(DS, + DecodeGPRspRegisterClass(Inst, Rn, Address, Decoder))) || // src + (!Check(DS, DecodeT2SOImm(Inst, Imm12, Address, Decoder))) || // imm12 + (!Check(DS, DecodeCCOutOperand(Inst, S, Address, Decoder)))) // cc_out + return MCDisassembler::Fail; + } + + Inst.addOperand(MCOperand::createReg(0)); // pred + + return DS; +} \ No newline at end of file diff --git a/llvm/lib/Target/ARM/Thumb2InstrInfo.cpp b/llvm/lib/Target/ARM/Thumb2InstrInfo.cpp --- a/llvm/lib/Target/ARM/Thumb2InstrInfo.cpp +++ b/llvm/lib/Target/ARM/Thumb2InstrInfo.cpp @@ -303,50 +303,43 @@ continue; } + // Try to use T1, as it smaller + if ((DestReg == ARM::SP) && (ThisVal < ((1 << 7) - 1) * 4)) { + assert((ThisVal & 3) == 0 && "Stack update is not multiple of 4?"); + Opc = isSub ? ARM::tSUBspi : ARM::tADDspi; + BuildMI(MBB, MBBI, dl, TII.get(Opc), DestReg) + .addReg(BaseReg) + .addImm(ThisVal / 4) + .setMIFlags(MIFlags) + .add(predOps(ARMCC::AL)); + break; + } bool HasCCOut = true; - if (BaseReg == ARM::SP) { - // sub sp, sp, #imm7 - if (DestReg == ARM::SP && (ThisVal < ((1 << 7)-1) * 4)) { - assert((ThisVal & 3) == 0 && "Stack update is not multiple of 4?"); - Opc = isSub ? ARM::tSUBspi : ARM::tADDspi; - BuildMI(MBB, MBBI, dl, TII.get(Opc), DestReg) - .addReg(BaseReg) - .addImm(ThisVal / 4) - .setMIFlags(MIFlags) - .add(predOps(ARMCC::AL)); - NumBytes = 0; - continue; - } - - // sub rd, sp, so_imm - Opc = isSub ? ARM::t2SUBri : ARM::t2ADDri; - if (ARM_AM::getT2SOImmVal(NumBytes) != -1) { - NumBytes = 0; - } else { - // FIXME: Move this to ARMAddressingModes.h? - unsigned RotAmt = countLeadingZeros(ThisVal); - ThisVal = ThisVal & ARM_AM::rotr32(0xff000000U, RotAmt); - NumBytes &= ~ThisVal; - assert(ARM_AM::getT2SOImmVal(ThisVal) != -1 && - "Bit extraction didn't work?"); - } + int ImmIsT2SO = ARM_AM::getT2SOImmVal(ThisVal); + bool ToSP = DestReg == ARM::SP; + assert((ToSP?DestReg == BaseReg:true) && "Writing to SP, from other register."); + unsigned t2SUB = ToSP ? ARM::t2SUBspImm : ARM::t2SUBri; + unsigned t2ADD = ToSP ? ARM::t2ADDspImm : ARM::t2ADDri; + unsigned t2SUBi12 = ToSP ? ARM::t2SUBspImm12 : ARM::t2SUBri12; + unsigned t2ADDi12 = ToSP ? ARM::t2ADDspImm12 : ARM::t2ADDri12; + Opc = isSub ? t2SUB : t2ADD; + // Prefer T2: sub rd, rn, so_imm | sub sp, sp, so_imm + if (ImmIsT2SO != -1) { + NumBytes = 0; + } else if (ThisVal < 4096) { + // Prefer T3 if can make it in a single go: subw rd, rn, imm12 | subw sp, + // sp, imm12 + Opc = isSub ? t2SUBi12 : t2ADDi12; + HasCCOut = false; + NumBytes = 0; } else { - assert(DestReg != ARM::SP && BaseReg != ARM::SP); - Opc = isSub ? ARM::t2SUBri : ARM::t2ADDri; - if (ARM_AM::getT2SOImmVal(NumBytes) != -1) { - NumBytes = 0; - } else if (ThisVal < 4096) { - Opc = isSub ? ARM::t2SUBri12 : ARM::t2ADDri12; - HasCCOut = false; - NumBytes = 0; - } else { - // FIXME: Move this to ARMAddressingModes.h? - unsigned RotAmt = countLeadingZeros(ThisVal); - ThisVal = ThisVal & ARM_AM::rotr32(0xff000000U, RotAmt); - NumBytes &= ~ThisVal; - assert(ARM_AM::getT2SOImmVal(ThisVal) != -1 && - "Bit extraction didn't work?"); - } + // Use one T2 instruction to reduce NumBytes + // FIXME: Move this to ARMAddressingModes.h? + unsigned RotAmt = countLeadingZeros(ThisVal); + ThisVal = ThisVal & ARM_AM::rotr32(0xff000000U, RotAmt); + NumBytes &= ~ThisVal; + assert(ARM_AM::getT2SOImmVal(ThisVal) != -1 && + "Bit extraction didn't work?"); } // Build the new ADD / SUB. @@ -492,8 +485,9 @@ if (Opcode == ARM::INLINEASM || Opcode == ARM::INLINEASM_BR) AddrMode = ARMII::AddrModeT2_i12; // FIXME. mode for thumb2? - if (Opcode == ARM::t2ADDri || Opcode == ARM::t2ADDri12) { - Offset += MI.getOperand(FrameRegIdx+1).getImm(); + const bool IsSP = Opcode == ARM::t2ADDspImm12 || Opcode == ARM::t2ADDspImm; + if (IsSP || Opcode == ARM::t2ADDri || Opcode == ARM::t2ADDri12) { + Offset += MI.getOperand(FrameRegIdx + 1).getImm(); unsigned PredReg; if (Offset == 0 && getInstrPredicate(MI, PredReg) == ARMCC::AL && @@ -509,14 +503,14 @@ return true; } - bool HasCCOut = Opcode != ARM::t2ADDri12; + bool HasCCOut = (Opcode != ARM::t2ADDspImm12 && Opcode != ARM::t2ADDri12); if (Offset < 0) { Offset = -Offset; isSub = true; - MI.setDesc(TII.get(ARM::t2SUBri)); + MI.setDesc(IsSP ? TII.get(ARM::t2SUBspImm) : TII.get(ARM::t2SUBri)); } else { - MI.setDesc(TII.get(ARM::t2ADDri)); + MI.setDesc(IsSP ? TII.get(ARM::t2ADDspImm) : TII.get(ARM::t2ADDri)); } // Common case: small offset, fits into instruction. @@ -531,14 +525,15 @@ } // Another common case: imm12. if (Offset < 4096 && - (!HasCCOut || MI.getOperand(MI.getNumOperands()-1).getReg() == 0)) { - unsigned NewOpc = isSub ? ARM::t2SUBri12 : ARM::t2ADDri12; + (!HasCCOut || MI.getOperand(MI.getNumOperands() - 1).getReg() == 0)) { + unsigned NewOpc = isSub ? IsSP ? ARM::t2SUBspImm12 : ARM::t2SUBri12 + : IsSP ? ARM::t2ADDspImm12 : ARM::t2ADDri12; MI.setDesc(TII.get(NewOpc)); MI.getOperand(FrameRegIdx).ChangeToRegister(FrameReg, false); - MI.getOperand(FrameRegIdx+1).ChangeToImmediate(Offset); + MI.getOperand(FrameRegIdx + 1).ChangeToImmediate(Offset); // Remove the cc_out operand. if (HasCCOut) - MI.RemoveOperand(MI.getNumOperands()-1); + MI.RemoveOperand(MI.getNumOperands() - 1); Offset = 0; return true; } diff --git a/llvm/lib/Target/ARM/Thumb2SizeReduction.cpp b/llvm/lib/Target/ARM/Thumb2SizeReduction.cpp --- a/llvm/lib/Target/ARM/Thumb2SizeReduction.cpp +++ b/llvm/lib/Target/ARM/Thumb2SizeReduction.cpp @@ -82,6 +82,8 @@ // Wide, Narrow1, Narrow2, imm1,imm2, lo1, lo2, P/C,PF,S,AM { ARM::t2ADCrr, 0, ARM::tADC, 0, 0, 0, 1, 0,0, 0,0,0 }, { ARM::t2ADDri, ARM::tADDi3, ARM::tADDi8, 3, 8, 1, 1, 0,0, 0,1,0 }, + { ARM::t2ADDspImm,ARM::tADDi3,ARM::tADDi8, 3, 8, 1, 1, 0,0, 0,1,0 }, + { ARM::t2ADDspImm12,ARM::tADDi3,ARM::tADDi8, 3, 8, 1, 1, 0,0, 0,1,0 }, { ARM::t2ADDrr, ARM::tADDrr, ARM::tADDhirr, 0, 0, 1, 0, 0,1, 0,0,0 }, { ARM::t2ADDSri,ARM::tADDi3, ARM::tADDi8, 3, 8, 1, 1, 2,2, 0,1,0 }, { ARM::t2ADDSrr,ARM::tADDrr, 0, 0, 0, 1, 0, 2,0, 0,1,0 }, @@ -116,6 +118,8 @@ { ARM::t2RSBSri,ARM::tRSB, 0, 0, 0, 1, 0, 2,0, 0,1,0 }, { ARM::t2SBCrr, 0, ARM::tSBC, 0, 0, 0, 1, 0,0, 0,0,0 }, { ARM::t2SUBri, ARM::tSUBi3, ARM::tSUBi8, 3, 8, 1, 1, 0,0, 0,0,0 }, + { ARM::t2SUBspImm,ARM::tSUBi3,ARM::tSUBi8, 3, 8, 1, 1, 0,0, 0,0,0 }, + { ARM::t2SUBspImm12,ARM::tSUBi3,ARM::tSUBi8, 3, 8, 1, 1, 0,0, 0,0,0 }, { ARM::t2SUBrr, ARM::tSUBrr, 0, 0, 0, 1, 0, 0,0, 0,0,0 }, { ARM::t2SUBSri,ARM::tSUBi3, ARM::tSUBi8, 3, 8, 1, 1, 2,2, 0,0,0 }, { ARM::t2SUBSrr,ARM::tSUBrr, 0, 0, 0, 1, 0, 2,0, 0,0,0 }, @@ -623,7 +627,7 @@ const ReduceEntry &Entry, bool LiveCPSR, bool IsSelfLoop) { unsigned Opc = MI->getOpcode(); - if (Opc == ARM::t2ADDri) { + if (Opc == ARM::t2ADDri || Opc == ARM::t2ADDspImm || Opc == ARM::t2ADDspImm12) { // If the source register is SP, try to reduce to tADDrSPi, otherwise // it's a normal reduce. if (MI->getOperand(1).getReg() != ARM::SP) { diff --git a/llvm/test/CodeGen/ARM/GlobalISel/thumb-select-arithmetic-ops.mir b/llvm/test/CodeGen/ARM/GlobalISel/thumb-select-arithmetic-ops.mir --- a/llvm/test/CodeGen/ARM/GlobalISel/thumb-select-arithmetic-ops.mir +++ b/llvm/test/CodeGen/ARM/GlobalISel/thumb-select-arithmetic-ops.mir @@ -64,7 +64,7 @@ %1(s32) = G_CONSTANT i32 786444 ; 0x000c000c %2(s32) = G_ADD %0, %1 - ; CHECK: [[VREGRES:%[0-9]+]]:gprnopc = t2ADDri [[VREGX]], 786444, 14, $noreg, $noreg + ; CHECK: [[VREGRES:%[0-9]+]]:rgpr = t2ADDri [[VREGX]], 786444, 14, $noreg, $noreg $r0 = COPY %2(s32) ; CHECK: $r0 = COPY [[VREGRES]] @@ -92,7 +92,7 @@ %1(s32) = G_CONSTANT i32 4093 %2(s32) = G_ADD %0, %1 - ; CHECK: [[VREGRES:%[0-9]+]]:gprnopc = t2ADDri12 [[VREGX]], 4093, 14, $noreg + ; CHECK: [[VREGRES:%[0-9]+]]:rgpr = t2ADDri12 [[VREGX]], 4093, 14, $noreg $r0 = COPY %2(s32) ; CHECK: $r0 = COPY [[VREGRES]] @@ -178,7 +178,7 @@ %1(s32) = G_CONSTANT i32 786444 ; 0x000c000c %2(s32) = G_SUB %0, %1 - ; CHECK: [[VREGRES:%[0-9]+]]:gprnopc = t2SUBri [[VREGX]], 786444, 14, $noreg, $noreg + ; CHECK: [[VREGRES:%[0-9]+]]:rgpr = t2SUBri [[VREGX]], 786444, 14, $noreg, $noreg $r0 = COPY %2(s32) ; CHECK: $r0 = COPY [[VREGRES]] diff --git a/llvm/test/CodeGen/ARM/GlobalISel/thumb-select-load-store.mir b/llvm/test/CodeGen/ARM/GlobalISel/thumb-select-load-store.mir --- a/llvm/test/CodeGen/ARM/GlobalISel/thumb-select-load-store.mir +++ b/llvm/test/CodeGen/ARM/GlobalISel/thumb-select-load-store.mir @@ -168,7 +168,7 @@ liveins: $r0, $r1, $r2, $r3 %0(p0) = G_FRAME_INDEX %fixed-stack.2 - ; CHECK: [[FI32VREG:%[0-9]+]]:gprnopc = t2ADDri %fixed-stack.[[FI32]], 0, 14, $noreg, $noreg + ; CHECK: [[FI32VREG:%[0-9]+]]:rgpr = t2ADDri %fixed-stack.[[FI32]], 0, 14, $noreg, $noreg %1(s32) = G_LOAD %0(p0) :: (load 4) ; CHECK: [[LD32VREG:%[0-9]+]]:gpr = t2LDRi12 [[FI32VREG]], 0, 14, $noreg @@ -177,7 +177,7 @@ ; CHECK: $r0 = COPY [[LD32VREG]] %2(p0) = G_FRAME_INDEX %fixed-stack.0 - ; CHECK: [[FI1VREG:%[0-9]+]]:gprnopc = t2ADDri %fixed-stack.[[FI1]], 0, 14, $noreg, $noreg + ; CHECK: [[FI1VREG:%[0-9]+]]:rgpr = t2ADDri %fixed-stack.[[FI1]], 0, 14, $noreg, $noreg %3(s1) = G_LOAD %2(p0) :: (load 1) ; CHECK: [[LD1VREG:%[0-9]+]]:gprnopc = t2LDRBi12 [[FI1VREG]], 0, 14, $noreg diff --git a/llvm/test/CodeGen/Thumb2/fp16-stacksplot.mir b/llvm/test/CodeGen/Thumb2/fp16-stacksplot.mir --- a/llvm/test/CodeGen/Thumb2/fp16-stacksplot.mir +++ b/llvm/test/CodeGen/Thumb2/fp16-stacksplot.mir @@ -27,7 +27,7 @@ ; CHECK: frame-setup CFI_INSTRUCTION offset $r6, -28 ; CHECK: frame-setup CFI_INSTRUCTION offset $r5, -32 ; CHECK: frame-setup CFI_INSTRUCTION offset $r4, -36 - ; CHECK: $sp = frame-setup t2SUBri killed $sp, 1208, 14, $noreg, $noreg + ; CHECK: $sp = frame-setup t2SUBspImm killed $sp, 1208, 14, $noreg, $noreg ; CHECK: frame-setup CFI_INSTRUCTION def_cfa_offset 1244 ; CHECK: $r0 = IMPLICIT_DEF ; CHECK: $r1 = IMPLICIT_DEF diff --git a/llvm/test/CodeGen/Thumb2/large-call.ll b/llvm/test/CodeGen/Thumb2/large-call.ll --- a/llvm/test/CodeGen/Thumb2/large-call.ll +++ b/llvm/test/CodeGen/Thumb2/large-call.ll @@ -9,7 +9,7 @@ ; CHECK: main ; CHECK: vmov.f64 ; Adjust SP for the large call -; CHECK: sub sp, +; CHECK: subw sp, ; Store to call frame + #8 ; CHECK: vstr{{.*\[}}sp, #8] ; Don't clobber that store until the call. diff --git a/llvm/test/CodeGen/Thumb2/mve-stacksplot.mir b/llvm/test/CodeGen/Thumb2/mve-stacksplot.mir --- a/llvm/test/CodeGen/Thumb2/mve-stacksplot.mir +++ b/llvm/test/CodeGen/Thumb2/mve-stacksplot.mir @@ -116,8 +116,7 @@ ; CHECK: frame-setup CFI_INSTRUCTION offset $r6, -28 ; CHECK: frame-setup CFI_INSTRUCTION offset $r5, -32 ; CHECK: frame-setup CFI_INSTRUCTION offset $r4, -36 - ; CHECK: $sp = frame-setup t2SUBri killed $sp, 1216, 14, $noreg, $noreg - ; CHECK: $sp = frame-setup tSUBspi $sp, 1, 14, $noreg + ; CHECK: $sp = frame-setup t2SUBspImm12 killed $sp, 1220, 14, $noreg ; CHECK: frame-setup CFI_INSTRUCTION def_cfa_offset 1256 ; CHECK: $r0 = IMPLICIT_DEF ; CHECK: $r1 = IMPLICIT_DEF diff --git a/llvm/test/CodeGen/Thumb2/peephole-addsub.mir b/llvm/test/CodeGen/Thumb2/peephole-addsub.mir --- a/llvm/test/CodeGen/Thumb2/peephole-addsub.mir +++ b/llvm/test/CodeGen/Thumb2/peephole-addsub.mir @@ -22,7 +22,7 @@ %0:rgpr = COPY $r0 %2:rgpr = t2MOVi 1, 14, $noreg, $noreg %3:gprnopc = t2ADDrr %0, %1, 14, $noreg, $noreg - %4:gprnopc = t2SUBri %3, 0, 14, $noreg, def dead $cpsr + %4:rgpr = t2SUBri %3, 0, 14, $noreg, def dead $cpsr t2CMPri killed %3, 0, 14, $noreg, implicit-def $cpsr %5:rgpr = t2MOVCCi %2, 0, 7, $cpsr $r0 = COPY %5 @@ -30,6 +30,6 @@ # CHECK-LABEL: name: test # CHECK: %3:gprnopc = t2ADDrr %0, %1, 14, $noreg, $noreg -# CHECK-NEXT: %4:gprnopc = t2SUBri %3, 0, 14, $noreg, def $cpsr +# CHECK-NEXT: %4:rgpr = t2SUBri %3, 0, 14, $noreg, def $cpsr # CHECK-NEXT: %5:rgpr = t2MOVCCi %2, 0, 7, $cpsr ... diff --git a/llvm/test/CodeGen/Thumb2/peephole-cmp.mir b/llvm/test/CodeGen/Thumb2/peephole-cmp.mir --- a/llvm/test/CodeGen/Thumb2/peephole-cmp.mir +++ b/llvm/test/CodeGen/Thumb2/peephole-cmp.mir @@ -23,7 +23,7 @@ liveins: $r0 %0:rgpr = COPY $r0 - %1:gprnopc = t2ADDri %stack.0.f, 0, 14, $noreg, $noreg + %1:rgpr = t2ADDri %stack.0.f, 0, 14, $noreg, $noreg t2CMPrr %1, %0, 14, $noreg, implicit-def $cpsr t2Bcc %bb.2, 3, $cpsr t2B %bb.1, 14, $noreg @@ -37,7 +37,7 @@ tBX_RET 14, $noreg # CHECK-LABEL: name: test_addir_frameindex -# CHECK: %1:gprnopc = t2ADDri %stack.0.f, 0, 14, $noreg, $noreg +# CHECK: %1:rgpr = t2ADDri %stack.0.f, 0, 14, $noreg, $noreg # CHECK-NEXT: t2CMPrr %1, %0, 14, $noreg, implicit-def $cpsr # CHECK-NEXT: t2Bcc %bb.2, 3, $cpsr ... diff --git a/llvm/test/MC/ARM/basic-thumb-instructions.s b/llvm/test/MC/ARM/basic-thumb-instructions.s --- a/llvm/test/MC/ARM/basic-thumb-instructions.s +++ b/llvm/test/MC/ARM/basic-thumb-instructions.s @@ -63,7 +63,7 @@ add sp, sp, #-8 add sp, #-8 -@ CHECK: add sp, #4 @ encoding: [0x01,0xb0] +@ CHECK: add sp, #4 @ encoding: [0x01,0xb0] @ Fixme @ CHECK: add sp, #508 @ encoding: [0x7f,0xb0] @ CHECK: add sp, #4 @ encoding: [0x01,0xb0] @ CHECK: add r2, sp, #8 @ encoding: [0x02,0xaa] diff --git a/llvm/test/MC/ARM/invalid-addsub.s b/llvm/test/MC/ARM/invalid-addsub.s --- a/llvm/test/MC/ARM/invalid-addsub.s +++ b/llvm/test/MC/ARM/invalid-addsub.s @@ -1,20 +1,62 @@ @ RUN: not llvm-mc -triple thumbv7-apple-ios %s -o - 2>&1 | FileCheck %s - -@ CHECK: error: source register must be sp if destination is sp -@ CHECK: error: source register must be sp if destination is sp -@ CHECK: error: source register must be sp if destination is sp -@ CHECK: error: source register must be sp if destination is sp add sp, r5, #1 addw sp, r7, #4 add sp, r3, r2 add sp, r3, r5, lsl #3 - - -@ CHECK: error: source register must be sp if destination is sp -@ CHECK: error: source register must be sp if destination is sp -@ CHECK: error: source register must be sp if destination is sp -@ CHECK: error: source register must be sp if destination is sp sub sp, r5, #1 subw sp, r7, #4 sub sp, r3, r2 sub sp, r3, r5, lsl #3 +@ CHECK: error: invalid instruction, any one of the following would fix this: +@ CHECK-NEXT: add sp, r5, #1 +@ CHECK-NEXT: ^ +@ CHECK-NEXT: note: invalid operand for instruction +@ CHECK-NEXT: add sp, r5, #1 +@ CHECK-NEXT: ^ +@ CHECK-NEXT: note: operand must be a register in range [r0, r12] or r14 +@ CHECK-NEXT: add sp, r5, #1 +@ CHECK-NEXT: ^ +@ CHECK-NEXT: note: operand must be a register in range [r0, r12] or r14 +@ CHECK-NEXT: add sp, r5, #1 +@ CHECK-NEXT: ^ +@ CHECK-NEXT: error: invalid instruction, any one of the following would fix this: +@ CHECK-NEXT: addw sp, r7, #4 +@ CHECK-NEXT: ^ +@ CHECK-NEXT: note: operand must be a register in range [r0, r12] or r14 +@ CHECK-NEXT: addw sp, r7, #4 +@ CHECK-NEXT: ^ +@ CHECK-NEXT: note: operand must be a register sp +@ CHECK-NEXT: addw sp, r7, #4 +@ CHECK-NEXT: ^ +@ CHECK-NEXT: error: source register must be sp if destination is sp +@ CHECK-NEXT: add sp, r3, r2 +@ CHECK-NEXT: ^ +@ CHECK-NEXT: error: source register must be sp if destination is sp +@ CHECK-NEXT: add sp, r3, r5, lsl #3 +@ CHECK-NEXT: ^ +@ CHECK-NEXT: error: invalid instruction, any one of the following would fix this: +@ CHECK-NEXT: sub sp, r5, #1 +@ CHECK-NEXT: ^ +@ CHECK-NEXT: note: invalid operand for instruction +@ CHECK-NEXT: sub sp, r5, #1 +@ CHECK-NEXT: ^ +@ CHECK-NEXT: note: operand must be a register in range [r0, r12] or r14 +@ CHECK-NEXT: sub sp, r5, #1 +@ CHECK-NEXT: ^ +@ CHECK-NEXT: note: operand must be a register in range [r0, r12] or r14 +@ CHECK-NEXT: sub sp, r5, #1 +@ CHECK-NEXT: ^ +@ CHECK-NEXT: error: invalid instruction, any one of the following would fix this: +@ CHECK-NEXT: subw sp, r7, #4 +@ CHECK-NEXT: ^ +@ CHECK-NEXT: note: operand must be a register in range [r0, r12] or r14 +@ CHECK-NEXT: subw sp, r7, #4 +@ CHECK-NEXT: ^ +@ CHECK-NEXT: note: operand must be a register sp +@ CHECK-NEXT: subw sp, r7, #4 +@ CHECK-NEXT: ^ +@ CHECK-NEXT: error: source register must be sp if destination is sp +@ CHECK-NEXT: sub sp, r3, r2 +@ CHECK-NEXT: ^ +@ CHECK-NEXT: error: source register must be sp if destination is sp +@ CHECK-NEXT: sub sp, r3, r5, lsl #3 \ No newline at end of file diff --git a/llvm/test/MC/ARM/register-token-source-loc.s b/llvm/test/MC/ARM/register-token-source-loc.s --- a/llvm/test/MC/ARM/register-token-source-loc.s +++ b/llvm/test/MC/ARM/register-token-source-loc.s @@ -1,12 +1,11 @@ // RUN: not llvm-mc -triple armv6m--none-eabi < %s 2>&1 | FileCheck %s - -// Some of these CHECK lines need to uses regexes to that the amount of -// whitespace between the start of the line and the caret is significant. - add sp, r0, #4 -// CHECK: error: invalid instruction, any one of the following would fix this: -// CHECK: note: instruction requires: thumb2 -// CHECK: note: operand must be a register sp -// CHECK-NEXT: {{^ add sp, r0, #4}} -// CHECK-NEXT: {{^ \^}} -// CHECK: note: too many operands for instruction +// CHECK: error: invalid instruction, any one of the following would fix this: +// CHECK-NEXT: add sp, r0, #4 +// CHECK-NEXT: ^ +// CHECK-NEXT: note: operand must be a register sp +// CHECK-NEXT: add sp, r0, #4 +// CHECK-NEXT: ^ +// CHECK-NEXT: note: too many operands for instruction +// CHECK-NEXT: add sp, r0, #4 +// CHECK-NEXT: ^ diff --git a/llvm/test/MC/ARM/thumb-diagnostics.s b/llvm/test/MC/ARM/thumb-diagnostics.s --- a/llvm/test/MC/ARM/thumb-diagnostics.s +++ b/llvm/test/MC/ARM/thumb-diagnostics.s @@ -242,25 +242,37 @@ add sp, #-1 add sp, #3 add sp, sp, #512 - add r2, sp, #1024 +@ add r2, sp, #1024 @ CHECK-ERRORS: error: invalid instruction, any one of the following would fix this: -@ CHECK-ERRORS: add sp, #-1 -@ CHECK-ERRORS: ^ +@ CHECK-ERRORS: add sp, #-1 +@ CHECK-ERRORS: ^ @ CHECK-ERRORS: note: operand must be a register in range [r0, r15] -@ CHECK-ERRORS: note: instruction requires: thumb2 +@ CHECK-ERRORS: add sp, #-1 +@ CHECK-ERRORS: ^ +@ CHECK-ERRORS: note: invalid operand for instruction +@ CHECK-ERRORS: add sp, #-1 +@ CHECK-ERRORS: ^ @ CHECK-ERRORS: error: invalid instruction, any one of the following would fix this: @ CHECK-ERRORS: add sp, #3 @ CHECK-ERRORS: ^ @ CHECK-ERRORS: note: operand must be a register in range [r0, r15] -@ CHECK-ERRORS: note: instruction requires: thumb2 +@ CHECK-ERRORS: note: invalid operand for instruction +@ CHECK-ERRORS: add sp, #3 +@ CHECK-ERRORS: ^ @ CHECK-ERRORS: error: invalid instruction, any one of the following would fix this: -@ CHECK-ERRORS: add sp, sp, #512 -@ CHECK-ERRORS: ^ +@ CHECK-ERRORS: add sp, sp, #512 +@ CHECK-ERRORS: ^ +@ CHECK-ERRORS: note: operand must be a register in range [r0, r15] +@ CHECK-ERRORS: add sp, sp, #512 +@ CHECK-ERRORS: ^ +@ CHECK-ERRORS: note: invalid operand for instruction +@ CHECK-ERRORS: add sp, sp, #512 +@ CHECK-ERRORS: ^ @ CHECK-ERRORS: note: operand must be a register in range [r0, r15] @ CHECK-ERRORS: note: instruction requires: thumb2 -@ CHECK-ERRORS: error: instruction requires: thumb2 -@ CHECK-ERRORS: add r2, sp, #1024 -@ CHECK-ERRORS: ^ +@ CH ECK-ERRORS: error: instruction requires: thumb2 +@ CH ECK-ERRORS: add r2, sp, #1024 +@ CH ECK-ERRORS: ^ add r2, sp, ip @ CHECK-ERRORS: error: source register must be the same as destination