mirror of
https://github.com/RPCS3/llvm.git
synced 2025-05-13 08:56:04 +00:00
[ARM] Replace HasT2ExtractPack with HasDSP
Removed the HasT2ExtractPack feature and replaced its references with HasDSP. This then allows the Thumb2 extend instructions to be selected for ARMv8M +dsp. These instruction descriptions have also been refactored and more target tests have been added for their isel. Differential Revision: https://reviews.llvm.org/D29623 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@295452 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
2566cbcc53
commit
50a37dcbc4
@ -72,8 +72,6 @@ def FeatureHWDiv : SubtargetFeature<"hwdiv", "HasHardwareDivide", "true",
|
||||
def FeatureHWDivARM : SubtargetFeature<"hwdiv-arm",
|
||||
"HasHardwareDivideInARM", "true",
|
||||
"Enable divide instructions in ARM mode">;
|
||||
def FeatureT2XtPk : SubtargetFeature<"t2xtpk", "HasT2ExtractPack", "true",
|
||||
"Enable Thumb2 extract and pack instructions">;
|
||||
def FeatureDB : SubtargetFeature<"db", "HasDataBarrier", "true",
|
||||
"Has data barrier (dmb / dsb) instructions">;
|
||||
def FeatureV7Clrex : SubtargetFeature<"v7clrex", "HasV7Clrex", "true",
|
||||
@ -297,8 +295,7 @@ def HasV7Ops : SubtargetFeature<"v7", "HasV7Ops", "true",
|
||||
FeatureV7Clrex]>;
|
||||
def HasV8Ops : SubtargetFeature<"v8", "HasV8Ops", "true",
|
||||
"Support ARM v8 instructions",
|
||||
[HasV7Ops, FeatureAcquireRelease,
|
||||
FeatureT2XtPk]>;
|
||||
[HasV7Ops, FeatureAcquireRelease]>;
|
||||
def HasV8_1aOps : SubtargetFeature<"v8.1a", "HasV8_1aOps", "true",
|
||||
"Support ARM v8.1a instructions",
|
||||
[HasV8Ops]>;
|
||||
@ -393,8 +390,7 @@ def ARMv5tej : Architecture<"armv5tej", "ARMv5tej", [HasV5TEOps]>;
|
||||
def ARMv6 : Architecture<"armv6", "ARMv6", [HasV6Ops]>;
|
||||
|
||||
def ARMv6t2 : Architecture<"armv6t2", "ARMv6t2", [HasV6T2Ops,
|
||||
FeatureDSP,
|
||||
FeatureT2XtPk]>;
|
||||
FeatureDSP]>;
|
||||
|
||||
def ARMv6k : Architecture<"armv6k", "ARMv6k", [HasV6KOps]>;
|
||||
|
||||
@ -415,8 +411,7 @@ def ARMv7a : Architecture<"armv7-a", "ARMv7a", [HasV7Ops,
|
||||
FeatureNEON,
|
||||
FeatureDB,
|
||||
FeatureDSP,
|
||||
FeatureAClass,
|
||||
FeatureT2XtPk]>;
|
||||
FeatureAClass]>;
|
||||
|
||||
def ARMv7ve : Architecture<"armv7ve", "ARMv7ve", [HasV7Ops,
|
||||
FeatureNEON,
|
||||
@ -425,15 +420,13 @@ def ARMv7ve : Architecture<"armv7ve", "ARMv7ve", [HasV7Ops,
|
||||
FeatureTrustZone,
|
||||
FeatureMP,
|
||||
FeatureVirtualization,
|
||||
FeatureAClass,
|
||||
FeatureT2XtPk]>;
|
||||
FeatureAClass]>;
|
||||
|
||||
def ARMv7r : Architecture<"armv7-r", "ARMv7r", [HasV7Ops,
|
||||
FeatureDB,
|
||||
FeatureDSP,
|
||||
FeatureHWDiv,
|
||||
FeatureRClass,
|
||||
FeatureT2XtPk]>;
|
||||
FeatureRClass]>;
|
||||
|
||||
def ARMv7m : Architecture<"armv7-m", "ARMv7m", [HasV7Ops,
|
||||
FeatureThumb2,
|
||||
@ -448,8 +441,7 @@ def ARMv7em : Architecture<"armv7e-m", "ARMv7em", [HasV7Ops,
|
||||
FeatureDB,
|
||||
FeatureHWDiv,
|
||||
FeatureMClass,
|
||||
FeatureDSP,
|
||||
FeatureT2XtPk]>;
|
||||
FeatureDSP]>;
|
||||
|
||||
def ARMv8a : Architecture<"armv8-a", "ARMv8a", [HasV8Ops,
|
||||
FeatureAClass,
|
||||
@ -491,7 +483,6 @@ def ARMv82a : Architecture<"armv8.2-a", "ARMv82a", [HasV8_2aOps,
|
||||
def ARMv8r : Architecture<"armv8-r", "ARMv8r", [HasV8Ops,
|
||||
FeatureRClass,
|
||||
FeatureDB,
|
||||
FeatureT2XtPk,
|
||||
FeatureDSP,
|
||||
FeatureCRC,
|
||||
FeatureMP,
|
||||
@ -764,7 +755,6 @@ def : ProcNoItin<"cortex-m23", [ARMv8mBaseline,
|
||||
|
||||
def : ProcNoItin<"cortex-m33", [ARMv8mMainline,
|
||||
FeatureDSP,
|
||||
FeatureT2XtPk,
|
||||
FeatureFPARMv8,
|
||||
FeatureD16,
|
||||
FeatureVFPOnlySP]>;
|
||||
|
@ -10031,7 +10031,7 @@ static SDValue PerformORCombine(SDNode *N,
|
||||
(Mask == ~Mask2)) {
|
||||
// The pack halfword instruction works better for masks that fit it,
|
||||
// so use that when it's available.
|
||||
if (Subtarget->hasT2ExtractPack() &&
|
||||
if (Subtarget->hasDSP() &&
|
||||
(Mask == 0xffff || Mask == 0xffff0000))
|
||||
return SDValue();
|
||||
// 2a
|
||||
@ -10047,7 +10047,7 @@ static SDValue PerformORCombine(SDNode *N,
|
||||
(~Mask == Mask2)) {
|
||||
// The pack halfword instruction works better for masks that fit it,
|
||||
// so use that when it's available.
|
||||
if (Subtarget->hasT2ExtractPack() &&
|
||||
if (Subtarget->hasDSP() &&
|
||||
(Mask2 == 0xffff || Mask2 == 0xffff0000))
|
||||
return SDValue();
|
||||
// 2b
|
||||
|
@ -1013,9 +1013,6 @@ class Thumb2DSPPat<dag pattern, dag result> : Pat<pattern, result> {
|
||||
class Thumb2DSPMulPat<dag pattern, dag result> : Pat<pattern, result> {
|
||||
list<Predicate> Predicates = [IsThumb2, UseMulOps, HasDSP];
|
||||
}
|
||||
class Thumb2ExtractPat<dag pattern, dag result> : Pat<pattern, result> {
|
||||
list<Predicate> Predicates = [IsThumb2, HasT2ExtractPack];
|
||||
}
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Thumb Instruction Format Definitions.
|
||||
//
|
||||
|
@ -249,9 +249,6 @@ def HasDivide : Predicate<"Subtarget->hasDivide()">,
|
||||
AssemblerPredicate<"FeatureHWDiv", "divide in THUMB">;
|
||||
def HasDivideInARM : Predicate<"Subtarget->hasDivideInARMMode()">,
|
||||
AssemblerPredicate<"FeatureHWDivARM", "divide in ARM">;
|
||||
def HasT2ExtractPack : Predicate<"Subtarget->hasT2ExtractPack()">,
|
||||
AssemblerPredicate<"FeatureT2XtPk",
|
||||
"pack/extract">;
|
||||
def HasDSP : Predicate<"Subtarget->hasDSP()">,
|
||||
AssemblerPredicate<"FeatureDSP", "dsp">;
|
||||
def HasDB : Predicate<"Subtarget->hasDataBarrier()">,
|
||||
|
@ -1121,28 +1121,10 @@ multiclass T2I_st<bits<2> opcod, string opc,
|
||||
|
||||
/// T2I_ext_rrot - A unary operation with two forms: one whose operand is a
|
||||
/// register and one whose operand is a register rotated by 8/16/24.
|
||||
class T2I_ext_rrot<bits<3> opcod, string opc, PatFrag opnode>
|
||||
: T2TwoReg<(outs rGPR:$Rd), (ins rGPR:$Rm, rot_imm:$rot), IIC_iEXTr,
|
||||
opc, ".w\t$Rd, $Rm$rot",
|
||||
[(set rGPR:$Rd, (opnode (rotr rGPR:$Rm, rot_imm:$rot)))]>,
|
||||
Requires<[IsThumb2]> {
|
||||
let Inst{31-27} = 0b11111;
|
||||
let Inst{26-23} = 0b0100;
|
||||
let Inst{22-20} = opcod;
|
||||
let Inst{19-16} = 0b1111; // Rn
|
||||
let Inst{15-12} = 0b1111;
|
||||
let Inst{7} = 1;
|
||||
|
||||
bits<2> rot;
|
||||
let Inst{5-4} = rot{1-0}; // rotate
|
||||
}
|
||||
|
||||
// UXTB16 - Requres T2ExtractPack, does not need the .w qualifier.
|
||||
class T2I_ext_rrot_uxtb16<bits<3> opcod, string opc, PatFrag opnode>
|
||||
: T2TwoReg<(outs rGPR:$Rd), (ins rGPR:$Rm, rot_imm:$rot),
|
||||
IIC_iEXTr, opc, "\t$Rd, $Rm$rot",
|
||||
[(set rGPR:$Rd, (opnode (rotr rGPR:$Rm, rot_imm:$rot)))]>,
|
||||
Requires<[HasT2ExtractPack, IsThumb2]> {
|
||||
class T2I_ext_rrot_base<bits<3> opcod, dag iops, dag oops,
|
||||
string opc, string oprs,
|
||||
list<dag> pattern>
|
||||
: T2TwoReg<iops, oops, IIC_iEXTr, opc, oprs, pattern> {
|
||||
bits<2> rot;
|
||||
let Inst{31-27} = 0b11111;
|
||||
let Inst{26-23} = 0b0100;
|
||||
@ -1150,46 +1132,31 @@ class T2I_ext_rrot_uxtb16<bits<3> opcod, string opc, PatFrag opnode>
|
||||
let Inst{19-16} = 0b1111; // Rn
|
||||
let Inst{15-12} = 0b1111;
|
||||
let Inst{7} = 1;
|
||||
let Inst{5-4} = rot;
|
||||
let Inst{5-4} = rot; // rotate
|
||||
}
|
||||
|
||||
// SXTB16 - Requres T2ExtractPack, does not need the .w qualifier, no pattern
|
||||
// supported yet.
|
||||
class T2I_ext_rrot_sxtb16<bits<3> opcod, string opc>
|
||||
: T2TwoReg<(outs rGPR:$Rd), (ins rGPR:$Rm, rot_imm:$rot), IIC_iEXTr,
|
||||
opc, "\t$Rd, $Rm$rot", []>,
|
||||
Requires<[IsThumb2, HasT2ExtractPack]> {
|
||||
bits<2> rot;
|
||||
let Inst{31-27} = 0b11111;
|
||||
let Inst{26-23} = 0b0100;
|
||||
let Inst{22-20} = opcod;
|
||||
let Inst{19-16} = 0b1111; // Rn
|
||||
let Inst{15-12} = 0b1111;
|
||||
let Inst{7} = 1;
|
||||
let Inst{5-4} = rot;
|
||||
}
|
||||
class T2I_ext_rrot<bits<3> opcod, string opc>
|
||||
: T2I_ext_rrot_base<opcod,
|
||||
(outs rGPR:$Rd),
|
||||
(ins rGPR:$Rm, rot_imm:$rot),
|
||||
opc, ".w\t$Rd, $Rm$rot", []>,
|
||||
Requires<[IsThumb2]>;
|
||||
|
||||
// UXTB16, SXTB16 - Requires HasDSP, does not need the .w qualifier.
|
||||
class T2I_ext_rrot_xtb16<bits<3> opcod, string opc>
|
||||
: T2I_ext_rrot_base<opcod,
|
||||
(outs rGPR:$Rd),
|
||||
(ins rGPR:$Rm, rot_imm:$rot),
|
||||
opc, "\t$Rd, $Rm$rot", []>,
|
||||
Requires<[HasDSP, IsThumb2]>;
|
||||
|
||||
/// T2I_exta_rrot - A binary operation with two forms: one whose operand is a
|
||||
/// register and one whose operand is a register rotated by 8/16/24.
|
||||
class T2I_exta_rrot<bits<3> opcod, string opc, PatFrag opnode>
|
||||
class T2I_exta_rrot<bits<3> opcod, string opc>
|
||||
: T2ThreeReg<(outs rGPR:$Rd),
|
||||
(ins rGPR:$Rn, rGPR:$Rm, rot_imm:$rot),
|
||||
IIC_iEXTAsr, opc, "\t$Rd, $Rn, $Rm$rot",
|
||||
[(set rGPR:$Rd, (opnode rGPR:$Rn, (rotr rGPR:$Rm,rot_imm:$rot)))]>,
|
||||
Requires<[HasT2ExtractPack, IsThumb2]> {
|
||||
bits<2> rot;
|
||||
let Inst{31-27} = 0b11111;
|
||||
let Inst{26-23} = 0b0100;
|
||||
let Inst{22-20} = opcod;
|
||||
let Inst{15-12} = 0b1111;
|
||||
let Inst{7} = 1;
|
||||
let Inst{5-4} = rot;
|
||||
}
|
||||
|
||||
class T2I_exta_rrot_np<bits<3> opcod, string opc>
|
||||
: T2ThreeReg<(outs rGPR:$Rd), (ins rGPR:$Rn, rGPR:$Rm,rot_imm:$rot),
|
||||
IIC_iEXTAsr, opc, "\t$Rd, $Rn, $Rm$rot", []>,
|
||||
Requires<[HasT2ExtractPack, IsThumb2]> {
|
||||
Requires<[HasDSP, IsThumb2]> {
|
||||
bits<2> rot;
|
||||
let Inst{31-27} = 0b11111;
|
||||
let Inst{26-23} = 0b0100;
|
||||
@ -1969,31 +1936,39 @@ def : T2Pat<(or rGPR:$src, 0xffff0000), (t2MOVTi16 rGPR:$src, 0xffff)>;
|
||||
|
||||
// Sign extenders
|
||||
|
||||
def t2SXTB : T2I_ext_rrot<0b100, "sxtb",
|
||||
UnOpFrag<(sext_inreg node:$Src, i8)>>;
|
||||
def t2SXTH : T2I_ext_rrot<0b000, "sxth",
|
||||
UnOpFrag<(sext_inreg node:$Src, i16)>>;
|
||||
def t2SXTB16 : T2I_ext_rrot_sxtb16<0b010, "sxtb16">;
|
||||
def t2SXTB : T2I_ext_rrot<0b100, "sxtb">;
|
||||
def t2SXTH : T2I_ext_rrot<0b000, "sxth">;
|
||||
def t2SXTB16 : T2I_ext_rrot_xtb16<0b010, "sxtb16">;
|
||||
|
||||
def t2SXTAB : T2I_exta_rrot<0b100, "sxtab">;
|
||||
def t2SXTAH : T2I_exta_rrot<0b000, "sxtah">;
|
||||
def t2SXTAB16 : T2I_exta_rrot<0b010, "sxtab16">;
|
||||
|
||||
def : T2Pat<(sext_inreg (rotr rGPR:$Rn, rot_imm:$rot), i8),
|
||||
(t2SXTB rGPR:$Rn, rot_imm:$rot)>;
|
||||
def : T2Pat<(sext_inreg (rotr rGPR:$Rn, rot_imm:$rot), i16),
|
||||
(t2SXTH rGPR:$Rn, rot_imm:$rot)>;
|
||||
def : Thumb2DSPPat<(add rGPR:$Rn,
|
||||
(sext_inreg (rotr rGPR:$Rm, rot_imm:$rot), i8)),
|
||||
(t2SXTAB rGPR:$Rn, rGPR:$Rm, rot_imm:$rot)>;
|
||||
def : Thumb2DSPPat<(add rGPR:$Rn,
|
||||
(sext_inreg (rotr rGPR:$Rm, rot_imm:$rot), i16)),
|
||||
(t2SXTAH rGPR:$Rn, rGPR:$Rm, rot_imm:$rot)>;
|
||||
|
||||
def t2SXTAB : T2I_exta_rrot<0b100, "sxtab",
|
||||
BinOpFrag<(add node:$LHS, (sext_inreg node:$RHS, i8))>>;
|
||||
def t2SXTAH : T2I_exta_rrot<0b000, "sxtah",
|
||||
BinOpFrag<(add node:$LHS, (sext_inreg node:$RHS,i16))>>;
|
||||
def t2SXTAB16 : T2I_exta_rrot_np<0b010, "sxtab16">;
|
||||
|
||||
// A simple right-shift can also be used in most cases (the exception is the
|
||||
// SXTH operations with a rotate of 24: there the non-contiguous bits are
|
||||
// relevant).
|
||||
def : Thumb2ExtractPat<(add rGPR:$Rn, (sext_inreg
|
||||
def : Thumb2DSPPat<(add rGPR:$Rn, (sext_inreg
|
||||
(srl rGPR:$Rm, rot_imm:$rot), i8)),
|
||||
(t2SXTAB rGPR:$Rn, rGPR:$Rm, rot_imm:$rot)>;
|
||||
def : Thumb2ExtractPat<(add rGPR:$Rn, (sext_inreg
|
||||
def : Thumb2DSPPat<(add rGPR:$Rn, (sext_inreg
|
||||
(srl rGPR:$Rm, imm8_or_16:$rot), i16)),
|
||||
(t2SXTAH rGPR:$Rn, rGPR:$Rm, rot_imm:$rot)>;
|
||||
def : Thumb2ExtractPat<(add rGPR:$Rn, (sext_inreg
|
||||
def : Thumb2DSPPat<(add rGPR:$Rn, (sext_inreg
|
||||
(rotr rGPR:$Rm, (i32 24)), i16)),
|
||||
(t2SXTAH rGPR:$Rn, rGPR:$Rm, (i32 3))>;
|
||||
def : Thumb2ExtractPat<(add rGPR:$Rn, (sext_inreg
|
||||
def : Thumb2DSPPat<(add rGPR:$Rn, (sext_inreg
|
||||
(or (srl rGPR:$Rm, (i32 24)),
|
||||
(shl rGPR:$Rm, (i32 8))), i16)),
|
||||
(t2SXTAH rGPR:$Rn, rGPR:$Rm, (i32 3))>;
|
||||
@ -2001,12 +1976,16 @@ def : Thumb2ExtractPat<(add rGPR:$Rn, (sext_inreg
|
||||
// Zero extenders
|
||||
|
||||
let AddedComplexity = 16 in {
|
||||
def t2UXTB : T2I_ext_rrot<0b101, "uxtb",
|
||||
UnOpFrag<(and node:$Src, 0x000000FF)>>;
|
||||
def t2UXTH : T2I_ext_rrot<0b001, "uxth",
|
||||
UnOpFrag<(and node:$Src, 0x0000FFFF)>>;
|
||||
def t2UXTB16 : T2I_ext_rrot_uxtb16<0b011, "uxtb16",
|
||||
UnOpFrag<(and node:$Src, 0x00FF00FF)>>;
|
||||
def t2UXTB : T2I_ext_rrot<0b101, "uxtb">;
|
||||
def t2UXTH : T2I_ext_rrot<0b001, "uxth">;
|
||||
def t2UXTB16 : T2I_ext_rrot_xtb16<0b011, "uxtb16">;
|
||||
|
||||
def : Thumb2DSPPat<(and (rotr rGPR:$Rm, rot_imm:$rot), 0x000000FF),
|
||||
(t2UXTB rGPR:$Rm, rot_imm:$rot)>;
|
||||
def : Thumb2DSPPat<(and (rotr rGPR:$Rm, rot_imm:$rot), 0x0000FFFF),
|
||||
(t2UXTH rGPR:$Rm, rot_imm:$rot)>;
|
||||
def : Thumb2DSPPat<(and (rotr rGPR:$Rm, rot_imm:$rot), 0x00FF00FF),
|
||||
(t2UXTB16 rGPR:$Rm, rot_imm:$rot)>;
|
||||
|
||||
// FIXME: This pattern incorrectly assumes the shl operator is a rotate.
|
||||
// The transformation should probably be done as a combiner action
|
||||
@ -2014,21 +1993,25 @@ def t2UXTB16 : T2I_ext_rrot_uxtb16<0b011, "uxtb16",
|
||||
// eight bits of the source into the lower eight bits of the result.
|
||||
//def : T2Pat<(and (shl rGPR:$Src, (i32 8)), 0xFF00FF),
|
||||
// (t2UXTB16 rGPR:$Src, 3)>,
|
||||
// Requires<[HasT2ExtractPack, IsThumb2]>;
|
||||
// Requires<[HasDSP, IsThumb2]>;
|
||||
def : T2Pat<(and (srl rGPR:$Src, (i32 8)), 0xFF00FF),
|
||||
(t2UXTB16 rGPR:$Src, 1)>,
|
||||
Requires<[HasT2ExtractPack, IsThumb2]>;
|
||||
Requires<[HasDSP, IsThumb2]>;
|
||||
|
||||
def t2UXTAB : T2I_exta_rrot<0b101, "uxtab",
|
||||
BinOpFrag<(add node:$LHS, (and node:$RHS, 0x00FF))>>;
|
||||
def t2UXTAH : T2I_exta_rrot<0b001, "uxtah",
|
||||
BinOpFrag<(add node:$LHS, (and node:$RHS, 0xFFFF))>>;
|
||||
def t2UXTAB16 : T2I_exta_rrot_np<0b011, "uxtab16">;
|
||||
def t2UXTAB : T2I_exta_rrot<0b101, "uxtab">;
|
||||
def t2UXTAH : T2I_exta_rrot<0b001, "uxtah">;
|
||||
def t2UXTAB16 : T2I_exta_rrot<0b011, "uxtab16">;
|
||||
|
||||
def : Thumb2ExtractPat<(add rGPR:$Rn, (and (srl rGPR:$Rm, rot_imm:$rot),
|
||||
def : Thumb2DSPPat<(add rGPR:$Rn, (and (rotr rGPR:$Rm, rot_imm:$rot),
|
||||
0x00FF)),
|
||||
(t2UXTAB rGPR:$Rn, rGPR:$Rm, rot_imm:$rot)>;
|
||||
def : Thumb2DSPPat<(add rGPR:$Rn, (and (rotr rGPR:$Rm, rot_imm:$rot),
|
||||
0xFFFF)),
|
||||
(t2UXTAH rGPR:$Rn, rGPR:$Rm, rot_imm:$rot)>;
|
||||
def : Thumb2DSPPat<(add rGPR:$Rn, (and (srl rGPR:$Rm, rot_imm:$rot),
|
||||
0xFF)),
|
||||
(t2UXTAB rGPR:$Rn, rGPR:$Rm, rot_imm:$rot)>;
|
||||
def : Thumb2ExtractPat<(add rGPR:$Rn, (and (srl rGPR:$Rm, imm8_or_16:$rot),
|
||||
def : Thumb2DSPPat<(add rGPR:$Rn, (and (srl rGPR:$Rm, imm8_or_16:$rot),
|
||||
0xFFFF)),
|
||||
(t2UXTAH rGPR:$Rn, rGPR:$Rm, rot_imm:$rot)>;
|
||||
}
|
||||
@ -2819,7 +2802,7 @@ def t2PKHBT : T2ThreeReg<
|
||||
[(set rGPR:$Rd, (or (and rGPR:$Rn, 0xFFFF),
|
||||
(and (shl rGPR:$Rm, pkh_lsl_amt:$sh),
|
||||
0xFFFF0000)))]>,
|
||||
Requires<[HasT2ExtractPack, IsThumb2]>,
|
||||
Requires<[HasDSP, IsThumb2]>,
|
||||
Sched<[WriteALUsi, ReadALU]> {
|
||||
let Inst{31-27} = 0b11101;
|
||||
let Inst{26-25} = 0b01;
|
||||
@ -2835,10 +2818,10 @@ def t2PKHBT : T2ThreeReg<
|
||||
// Alternate cases for PKHBT where identities eliminate some nodes.
|
||||
def : T2Pat<(or (and rGPR:$src1, 0xFFFF), (and rGPR:$src2, 0xFFFF0000)),
|
||||
(t2PKHBT rGPR:$src1, rGPR:$src2, 0)>,
|
||||
Requires<[HasT2ExtractPack, IsThumb2]>;
|
||||
Requires<[HasDSP, IsThumb2]>;
|
||||
def : T2Pat<(or (and rGPR:$src1, 0xFFFF), (shl rGPR:$src2, imm16_31:$sh)),
|
||||
(t2PKHBT rGPR:$src1, rGPR:$src2, imm16_31:$sh)>,
|
||||
Requires<[HasT2ExtractPack, IsThumb2]>;
|
||||
Requires<[HasDSP, IsThumb2]>;
|
||||
|
||||
// Note: Shifts of 1-15 bits will be transformed to srl instead of sra and
|
||||
// will match the pattern below.
|
||||
@ -2848,7 +2831,7 @@ def t2PKHTB : T2ThreeReg<
|
||||
[(set rGPR:$Rd, (or (and rGPR:$Rn, 0xFFFF0000),
|
||||
(and (sra rGPR:$Rm, pkh_asr_amt:$sh),
|
||||
0xFFFF)))]>,
|
||||
Requires<[HasT2ExtractPack, IsThumb2]>,
|
||||
Requires<[HasDSP, IsThumb2]>,
|
||||
Sched<[WriteALUsi, ReadALU]> {
|
||||
let Inst{31-27} = 0b11101;
|
||||
let Inst{26-25} = 0b01;
|
||||
@ -2867,14 +2850,14 @@ def t2PKHTB : T2ThreeReg<
|
||||
// pkhtb src1, src2, asr (17..31).
|
||||
def : T2Pat<(or (and rGPR:$src1, 0xFFFF0000), (srl rGPR:$src2, imm16:$sh)),
|
||||
(t2PKHTB rGPR:$src1, rGPR:$src2, imm16:$sh)>,
|
||||
Requires<[HasT2ExtractPack, IsThumb2]>;
|
||||
Requires<[HasDSP, IsThumb2]>;
|
||||
def : T2Pat<(or (and rGPR:$src1, 0xFFFF0000), (sra rGPR:$src2, imm16_31:$sh)),
|
||||
(t2PKHTB rGPR:$src1, rGPR:$src2, imm16_31:$sh)>,
|
||||
Requires<[HasT2ExtractPack, IsThumb2]>;
|
||||
Requires<[HasDSP, IsThumb2]>;
|
||||
def : T2Pat<(or (and rGPR:$src1, 0xFFFF0000),
|
||||
(and (srl rGPR:$src2, imm1_15:$sh), 0xFFFF)),
|
||||
(t2PKHTB rGPR:$src1, rGPR:$src2, imm1_15:$sh)>,
|
||||
Requires<[HasT2ExtractPack, IsThumb2]>;
|
||||
Requires<[HasDSP, IsThumb2]>;
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// CRC32 Instructions
|
||||
@ -4216,13 +4199,13 @@ def : T2Pat<(and rGPR:$Rm, 0x000000FF), (t2UXTB rGPR:$Rm, 0)>,
|
||||
def : T2Pat<(and rGPR:$Rm, 0x0000FFFF), (t2UXTH rGPR:$Rm, 0)>,
|
||||
Requires<[IsThumb2]>;
|
||||
def : T2Pat<(and rGPR:$Rm, 0x00FF00FF), (t2UXTB16 rGPR:$Rm, 0)>,
|
||||
Requires<[HasT2ExtractPack, IsThumb2]>;
|
||||
Requires<[HasDSP, IsThumb2]>;
|
||||
def : T2Pat<(add rGPR:$Rn, (and rGPR:$Rm, 0x00FF)),
|
||||
(t2UXTAB rGPR:$Rn, rGPR:$Rm, 0)>,
|
||||
Requires<[HasT2ExtractPack, IsThumb2]>;
|
||||
Requires<[HasDSP, IsThumb2]>;
|
||||
def : T2Pat<(add rGPR:$Rn, (and rGPR:$Rm, 0xFFFF)),
|
||||
(t2UXTAH rGPR:$Rn, rGPR:$Rm, 0)>,
|
||||
Requires<[HasT2ExtractPack, IsThumb2]>;
|
||||
Requires<[HasDSP, IsThumb2]>;
|
||||
}
|
||||
|
||||
def : T2Pat<(sext_inreg rGPR:$Src, i8), (t2SXTB rGPR:$Src, 0)>,
|
||||
@ -4231,10 +4214,10 @@ def : T2Pat<(sext_inreg rGPR:$Src, i16), (t2SXTH rGPR:$Src, 0)>,
|
||||
Requires<[IsThumb2]>;
|
||||
def : T2Pat<(add rGPR:$Rn, (sext_inreg rGPR:$Rm, i8)),
|
||||
(t2SXTAB rGPR:$Rn, rGPR:$Rm, 0)>,
|
||||
Requires<[HasT2ExtractPack, IsThumb2]>;
|
||||
Requires<[HasDSP, IsThumb2]>;
|
||||
def : T2Pat<(add rGPR:$Rn, (sext_inreg rGPR:$Rm, i16)),
|
||||
(t2SXTAH rGPR:$Rn, rGPR:$Rm, 0)>,
|
||||
Requires<[HasT2ExtractPack, IsThumb2]>;
|
||||
Requires<[HasDSP, IsThumb2]>;
|
||||
|
||||
// Atomic load/store patterns
|
||||
def : T2Pat<(atomic_load_8 t2addrmode_imm12:$addr),
|
||||
@ -4431,10 +4414,10 @@ def : t2InstAlias<"mvn${s}${p} $Rd, $ShiftedRm",
|
||||
// input operands swapped when the shift amount is zero (i.e., unspecified).
|
||||
def : InstAlias<"pkhbt${p} $Rd, $Rn, $Rm",
|
||||
(t2PKHBT rGPR:$Rd, rGPR:$Rn, rGPR:$Rm, 0, pred:$p), 0>,
|
||||
Requires<[HasT2ExtractPack, IsThumb2]>;
|
||||
Requires<[HasDSP, IsThumb2]>;
|
||||
def : InstAlias<"pkhtb${p} $Rd, $Rn, $Rm",
|
||||
(t2PKHBT rGPR:$Rd, rGPR:$Rm, rGPR:$Rn, 0, pred:$p), 0>,
|
||||
Requires<[HasT2ExtractPack, IsThumb2]>;
|
||||
Requires<[HasDSP, IsThumb2]>;
|
||||
|
||||
// PUSH/POP aliases for STM/LDM
|
||||
def : t2InstAlias<"push${p}.w $regs", (t2STMDB_UPD SP, pred:$p, reglist:$regs)>;
|
||||
@ -4513,16 +4496,16 @@ def : t2InstAlias<"strh${p} $Rt, $addr",
|
||||
// Extend instruction optional rotate operand.
|
||||
def : InstAlias<"sxtab${p} $Rd, $Rn, $Rm",
|
||||
(t2SXTAB rGPR:$Rd, rGPR:$Rn, rGPR:$Rm, 0, pred:$p), 0>,
|
||||
Requires<[HasT2ExtractPack, IsThumb2]>;
|
||||
Requires<[HasDSP, IsThumb2]>;
|
||||
def : InstAlias<"sxtah${p} $Rd, $Rn, $Rm",
|
||||
(t2SXTAH rGPR:$Rd, rGPR:$Rn, rGPR:$Rm, 0, pred:$p), 0>,
|
||||
Requires<[HasT2ExtractPack, IsThumb2]>;
|
||||
Requires<[HasDSP, IsThumb2]>;
|
||||
def : InstAlias<"sxtab16${p} $Rd, $Rn, $Rm",
|
||||
(t2SXTAB16 rGPR:$Rd, rGPR:$Rn, rGPR:$Rm, 0, pred:$p), 0>,
|
||||
Requires<[HasT2ExtractPack, IsThumb2]>;
|
||||
Requires<[HasDSP, IsThumb2]>;
|
||||
def : InstAlias<"sxtb16${p} $Rd, $Rm",
|
||||
(t2SXTB16 rGPR:$Rd, rGPR:$Rm, 0, pred:$p), 0>,
|
||||
Requires<[HasT2ExtractPack, IsThumb2]>;
|
||||
Requires<[HasDSP, IsThumb2]>;
|
||||
|
||||
def : t2InstAlias<"sxtb${p} $Rd, $Rm",
|
||||
(t2SXTB rGPR:$Rd, rGPR:$Rm, 0, pred:$p)>;
|
||||
@ -4535,16 +4518,16 @@ def : t2InstAlias<"sxth${p}.w $Rd, $Rm",
|
||||
|
||||
def : InstAlias<"uxtab${p} $Rd, $Rn, $Rm",
|
||||
(t2UXTAB rGPR:$Rd, rGPR:$Rn, rGPR:$Rm, 0, pred:$p), 0>,
|
||||
Requires<[HasT2ExtractPack, IsThumb2]>;
|
||||
Requires<[HasDSP, IsThumb2]>;
|
||||
def : InstAlias<"uxtah${p} $Rd, $Rn, $Rm",
|
||||
(t2UXTAH rGPR:$Rd, rGPR:$Rn, rGPR:$Rm, 0, pred:$p), 0>,
|
||||
Requires<[HasT2ExtractPack, IsThumb2]>;
|
||||
Requires<[HasDSP, IsThumb2]>;
|
||||
def : InstAlias<"uxtab16${p} $Rd, $Rn, $Rm",
|
||||
(t2UXTAB16 rGPR:$Rd, rGPR:$Rn, rGPR:$Rm, 0, pred:$p), 0>,
|
||||
Requires<[HasT2ExtractPack, IsThumb2]>;
|
||||
Requires<[HasDSP, IsThumb2]>;
|
||||
def : InstAlias<"uxtb16${p} $Rd, $Rm",
|
||||
(t2UXTB16 rGPR:$Rd, rGPR:$Rm, 0, pred:$p), 0>,
|
||||
Requires<[HasT2ExtractPack, IsThumb2]>;
|
||||
Requires<[HasDSP, IsThumb2]>;
|
||||
|
||||
def : t2InstAlias<"uxtb${p} $Rd, $Rm",
|
||||
(t2UXTB rGPR:$Rd, rGPR:$Rm, 0, pred:$p)>;
|
||||
@ -4560,7 +4543,7 @@ def : t2InstAlias<"uxtb${p} $Rd, $Rm$rot",
|
||||
(t2UXTB rGPR:$Rd, rGPR:$Rm, rot_imm:$rot, pred:$p)>;
|
||||
def : InstAlias<"uxtb16${p} $Rd, $Rm$rot",
|
||||
(t2UXTB16 rGPR:$Rd, rGPR:$Rm, rot_imm:$rot, pred:$p), 0>,
|
||||
Requires<[HasT2ExtractPack, IsThumb2]>;
|
||||
Requires<[HasDSP, IsThumb2]>;
|
||||
def : t2InstAlias<"uxth${p} $Rd, $Rm$rot",
|
||||
(t2UXTH rGPR:$Rd, rGPR:$Rm, rot_imm:$rot, pred:$p)>;
|
||||
|
||||
@ -4568,7 +4551,7 @@ def : t2InstAlias<"sxtb${p} $Rd, $Rm$rot",
|
||||
(t2SXTB rGPR:$Rd, rGPR:$Rm, rot_imm:$rot, pred:$p)>;
|
||||
def : InstAlias<"sxtb16${p} $Rd, $Rm$rot",
|
||||
(t2SXTB16 rGPR:$Rd, rGPR:$Rm, rot_imm:$rot, pred:$p), 0>,
|
||||
Requires<[HasT2ExtractPack, IsThumb2]>;
|
||||
Requires<[HasDSP, IsThumb2]>;
|
||||
def : t2InstAlias<"sxth${p} $Rd, $Rm$rot",
|
||||
(t2SXTH rGPR:$Rd, rGPR:$Rm, rot_imm:$rot, pred:$p)>;
|
||||
|
||||
|
@ -213,10 +213,6 @@ protected:
|
||||
/// HasHardwareDivideInARM - True if subtarget supports [su]div in ARM mode
|
||||
bool HasHardwareDivideInARM = false;
|
||||
|
||||
/// HasT2ExtractPack - True if subtarget supports thumb2 extract/pack
|
||||
/// instructions.
|
||||
bool HasT2ExtractPack = false;
|
||||
|
||||
/// HasDataBarrier - True if the subtarget supports DMB / DSB data barrier
|
||||
/// instructions.
|
||||
bool HasDataBarrier = false;
|
||||
@ -508,7 +504,6 @@ public:
|
||||
|
||||
bool hasDivide() const { return HasHardwareDivide; }
|
||||
bool hasDivideInARMMode() const { return HasHardwareDivideInARM; }
|
||||
bool hasT2ExtractPack() const { return HasT2ExtractPack; }
|
||||
bool hasDataBarrier() const { return HasDataBarrier; }
|
||||
bool hasV7Clrex() const { return HasV7Clrex; }
|
||||
bool hasAcquireRelease() const { return HasAcquireRelease; }
|
||||
|
@ -1,38 +1,45 @@
|
||||
; RUN: llc -mtriple=thumb-eabi -mcpu=cortex-m3 %s -o - | FileCheck %s
|
||||
; RUN: llc -mtriple=thumb-eabi -mcpu=cortex-m4 %s -o - | FileCheck %s --check-prefix=CHECK-M4
|
||||
; RUN: llc -mtriple=thumb-eabi -mcpu=cortex-m3 %s -o - | FileCheck %s --check-prefix=CHECK-NO-DSP
|
||||
; RUN: llc -mtriple=thumb-eabi -mcpu=cortex-m4 %s -o - | FileCheck %s --check-prefix=CHECK-DSP
|
||||
; RUN: llc -mtriple=thumbv7em-eabi %s -o - | FileCheck %s -check-prefix=CHECK-DSP
|
||||
; RUN: llc -mtriple=thumbv8m.main-none-eabi %s -o - | FileCheck %s -check-prefix=CHECK-NO-DSP
|
||||
; RUN: llc -mtriple=thumbv8m.main-none-eabi -mattr=+dsp %s -o - | FileCheck %s -check-prefix=CHECK-DSP
|
||||
|
||||
define i32 @test1(i16 zeroext %z) nounwind {
|
||||
; CHECK-LABEL: test1:
|
||||
; CHECK: sxth
|
||||
; CHECK-DSP: sxth
|
||||
; CHECK-NO-DSP: sxth
|
||||
%r = sext i16 %z to i32
|
||||
ret i32 %r
|
||||
}
|
||||
|
||||
define i32 @test2(i8 zeroext %z) nounwind {
|
||||
; CHECK-LABEL: test2:
|
||||
; CHECK: sxtb
|
||||
; CHECK-DSP: sxtb
|
||||
; CHECK-NO-DSP: sxtb
|
||||
%r = sext i8 %z to i32
|
||||
ret i32 %r
|
||||
}
|
||||
|
||||
define i32 @test3(i16 signext %z) nounwind {
|
||||
; CHECK-LABEL: test3:
|
||||
; CHECK: uxth
|
||||
; CHECK-DSP: uxth
|
||||
; CHECK-NO-DSP: uxth
|
||||
%r = zext i16 %z to i32
|
||||
ret i32 %r
|
||||
}
|
||||
|
||||
define i32 @test4(i8 signext %z) nounwind {
|
||||
; CHECK-LABEL: test4:
|
||||
; CHECK: uxtb
|
||||
; CHECK-DSP: uxtb
|
||||
; CHECK-NO-DSP: uxtb
|
||||
%r = zext i8 %z to i32
|
||||
ret i32 %r
|
||||
}
|
||||
|
||||
define i32 @test5(i32 %a, i8 %b) {
|
||||
; CHECK-LABEL: test5:
|
||||
; CHECK-NOT: sxtab
|
||||
; CHECK-M4: sxtab r0, r0, r1
|
||||
; CHECK-DSP: sxtab r0, r0, r1
|
||||
; CHECK-NO-DSP-NOT: sxtab
|
||||
%sext = sext i8 %b to i32
|
||||
%add = add i32 %a, %sext
|
||||
ret i32 %add
|
||||
@ -40,8 +47,8 @@ define i32 @test5(i32 %a, i8 %b) {
|
||||
|
||||
define i32 @test6(i32 %a, i32 %b) {
|
||||
; CHECK-LABEL: test6:
|
||||
; CHECK-NOT: sxtab
|
||||
; CHECK-M4: sxtab r0, r0, r1
|
||||
; CHECK-DSP: sxtab r0, r0, r1
|
||||
; CHECK-NO-DSP-NOT: sxtab
|
||||
%shl = shl i32 %b, 24
|
||||
%ashr = ashr i32 %shl, 24
|
||||
%add = add i32 %a, %ashr
|
||||
@ -50,8 +57,8 @@ define i32 @test6(i32 %a, i32 %b) {
|
||||
|
||||
define i32 @test7(i32 %a, i16 %b) {
|
||||
; CHECK-LABEL: test7:
|
||||
; CHECK-NOT: sxtah
|
||||
; CHECK-M4: sxtah r0, r0, r1
|
||||
; CHECK-DSP: sxtah r0, r0, r1
|
||||
; CHECK-NO-DSPNOT: sxtah
|
||||
%sext = sext i16 %b to i32
|
||||
%add = add i32 %a, %sext
|
||||
ret i32 %add
|
||||
@ -59,8 +66,8 @@ define i32 @test7(i32 %a, i16 %b) {
|
||||
|
||||
define i32 @test8(i32 %a, i32 %b) {
|
||||
; CHECK-LABEL: test8:
|
||||
; CHECK-NOT: sxtah
|
||||
; CHECK-M4: sxtah r0, r0, r1
|
||||
; CHECK-DSP: sxtah r0, r0, r1
|
||||
; CHECK-NO-DSP-NOT: sxtah
|
||||
%shl = shl i32 %b, 16
|
||||
%ashr = ashr i32 %shl, 16
|
||||
%add = add i32 %a, %ashr
|
||||
@ -69,8 +76,8 @@ define i32 @test8(i32 %a, i32 %b) {
|
||||
|
||||
define i32 @test9(i32 %a, i8 %b) {
|
||||
; CHECK-LABEL: test9:
|
||||
; CHECK-NOT: uxtab
|
||||
; CHECK-M4: uxtab r0, r0, r1
|
||||
; CHECK-DSP: uxtab r0, r0, r1
|
||||
; CHECK-NO-DSP-NOT: uxtab
|
||||
%zext = zext i8 %b to i32
|
||||
%add = add i32 %a, %zext
|
||||
ret i32 %add
|
||||
@ -78,8 +85,8 @@ define i32 @test9(i32 %a, i8 %b) {
|
||||
|
||||
define i32 @test10(i32 %a, i32 %b) {
|
||||
;CHECK-LABEL: test10:
|
||||
;CHECK-NOT: uxtab
|
||||
;CHECK-M4: uxtab r0, r0, r1
|
||||
;CHECK-DSP: uxtab r0, r0, r1
|
||||
;CHECK-NO-DSP-NOT: uxtab
|
||||
%and = and i32 %b, 255
|
||||
%add = add i32 %a, %and
|
||||
ret i32 %add
|
||||
@ -87,8 +94,8 @@ define i32 @test10(i32 %a, i32 %b) {
|
||||
|
||||
define i32 @test11(i32 %a, i16 %b) {
|
||||
; CHECK-LABEL: test11:
|
||||
; CHECK-NOT: uxtah
|
||||
; CHECK-M4: uxtah r0, r0, r1
|
||||
; CHECK-DSP: uxtah r0, r0, r1
|
||||
; CHECK-NO-DSP-NOT: uxtah
|
||||
%zext = zext i16 %b to i32
|
||||
%add = add i32 %a, %zext
|
||||
ret i32 %add
|
||||
@ -96,8 +103,8 @@ define i32 @test11(i32 %a, i16 %b) {
|
||||
|
||||
define i32 @test12(i32 %a, i32 %b) {
|
||||
;CHECK-LABEL: test12:
|
||||
;CHECK-NOT: uxtah
|
||||
;CHECK-M4: uxtah r0, r0, r1
|
||||
;CHECK-DSP: uxtah r0, r0, r1
|
||||
;CHECK-NO-DSP-NOT: uxtah
|
||||
%and = and i32 %b, 65535
|
||||
%add = add i32 %a, %and
|
||||
ret i32 %add
|
||||
|
@ -1,18 +1,21 @@
|
||||
; RUN: llc -mtriple=thumb-eabi -mcpu=arm1156t2-s -mattr=+thumb2,+t2xtpk %s -o - | FileCheck %s
|
||||
; RUN: llc -mtriple=thumb-eabi -mcpu=cortex-m3 %s -o - | FileCheck %s --check-prefix=CHECK-M3
|
||||
; RUN: llc -mtriple=thumb-eabi -mcpu=arm1156t2-s %s -o - | FileCheck %s --check-prefix=CHECK-DSP
|
||||
; RUN: llc -mtriple=thumb-eabi -mcpu=cortex-m3 %s -o - | FileCheck %s --check-prefix=CHECK-NO-DSP
|
||||
; RUN: llc -mtriple=thumbv7em-eabi %s -o - | FileCheck %s -check-prefix=CHECK-DSP
|
||||
; RUN: llc -mtriple=thumbv8m.main-none-eabi %s -o - | FileCheck %s -check-prefix=CHECK-NO-DSP
|
||||
; RUN: llc -mtriple=thumbv8m.main-none-eabi -mattr=+dsp %s -o - | FileCheck %s -check-prefix=CHECK-DSP
|
||||
|
||||
define i32 @test0(i8 %A) {
|
||||
; CHECK-LABEL: test0:
|
||||
; CHECK: sxtb r0, r0
|
||||
; CHECK-M3: sxtb r0, r0
|
||||
; CHECK-DSP: sxtb r0, r0
|
||||
; CHECK-NO-DSP: sxtb r0, r0
|
||||
%B = sext i8 %A to i32
|
||||
ret i32 %B
|
||||
}
|
||||
|
||||
define signext i8 @test1(i32 %A) {
|
||||
; CHECK-LABEL: test1:
|
||||
; CHECK: sbfx r0, r0, #8, #8
|
||||
; CHECK-M3: sbfx r0, r0, #8, #8
|
||||
; CHECK-DSP: sbfx r0, r0, #8, #8
|
||||
; CHECK-NO-DSP: sbfx r0, r0, #8, #8
|
||||
%B = lshr i32 %A, 8
|
||||
%C = shl i32 %A, 24
|
||||
%D = or i32 %B, %C
|
||||
@ -22,8 +25,8 @@ define signext i8 @test1(i32 %A) {
|
||||
|
||||
define signext i32 @test2(i32 %A, i32 %X) {
|
||||
; CHECK-LABEL: test2:
|
||||
; CHECK: sxtab r0, r1, r0, ror #8
|
||||
; CHECK-M3-NOT: sxtab
|
||||
; CHECK-DSP: sxtab r0, r1, r0, ror #8
|
||||
; CHECK-NO-DSP-NOT: sxtab
|
||||
%B = lshr i32 %A, 8
|
||||
%C = shl i32 %A, 24
|
||||
%D = or i32 %B, %C
|
||||
@ -35,8 +38,8 @@ define signext i32 @test2(i32 %A, i32 %X) {
|
||||
|
||||
define i32 @test3(i32 %A, i32 %X) {
|
||||
; CHECK-LABEL: test3:
|
||||
; CHECK: sxtah r0, r0, r1, ror #8
|
||||
; CHECK-M3-NOT: sxtah
|
||||
; CHECK-DSP: sxtah r0, r0, r1, ror #8
|
||||
; CHECK-NO-DSP-NOT: sxtah
|
||||
%X.hi = lshr i32 %X, 8
|
||||
%X.trunc = trunc i32 %X.hi to i16
|
||||
%addend = sext i16 %X.trunc to i32
|
||||
@ -46,8 +49,8 @@ define i32 @test3(i32 %A, i32 %X) {
|
||||
|
||||
define signext i32 @test4(i32 %A, i32 %X) {
|
||||
; CHECK-LABEL: test4:
|
||||
; CHECK: sxtab r0, r1, r0, ror #16
|
||||
; CHECK-M3-NOT: sxtab
|
||||
; CHECK-DSP: sxtab r0, r1, r0, ror #16
|
||||
; CHECK-NO-DSP-NOT: sxtab
|
||||
%B = lshr i32 %A, 16
|
||||
%C = shl i32 %A, 16
|
||||
%D = or i32 %B, %C
|
||||
@ -59,8 +62,8 @@ define signext i32 @test4(i32 %A, i32 %X) {
|
||||
|
||||
define signext i32 @test5(i32 %A, i32 %X) {
|
||||
; CHECK-LABEL: test5:
|
||||
; CHECK: sxtah r0, r1, r0, ror #24
|
||||
; CHECK-M3-NOT: sxtah
|
||||
; CHECK-DSP: sxtah r0, r1, r0, ror #24
|
||||
; CHECK-NO-DSP-NOT: sxtah
|
||||
%B = lshr i32 %A, 24
|
||||
%C = shl i32 %A, 8
|
||||
%D = or i32 %B, %C
|
||||
|
@ -1,21 +1,22 @@
|
||||
; RUN: llc -mtriple=thumb-eabi -mcpu=cortex-a8 %s -o - | FileCheck %s --check-prefix=A8
|
||||
; RUN: llc -mtriple=thumb-eabi -mcpu=cortex-m3 %s -o - | FileCheck %s --check-prefix=M3
|
||||
; RUN: llc -mtriple=thumb-eabi -mcpu=cortex-a8 %s -o - | FileCheck %s --check-prefix=CHECK-DSP
|
||||
; RUN: llc -mtriple=thumb-eabi -mcpu=cortex-m3 %s -o - | FileCheck %s --check-prefix=CHECK-NO-DSP
|
||||
; RUN: llc -mtriple=thumbv7em-eabi %s -o - | FileCheck %s -check-prefix=CHECK-DSP
|
||||
; RUN: llc -mtriple=thumbv8m.main-none-eabi %s -o - | FileCheck %s -check-prefix=CHECK-NO-DSP
|
||||
; RUN: llc -mtriple=thumbv8m.main-none-eabi -mattr=+dsp %s -o - | FileCheck %s -check-prefix=CHECK-DSP
|
||||
; rdar://11318438
|
||||
|
||||
define zeroext i8 @test1(i32 %A.u) {
|
||||
; CHECK-LABEL: test1:
|
||||
; A8: uxtb r0, r0
|
||||
; CHECK-DSP: uxtb r0, r0
|
||||
; CHECK-NO-DSP: uxtb r0, r0
|
||||
%B.u = trunc i32 %A.u to i8
|
||||
ret i8 %B.u
|
||||
}
|
||||
|
||||
define zeroext i32 @test2(i32 %A.u, i32 %B.u) {
|
||||
; CHECK-LABEL: test2:
|
||||
; A8: uxtab r0, r0, r1
|
||||
|
||||
; M3: uxtb r1, r1
|
||||
; M3-NOT: uxtab
|
||||
; M3: add r0, r1
|
||||
; CHECK-DSP: uxtab r0, r0, r1
|
||||
; CHECK-NO-DSP-NOT: uxtab
|
||||
%C.u = trunc i32 %B.u to i8
|
||||
%D.u = zext i8 %C.u to i32
|
||||
%E.u = add i32 %A.u, %D.u
|
||||
@ -24,8 +25,8 @@ define zeroext i32 @test2(i32 %A.u, i32 %B.u) {
|
||||
|
||||
define zeroext i32 @test3(i32 %A.u) {
|
||||
; CHECK-LABEL: test3:
|
||||
; A8: ubfx r0, r0, #8, #16
|
||||
; M3: ubfx r0, r0, #8, #16
|
||||
; CHECK-DSP: ubfx r0, r0, #8, #16
|
||||
; CHECK-NO-DSP: ubfx r0, r0, #8, #16
|
||||
%B.u = lshr i32 %A.u, 8
|
||||
%C.u = shl i32 %A.u, 24
|
||||
%D.u = or i32 %B.u, %C.u
|
||||
@ -36,8 +37,8 @@ define zeroext i32 @test3(i32 %A.u) {
|
||||
|
||||
define i32 @test4(i32 %A, i32 %X) {
|
||||
; CHECK-LABEL: test4:
|
||||
; A8: uxtab r0, r0, r1, ror #16
|
||||
; M3-NOT: uxtab
|
||||
; CHECK-DSP: uxtab r0, r0, r1, ror #16
|
||||
; CHECK-NO-DSP-NOT: uxtab
|
||||
%X.hi = lshr i32 %X, 16
|
||||
%X.trunc = trunc i32 %X.hi to i8
|
||||
%addend = zext i8 %X.trunc to i32
|
||||
@ -47,8 +48,8 @@ define i32 @test4(i32 %A, i32 %X) {
|
||||
|
||||
define i32 @test5(i32 %A, i32 %X) {
|
||||
; CHECK-LABEL: test5:
|
||||
; A8: uxtah r0, r0, r1, ror #8
|
||||
; M3-NOT: uxtah
|
||||
; CHECK-DSP: uxtah r0, r0, r1, ror #8
|
||||
; CHECK-NO-DSP-NOT: uxtah
|
||||
%X.hi = lshr i32 %X, 8
|
||||
%X.trunc = trunc i32 %X.hi to i16
|
||||
%addend = zext i16 %X.trunc to i32
|
||||
@ -58,8 +59,8 @@ define i32 @test5(i32 %A, i32 %X) {
|
||||
|
||||
define i32 @test6(i32 %A, i32 %X) {
|
||||
; CHECK-LABEL: test6:
|
||||
; A8: uxtab r0, r0, r1, ror #8
|
||||
; M3-NOT: uxtab
|
||||
; CHECK-DSP: uxtab r0, r0, r1, ror #8
|
||||
; CHECK-NO-DSP-NOT: uxtab
|
||||
%X.hi = lshr i32 %X, 8
|
||||
%X.trunc = trunc i32 %X.hi to i8
|
||||
%addend = zext i8 %X.trunc to i32
|
||||
@ -69,8 +70,8 @@ define i32 @test6(i32 %A, i32 %X) {
|
||||
|
||||
define i32 @test7(i32 %A, i32 %X) {
|
||||
; CHECK-LABEL: test7:
|
||||
; A8: uxtah r0, r0, r1, ror #24
|
||||
; M3-NOT: uxtah
|
||||
; CHECK-DSP: uxtah r0, r0, r1, ror #24
|
||||
; CHECK-NO-DSP-NOT: uxtah
|
||||
%lshr = lshr i32 %X, 24
|
||||
%shl = shl i32 %X, 8
|
||||
%or = or i32 %lshr, %shl
|
||||
@ -82,8 +83,8 @@ define i32 @test7(i32 %A, i32 %X) {
|
||||
|
||||
define i32 @test8(i32 %A, i32 %X) {
|
||||
; CHECK-LABEL: test8:
|
||||
; A8: uxtah r0, r0, r1, ror #24
|
||||
; M3-NOT: uxtah
|
||||
; CHECK-DSP: uxtah r0, r0, r1, ror #24
|
||||
; CHECK-NO-DSP-NOT: uxtah
|
||||
%lshr = lshr i32 %X, 24
|
||||
%shl = shl i32 %X, 8
|
||||
%or = or i32 %lshr, %shl
|
||||
|
@ -1,72 +1,63 @@
|
||||
; RUN: llc -mtriple=thumb-eabi -mcpu=cortex-a8 %s -o - | FileCheck %s -check-prefix=ARMv7A
|
||||
; RUN: llc -mtriple=thumb-eabi -mcpu=cortex-m3 %s -o - | FileCheck %s -check-prefix=ARMv7M
|
||||
; RUN: llc -mtriple=thumb-eabi -mcpu=cortex-a8 %s -o - | FileCheck %s -check-prefix=CHECK-DSP
|
||||
; RUN: llc -mtriple=thumb-eabi -mcpu=cortex-m3 %s -o - | FileCheck %s -check-prefix=CHECK-NO-DSP
|
||||
; RUN: llc -mtriple=thumbv7em-eabi %s -o - | FileCheck %s -check-prefix=CHECK-DSP
|
||||
; RUN: llc -mtriple=thumbv8m.main-none-eabi %s -o - | FileCheck %s -check-prefix=CHECK-NO-DSP
|
||||
; RUN: llc -mtriple=thumbv8m.main-none-eabi -mattr=+dsp %s -o - | FileCheck %s -check-prefix=CHECK-DSP
|
||||
|
||||
define i32 @test1(i32 %x) {
|
||||
; ARMv7A: test1
|
||||
; ARMv7A: uxtb16 r0, r0
|
||||
|
||||
; ARMv7M: test1
|
||||
; ARMv7M: bic r0, r0, #-16711936
|
||||
; CHECK-LABEL: test1
|
||||
; CHECK-DSP: uxtb16 r0, r0
|
||||
; CHECK-NO-DSP: bic r0, r0, #-16711936
|
||||
%tmp1 = and i32 %x, 16711935 ; <i32> [#uses=1]
|
||||
ret i32 %tmp1
|
||||
}
|
||||
|
||||
; PR7503
|
||||
define i32 @test2(i32 %x) {
|
||||
; ARMv7A: test2
|
||||
; ARMv7A: uxtb16 r0, r0, ror #8
|
||||
|
||||
; ARMv7M: test2
|
||||
; ARMv7M: mov.w r1, #16711935
|
||||
; ARMv7M: and.w r0, r1, r0, lsr #8
|
||||
; CHECK-LABEL: test2
|
||||
; CHECK-DSP: uxtb16 r0, r0, ror #8
|
||||
; CHECK-NO-DSP: mov.w r1, #16711935
|
||||
; CHECK-NO-DSP: and.w r0, r1, r0, lsr #8
|
||||
%tmp1 = lshr i32 %x, 8 ; <i32> [#uses=1]
|
||||
%tmp2 = and i32 %tmp1, 16711935 ; <i32> [#uses=1]
|
||||
ret i32 %tmp2
|
||||
}
|
||||
|
||||
define i32 @test3(i32 %x) {
|
||||
; ARMv7A: test3
|
||||
; ARMv7A: uxtb16 r0, r0, ror #8
|
||||
|
||||
; ARMv7M: test3
|
||||
; ARMv7M: mov.w r1, #16711935
|
||||
; ARMv7M: and.w r0, r1, r0, lsr #8
|
||||
; CHECK-LABEL: test3
|
||||
; CHECK-DSP: uxtb16 r0, r0, ror #8
|
||||
; CHECK-NO-DSP: mov.w r1, #16711935
|
||||
; CHECK-NO-DSP: and.w r0, r1, r0, lsr #8
|
||||
%tmp1 = lshr i32 %x, 8 ; <i32> [#uses=1]
|
||||
%tmp2 = and i32 %tmp1, 16711935 ; <i32> [#uses=1]
|
||||
ret i32 %tmp2
|
||||
}
|
||||
|
||||
define i32 @test4(i32 %x) {
|
||||
; ARMv7A: test4
|
||||
; ARMv7A: uxtb16 r0, r0, ror #8
|
||||
|
||||
; ARMv7M: test4
|
||||
; ARMv7M: mov.w r1, #16711935
|
||||
; ARMv7M: and.w r0, r1, r0, lsr #8
|
||||
; CHECK-LABEL: test4
|
||||
; CHECK-DSP: uxtb16 r0, r0, ror #8
|
||||
; CHECK-NO-DSP: mov.w r1, #16711935
|
||||
; CHECK-NO-DSP: and.w r0, r1, r0, lsr #8
|
||||
%tmp1 = lshr i32 %x, 8 ; <i32> [#uses=1]
|
||||
%tmp6 = and i32 %tmp1, 16711935 ; <i32> [#uses=1]
|
||||
ret i32 %tmp6
|
||||
}
|
||||
|
||||
define i32 @test5(i32 %x) {
|
||||
; ARMv7A: test5
|
||||
; ARMv7A: uxtb16 r0, r0, ror #8
|
||||
|
||||
; ARMv7M: test5
|
||||
; ARMv7M: mov.w r1, #16711935
|
||||
; ARMv7M: and.w r0, r1, r0, lsr #8
|
||||
; CHECK-LABEL: test5
|
||||
; CHECK-DSP: uxtb16 r0, r0, ror #8
|
||||
; CHECK-NO-DSP: mov.w r1, #16711935
|
||||
; CHECK-NO-DSP: and.w r0, r1, r0, lsr #8
|
||||
%tmp1 = lshr i32 %x, 8 ; <i32> [#uses=1]
|
||||
%tmp2 = and i32 %tmp1, 16711935 ; <i32> [#uses=1]
|
||||
ret i32 %tmp2
|
||||
}
|
||||
|
||||
define i32 @test6(i32 %x) {
|
||||
; ARMv7A: test6
|
||||
; ARMv7A: uxtb16 r0, r0, ror #16
|
||||
|
||||
; ARMv7M: test6
|
||||
; ARMv7M: mov.w r1, #16711935
|
||||
; ARMv7M: and.w r0, r1, r0, ror #16
|
||||
; CHECK-LABEL: test6
|
||||
; CHECK-DSP: uxtb16 r0, r0, ror #16
|
||||
; CHECK-NO-DSP: mov.w r1, #16711935
|
||||
; CHECK-NO-DSP: and.w r0, r1, r0, ror #16
|
||||
%tmp1 = lshr i32 %x, 16 ; <i32> [#uses=1]
|
||||
%tmp2 = and i32 %tmp1, 255 ; <i32> [#uses=1]
|
||||
%tmp4 = shl i32 %x, 16 ; <i32> [#uses=1]
|
||||
@ -76,12 +67,10 @@ define i32 @test6(i32 %x) {
|
||||
}
|
||||
|
||||
define i32 @test7(i32 %x) {
|
||||
; ARMv7A: test7
|
||||
; ARMv7A: uxtb16 r0, r0, ror #16
|
||||
|
||||
; ARMv7M: test7
|
||||
; ARMv7M: mov.w r1, #16711935
|
||||
; ARMv7M: and.w r0, r1, r0, ror #16
|
||||
; CHECK-LABEL: test7
|
||||
; CHECK-DSP: uxtb16 r0, r0, ror #16
|
||||
; CHECK-NO-DSP: mov.w r1, #16711935
|
||||
; CHECK-NO-DSP: and.w r0, r1, r0, ror #16
|
||||
%tmp1 = lshr i32 %x, 16 ; <i32> [#uses=1]
|
||||
%tmp2 = and i32 %tmp1, 255 ; <i32> [#uses=1]
|
||||
%tmp4 = shl i32 %x, 16 ; <i32> [#uses=1]
|
||||
@ -91,12 +80,10 @@ define i32 @test7(i32 %x) {
|
||||
}
|
||||
|
||||
define i32 @test8(i32 %x) {
|
||||
; ARMv7A: test8
|
||||
; ARMv7A: uxtb16 r0, r0, ror #24
|
||||
|
||||
; ARMv7M: test8
|
||||
; ARMv7M: mov.w r1, #16711935
|
||||
; ARMv7M: and.w r0, r1, r0, ror #24
|
||||
; CHECK-LABEL: test8
|
||||
; CHECK-DSP: uxtb16 r0, r0, ror #24
|
||||
; CHECK-NO-DSP: mov.w r1, #16711935
|
||||
; CHECK-NO-DSP: and.w r0, r1, r0, ror #24
|
||||
%tmp1 = shl i32 %x, 8 ; <i32> [#uses=1]
|
||||
%tmp2 = and i32 %tmp1, 16711680 ; <i32> [#uses=1]
|
||||
%tmp5 = lshr i32 %x, 24 ; <i32> [#uses=1]
|
||||
@ -105,12 +92,10 @@ define i32 @test8(i32 %x) {
|
||||
}
|
||||
|
||||
define i32 @test9(i32 %x) {
|
||||
; ARMv7A: test9
|
||||
; ARMv7A: uxtb16 r0, r0, ror #24
|
||||
|
||||
; ARMv7M: test9
|
||||
; ARMv7M: mov.w r1, #16711935
|
||||
; ARMv7M: and.w r0, r1, r0, ror #24
|
||||
; CHECK-LABEL: test9
|
||||
; CHECK-DSP: uxtb16 r0, r0, ror #24
|
||||
; CHECK-NO-DSP: mov.w r1, #16711935
|
||||
; CHECK-NO-DSP: and.w r0, r1, r0, ror #24
|
||||
%tmp1 = lshr i32 %x, 24 ; <i32> [#uses=1]
|
||||
%tmp4 = shl i32 %x, 8 ; <i32> [#uses=1]
|
||||
%tmp5 = and i32 %tmp4, 16711680 ; <i32> [#uses=1]
|
||||
@ -119,19 +104,18 @@ define i32 @test9(i32 %x) {
|
||||
}
|
||||
|
||||
define i32 @test10(i32 %p0) {
|
||||
; ARMv7A: test10
|
||||
; ARMv7A: mov.w r1, #16253176
|
||||
; ARMv7A: and.w r0, r1, r0, lsr #7
|
||||
; ARMv7A: lsrs r1, r0, #5
|
||||
; ARMv7A: uxtb16 r1, r1
|
||||
; ARMv7A: orrs r0, r1
|
||||
; CHECK-LABEL: test10
|
||||
; CHECK-DSP: mov.w r1, #16253176
|
||||
; CHECK-DSP: and.w r0, r1, r0, lsr #7
|
||||
; CHECK-DSP: lsrs r1, r0, #5
|
||||
; CHECK-DSP: uxtb16 r1, r1
|
||||
; CHECk-DSP: orrs r0, r1
|
||||
|
||||
; ARMv7M: test10
|
||||
; ARMv7M: mov.w r1, #16253176
|
||||
; ARMv7M: and.w r0, r1, r0, lsr #7
|
||||
; ARMv7M: mov.w r1, #458759
|
||||
; ARMv7M: and.w r1, r1, r0, lsr #5
|
||||
; ARMv7M: orrs r0, r1
|
||||
; CHECK-NO-DSP: mov.w r1, #16253176
|
||||
; CHECK-NO-DSP: and.w r0, r1, r0, lsr #7
|
||||
; CHECK-NO-DSP: mov.w r1, #458759
|
||||
; CHECK-NO-DSP: and.w r1, r1, r0, lsr #5
|
||||
; CHECK-NO-DSP: orrs r0, r1
|
||||
%tmp1 = lshr i32 %p0, 7 ; <i32> [#uses=1]
|
||||
%tmp2 = and i32 %tmp1, 16253176 ; <i32> [#uses=2]
|
||||
%tmp4 = lshr i32 %tmp2, 5 ; <i32> [#uses=1]
|
||||
|
Loading…
x
Reference in New Issue
Block a user