[llvm] [M68k] Do not allow addressing modes k and q as MOVE targets (llvm#200826) (PR #201653)
Michael Karcher via llvm-commits
llvm-commits at lists.llvm.org
Fri Jun 12 00:44:14 PDT 2026
https://github.com/karcherm updated https://github.com/llvm/llvm-project/pull/201653
>From e722fed2b8b048aff071183187f7d101a908bb5b Mon Sep 17 00:00:00 2001
From: "Michael.Karcher" <github at michael-karcher.net>
Date: Thu, 4 Jun 2026 19:51:24 +0200
Subject: [PATCH 1/2] [M68k] Do not allow addressing modes k and q as MOVE
targets (#200826)
- Remove MOVE patterns that generate invalid M68k opcodes
- Remove atomic-store patterns that redirect to the invalild MOVE instructions
- Update tests to not expect invalid MOVE operands
---
llvm/lib/Target/M68k/M68kInstrAtomics.td | 8 ------
llvm/lib/Target/M68k/M68kInstrData.td | 27 ++++++++++---------
.../CodeGen/M68k/CodeModel/Small/small-pic.ll | 5 ++--
.../M68k/CodeModel/Small/small-static.ll | 18 ++++++++-----
llvm/test/CodeGen/M68k/Control/cmp.ll | 7 ++---
.../M68k/is-pcrel-register-operand-legal.mir | 2 --
6 files changed, 32 insertions(+), 35 deletions(-)
diff --git a/llvm/lib/Target/M68k/M68kInstrAtomics.td b/llvm/lib/Target/M68k/M68kInstrAtomics.td
index b2b64ca853220..fe253f0b65394 100644
--- a/llvm/lib/Target/M68k/M68kInstrAtomics.td
+++ b/llvm/lib/Target/M68k/M68kInstrAtomics.td
@@ -33,14 +33,6 @@ foreach size = [8, 16, 32] in {
def : Pat<(!cast<SDPatternOperator>("atomic_store_"#size) !cast<MxRegOp>("MxDRD"#size):$val, MxCP_ARID:$ptr),
(!cast<MxInst>("MOV"#size#"pd") !cast<MxMemOp>("MxARID"#size):$ptr,
!cast<MxRegOp>("MxDRD"#size):$val)>;
-
- def : Pat<(!cast<SDPatternOperator>("atomic_store_"#size) !cast<MxRegOp>("MxDRD"#size):$val, MxCP_PCD:$ptr),
- (!cast<MxInst>("MOV"#size#"qd") !cast<MxMemOp>("MxPCD"#size):$ptr,
- !cast<MxRegOp>("MxDRD"#size):$val)>;
-
- def : Pat<(!cast<SDPatternOperator>("atomic_store_"#size) !cast<MxRegOp>("MxDRD"#size):$val, MxCP_PCI:$ptr),
- (!cast<MxInst>("MOV"#size#"kd") !cast<MxMemOp>("MxPCI"#size):$ptr,
- !cast<MxRegOp>("MxDRD"#size):$val)>;
}
let Predicates = [AtLeastM68020] in {
diff --git a/llvm/lib/Target/M68k/M68kInstrData.td b/llvm/lib/Target/M68k/M68kInstrData.td
index 7a579a9ddbdb1..fd654be09dc97 100644
--- a/llvm/lib/Target/M68k/M68kInstrData.td
+++ b/llvm/lib/Target/M68k/M68kInstrData.td
@@ -104,7 +104,8 @@ multiclass MxMoveOperandEncodings<string opnd_name> {
defm Src : MxMoveOperandEncodings<"src">;
defm Dst : MxMoveOperandEncodings<"dst">;
-defvar MxMoveSupportedAMs = ["o", "e", "k", "q", "f", "p", "b", "j"];
+defvar MxMoveSrcAMs = ["o", "e", "k", "q", "f", "p", "b", "j"];
+defvar MxMoveDstAMs = ["o", "e", "f", "p", "b", "j"];
let Defs = [CCR] in
class MxMove<string size, dag outs, dag ins, list<dag> pattern, MxMoveEncoding enc>
@@ -150,7 +151,7 @@ class MxMove_MI<MxType TYPE, MxOpBundle DST, MxMoveEncoding ENC,
} // let mayStore = 1
foreach REG = ["r", "a", "d"] in
-foreach AM = MxMoveSupportedAMs in {
+foreach AM = MxMoveDstAMs in {
foreach TYPE = !if(!eq(REG, "d"), [MxType8, MxType16, MxType32], [MxType16, MxType32]) in
def MOV # TYPE.Size # AM # REG # TYPE.Postfix
: MxMove_MR<TYPE, !cast<MxOpBundle>("MxOp"#TYPE.Size#"AddrMode_"#AM), REG,
@@ -159,7 +160,7 @@ foreach AM = MxMoveSupportedAMs in {
!cast<MxEncMemOp>("MxMoveSrcOpEnc_"#REG)>>;
} // foreach AM
-foreach AM = MxMoveSupportedAMs in {
+foreach AM = MxMoveDstAMs in {
foreach TYPE = [MxType8, MxType16, MxType32] in
def MOV # TYPE.Size # AM # i # TYPE.Postfix
: MxMove_MI<TYPE, !cast<MxOpBundle>("MxOp"#TYPE.Size#"AddrMode_"#AM),
@@ -196,7 +197,7 @@ class MxMove_RM<MxType TYPE, string DST_REG, MxOpBundle SRC, MxEncMemOp SRC_ENC,
MxMoveEncoding<SIZE_ENC, DST_ENC, SRC_ENC>>;
foreach REG = ["r", "a", "d"] in
-foreach AM = MxMoveSupportedAMs in {
+foreach AM = MxMoveSrcAMs in {
foreach TYPE = !if(!eq(REG, "d"), [MxType8, MxType16, MxType32], [MxType16, MxType32]) in
def MOV # TYPE.Size # REG # AM # TYPE.Postfix
: MxMove_RM<TYPE, REG, !cast<MxOpBundle>("MxOp"#TYPE.Size#"AddrMode_"#AM),
@@ -206,7 +207,7 @@ foreach AM = MxMoveSupportedAMs in {
// Tail call version
let Pattern = [(null_frag)] in {
foreach REG = ["r", "a"] in
- foreach AM = MxMoveSupportedAMs in {
+ foreach AM = MxMoveSrcAMs in {
foreach TYPE = [MxType16, MxType32] in
def MOV # TYPE.Size # REG # AM # _TC
: MxMove_RM<TYPE, REG, !cast<MxOpBundle>("MxOp"#TYPE.Size#"AddrMode_"#AM),
@@ -234,8 +235,8 @@ class MxMove_MM_Safe<MxType TYPE, PatFrag StoreLoad,
MxMoveEncoding<!cast<MxMoveSize>("MxMoveSize"#TYPE.Size),
DST_ENC, SRC_ENC>>;
-foreach DST_AM = MxMoveSupportedAMs in
-foreach SRC_AM = MxMoveSupportedAMs in {
+foreach DST_AM = MxMoveDstAMs in
+foreach SRC_AM = MxMoveSrcAMs in {
def MOV8 # DST_AM # SRC_AM # !cast<MxType>("MxType8").Postfix
: MxMove_MM_Safe<MxType8, Mxstoreloadi8_safe,
!cast<MxOpBundle>("MxOp8AddrMode_"#DST_AM),
@@ -331,7 +332,7 @@ class MxMOVEM_MR<MxType TYPE, bit SIZE_ENC,
let Inst = MxMOVEMEncoding<MEM_ENC, SIZE_ENC, MxMOVEM_MR, "mask">.Value;
}
-foreach AM = MxMoveSupportedAMs in {
+foreach AM = MxMoveDstAMs in {
foreach TYPE = [MxType16, MxType32] in
def MOVM # TYPE.Size # AM # m # TYPE.Postfix
: MxMOVEM_MR<TYPE, !if(!eq(TYPE, MxType16), MxMOVEM_W, MxMOVEM_L),
@@ -349,7 +350,7 @@ class MxMOVEM_RM<MxType TYPE, bit SIZE_ENC,
let Inst = MxMOVEMEncoding<MEM_ENC, SIZE_ENC, MxMOVEM_RM, "mask">.Value;
}
-foreach AM = MxMoveSupportedAMs in {
+foreach AM = MxMoveSrcAMs in {
foreach TYPE = [MxType16, MxType32] in
def MOVM # TYPE.Size # m # AM # TYPE.Postfix
: MxMOVEM_RM<TYPE, !if(!eq(TYPE, MxType16), MxMOVEM_W, MxMOVEM_L),
@@ -408,7 +409,7 @@ class MxMoveToCCRPseudo<MxOperand MEMOp>
} // let Defs = [CCR]
let mayLoad = 1 in
-foreach AM = MxMoveSupportedAMs in {
+foreach AM = MxMoveSrcAMs in {
def MOV16c # AM : MxMoveToCCR<!cast<MxOpBundle>("MxOp16AddrMode_"#AM).Op,
!cast<MxEncMemOp>("MxMoveSrcOpEnc_"#AM)>;
def MOV8c # AM : MxMoveToCCRPseudo<!cast<MxOpBundle>("MxOp8AddrMode_"#AM).Op>;
@@ -447,7 +448,7 @@ class MxMoveFromCCR_RPseudo<MxOperand MEMOp>
} // let Uses = [CCR]
let mayStore = 1 in
-foreach AM = MxMoveSupportedAMs in {
+foreach AM = MxMoveDstAMs in {
def MOV16 # AM # c
: MxMoveFromCCR_M<!cast<MxOpBundle>("MxOp16AddrMode_"#AM).Op,
!cast<MxEncMemOp>("MxMoveDstOpEnc_"#AM)>;
@@ -476,7 +477,7 @@ class MxMoveToSR<MxOperand MEMOp, MxEncMemOp SRC_ENC>
} // let Defs = [SR]
let mayLoad = 1 in
-foreach AM = MxMoveSupportedAMs in {
+foreach AM = MxMoveSrcAMs in {
def MOV16s # AM : MxMoveToSR<!cast<MxOpBundle>("MxOp16AddrMode_"#AM).Op,
!cast<MxEncMemOp>("MxMoveSrcOpEnc_"#AM)>;
} // foreach AM
@@ -506,7 +507,7 @@ class MxMoveFromSR_M<MxOperand MEMOp, MxEncMemOp DST_ENC>
} // let Uses = [SR]
let mayStore = 1 in
-foreach AM = MxMoveSupportedAMs in {
+foreach AM = MxMoveDstAMs in {
def MOV16 # AM # s
: MxMoveFromSR_M<!cast<MxOpBundle>("MxOp16AddrMode_"#AM).Op,
!cast<MxEncMemOp>("MxMoveDstOpEnc_"#AM)>;
diff --git a/llvm/test/CodeGen/M68k/CodeModel/Small/small-pic.ll b/llvm/test/CodeGen/M68k/CodeModel/Small/small-pic.ll
index 37115953e5be3..04a42689cb281 100644
--- a/llvm/test/CodeGen/M68k/CodeModel/Small/small-pic.ll
+++ b/llvm/test/CodeGen/M68k/CodeModel/Small/small-pic.ll
@@ -101,8 +101,9 @@ define void @test5() nounwind {
; CHECK-LABEL: test5:
; CHECK: ; %bb.0: ; %entry
; CHECK-NEXT: lea (dst6,%pc), %a0
-; CHECK-NEXT: move.l %a0, (ptr6,%pc)
-; CHECK-NEXT: move.l (src6,%pc), (dst6,%pc)
+; CHECK-NEXT: lea (ptr6,%pc), %a1
+; CHECK-NEXT: move.l %a0, (%a1)
+; CHECK-NEXT: move.l (src6,%pc), (%a0)
; CHECK-NEXT: rts
entry:
store ptr @dst6, ptr @ptr6
diff --git a/llvm/test/CodeGen/M68k/CodeModel/Small/small-static.ll b/llvm/test/CodeGen/M68k/CodeModel/Small/small-static.ll
index 1b946c19b250f..5c479979d68a7 100644
--- a/llvm/test/CodeGen/M68k/CodeModel/Small/small-static.ll
+++ b/llvm/test/CodeGen/M68k/CodeModel/Small/small-static.ll
@@ -11,8 +11,9 @@ define void @test0() nounwind {
; CHECK-LABEL: test0:
; CHECK: ; %bb.0: ; %entry
; CHECK-NEXT: lea (dst,%pc), %a0
-; CHECK-NEXT: move.l %a0, (ptr,%pc)
-; CHECK-NEXT: move.l (src,%pc), (dst,%pc)
+; CHECK-NEXT: lea (ptr,%pc), %a1
+; CHECK-NEXT: move.l %a0, (%a1)
+; CHECK-NEXT: move.l (src,%pc), (%a0)
; CHECK-NEXT: rts
entry:
store ptr @dst, ptr @ptr
@@ -29,8 +30,9 @@ define void @test1() nounwind {
; CHECK-LABEL: test1:
; CHECK: ; %bb.0: ; %entry
; CHECK-NEXT: lea (dst2,%pc), %a0
-; CHECK-NEXT: move.l %a0, (ptr2,%pc)
-; CHECK-NEXT: move.l (src2,%pc), (dst2,%pc)
+; CHECK-NEXT: lea (ptr2,%pc), %a1
+; CHECK-NEXT: move.l %a0, (%a1)
+; CHECK-NEXT: move.l (src2,%pc), (%a0)
; CHECK-NEXT: rts
entry:
store ptr @dst2, ptr @ptr2
@@ -62,7 +64,8 @@ define void @test3() nounwind {
; CHECK: ; %bb.0: ; %entry
; CHECK-NEXT: suba.l #4, %sp
; CHECK-NEXT: jsr afoo
-; CHECK-NEXT: move.l %a0, (pfoo,%pc)
+; CHECK-NEXT: lea (pfoo,%pc), %a1
+; CHECK-NEXT: move.l %a0, (%a1)
; CHECK-NEXT: jsr (%a0)
; CHECK-NEXT: adda.l #4, %sp
; CHECK-NEXT: rts
@@ -96,8 +99,9 @@ define void @test5() nounwind {
; CHECK-LABEL: test5:
; CHECK: ; %bb.0: ; %entry
; CHECK-NEXT: lea (dst6,%pc), %a0
-; CHECK-NEXT: move.l %a0, (ptr6,%pc)
-; CHECK-NEXT: move.l (src6,%pc), (dst6,%pc)
+; CHECK-NEXT: lea (ptr6,%pc), %a1
+; CHECK-NEXT: move.l %a0, (%a1)
+; CHECK-NEXT: move.l (src6,%pc), (%a0)
; CHECK-NEXT: rts
entry:
store ptr @dst6, ptr @ptr6
diff --git a/llvm/test/CodeGen/M68k/Control/cmp.ll b/llvm/test/CodeGen/M68k/Control/cmp.ll
index 01dfaeb1b2ec2..ae78534df4cd5 100644
--- a/llvm/test/CodeGen/M68k/Control/cmp.ll
+++ b/llvm/test/CodeGen/M68k/Control/cmp.ll
@@ -294,7 +294,7 @@ define void @test20(i32 %bf.load, i8 %x1, ptr %b_addr) {
; CHECK-NEXT: ; %bb.0:
; CHECK-NEXT: suba.l #4, %sp
; CHECK-NEXT: .cfi_def_cfa_offset -8
-; CHECK-NEXT: movem.l %d2, (0,%sp) ; 8-byte Folded Spill
+; CHECK-NEXT: movem.l %d2, (0,%sp) ; 8-byte Folded Spill
; CHECK-NEXT: move.l #16777215, %d0
; CHECK-NEXT: and.l (8,%sp), %d0
; CHECK-NEXT: sne %d1
@@ -310,8 +310,9 @@ define void @test20(i32 %bf.load, i8 %x1, ptr %b_addr) {
; CHECK-NEXT: cmpi.l #0, %d0
; CHECK-NEXT: sne %d0
; CHECK-NEXT: and.b #1, %d0
-; CHECK-NEXT: move.b %d0, (d,%pc)
-; CHECK-NEXT: movem.l (0,%sp), %d2 ; 8-byte Folded Reload
+; CHECK-NEXT: lea (d,%pc), %a0
+; CHECK-NEXT: move.b %d0, (%a0)
+; CHECK-NEXT: movem.l (0,%sp), %d2 ; 8-byte Folded Reload
; CHECK-NEXT: adda.l #4, %sp
; CHECK-NEXT: rts
%bf.shl = shl i32 %bf.load, 8
diff --git a/llvm/test/CodeGen/M68k/is-pcrel-register-operand-legal.mir b/llvm/test/CodeGen/M68k/is-pcrel-register-operand-legal.mir
index a755164937b16..3e2adff67744a 100644
--- a/llvm/test/CodeGen/M68k/is-pcrel-register-operand-legal.mir
+++ b/llvm/test/CodeGen/M68k/is-pcrel-register-operand-legal.mir
@@ -4,7 +4,5 @@ name: is-pcrel-register-operand-legal
body: |
bb.0.entry:
; CHECK: move.l (0,%pc,%a0), (%a1)
- ; CHECK: move.l (%a0), (0,%pc,%a1)
MOV32jk $a1, 0, $a0, implicit-def $ccr
- MOV32kj 0, $a1, $a0, implicit-def $ccr
\ No newline at end of file
>From 663e9bb768c985af88ae474ab163858c3c5deec3 Mon Sep 17 00:00:00 2001
From: "Michael.Karcher" <github at michael-karcher.net>
Date: Fri, 12 Jun 2026 09:42:27 +0200
Subject: [PATCH 2/2] [M68k] Add test for atomic PC-relative store
---
llvm/test/CodeGen/M68k/Atomics/load-store.ll | 21 ++++++++++++++++++++
1 file changed, 21 insertions(+)
diff --git a/llvm/test/CodeGen/M68k/Atomics/load-store.ll b/llvm/test/CodeGen/M68k/Atomics/load-store.ll
index 8ed3ae81d0920..adb715eb8d327 100644
--- a/llvm/test/CodeGen/M68k/Atomics/load-store.ll
+++ b/llvm/test/CodeGen/M68k/Atomics/load-store.ll
@@ -684,3 +684,24 @@ start:
exit: ; preds = %start
ret i32 %2
}
+
+ at dst = external global i32
+
+define void @test0() nounwind {
+; NO-ATOMIC-LABEL: test0:
+; NO-ATOMIC: ; %bb.0: ; %entry
+; NO-ATOMIC-NEXT: moveq #0, %d0
+; NO-ATOMIC-NEXT: lea (dst,%pc), %a0
+; NO-ATOMIC-NEXT: move.l %d0, (%a0)
+; NO-ATOMIC-NEXT: rts
+;
+; ATOMIC-LABEL: test0:
+; ATOMIC: ; %bb.0: ; %entry
+; ATOMIC-NEXT: moveq #0, %d0
+; ATOMIC-NEXT: lea (dst,%pc), %a0
+; ATOMIC-NEXT: move.l %d0, (%a0)
+; ATOMIC-NEXT: rts
+entry:
+ store atomic i32 0, ptr @dst unordered, align 4
+ ret void
+}
More information about the llvm-commits
mailing list