Skip to content

Commit

Permalink
[M68k] always use movem for register spills / spill 8 bit registers i…
Browse files Browse the repository at this point in the history
…nto 16 bit slots
  • Loading branch information
TechnoElf committed Jan 9, 2025
1 parent fdf72c9 commit 3cdcef9
Show file tree
Hide file tree
Showing 6 changed files with 524 additions and 52 deletions.
16 changes: 4 additions & 12 deletions llvm/lib/Target/M68k/M68kExpandPseudo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -193,31 +193,23 @@ bool M68kExpandPseudo::ExpandMI(MachineBasicBlock &MBB,
case M68k::MOV8dc:
return TII->ExpandCCR(MIB, /*IsToCCR=*/false);

case M68k::MOVM8jm_P:
return TII->ExpandMOVEM(MIB, TII->get(M68k::MOVM32jm), /*IsRM=*/false);
case M68k::MOVM16jm_P:
return TII->ExpandMOVEM(MIB, TII->get(M68k::MOVM32jm), /*IsRM=*/false);
return TII->ExpandMOVEM(MIB, TII->get(M68k::MOVM16jm), /*IsRM=*/false);
case M68k::MOVM32jm_P:
return TII->ExpandMOVEM(MIB, TII->get(M68k::MOVM32jm), /*IsRM=*/false);

case M68k::MOVM8pm_P:
return TII->ExpandMOVEM(MIB, TII->get(M68k::MOVM32pm), /*IsRM=*/false);
case M68k::MOVM16pm_P:
return TII->ExpandMOVEM(MIB, TII->get(M68k::MOVM32pm), /*IsRM=*/false);
return TII->ExpandMOVEM(MIB, TII->get(M68k::MOVM16pm), /*IsRM=*/false);
case M68k::MOVM32pm_P:
return TII->ExpandMOVEM(MIB, TII->get(M68k::MOVM32pm), /*IsRM=*/false);

case M68k::MOVM8mj_P:
return TII->ExpandMOVEM(MIB, TII->get(M68k::MOVM32mj), /*IsRM=*/true);
case M68k::MOVM16mj_P:
return TII->ExpandMOVEM(MIB, TII->get(M68k::MOVM32mj), /*IsRM=*/true);
return TII->ExpandMOVEM(MIB, TII->get(M68k::MOVM16mj), /*IsRM=*/true);
case M68k::MOVM32mj_P:
return TII->ExpandMOVEM(MIB, TII->get(M68k::MOVM32mj), /*IsRM=*/true);

case M68k::MOVM8mp_P:
return TII->ExpandMOVEM(MIB, TII->get(M68k::MOVM32mp), /*IsRM=*/true);
case M68k::MOVM16mp_P:
return TII->ExpandMOVEM(MIB, TII->get(M68k::MOVM32mp), /*IsRM=*/true);
return TII->ExpandMOVEM(MIB, TII->get(M68k::MOVM16mp), /*IsRM=*/true);
case M68k::MOVM32mp_P:
return TII->ExpandMOVEM(MIB, TII->get(M68k::MOVM32mp), /*IsRM=*/true);

Expand Down
4 changes: 0 additions & 4 deletions llvm/lib/Target/M68k/M68kInstrData.td
Original file line number Diff line number Diff line change
Expand Up @@ -337,20 +337,16 @@ class MxMOVEM_RM_Pseudo<MxType TYPE, MxOperand MEMOp>
: MxPseudo<(outs TYPE.ROp:$dst), (ins MEMOp:$src)>;

// Mem <- Reg
def MOVM8jm_P : MxMOVEM_MR_Pseudo<MxType8d, MxType8.JOp>;
def MOVM16jm_P : MxMOVEM_MR_Pseudo<MxType16r, MxType16.JOp>;
def MOVM32jm_P : MxMOVEM_MR_Pseudo<MxType32r, MxType32.JOp>;

def MOVM8pm_P : MxMOVEM_MR_Pseudo<MxType8d, MxType8.POp>;
def MOVM16pm_P : MxMOVEM_MR_Pseudo<MxType16r, MxType16.POp>;
def MOVM32pm_P : MxMOVEM_MR_Pseudo<MxType32r, MxType32.POp>;

// Reg <- Mem
def MOVM8mj_P : MxMOVEM_RM_Pseudo<MxType8d, MxType8.JOp>;
def MOVM16mj_P : MxMOVEM_RM_Pseudo<MxType16r, MxType16.JOp>;
def MOVM32mj_P : MxMOVEM_RM_Pseudo<MxType32r, MxType32.JOp>;

def MOVM8mp_P : MxMOVEM_RM_Pseudo<MxType8d, MxType8.POp>;
def MOVM16mp_P : MxMOVEM_RM_Pseudo<MxType16r, MxType16.POp>;
def MOVM32mp_P : MxMOVEM_RM_Pseudo<MxType32r, MxType32.POp>;

Expand Down
35 changes: 15 additions & 20 deletions llvm/lib/Target/M68k/M68kInstrInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -542,7 +542,6 @@ bool M68kInstrInfo::ExpandCCR(MachineInstrBuilder &MIB, bool IsToCCR) const {
bool M68kInstrInfo::ExpandMOVEM(MachineInstrBuilder &MIB,
const MCInstrDesc &Desc, bool IsRM) const {
int Reg = 0, Offset = 0, Base = 0;
auto XR32 = RI.getRegClass(M68k::XR32RegClassID);
auto DL = MIB->getDebugLoc();
auto MI = MIB.getInstr();
auto &MBB = *MIB->getParent();
Expand All @@ -557,13 +556,6 @@ bool M68kInstrInfo::ExpandMOVEM(MachineInstrBuilder &MIB,
Reg = MIB->getOperand(2).getReg();
}

// If the register is not in XR32 then it is smaller than 32 bit, we
// implicitly promote it to 32
if (!XR32->contains(Reg)) {
Reg = RI.getMatchingMegaReg(Reg, XR32);
assert(Reg && "Has not meaningful MEGA register");
}

unsigned Mask = 1 << RI.getSpillRegisterOrder(Reg);
if (IsRM) {
BuildMI(MBB, MI, DL, Desc)
Expand Down Expand Up @@ -734,22 +726,25 @@ namespace {
unsigned getLoadStoreRegOpcode(unsigned Reg, const TargetRegisterClass *RC,
const TargetRegisterInfo *TRI,
const M68kSubtarget &STI, bool load) {
switch (TRI->getRegSizeInBits(*RC)) {
switch (TRI->getSpillSize(*RC)) {
default:
LLVM_DEBUG(
dbgs() << "Cannot determine appropriate opcode for load/store to/from "
<< TRI->getName(Reg) << " of class " << TRI->getRegClassName(RC)
<< " with spill size " << TRI->getSpillSize(*RC) << '\n');
llvm_unreachable("Unknown spill size");
case 8:
case 2:
if (M68k::XR16RegClass.hasSubClassEq(RC))
return load ? M68k::MOVM16mp_P : M68k::MOVM16pm_P;
if (M68k::DR8RegClass.hasSubClassEq(RC))
return load ? M68k::MOV8dp : M68k::MOV8pd;
return load ? M68k::MOVM16mp_P : M68k::MOVM16pm_P;
if (M68k::CCRCRegClass.hasSubClassEq(RC))
return load ? M68k::MOV16cp : M68k::MOV16pc;

llvm_unreachable("Unknown 1-byte regclass");
case 16:
assert(M68k::XR16RegClass.hasSubClassEq(RC) && "Unknown 2-byte regclass");
return load ? M68k::MOVM16mp_P : M68k::MOVM16pm_P;
case 32:
assert(M68k::XR32RegClass.hasSubClassEq(RC) && "Unknown 4-byte regclass");
return load ? M68k::MOVM32mp_P : M68k::MOVM32pm_P;
return load ? M68k::MOVM16mp_P : M68k::MOVM16pm_P;
llvm_unreachable("Unknown 2-byte regclass");
case 4:
if (M68k::XR32RegClass.hasSubClassEq(RC))
return load ? M68k::MOVM32mp_P : M68k::MOVM32pm_P;
llvm_unreachable("Unknown 4-byte regclass");
}
}

Expand Down
35 changes: 30 additions & 5 deletions llvm/lib/Target/M68k/M68kRegisterInfo.td
Original file line number Diff line number Diff line change
Expand Up @@ -99,52 +99,77 @@ class MxRegClass<list<ValueType> regTypes, int alignment, dag regList>
: RegisterClass<"M68k", regTypes, alignment, regList>;

// Data Registers
let RegInfos = RegInfoByHwMode<[DefaultMode], [RegInfo<8,16,16>]> in
def DR8 : MxRegClass<[i8], 16, (sequence "BD%u", 0, 7)>;
let RegInfos = RegInfoByHwMode<[DefaultMode], [RegInfo<16,16,16>]> in
def DR16 : MxRegClass<[i16], 16, (sequence "WD%u", 0, 7)>;
let RegInfos = RegInfoByHwMode<[DefaultMode], [RegInfo<32,32,32>]> in
def DR32 : MxRegClass<[i32], 32, (sequence "D%u", 0, 7)>;

// Address Registers
let RegInfos = RegInfoByHwMode<[DefaultMode], [RegInfo<16,16,16>]> in
def AR16 : MxRegClass<[i16], 16, (add (sequence "WA%u", 0, 6), WSP)>;
let RegInfos = RegInfoByHwMode<[DefaultMode], [RegInfo<32,32,32>]> in
def AR32 : MxRegClass<[i32], 32, (add (sequence "A%u", 0, 6), SP)>;

let RegInfos = RegInfoByHwMode<[DefaultMode], [RegInfo<32,32,32>]> in
def AR32_NOSP : MxRegClass<[i32], 32, (sequence "A%u", 0, 6)>;

// Index Register Classes
// FIXME try alternative ordering like `D0, D1, A0, A1, ...`
let RegInfos = RegInfoByHwMode<[DefaultMode], [RegInfo<16,16,16>]> in
def XR16 : MxRegClass<[i16], 16, (add DR16, AR16)>;
let RegInfos = RegInfoByHwMode<[DefaultMode], [RegInfo<32,32,32>]> in
def XR32 : MxRegClass<[i32], 32, (add DR32, AR32)>;

let RegInfos = RegInfoByHwMode<[DefaultMode], [RegInfo<32,32,32>]> in
def SPC : MxRegClass<[i32], 32, (add SP)>;

// Floating Point Data Registers
let RegInfos = RegInfoByHwMode<[DefaultMode], [RegInfo<32,32,32>]> in
def FPDR32 : MxRegClass<[f32], 32, (sequence "FP%u", 0, 7)>;
let RegInfos = RegInfoByHwMode<[DefaultMode], [RegInfo<64,64,32>]> in
def FPDR64 : MxRegClass<[f64], 32, (add FPDR32)>;
let RegInfos = RegInfoByHwMode<[DefaultMode], [RegInfo<80,128,32>]> in
def FPDR80 : MxRegClass<[f80], 32, (add FPDR32)>;

let CopyCost = -1 in {
let RegInfos = RegInfoByHwMode<[DefaultMode], [RegInfo<8,16,16>]> in
def CCRC : MxRegClass<[i8], 16, (add CCR)>;
let RegInfos = RegInfoByHwMode<[DefaultMode], [RegInfo<16,16,16>]> in
def SRC : MxRegClass<[i16], 16, (add SR)>;

// Float Point System Control Registers
def FPIC : MxRegClass<[i32], 32, (add FPIAR)>;
def FPCSC : MxRegClass<[i32], 32, (add FPC, FPS)>;
def FPSYSC : MxRegClass<[i32], 32, (add FPCSC, FPIC)>;
let RegInfos = RegInfoByHwMode<[DefaultMode], [RegInfo<32,32,32>]> in {
def FPIC : MxRegClass<[i32], 32, (add FPIAR)>;
def FPCSC : MxRegClass<[i32], 32, (add FPC, FPS)>;
def FPSYSC : MxRegClass<[i32], 32, (add FPCSC, FPIC)>;
}
}

let isAllocatable = 0 in {
let RegInfos = RegInfoByHwMode<[DefaultMode], [RegInfo<32,32,32>]> in
def PCC : MxRegClass<[i32], 32, (add PC)>;
}

// Register used with tail call
let RegInfos = RegInfoByHwMode<[DefaultMode], [RegInfo<16,16,16>]> in
def DR16_TC : MxRegClass<[i16], 16, (add D0, D1)>;
let RegInfos = RegInfoByHwMode<[DefaultMode], [RegInfo<32,32,32>]> in
def DR32_TC : MxRegClass<[i32], 32, (add D0, D1)>;

let RegInfos = RegInfoByHwMode<[DefaultMode], [RegInfo<16,16,16>]> in
def AR16_TC : MxRegClass<[i16], 16, (add A0, A1)>;
let RegInfos = RegInfoByHwMode<[DefaultMode], [RegInfo<32,32,32>]> in
def AR32_TC : MxRegClass<[i32], 32, (add A0, A1)>;

let RegInfos = RegInfoByHwMode<[DefaultMode], [RegInfo<16,16,16>]> in
def XR16_TC : MxRegClass<[i16], 16, (add DR16_TC, AR16_TC)>;
let RegInfos = RegInfoByHwMode<[DefaultMode], [RegInfo<32,32,32>]> in
def XR32_TC : MxRegClass<[i32], 32, (add DR32_TC, AR32_TC)>;

// These classes provide spill/restore order if used with MOVEM instruction
def SPILL : MxRegClass<[i32], 32, (add XR32)>;
def SPILL_R : MxRegClass<[i32], 32, (add SP, (sequence "A%u", 6, 0), (sequence "D%u", 7, 0))>;
let RegInfos = RegInfoByHwMode<[DefaultMode], [RegInfo<32,32,32>]> in {
def SPILL : MxRegClass<[i32], 32, (add XR32)>;
def SPILL_R : MxRegClass<[i32], 32, (add SP, (sequence "A%u", 6, 0), (sequence "D%u", 7, 0))>;
}
22 changes: 11 additions & 11 deletions llvm/test/CodeGen/M68k/PR57660.ll
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,10 @@ define dso_local void @foo1() {
; CHECK-NEXT: suba.l #2, %sp
; CHECK-NEXT: .cfi_def_cfa_offset -6
; CHECK-NEXT: moveq #0, %d0
; CHECK-NEXT: move.b %d0, (0,%sp) ; 1-byte Folded Spill
; CHECK-NEXT: movem.w %d0, (0,%sp)
; CHECK-NEXT: .LBB0_1: ; %do.body
; CHECK-NEXT: ; =>This Inner Loop Header: Depth=1
; CHECK-NEXT: move.b (0,%sp), %d0 ; 1-byte Folded Reload
; CHECK-NEXT: movem.w (0,%sp), %d0
; CHECK-NEXT: cmpi.b #0, %d0
; CHECK-NEXT: bne .LBB0_1
; CHECK-NEXT: ; %bb.2: ; %do.end
Expand Down Expand Up @@ -39,24 +39,24 @@ define i32 @foo2(ptr noundef %0) {
; CHECK-NEXT: .cfi_def_cfa_offset -8
; CHECK-NEXT: move.l (8,%sp), %a0
; CHECK-NEXT: move.b (%a0), %d0
; CHECK-NEXT: move.b %d0, (0,%sp) ; 1-byte Folded Spill
; CHECK-NEXT: movem.w %d0, (0,%sp)
; CHECK-NEXT: and.b #1, %d0
; CHECK-NEXT: move.b %d0, (2,%sp) ; 1-byte Folded Spill
; CHECK-NEXT: movem.w %d0, (2,%sp)
; CHECK-NEXT: sub.b #1, %d0
; CHECK-NEXT: bgt .LBB1_2
; CHECK-NEXT: ; %bb.1: ; %if
; CHECK-NEXT: move.b (2,%sp), %d0 ; 1-byte Folded Reload
; CHECK-NEXT: move.b (0,%sp), %d1 ; 1-byte Folded Reload
; CHECK-NEXT: movem.w (2,%sp), %d0
; CHECK-NEXT: movem.w (0,%sp), %d1
; CHECK-NEXT: add.b %d1, %d0
; CHECK-NEXT: bra .LBB1_3
; CHECK-NEXT: .LBB1_2: ; %else
; CHECK-NEXT: move.b (2,%sp), %d1 ; 1-byte Folded Reload
; CHECK-NEXT: move.b (0,%sp), %d0 ; 1-byte Folded Reload
; CHECK-NEXT: movem.w (2,%sp), %d1
; CHECK-NEXT: movem.w (0,%sp), %d0
; CHECK-NEXT: sub.b %d1, %d0
; CHECK-NEXT: move.b %d0, (0,%sp) ; 1-byte Folded Spill
; CHECK-NEXT: movem.w %d0, (0,%sp)
; CHECK-NEXT: .LBB1_3: ; %cont
; CHECK-NEXT: move.b %d0, (2,%sp) ; 1-byte Folded Spill
; CHECK-NEXT: move.b (2,%sp), %d0 ; 1-byte Folded Reload
; CHECK-NEXT: movem.w %d0, (2,%sp)
; CHECK-NEXT: movem.w (2,%sp), %d0
; CHECK-NEXT: ext.w %d0
; CHECK-NEXT: ext.l %d0
; CHECK-NEXT: adda.l #4, %sp
Expand Down
Loading

0 comments on commit 3cdcef9

Please sign in to comment.