Skip to content

Commit

Permalink
[M68k] Separate ADDA from ADD and migrate rest of the arithmetic MC t…
Browse files Browse the repository at this point in the history
…ests

Previously ADD & ADDA (as well as SUB & SUBA) instructions are mixed
together, which not only violated Motorola assembly's syntax but also
made asm parsing more difficult. This patch separates these two kinds of
instructions migrate rest of the tests from
test/CodeGen/M68k/Encoding/Arithmetic to test/MC/M68k/Arithmetic.

Note that we observed minor regressions on codegen quality: Sometimes
isel uses ADD instead of ADDA even the latter can lead to shorter
sequence of code. This issue implies that some isel patterns might need
to be updated.
  • Loading branch information
mshockwave committed Aug 8, 2021
1 parent 4c0d15f commit 657bb72
Show file tree
Hide file tree
Showing 45 changed files with 495 additions and 763 deletions.
20 changes: 20 additions & 0 deletions llvm/lib/Target/M68k/AsmParser/M68kAsmParser.cpp
Expand Up @@ -149,8 +149,16 @@ class M68kOperand : public MCParsedAsmOperand {

// Reg
bool isReg() const override;
bool isAReg() const;
bool isDReg() const;
unsigned getReg() const override;
void addRegOperands(MCInst &Inst, unsigned N) const;
void addARegOperands(MCInst &Inst, unsigned N) const {
addRegOperands(Inst, N);
}
void addDRegOperands(MCInst &Inst, unsigned N) const {
addRegOperands(Inst, N);
}

static std::unique_ptr<M68kOperand> createMemOp(M68kMemOp MemOp, SMLoc Start,
SMLoc End);
Expand Down Expand Up @@ -412,6 +420,18 @@ static inline bool checkRegisterClass(unsigned RegNo, bool Data, bool Address,
}
}

bool M68kOperand::isAReg() const {
return isReg() && checkRegisterClass(getReg(),
/*Data=*/false,
/*Address=*/true, /*SP=*/true);
}

bool M68kOperand::isDReg() const {
return isReg() && checkRegisterClass(getReg(),
/*Data=*/true,
/*Address=*/false, /*SP=*/false);
}

unsigned M68kAsmParser::validateTargetOperandClass(MCParsedAsmOperand &Op,
unsigned Kind) {
M68kOperand &Operand = (M68kOperand &)Op;
Expand Down
8 changes: 4 additions & 4 deletions llvm/lib/Target/M68k/M68kFrameLowering.cpp
Expand Up @@ -357,7 +357,7 @@ void M68kFrameLowering::emitSPUpdate(MachineBasicBlock &MBB,
if (Reg) {
unsigned Opc = M68k::MOV32ri;
BuildMI(MBB, MBBI, DL, TII.get(Opc), Reg).addImm(Offset);
Opc = IsSub ? M68k::SUB32rr : M68k::ADD32rr;
Opc = IsSub ? M68k::SUB32ar : M68k::ADD32ar;
MachineInstr *MI = BuildMI(MBB, MBBI, DL, TII.get(Opc), StackPtr)
.addReg(StackPtr)
.addReg(Reg);
Expand Down Expand Up @@ -400,13 +400,13 @@ int M68kFrameLowering::mergeSPUpdates(MachineBasicBlock &MBB,
return Offset;
}

if (Opc == M68k::ADD32ri && PI->getOperand(0).getReg() == StackPtr) {
if (Opc == M68k::ADD32ai && PI->getOperand(0).getReg() == StackPtr) {
assert(PI->getOperand(1).getReg() == StackPtr);
Offset += PI->getOperand(2).getImm();
MBB.erase(PI);
if (!MergeWithPrevious)
MBBI = NI;
} else if (Opc == M68k::SUB32ri && PI->getOperand(0).getReg() == StackPtr) {
} else if (Opc == M68k::SUB32ai && PI->getOperand(0).getReg() == StackPtr) {
assert(PI->getOperand(1).getReg() == StackPtr);
Offset -= PI->getOperand(2).getImm();
MBB.erase(PI);
Expand All @@ -426,7 +426,7 @@ MachineInstrBuilder M68kFrameLowering::BuildStackAdjustment(

bool IsSub = Offset < 0;
uint64_t AbsOffset = IsSub ? -Offset : Offset;
unsigned Opc = IsSub ? M68k::SUB32ri : M68k::ADD32ri;
unsigned Opc = IsSub ? M68k::SUB32ai : M68k::ADD32ai;

MachineInstrBuilder MI = BuildMI(MBB, MBBI, DL, TII.get(Opc), StackPtr)
.addReg(StackPtr)
Expand Down
95 changes: 56 additions & 39 deletions llvm/lib/Target/M68k/M68kInstrArithmetic.td
Expand Up @@ -88,14 +88,15 @@ let Defs = [CCR] in {
let Constraints = "$src = $dst" in {

// $reg, $ccr <- $reg op $reg
class MxBiArOp_RFRR_xEA<string MN, SDNode NODE, MxType TYPE, bits<4> CMD, MxBead REG>
: MxInst<(outs TYPE.ROp:$dst), (ins TYPE.ROp:$src, TYPE.ROp:$opd),
MN#"."#TYPE.Prefix#"\t$opd, $dst",
[(set TYPE.VT:$dst, CCR, (NODE TYPE.VT:$src, TYPE.VT:$opd))],
class MxBiArOp_RFRR_xEA<string MN, SDNode NODE, MxType DST_TYPE, MxType SRC_TYPE,
bits<4> CMD, MxBead REG>
: MxInst<(outs DST_TYPE.ROp:$dst), (ins DST_TYPE.ROp:$src, SRC_TYPE.ROp:$opd),
MN#"."#DST_TYPE.Prefix#"\t$opd, $dst",
[(set DST_TYPE.VT:$dst, CCR, (NODE DST_TYPE.VT:$src, SRC_TYPE.VT:$opd))],
MxArithEncoding<MxBead4Bits<CMD>,
!cast<MxEncOpMode>("MxOpMode"#TYPE.Size#TYPE.RLet#"EA"),
!cast<MxEncOpMode>("MxOpMode"#DST_TYPE.Size#DST_TYPE.RLet#"EA"),
REG,
!cast<MxEncEA>("MxEncEA"#TYPE.RLet#"_2"),
!cast<MxEncEA>("MxEncEA"#SRC_TYPE.RLet#"_2"),
MxExtEmpty>>;

/// This Op is similar to the one above except it uses reversed opmode, some
Expand Down Expand Up @@ -260,11 +261,19 @@ multiclass MxBiArOp_DF<string MN, SDNode NODE, bit isComm,
def NAME#"32ji" : MxBiArOp_FMI<MN, NODE, MxType32, MxType32.JOp, MxType32.JPat,
CMDI, MxEncEAj_0, MxExtEmpty>;

def NAME#"16dr" : MxBiArOp_RFRR_xEA<MN, NODE, MxType16d, MxType16r,
CMD, MxBeadDReg<0>>;
def NAME#"32dr" : MxBiArOp_RFRR_xEA<MN, NODE, MxType32d, MxType32r,
CMD, MxBeadDReg<0>>;

let isCommutable = isComm in {

def NAME#"8dd" : MxBiArOp_RFRR_xEA<MN, NODE, MxType8d, CMD, MxBeadDReg<0>>;
def NAME#"16dd" : MxBiArOp_RFRR_xEA<MN, NODE, MxType16d, CMD, MxBeadDReg<0>>;
def NAME#"32dd" : MxBiArOp_RFRR_xEA<MN, NODE, MxType32d, CMD, MxBeadDReg<0>>;
def NAME#"8dd" : MxBiArOp_RFRR_xEA<MN, NODE, MxType8d, MxType8d,
CMD, MxBeadDReg<0>>;
def NAME#"16dd" : MxBiArOp_RFRR_xEA<MN, NODE, MxType16d, MxType16d,
CMD, MxBeadDReg<0>>;
def NAME#"32dd" : MxBiArOp_RFRR_xEA<MN, NODE, MxType32d, MxType32d,
CMD, MxBeadDReg<0>>;

} // isComm

Expand All @@ -278,29 +287,29 @@ let Pattern = [(null_frag)] in
multiclass MxBiArOp_AF<string MN, SDNode NODE, bit isComm,
bits<4> CMD, bits<4> CMDI> {

def NAME#"32rk" : MxBiArOp_RFRM<MN, NODE, MxType32r, MxType32.KOp, MxType32.KPat,
def NAME#"32ak" : MxBiArOp_RFRM<MN, NODE, MxType32a, MxType32.KOp, MxType32.KPat,
CMD, MxEncEAk, MxExtBrief_2>;
def NAME#"32rq" : MxBiArOp_RFRM<MN, NODE, MxType32r, MxType32.QOp, MxType32.QPat,
def NAME#"32aq" : MxBiArOp_RFRM<MN, NODE, MxType32a, MxType32.QOp, MxType32.QPat,
CMD, MxEncEAq, MxExtI16_2>;
def NAME#"32rf" : MxBiArOp_RFRM<MN, NODE, MxType32r, MxType32.FOp, MxType32.FPat,
def NAME#"32af" : MxBiArOp_RFRM<MN, NODE, MxType32a, MxType32.FOp, MxType32.FPat,
CMD, MxEncEAf_2, MxExtBrief_2>;
def NAME#"32rp" : MxBiArOp_RFRM<MN, NODE, MxType32r, MxType32.POp, MxType32.PPat,
def NAME#"32ap" : MxBiArOp_RFRM<MN, NODE, MxType32a, MxType32.POp, MxType32.PPat,
CMD, MxEncEAp_2, MxExtI16_2>;
def NAME#"32rj" : MxBiArOp_RFRM<MN, NODE, MxType32r, MxType32.JOp, MxType32.JPat,
def NAME#"32aj" : MxBiArOp_RFRM<MN, NODE, MxType32a, MxType32.JOp, MxType32.JPat,
CMD, MxEncEAj_2, MxExtEmpty>;
def NAME#"32ri" : MxBiArOp_RFRI_xEA<MN, NODE, MxType32r, CMD>;
def NAME#"32ai" : MxBiArOp_RFRI_xEA<MN, NODE, MxType32a, CMD>;

let isCommutable = isComm in
def NAME#"32rr" : MxBiArOp_RFRR_xEA<MN, NODE, MxType32r, CMD, MxBeadReg<0>>;
def NAME#"32ar" : MxBiArOp_RFRR_xEA<MN, NODE, MxType32a, MxType32r,
CMD, MxBeadReg<0>>;

} // MxBiArOp_AF

// NOTE These naturally produce CCR

defm ADD : MxBiArOp_DF<"add", MxAdd, 1, 0xD, 0x6>;
defm ADD : MxBiArOp_AF<"add", MxAdd, 1, 0xD, 0x6>;
defm SUB : MxBiArOp_DF<"sub", MxSub, 0, 0x9, 0x4>;
defm SUB : MxBiArOp_AF<"sub", MxSub, 0, 0x9, 0x4>;
defm ADD : MxBiArOp_DF<"add", MxAdd, 1, 0xD, 0x6>;
defm ADD : MxBiArOp_AF<"adda", MxAdd, 1, 0xD, 0x6>;
defm SUB : MxBiArOp_DF<"sub", MxSub, 0, 0x9, 0x4>;
defm SUB : MxBiArOp_AF<"suba", MxSub, 0, 0x9, 0x4>;


let Uses = [CCR], Defs = [CCR] in {
Expand Down Expand Up @@ -366,13 +375,16 @@ defm XOR : MxBiArOp_DF_EAd<"eor", MxXor, 0xB, 0xA>;
//===----------------------------------------------------------------------===//

let Defs = [CCR] in {
class MxCmp_RR<MxType TYPE>
: MxInst<(outs), (ins TYPE.ROp:$lhs, TYPE.ROp:$rhs),
"cmp."#TYPE.Prefix#"\t$lhs, $rhs",
[(set CCR, (MxCmp TYPE.VT:$lhs, TYPE.VT:$rhs))],
class MxCmp_RR<MxType LHS_TYPE, MxType RHS_TYPE = LHS_TYPE,
MxBead REG = MxBeadDReg<1>>
: MxInst<(outs), (ins LHS_TYPE.ROp:$lhs, RHS_TYPE.ROp:$rhs),
"cmp."#RHS_TYPE.Prefix#"\t$lhs, $rhs",
[(set CCR, (MxCmp LHS_TYPE.VT:$lhs, RHS_TYPE.VT:$rhs))],
MxArithEncoding<MxBead4Bits<0xB>,
!cast<MxEncOpMode>("MxOpMode"#TYPE.Size#"dEA"),
MxBeadDReg<1>, MxEncEAd_0, MxExtEmpty>>;
!cast<MxEncOpMode>("MxOpMode"#RHS_TYPE.Size#RHS_TYPE.RLet#"EA"),
REG,
!cast<MxEncEA>("MxEncEA"#LHS_TYPE.RLet#"_0"),
MxExtEmpty>>;

class MxCmp_RI<MxType TYPE>
: MxInst<(outs), (ins TYPE.IOp:$imm, TYPE.ROp:$reg),
Expand Down Expand Up @@ -444,11 +456,16 @@ multiclass MMxCmp_MI<MxType TYPE> {
}

foreach S = [8, 16, 32] in {
def CMP#S#dd : MxCmp_RR<!cast<MxType>("MxType"#S#"d")>;
def CMP#S#di : MxCmp_RI<!cast<MxType>("MxType"#S#"d")>;
def CMP#S#bi : MxCmp_BI<!cast<MxType>("MxType"#S#"d")>;
} // foreach

def CMP8dd : MxCmp_RR<MxType8d>;
foreach S = [16, 32] in {
def CMP#S#dr : MxCmp_RR<!cast<MxType>("MxType"#S#"r"),
!cast<MxType>("MxType"#S#"d")>;
}

// cmp mem, Dn
defm CMP8d : MMxCmp_RM<MxType8d>;
defm CMP16d : MMxCmp_RM<MxType16d>;
Expand Down Expand Up @@ -737,33 +754,33 @@ foreach N = ["add", "addc"] in {
def : Pat<(!cast<SDNode>(N) i8 :$src, i8 :$opd),
(ADD8dd MxDRD8 :$src, MxDRD8 :$opd)>;
def : Pat<(!cast<SDNode>(N) i16:$src, i16:$opd),
(ADD16dd MxDRD16:$src, MxDRD16:$opd)>;
(ADD16dr MxXRD16:$src, MxDRD16:$opd)>;
def : Pat<(!cast<SDNode>(N) i32:$src, i32:$opd),
(ADD32rr MxXRD32:$src, MxXRD32:$opd)>;
(ADD32dr MxXRD32:$src, MxDRD32:$opd)>;

// add (An), reg
def : Pat<(!cast<SDNode>(N) MxType8.VT:$src, (Mxloadi8 MxType8.JPat:$opd)),
(ADD8dj MxDRD8:$src, MxType8.JOp:$opd)>;
def : Pat<(!cast<SDNode>(N) MxType16.VT:$src, (Mxloadi16 MxType16.JPat:$opd)),
(ADD16dj MxDRD16:$src, MxType16.JOp:$opd)>;
def : Pat<(!cast<SDNode>(N) MxType32.VT:$src, (Mxloadi32 MxType32.JPat:$opd)),
(ADD32rj MxXRD32:$src, MxType32.JOp:$opd)>;
(ADD32dj MxDRD32:$src, MxType32.JOp:$opd)>;

// add (i,An), reg
def : Pat<(!cast<SDNode>(N) MxType8.VT:$src, (Mxloadi8 MxType8.PPat:$opd)),
(ADD8dp MxDRD8:$src, MxType8.POp:$opd)>;
def : Pat<(!cast<SDNode>(N) MxType16.VT:$src, (Mxloadi16 MxType16.PPat:$opd)),
(ADD16dp MxDRD16:$src, MxType16.POp:$opd)>;
def : Pat<(!cast<SDNode>(N) MxType32.VT:$src, (Mxloadi32 MxType32.PPat:$opd)),
(ADD32rp MxXRD32:$src, MxType32.POp:$opd)>;
(ADD32dp MxDRD32:$src, MxType32.POp:$opd)>;

// add (i,An,Xn), reg
def : Pat<(!cast<SDNode>(N) MxType8.VT:$src, (Mxloadi8 MxType8.FPat:$opd)),
(ADD8df MxDRD8:$src, MxType8.FOp:$opd)>;
def : Pat<(!cast<SDNode>(N) MxType16.VT:$src, (Mxloadi16 MxType16.FPat:$opd)),
(ADD16df MxDRD16:$src, MxType16.FOp:$opd)>;
def : Pat<(!cast<SDNode>(N) MxType32.VT:$src, (Mxloadi32 MxType32.FPat:$opd)),
(ADD32rf MxXRD32:$src, MxType32.FOp:$opd)>;
(ADD32df MxDRD32:$src, MxType32.FOp:$opd)>;

// add reg, imm
def : Pat<(!cast<SDNode>(N) i8: $src, MximmSExt8:$opd),
Expand All @@ -776,7 +793,7 @@ foreach N = ["add", "addc"] in {
// we make sure it will be selected over LEAp
let AddedComplexity = 15 in {
def : Pat<(!cast<SDNode>(N) i32:$src, MximmSExt32:$opd),
(ADD32ri MxXRD32:$src, imm:$opd)>;
(ADD32di MxDRD32:$src, imm:$opd)>;
} // AddedComplexity = 15

// add imm, (An)
Expand Down Expand Up @@ -806,7 +823,7 @@ foreach N = ["sub", "subc"] in {
def : Pat<(!cast<SDNode>(N) i16:$src, i16:$opd),
(SUB16dd MxDRD16:$src, MxDRD16:$opd)>;
def : Pat<(!cast<SDNode>(N) i32:$src, i32:$opd),
(SUB32rr MxXRD32:$src, MxXRD32:$opd)>;
(SUB32dd MxDRD32:$src, MxDRD32:$opd)>;


// sub (An), reg
Expand All @@ -815,31 +832,31 @@ foreach N = ["sub", "subc"] in {
def : Pat<(!cast<SDNode>(N) MxType16.VT:$src, (Mxloadi16 MxType16.JPat:$opd)),
(SUB16dj MxDRD16:$src, MxType16.JOp:$opd)>;
def : Pat<(!cast<SDNode>(N) MxType32.VT:$src, (Mxloadi32 MxType32.JPat:$opd)),
(SUB32rj MxXRD32:$src, MxType32.JOp:$opd)>;
(SUB32dj MxDRD32:$src, MxType32.JOp:$opd)>;

// sub (i,An), reg
def : Pat<(!cast<SDNode>(N) MxType8.VT:$src, (Mxloadi8 MxType8.PPat:$opd)),
(SUB8dp MxDRD8:$src, MxType8.POp:$opd)>;
def : Pat<(!cast<SDNode>(N) MxType16.VT:$src, (Mxloadi16 MxType16.PPat:$opd)),
(SUB16dp MxDRD16:$src, MxType16.POp:$opd)>;
def : Pat<(!cast<SDNode>(N) MxType32.VT:$src, (Mxloadi32 MxType32.PPat:$opd)),
(SUB32rp MxXRD32:$src, MxType32.POp:$opd)>;
(SUB32dp MxDRD32:$src, MxType32.POp:$opd)>;

// sub (i,An,Xn), reg
def : Pat<(!cast<SDNode>(N) MxType8.VT:$src, (Mxloadi8 MxType8.FPat:$opd)),
(SUB8df MxDRD8:$src, MxType8.FOp:$opd)>;
def : Pat<(!cast<SDNode>(N) MxType16.VT:$src, (Mxloadi16 MxType16.FPat:$opd)),
(SUB16df MxDRD16:$src, MxType16.FOp:$opd)>;
def : Pat<(!cast<SDNode>(N) MxType32.VT:$src, (Mxloadi32 MxType32.FPat:$opd)),
(SUB32rf MxXRD32:$src, MxType32.FOp:$opd)>;
(SUB32df MxDRD32:$src, MxType32.FOp:$opd)>;

// sub reg, imm
def : Pat<(!cast<SDNode>(N) i8 :$src, MximmSExt8 :$opd),
(SUB8di MxDRD8 :$src, imm:$opd)>;
def : Pat<(!cast<SDNode>(N) i16:$src, MximmSExt16:$opd),
(SUB16di MxDRD16:$src, imm:$opd)>;
def : Pat<(!cast<SDNode>(N) i32:$src, MximmSExt32:$opd),
(SUB32ri MxXRD32:$src, imm:$opd)>;
(SUB32di MxDRD32:$src, imm:$opd)>;

// sub imm, (An)
def : Pat<(store (!cast<SDNode>(N) (load MxType8.JPat:$dst), MxType8.IPat:$opd),
Expand Down
10 changes: 5 additions & 5 deletions llvm/lib/Target/M68k/M68kInstrCompiler.td
Expand Up @@ -23,15 +23,15 @@ def : Pat<(i32 (MxWrapper tjumptable :$src)), (MOV32ri tjumptable :$src)>;
def : Pat<(i32 (MxWrapper tblockaddress :$src)), (MOV32ri tblockaddress :$src)>;

def : Pat<(add MxDRD32:$src, (MxWrapper tconstpool:$opd)),
(ADD32ri MxDRD32:$src, tconstpool:$opd)>;
(ADD32di MxDRD32:$src, tconstpool:$opd)>;
def : Pat<(add MxARD32:$src, (MxWrapper tjumptable:$opd)),
(ADD32ri MxARD32:$src, tjumptable:$opd)>;
(ADD32ai MxARD32:$src, tjumptable:$opd)>;
def : Pat<(add MxARD32:$src, (MxWrapper tglobaladdr :$opd)),
(ADD32ri MxARD32:$src, tglobaladdr:$opd)>;
(ADD32ai MxARD32:$src, tglobaladdr:$opd)>;
def : Pat<(add MxARD32:$src, (MxWrapper texternalsym:$opd)),
(ADD32ri MxARD32:$src, texternalsym:$opd)>;
(ADD32ai MxARD32:$src, texternalsym:$opd)>;
def : Pat<(add MxARD32:$src, (MxWrapper tblockaddress:$opd)),
(ADD32ri MxARD32:$src, tblockaddress:$opd)>;
(ADD32ai MxARD32:$src, tblockaddress:$opd)>;

def : Pat<(store (i32 (MxWrapper tglobaladdr:$src)), iPTR:$dst),
(MOV32ji MxARI32:$dst, tglobaladdr:$src)>;
Expand Down
2 changes: 1 addition & 1 deletion llvm/lib/Target/M68k/M68kInstrFormats.td
Expand Up @@ -250,7 +250,7 @@ def MxOpMode16dEA : MxEncOpMode<MxBead3Bits<0b001>>;
def MxOpMode32dEA : MxEncOpMode<MxBead3Bits<0b010>>;

// op EA, An
def MxOpMode16aEA : MxEncOpMode<MxBead3Bits<0b110>>;
def MxOpMode16aEA : MxEncOpMode<MxBead3Bits<0b011>>;
def MxOpMode32aEA : MxEncOpMode<MxBead3Bits<0b111>>;

// op EA, Rn
Expand Down
2 changes: 1 addition & 1 deletion llvm/lib/Target/M68k/M68kInstrInfo.h
Expand Up @@ -173,7 +173,7 @@ static inline unsigned IsCMP(unsigned Op) {
case M68k::CMP8di:
case M68k::CMP8dj:
case M68k::CMP8dp:
case M68k::CMP16dd:
case M68k::CMP16dr:
case M68k::CMP16df:
case M68k::CMP16di:
case M68k::CMP16dj:
Expand Down
29 changes: 20 additions & 9 deletions llvm/lib/Target/M68k/M68kInstrInfo.td
Expand Up @@ -171,6 +171,13 @@ class MxOpClass<string name> : AsmOperandClass {
}

def MxRegClass : MxOpClass<"Reg">;
// Splitting asm register class to avoid ambiguous on operands'
// MatchClassKind. For instance, without this separation,
// both ADD32dd and ADD32dr has {MCK_RegClass, MCK_RegClass} for
// their operands, which makes AsmParser unable to pick the correct
// one in a deterministic way.
def MxARegClass : MxOpClass<"AReg">;
def MxDRegClass : MxOpClass<"DReg">;

class MxOperand<ValueType vt, MxSize size, string letter, RegisterClass rc, dag pat = (null_frag)> {
ValueType VT = vt;
Expand Down Expand Up @@ -200,20 +207,24 @@ def MxXRD32_TC : MxRegOp<i32, XR32_TC, MxSize32, "r">;

// DATA REGISTER DIRECT. The operand is in the data register specified by
// the effective address register field.
def MxDRD8 : MxRegOp<i8, DR8, MxSize8, "d">;
def MxDRD16 : MxRegOp<i16, DR16, MxSize16, "d">;
def MxDRD32 : MxRegOp<i32, DR32, MxSize32, "d">;
let ParserMatchClass = MxDRegClass in {
def MxDRD8 : MxRegOp<i8, DR8, MxSize8, "d">;
def MxDRD16 : MxRegOp<i16, DR16, MxSize16, "d">;
def MxDRD32 : MxRegOp<i32, DR32, MxSize32, "d">;

def MxDRD16_TC : MxRegOp<i16, DR16_TC, MxSize16, "d">;
def MxDRD32_TC : MxRegOp<i32, DR32_TC, MxSize32, "d">;
def MxDRD16_TC : MxRegOp<i16, DR16_TC, MxSize16, "d">;
def MxDRD32_TC : MxRegOp<i32, DR32_TC, MxSize32, "d">;
}

// ADDRESS REGISTER DIRECT. The operand is in the address register specified by
// the effective address register field.
def MxARD16 : MxRegOp<i16, AR16, MxSize16, "a">;
def MxARD32 : MxRegOp<i32, AR32, MxSize32, "a">;
let ParserMatchClass = MxARegClass in {
def MxARD16 : MxRegOp<i16, AR16, MxSize16, "a">;
def MxARD32 : MxRegOp<i32, AR32, MxSize32, "a">;

def MxARD16_TC : MxRegOp<i16, AR16_TC, MxSize16, "a">;
def MxARD32_TC : MxRegOp<i32, AR32_TC, MxSize32, "a">;
def MxARD16_TC : MxRegOp<i16, AR16_TC, MxSize16, "a">;
def MxARD32_TC : MxRegOp<i32, AR32_TC, MxSize32, "a">;
}

class MxMemOp<dag ops, MxSize size, string letter,
string printMethod = "printOperand",
Expand Down
2 changes: 1 addition & 1 deletion llvm/test/CodeGen/M68k/Alloc/dyn_alloca_aligned.ll
Expand Up @@ -12,7 +12,7 @@ define i32 @A(i32 %Size) {
; CHECK-NEXT: move.l %sp, %d0
; CHECK-NEXT: and.l #-128, %d0
; CHECK-NEXT: move.l %d0, %sp
; CHECK-NEXT: sub.l #128, %sp
; CHECK-NEXT: suba.l #128, %sp
; CHECK-NEXT: move.l %sp, %a4
; CHECK-NEXT: movem.l %a4, (116,%a4) ; 8-byte Folded Spill
; CHECK-NEXT: move.l (8,%a6), %d1
Expand Down

0 comments on commit 657bb72

Please sign in to comment.