Skip to content

Commit 2f40e3e

Browse files
authored
[M68k] implement large code model (#106381)
Fixes #106208.
1 parent 3ad6403 commit 2f40e3e

File tree

6 files changed

+640
-6
lines changed

6 files changed

+640
-6
lines changed

llvm/lib/Target/M68k/M68kSubtarget.cpp

Lines changed: 50 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,7 @@ M68kSubtarget &M68kSubtarget::initializeSubtargetDependencies(
115115
// ---------------------+------------+------------+------------+-------------
116116
// branch | pc-rel | pc-rel | pc-rel | pc-rel
117117
// ---------------------+------------+------------+------------+-------------
118-
// call global | @PLT | @PLT | @PLT | @PLT
118+
// call global | absolute | @PLT | absolute | @PLT
119119
// ---------------------+------------+------------+------------+-------------
120120
// call internal | pc-rel | pc-rel | pc-rel | pc-rel
121121
// ---------------------+------------+------------+------------+-------------
@@ -127,6 +127,24 @@ M68kSubtarget &M68kSubtarget::initializeSubtargetDependencies(
127127
// ---------------------+------------+------------+------------+-------------
128128
// data global big* | pc-rel | @GOTPCREL | absolute | @GOTPCREL
129129
// ---------------------+------------+------------+------------+-------------
130+
// | Large |
131+
// +-------------------------+
132+
// | Static | PIC |
133+
// ---------------------+------------+------------+
134+
// branch | absolute | pc-rel |
135+
// ---------------------+------------+------------+
136+
// call global | absolute | @PLT |
137+
// ---------------------+------------+------------+
138+
// call internal | absolute | pc-rel |
139+
// ---------------------+------------+------------+
140+
// data local | absolute | @GOTOFF |
141+
// ---------------------+------------+------------+
142+
// data local big* | absolute | @GOTOFF |
143+
// ---------------------+------------+------------+
144+
// data global | absolute | @GOTOFF |
145+
// ---------------------+------------+------------+
146+
// data global big* | absolute | @GOTOFF |
147+
// ---------------------+------------+------------+
130148
//
131149
// * Big data potentially cannot be reached within 16 bit offset and requires
132150
// special handling for old(x00 and x10) CPUs. Normally these symbols go into
@@ -142,8 +160,22 @@ M68kSubtarget &M68kSubtarget::initializeSubtargetDependencies(
142160
/// Classify a blockaddress reference for the current subtarget according to how
143161
/// we should reference it in a non-pcrel context.
144162
unsigned char M68kSubtarget::classifyBlockAddressReference() const {
145-
// Unless we start to support Large Code Model branching is always pc-rel
146-
return M68kII::MO_PC_RELATIVE_ADDRESS;
163+
switch (TM.getCodeModel()) {
164+
default:
165+
llvm_unreachable("Unsupported code model");
166+
case CodeModel::Small:
167+
case CodeModel::Kernel:
168+
case CodeModel::Medium: {
169+
return M68kII::MO_PC_RELATIVE_ADDRESS;
170+
}
171+
case CodeModel::Large: {
172+
if (isPositionIndependent()) {
173+
return M68kII::MO_PC_RELATIVE_ADDRESS;
174+
} else {
175+
return M68kII::MO_ABSOLUTE_ADDRESS;
176+
}
177+
}
178+
}
147179
}
148180

149181
unsigned char
@@ -171,6 +203,13 @@ M68kSubtarget::classifyLocalReference(const GlobalValue *GV) const {
171203
return M68kII::MO_ABSOLUTE_ADDRESS;
172204
}
173205
}
206+
case CodeModel::Large: {
207+
if (isPositionIndependent()) {
208+
return M68kII::MO_GOTOFF;
209+
} else {
210+
return M68kII::MO_ABSOLUTE_ADDRESS;
211+
}
212+
}
174213
}
175214
}
176215

@@ -212,6 +251,12 @@ unsigned char M68kSubtarget::classifyGlobalReference(const GlobalValue *GV,
212251

213252
return M68kII::MO_ABSOLUTE_ADDRESS;
214253
}
254+
case CodeModel::Large: {
255+
if (isPositionIndependent())
256+
return M68kII::MO_GOTOFF;
257+
258+
return M68kII::MO_ABSOLUTE_ADDRESS;
259+
}
215260
}
216261
}
217262

@@ -221,7 +266,8 @@ unsigned M68kSubtarget::getJumpTableEncoding() const {
221266
// the potential delta between the jump target and table base can be larger
222267
// than displacement field, which is True for older CPUs(16 bit disp)
223268
// in Medium model(can have large data way beyond 16 bit).
224-
if (TM.getCodeModel() == CodeModel::Medium && !atLeastM68020())
269+
if ((TM.getCodeModel() == CodeModel::Medium && !atLeastM68020()) ||
270+
TM.getCodeModel() == CodeModel::Large)
225271
return MachineJumpTableInfo::EK_Custom32;
226272

227273
return MachineJumpTableInfo::EK_LabelDifference32;

llvm/lib/Target/M68k/M68kTargetMachine.cpp

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -87,8 +87,6 @@ CodeModel::Model getEffectiveCodeModel(std::optional<CodeModel::Model> CM,
8787
bool JIT) {
8888
if (!CM) {
8989
return CodeModel::Small;
90-
} else if (CM == CodeModel::Large) {
91-
llvm_unreachable("Large code model is not supported");
9290
} else if (CM == CodeModel::Kernel) {
9391
llvm_unreachable("Kernel code model is not implemented yet");
9492
}
Lines changed: 205 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,205 @@
1+
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
2+
; RUN: llc < %s -O2 -mtriple=m68k -verify-machineinstrs \
3+
; RUN: -code-model=large -relocation-model=pic \
4+
; RUN: | FileCheck %s
5+
6+
@ptr = external global ptr
7+
@dst = external global i32
8+
@src = external global i32
9+
10+
define void @test0() nounwind {
11+
; CHECK-LABEL: test0:
12+
; CHECK: ; %bb.0: ; %entry
13+
; CHECK-NEXT: lea (_GLOBAL_OFFSET_TABLE_@GOTPCREL,%pc), %a0
14+
; CHECK-NEXT: move.l %a0, %a1
15+
; CHECK-NEXT: adda.l #dst@GOTOFF, %a1
16+
; CHECK-NEXT: move.l #ptr@GOTOFF, %d0
17+
; CHECK-NEXT: move.l %a1, (0,%a0,%d0)
18+
; CHECK-NEXT: move.l #src@GOTOFF, %d0
19+
; CHECK-NEXT: move.l #dst@GOTOFF, %d1
20+
; CHECK-NEXT: move.l (0,%a0,%d0), (0,%a0,%d1)
21+
; CHECK-NEXT: rts
22+
entry:
23+
store ptr @dst, ptr @ptr
24+
%tmp.s = load i32, ptr @src
25+
store i32 %tmp.s, ptr @dst
26+
ret void
27+
}
28+
29+
@ptr2 = global ptr null
30+
@dst2 = global i32 0
31+
@src2 = global i32 0
32+
33+
define void @test1() nounwind {
34+
; CHECK-LABEL: test1:
35+
; CHECK: ; %bb.0: ; %entry
36+
; CHECK-NEXT: lea (_GLOBAL_OFFSET_TABLE_@GOTPCREL,%pc), %a0
37+
; CHECK-NEXT: move.l %a0, %a1
38+
; CHECK-NEXT: adda.l #dst2@GOTOFF, %a1
39+
; CHECK-NEXT: move.l #ptr2@GOTOFF, %d0
40+
; CHECK-NEXT: move.l %a1, (0,%a0,%d0)
41+
; CHECK-NEXT: move.l #src2@GOTOFF, %d0
42+
; CHECK-NEXT: move.l #dst2@GOTOFF, %d1
43+
; CHECK-NEXT: move.l (0,%a0,%d0), (0,%a0,%d1)
44+
; CHECK-NEXT: rts
45+
entry:
46+
store ptr @dst2, ptr @ptr2
47+
%tmp.s = load i32, ptr @src2
48+
store i32 %tmp.s, ptr @dst2
49+
ret void
50+
}
51+
52+
declare ptr @malloc(i32)
53+
54+
define void @test2() nounwind {
55+
; CHECK-LABEL: test2:
56+
; CHECK: ; %bb.0: ; %entry
57+
; CHECK-NEXT: suba.l #4, %sp
58+
; CHECK-NEXT: move.l #40, (%sp)
59+
; CHECK-NEXT: jsr (malloc@PLT,%pc)
60+
; CHECK-NEXT: adda.l #4, %sp
61+
; CHECK-NEXT: rts
62+
entry:
63+
%ptr = call ptr @malloc(i32 40)
64+
ret void
65+
}
66+
67+
@pfoo = external global ptr
68+
declare ptr @afoo(...)
69+
70+
define void @test3() nounwind {
71+
; CHECK-LABEL: test3:
72+
; CHECK: ; %bb.0: ; %entry
73+
; CHECK-NEXT: suba.l #4, %sp
74+
; CHECK-NEXT: movem.l %a2, (0,%sp) ; 8-byte Folded Spill
75+
; CHECK-NEXT: lea (_GLOBAL_OFFSET_TABLE_@GOTPCREL,%pc), %a2
76+
; CHECK-NEXT: jsr (afoo@PLT,%pc)
77+
; CHECK-NEXT: move.l #pfoo@GOTOFF, %d0
78+
; CHECK-NEXT: move.l %a0, (0,%a2,%d0)
79+
; CHECK-NEXT: jsr (%a0)
80+
; CHECK-NEXT: movem.l (0,%sp), %a2 ; 8-byte Folded Reload
81+
; CHECK-NEXT: adda.l #4, %sp
82+
; CHECK-NEXT: rts
83+
entry:
84+
%tmp = call ptr(...) @afoo()
85+
store ptr %tmp, ptr @pfoo
86+
%tmp1 = load ptr, ptr @pfoo
87+
call void(...) %tmp1()
88+
ret void
89+
}
90+
91+
declare void @foo(...)
92+
93+
define void @test4() nounwind {
94+
; CHECK-LABEL: test4:
95+
; CHECK: ; %bb.0: ; %entry
96+
; CHECK-NEXT: suba.l #4, %sp
97+
; CHECK-NEXT: jsr (foo@PLT,%pc)
98+
; CHECK-NEXT: adda.l #4, %sp
99+
; CHECK-NEXT: rts
100+
entry:
101+
call void(...) @foo()
102+
ret void
103+
}
104+
105+
@ptr6 = internal global ptr null
106+
@dst6 = internal global i32 0
107+
@src6 = internal global i32 0
108+
109+
define void @test5() nounwind {
110+
; CHECK-LABEL: test5:
111+
; CHECK: ; %bb.0: ; %entry
112+
; CHECK-NEXT: lea (_GLOBAL_OFFSET_TABLE_@GOTPCREL,%pc), %a0
113+
; CHECK-NEXT: move.l %a0, %a1
114+
; CHECK-NEXT: adda.l #dst6@GOTOFF, %a1
115+
; CHECK-NEXT: move.l #ptr6@GOTOFF, %d0
116+
; CHECK-NEXT: move.l %a1, (0,%a0,%d0)
117+
; CHECK-NEXT: move.l #src6@GOTOFF, %d0
118+
; CHECK-NEXT: move.l #dst6@GOTOFF, %d1
119+
; CHECK-NEXT: move.l (0,%a0,%d0), (0,%a0,%d1)
120+
; CHECK-NEXT: rts
121+
entry:
122+
store ptr @dst6, ptr @ptr6
123+
%tmp.s = load i32, ptr @src6
124+
store i32 %tmp.s, ptr @dst6
125+
ret void
126+
}
127+
128+
define void @test7(i32 %n.u) nounwind {
129+
; CHECK-LABEL: test7:
130+
; CHECK: ; %bb.0: ; %entry
131+
; CHECK-NEXT: move.l (4,%sp), %d0
132+
; CHECK-NEXT: add.l #-1, %d0
133+
; CHECK-NEXT: move.l %d0, %d1
134+
; CHECK-NEXT: sub.l #12, %d1
135+
; CHECK-NEXT: bhi .LBB6_12
136+
; CHECK-NEXT: ; %bb.1: ; %entry
137+
; CHECK-NEXT: lea (_GLOBAL_OFFSET_TABLE_@GOTPCREL,%pc), %a0
138+
; CHECK-NEXT: lsl.l #2, %d0
139+
; CHECK-NEXT: move.l %a0, %a1
140+
; CHECK-NEXT: adda.l #.LJTI6_0@GOTOFF, %a1
141+
; CHECK-NEXT: move.l %a0, %d1
142+
; CHECK-NEXT: add.l (0,%a1,%d0), %d1
143+
; CHECK-NEXT: move.l %d1, %a0
144+
; CHECK-NEXT: jmp (%a0)
145+
; CHECK-NEXT: .LBB6_12: ; %bb2
146+
; CHECK-NEXT: bra foo6@PLT ; TAILCALL
147+
; CHECK-NEXT: .LBB6_3: ; %bb5
148+
; CHECK-NEXT: bra foo5@PLT ; TAILCALL
149+
; CHECK-NEXT: .LBB6_5: ; %bb1
150+
; CHECK-NEXT: bra foo2@PLT ; TAILCALL
151+
; CHECK-NEXT: .LBB6_2: ; %bb
152+
; CHECK-NEXT: bra foo1@PLT ; TAILCALL
153+
; CHECK-NEXT: .LBB6_9: ; %bb4
154+
; CHECK-NEXT: bra foo4@PLT ; TAILCALL
155+
; CHECK-NEXT: .LBB6_8: ; %bb3
156+
; CHECK-NEXT: bra foo3@PLT ; TAILCALL
157+
entry:
158+
switch i32 %n.u, label %bb12 [i32 1, label %bb i32 2, label %bb6 i32 4, label %bb7 i32 5, label %bb8 i32 6, label %bb10 i32 7, label %bb1 i32 8, label %bb3 i32 9, label %bb4 i32 10, label %bb9 i32 11, label %bb2 i32 12, label %bb5 i32 13, label %bb11 ]
159+
bb:
160+
tail call void(...) @foo1()
161+
ret void
162+
bb1:
163+
tail call void(...) @foo2()
164+
ret void
165+
bb2:
166+
tail call void(...) @foo6()
167+
ret void
168+
bb3:
169+
tail call void(...) @foo3()
170+
ret void
171+
bb4:
172+
tail call void(...) @foo4()
173+
ret void
174+
bb5:
175+
tail call void(...) @foo5()
176+
ret void
177+
bb6:
178+
tail call void(...) @foo1()
179+
ret void
180+
bb7:
181+
tail call void(...) @foo2()
182+
ret void
183+
bb8:
184+
tail call void(...) @foo6()
185+
ret void
186+
bb9:
187+
tail call void(...) @foo3()
188+
ret void
189+
bb10:
190+
tail call void(...) @foo4()
191+
ret void
192+
bb11:
193+
tail call void(...) @foo5()
194+
ret void
195+
bb12:
196+
tail call void(...) @foo6()
197+
ret void
198+
}
199+
200+
declare void @foo1(...)
201+
declare void @foo2(...)
202+
declare void @foo6(...)
203+
declare void @foo3(...)
204+
declare void @foo4(...)
205+
declare void @foo5(...)

0 commit comments

Comments
 (0)