[llvm] [M68k] implement large code model (PR #106381)
Janis Heims via llvm-commits
llvm-commits at lists.llvm.org
Thu Aug 29 03:44:32 PDT 2024
https://github.com/TechnoElf updated https://github.com/llvm/llvm-project/pull/106381
>From b724ce53a799c1563d13cb466a0e5783d8098c57 Mon Sep 17 00:00:00 2001
From: TechnoElf <technoelf at undertheprinter.com>
Date: Wed, 28 Aug 2024 14:13:27 +0200
Subject: [PATCH] [M68k] implement large code model
---
llvm/lib/Target/M68k/M68kSubtarget.cpp | 54 ++++-
llvm/lib/Target/M68k/M68kTargetMachine.cpp | 2 -
llvm/test/CodeGen/M68k/CodeModel/large-pic.ll | 205 ++++++++++++++++++
.../M68k/CodeModel/large-pie-global-access.ll | 139 ++++++++++++
llvm/test/CodeGen/M68k/CodeModel/large-pie.ll | 66 ++++++
.../CodeGen/M68k/CodeModel/large-static.ll | 180 +++++++++++++++
6 files changed, 640 insertions(+), 6 deletions(-)
create mode 100644 llvm/test/CodeGen/M68k/CodeModel/large-pic.ll
create mode 100644 llvm/test/CodeGen/M68k/CodeModel/large-pie-global-access.ll
create mode 100644 llvm/test/CodeGen/M68k/CodeModel/large-pie.ll
create mode 100644 llvm/test/CodeGen/M68k/CodeModel/large-static.ll
diff --git a/llvm/lib/Target/M68k/M68kSubtarget.cpp b/llvm/lib/Target/M68k/M68kSubtarget.cpp
index cacdbf559faa2d..53ec574ae5596c 100644
--- a/llvm/lib/Target/M68k/M68kSubtarget.cpp
+++ b/llvm/lib/Target/M68k/M68kSubtarget.cpp
@@ -115,7 +115,7 @@ M68kSubtarget &M68kSubtarget::initializeSubtargetDependencies(
// ---------------------+------------+------------+------------+-------------
// branch | pc-rel | pc-rel | pc-rel | pc-rel
// ---------------------+------------+------------+------------+-------------
-// call global | @PLT | @PLT | @PLT | @PLT
+// call global | absolute | @PLT | absolute | @PLT
// ---------------------+------------+------------+------------+-------------
// call internal | pc-rel | pc-rel | pc-rel | pc-rel
// ---------------------+------------+------------+------------+-------------
@@ -127,6 +127,24 @@ M68kSubtarget &M68kSubtarget::initializeSubtargetDependencies(
// ---------------------+------------+------------+------------+-------------
// data global big* | pc-rel | @GOTPCREL | absolute | @GOTPCREL
// ---------------------+------------+------------+------------+-------------
+// | Large |
+// +-------------------------+
+// | Static | PIC |
+// ---------------------+------------+------------+
+// branch | absolute | pc-rel |
+// ---------------------+------------+------------+
+// call global | absolute | @PLT |
+// ---------------------+------------+------------+
+// call internal | absolute | pc-rel |
+// ---------------------+------------+------------+
+// data local | absolute | @GOTOFF |
+// ---------------------+------------+------------+
+// data local big* | absolute | @GOTOFF |
+// ---------------------+------------+------------+
+// data global | absolute | @GOTOFF |
+// ---------------------+------------+------------+
+// data global big* | absolute | @GOTOFF |
+// ---------------------+------------+------------+
//
// * Big data potentially cannot be reached within 16 bit offset and requires
// special handling for old(x00 and x10) CPUs. Normally these symbols go into
@@ -142,8 +160,22 @@ M68kSubtarget &M68kSubtarget::initializeSubtargetDependencies(
/// Classify a blockaddress reference for the current subtarget according to how
/// we should reference it in a non-pcrel context.
unsigned char M68kSubtarget::classifyBlockAddressReference() const {
- // Unless we start to support Large Code Model branching is always pc-rel
- return M68kII::MO_PC_RELATIVE_ADDRESS;
+ switch (TM.getCodeModel()) {
+ default:
+ llvm_unreachable("Unsupported code model");
+ case CodeModel::Small:
+ case CodeModel::Kernel:
+ case CodeModel::Medium: {
+ return M68kII::MO_PC_RELATIVE_ADDRESS;
+ }
+ case CodeModel::Large: {
+ if (isPositionIndependent()) {
+ return M68kII::MO_PC_RELATIVE_ADDRESS;
+ } else {
+ return M68kII::MO_ABSOLUTE_ADDRESS;
+ }
+ }
+ }
}
unsigned char
@@ -171,6 +203,13 @@ M68kSubtarget::classifyLocalReference(const GlobalValue *GV) const {
return M68kII::MO_ABSOLUTE_ADDRESS;
}
}
+ case CodeModel::Large: {
+ if (isPositionIndependent()) {
+ return M68kII::MO_GOTOFF;
+ } else {
+ return M68kII::MO_ABSOLUTE_ADDRESS;
+ }
+ }
}
}
@@ -212,6 +251,12 @@ unsigned char M68kSubtarget::classifyGlobalReference(const GlobalValue *GV,
return M68kII::MO_ABSOLUTE_ADDRESS;
}
+ case CodeModel::Large: {
+ if (isPositionIndependent())
+ return M68kII::MO_GOTOFF;
+
+ return M68kII::MO_ABSOLUTE_ADDRESS;
+ }
}
}
@@ -221,7 +266,8 @@ unsigned M68kSubtarget::getJumpTableEncoding() const {
// the potential delta between the jump target and table base can be larger
// than displacement field, which is True for older CPUs(16 bit disp)
// in Medium model(can have large data way beyond 16 bit).
- if (TM.getCodeModel() == CodeModel::Medium && !atLeastM68020())
+ if ((TM.getCodeModel() == CodeModel::Medium && !atLeastM68020()) ||
+ TM.getCodeModel() == CodeModel::Large)
return MachineJumpTableInfo::EK_Custom32;
return MachineJumpTableInfo::EK_LabelDifference32;
diff --git a/llvm/lib/Target/M68k/M68kTargetMachine.cpp b/llvm/lib/Target/M68k/M68kTargetMachine.cpp
index b65de5e177b53e..2248837e6ca61b 100644
--- a/llvm/lib/Target/M68k/M68kTargetMachine.cpp
+++ b/llvm/lib/Target/M68k/M68kTargetMachine.cpp
@@ -87,8 +87,6 @@ CodeModel::Model getEffectiveCodeModel(std::optional<CodeModel::Model> CM,
bool JIT) {
if (!CM) {
return CodeModel::Small;
- } else if (CM == CodeModel::Large) {
- llvm_unreachable("Large code model is not supported");
} else if (CM == CodeModel::Kernel) {
llvm_unreachable("Kernel code model is not implemented yet");
}
diff --git a/llvm/test/CodeGen/M68k/CodeModel/large-pic.ll b/llvm/test/CodeGen/M68k/CodeModel/large-pic.ll
new file mode 100644
index 00000000000000..c937efa60b72b2
--- /dev/null
+++ b/llvm/test/CodeGen/M68k/CodeModel/large-pic.ll
@@ -0,0 +1,205 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
+; RUN: llc < %s -O2 -mtriple=m68k -verify-machineinstrs \
+; RUN: -code-model=large -relocation-model=pic \
+; RUN: | FileCheck %s
+
+ at ptr = external global ptr
+ at dst = external global i32
+ at src = external global i32
+
+define void @test0() nounwind {
+; CHECK-LABEL: test0:
+; CHECK: ; %bb.0: ; %entry
+; CHECK-NEXT: lea (_GLOBAL_OFFSET_TABLE_ at GOTPCREL,%pc), %a0
+; CHECK-NEXT: move.l %a0, %a1
+; CHECK-NEXT: adda.l #dst at GOTOFF, %a1
+; CHECK-NEXT: move.l #ptr at GOTOFF, %d0
+; CHECK-NEXT: move.l %a1, (0,%a0,%d0)
+; CHECK-NEXT: move.l #src at GOTOFF, %d0
+; CHECK-NEXT: move.l #dst at GOTOFF, %d1
+; CHECK-NEXT: move.l (0,%a0,%d0), (0,%a0,%d1)
+; CHECK-NEXT: rts
+entry:
+ store ptr @dst, ptr @ptr
+ %tmp.s = load i32, ptr @src
+ store i32 %tmp.s, ptr @dst
+ ret void
+}
+
+ at ptr2 = global ptr null
+ at dst2 = global i32 0
+ at src2 = global i32 0
+
+define void @test1() nounwind {
+; CHECK-LABEL: test1:
+; CHECK: ; %bb.0: ; %entry
+; CHECK-NEXT: lea (_GLOBAL_OFFSET_TABLE_ at GOTPCREL,%pc), %a0
+; CHECK-NEXT: move.l %a0, %a1
+; CHECK-NEXT: adda.l #dst2 at GOTOFF, %a1
+; CHECK-NEXT: move.l #ptr2 at GOTOFF, %d0
+; CHECK-NEXT: move.l %a1, (0,%a0,%d0)
+; CHECK-NEXT: move.l #src2 at GOTOFF, %d0
+; CHECK-NEXT: move.l #dst2 at GOTOFF, %d1
+; CHECK-NEXT: move.l (0,%a0,%d0), (0,%a0,%d1)
+; CHECK-NEXT: rts
+entry:
+ store ptr @dst2, ptr @ptr2
+ %tmp.s = load i32, ptr @src2
+ store i32 %tmp.s, ptr @dst2
+ ret void
+}
+
+declare ptr @malloc(i32)
+
+define void @test2() nounwind {
+; CHECK-LABEL: test2:
+; CHECK: ; %bb.0: ; %entry
+; CHECK-NEXT: suba.l #4, %sp
+; CHECK-NEXT: move.l #40, (%sp)
+; CHECK-NEXT: jsr (malloc at PLT,%pc)
+; CHECK-NEXT: adda.l #4, %sp
+; CHECK-NEXT: rts
+entry:
+ %ptr = call ptr @malloc(i32 40)
+ ret void
+}
+
+ at pfoo = external global ptr
+declare ptr @afoo(...)
+
+define void @test3() nounwind {
+; CHECK-LABEL: test3:
+; CHECK: ; %bb.0: ; %entry
+; CHECK-NEXT: suba.l #4, %sp
+; CHECK-NEXT: movem.l %a2, (0,%sp) ; 8-byte Folded Spill
+; CHECK-NEXT: lea (_GLOBAL_OFFSET_TABLE_ at GOTPCREL,%pc), %a2
+; CHECK-NEXT: jsr (afoo at PLT,%pc)
+; CHECK-NEXT: move.l #pfoo at GOTOFF, %d0
+; CHECK-NEXT: move.l %a0, (0,%a2,%d0)
+; CHECK-NEXT: jsr (%a0)
+; CHECK-NEXT: movem.l (0,%sp), %a2 ; 8-byte Folded Reload
+; CHECK-NEXT: adda.l #4, %sp
+; CHECK-NEXT: rts
+entry:
+ %tmp = call ptr(...) @afoo()
+ store ptr %tmp, ptr @pfoo
+ %tmp1 = load ptr, ptr @pfoo
+ call void(...) %tmp1()
+ ret void
+}
+
+declare void @foo(...)
+
+define void @test4() nounwind {
+; CHECK-LABEL: test4:
+; CHECK: ; %bb.0: ; %entry
+; CHECK-NEXT: suba.l #4, %sp
+; CHECK-NEXT: jsr (foo at PLT,%pc)
+; CHECK-NEXT: adda.l #4, %sp
+; CHECK-NEXT: rts
+entry:
+ call void(...) @foo()
+ ret void
+}
+
+ at ptr6 = internal global ptr null
+ at dst6 = internal global i32 0
+ at src6 = internal global i32 0
+
+define void @test5() nounwind {
+; CHECK-LABEL: test5:
+; CHECK: ; %bb.0: ; %entry
+; CHECK-NEXT: lea (_GLOBAL_OFFSET_TABLE_ at GOTPCREL,%pc), %a0
+; CHECK-NEXT: move.l %a0, %a1
+; CHECK-NEXT: adda.l #dst6 at GOTOFF, %a1
+; CHECK-NEXT: move.l #ptr6 at GOTOFF, %d0
+; CHECK-NEXT: move.l %a1, (0,%a0,%d0)
+; CHECK-NEXT: move.l #src6 at GOTOFF, %d0
+; CHECK-NEXT: move.l #dst6 at GOTOFF, %d1
+; CHECK-NEXT: move.l (0,%a0,%d0), (0,%a0,%d1)
+; CHECK-NEXT: rts
+entry:
+ store ptr @dst6, ptr @ptr6
+ %tmp.s = load i32, ptr @src6
+ store i32 %tmp.s, ptr @dst6
+ ret void
+}
+
+define void @test7(i32 %n.u) nounwind {
+; CHECK-LABEL: test7:
+; CHECK: ; %bb.0: ; %entry
+; CHECK-NEXT: move.l (4,%sp), %d0
+; CHECK-NEXT: add.l #-1, %d0
+; CHECK-NEXT: move.l %d0, %d1
+; CHECK-NEXT: sub.l #12, %d1
+; CHECK-NEXT: bhi .LBB6_12
+; CHECK-NEXT: ; %bb.1: ; %entry
+; CHECK-NEXT: lea (_GLOBAL_OFFSET_TABLE_ at GOTPCREL,%pc), %a0
+; CHECK-NEXT: lsl.l #2, %d0
+; CHECK-NEXT: move.l %a0, %a1
+; CHECK-NEXT: adda.l #.LJTI6_0 at GOTOFF, %a1
+; CHECK-NEXT: move.l %a0, %d1
+; CHECK-NEXT: add.l (0,%a1,%d0), %d1
+; CHECK-NEXT: move.l %d1, %a0
+; CHECK-NEXT: jmp (%a0)
+; CHECK-NEXT: .LBB6_12: ; %bb2
+; CHECK-NEXT: bra foo6 at PLT ; TAILCALL
+; CHECK-NEXT: .LBB6_3: ; %bb5
+; CHECK-NEXT: bra foo5 at PLT ; TAILCALL
+; CHECK-NEXT: .LBB6_5: ; %bb1
+; CHECK-NEXT: bra foo2 at PLT ; TAILCALL
+; CHECK-NEXT: .LBB6_2: ; %bb
+; CHECK-NEXT: bra foo1 at PLT ; TAILCALL
+; CHECK-NEXT: .LBB6_9: ; %bb4
+; CHECK-NEXT: bra foo4 at PLT ; TAILCALL
+; CHECK-NEXT: .LBB6_8: ; %bb3
+; CHECK-NEXT: bra foo3 at PLT ; TAILCALL
+entry:
+ 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 ]
+bb:
+ tail call void(...) @foo1()
+ ret void
+bb1:
+ tail call void(...) @foo2()
+ ret void
+bb2:
+ tail call void(...) @foo6()
+ ret void
+bb3:
+ tail call void(...) @foo3()
+ ret void
+bb4:
+ tail call void(...) @foo4()
+ ret void
+bb5:
+ tail call void(...) @foo5()
+ ret void
+bb6:
+ tail call void(...) @foo1()
+ ret void
+bb7:
+ tail call void(...) @foo2()
+ ret void
+bb8:
+ tail call void(...) @foo6()
+ ret void
+bb9:
+ tail call void(...) @foo3()
+ ret void
+bb10:
+ tail call void(...) @foo4()
+ ret void
+bb11:
+ tail call void(...) @foo5()
+ ret void
+bb12:
+ tail call void(...) @foo6()
+ ret void
+}
+
+declare void @foo1(...)
+declare void @foo2(...)
+declare void @foo6(...)
+declare void @foo3(...)
+declare void @foo4(...)
+declare void @foo5(...)
diff --git a/llvm/test/CodeGen/M68k/CodeModel/large-pie-global-access.ll b/llvm/test/CodeGen/M68k/CodeModel/large-pie-global-access.ll
new file mode 100644
index 00000000000000..f82b961382fbf0
--- /dev/null
+++ b/llvm/test/CodeGen/M68k/CodeModel/large-pie-global-access.ll
@@ -0,0 +1,139 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5
+; RUN: llc < %s -O2 -mtriple=m68k -verify-machineinstrs \
+; RUN: -code-model=large -relocation-model=pic \
+; RUN: | FileCheck %s
+
+; External Linkage
+ at a = global i32 0, align 4
+
+define i32 @my_access_global_a() #0 {
+; CHECK-LABEL: my_access_global_a:
+; CHECK: .cfi_startproc
+; CHECK-NEXT: ; %bb.0: ; %entry
+; CHECK-NEXT: lea (_GLOBAL_OFFSET_TABLE_ at GOTPCREL,%pc), %a0
+; CHECK-NEXT: move.l #a at GOTOFF, %d0
+; CHECK-NEXT: move.l (0,%a0,%d0), %d0
+; CHECK-NEXT: rts
+entry:
+ %0 = load i32, ptr @a, align 4
+ ret i32 %0
+}
+
+; WeakAny Linkage
+ at b = weak global i32 0, align 4
+
+define i32 @my_access_global_b() #0 {
+; CHECK-LABEL: my_access_global_b:
+; CHECK: .cfi_startproc
+; CHECK-NEXT: ; %bb.0: ; %entry
+; CHECK-NEXT: lea (_GLOBAL_OFFSET_TABLE_ at GOTPCREL,%pc), %a0
+; CHECK-NEXT: move.l #b at GOTOFF, %d0
+; CHECK-NEXT: move.l (0,%a0,%d0), %d0
+; CHECK-NEXT: rts
+entry:
+ %0 = load i32, ptr @b, align 4
+ ret i32 %0
+}
+
+; Internal Linkage
+ at c = internal global i32 0, align 4
+
+define i32 @my_access_global_c() #0 {
+; CHECK-LABEL: my_access_global_c:
+; CHECK: .cfi_startproc
+; CHECK-NEXT: ; %bb.0: ; %entry
+; CHECK-NEXT: lea (_GLOBAL_OFFSET_TABLE_ at GOTPCREL,%pc), %a0
+; CHECK-NEXT: move.l #c at GOTOFF, %d0
+; CHECK-NEXT: move.l (0,%a0,%d0), %d0
+; CHECK-NEXT: rts
+entry:
+ %0 = load i32, ptr @c, align 4
+ ret i32 %0
+}
+
+; External Linkage, only declaration.
+ at d = external global i32, align 4
+
+define i32 @my_access_global_load_d() #0 {
+; CHECK-LABEL: my_access_global_load_d:
+; CHECK: .cfi_startproc
+; CHECK-NEXT: ; %bb.0: ; %entry
+; CHECK-NEXT: lea (_GLOBAL_OFFSET_TABLE_ at GOTPCREL,%pc), %a0
+; CHECK-NEXT: move.l #d at GOTOFF, %d0
+; CHECK-NEXT: move.l (0,%a0,%d0), %d0
+; CHECK-NEXT: rts
+entry:
+ %0 = load i32, ptr @d, align 4
+ ret i32 %0
+}
+
+; External Linkage, only declaration, store a value.
+define i32 @my_access_global_store_d() #0 {
+; CHECK-LABEL: my_access_global_store_d:
+; CHECK: .cfi_startproc
+; CHECK-NEXT: ; %bb.0: ; %entry
+; CHECK-NEXT: lea (_GLOBAL_OFFSET_TABLE_ at GOTPCREL,%pc), %a0
+; CHECK-NEXT: move.l #d at GOTOFF, %d0
+; CHECK-NEXT: move.l #2, (0,%a0,%d0)
+; CHECK-NEXT: moveq #0, %d0
+; CHECK-NEXT: rts
+entry:
+ store i32 2, ptr @d, align 4
+ ret i32 0
+}
+
+; External Linkage, function pointer access.
+declare i32 @access_fp(ptr)
+declare i32 @foo()
+
+define i32 @my_access_fp_foo() #0 {
+; CHECK-LABEL: my_access_fp_foo:
+; CHECK: .cfi_startproc
+; CHECK-NEXT: ; %bb.0: ; %entry
+; CHECK-NEXT: suba.l #4, %sp
+; CHECK-NEXT: .cfi_def_cfa_offset -8
+; CHECK-NEXT: lea (_GLOBAL_OFFSET_TABLE_ at GOTPCREL,%pc), %a0
+; CHECK-NEXT: adda.l #foo at GOTOFF, %a0
+; CHECK-NEXT: move.l %a0, (%sp)
+; CHECK-NEXT: jsr (access_fp at PLT,%pc)
+; CHECK-NEXT: adda.l #4, %sp
+; CHECK-NEXT: rts
+entry:
+ %call = call i32 @access_fp(ptr @foo)
+ ret i32 %call
+}
+
+; LinkOnceODR Linkage, function pointer access.
+
+$bar = comdat any
+
+define linkonce_odr i32 @bar() comdat {
+; CHECK-LABEL: bar:
+; CHECK: .cfi_startproc
+; CHECK-NEXT: ; %bb.0: ; %entry
+; CHECK-NEXT: moveq #0, %d0
+; CHECK-NEXT: rts
+entry:
+ ret i32 0
+}
+
+define i32 @my_access_fp_bar() #0 {
+; CHECK-LABEL: my_access_fp_bar:
+; CHECK: .cfi_startproc
+; CHECK-NEXT: ; %bb.0: ; %entry
+; CHECK-NEXT: suba.l #4, %sp
+; CHECK-NEXT: .cfi_def_cfa_offset -8
+; CHECK-NEXT: lea (_GLOBAL_OFFSET_TABLE_ at GOTPCREL,%pc), %a0
+; CHECK-NEXT: adda.l #bar at GOTOFF, %a0
+; CHECK-NEXT: move.l %a0, (%sp)
+; CHECK-NEXT: jsr (access_fp at PLT,%pc)
+; CHECK-NEXT: adda.l #4, %sp
+; CHECK-NEXT: rts
+entry:
+ %call = call i32 @access_fp(ptr @bar)
+ ret i32 %call
+}
+
+!llvm.module.flags = !{!0, !1}
+!0 = !{i32 1, !"PIC Level", i32 1}
+!1 = !{i32 1, !"PIE Level", i32 1}
diff --git a/llvm/test/CodeGen/M68k/CodeModel/large-pie.ll b/llvm/test/CodeGen/M68k/CodeModel/large-pie.ll
new file mode 100644
index 00000000000000..ad902528d1dd3f
--- /dev/null
+++ b/llvm/test/CodeGen/M68k/CodeModel/large-pie.ll
@@ -0,0 +1,66 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
+; RUN: llc < %s -O0 -mtriple=m68k -verify-machineinstrs \
+; RUN: -code-model=large -relocation-model=pic \
+; RUN: | FileCheck %s
+
+define weak void @weak_foo() {
+; CHECK-LABEL: weak_foo:
+; CHECK: .cfi_startproc
+; CHECK-NEXT: ; %bb.0:
+; CHECK-NEXT: rts
+ ret void
+}
+
+define weak_odr void @weak_odr_foo() {
+; CHECK-LABEL: weak_odr_foo:
+; CHECK: .cfi_startproc
+; CHECK-NEXT: ; %bb.0:
+; CHECK-NEXT: rts
+ ret void
+}
+
+define internal void @internal_foo() {
+; CHECK-LABEL: internal_foo:
+; CHECK: .cfi_startproc
+; CHECK-NEXT: ; %bb.0:
+; CHECK-NEXT: rts
+ ret void
+}
+
+declare i32 @ext_baz()
+
+define void @foo() {
+; CHECK-LABEL: foo:
+; CHECK: .cfi_startproc
+; CHECK-NEXT: ; %bb.0:
+; CHECK-NEXT: rts
+ ret void
+}
+
+define void @bar() {
+; CHECK-LABEL: bar:
+; CHECK: .cfi_startproc
+; CHECK-NEXT: ; %bb.0: ; %entry
+; CHECK-NEXT: suba.l #4, %sp
+; CHECK-NEXT: .cfi_def_cfa_offset -8
+; CHECK-NEXT: jsr (foo at PLT,%pc)
+; CHECK-NEXT: jsr (weak_odr_foo at PLT,%pc)
+; CHECK-NEXT: jsr (weak_foo at PLT,%pc)
+; CHECK-NEXT: jsr (internal_foo,%pc)
+; CHECK-NEXT: jsr (ext_baz at PLT,%pc)
+; CHECK-NEXT: adda.l #4, %sp
+; CHECK-NEXT: rts
+entry:
+ call void @foo()
+ call void @weak_odr_foo()
+ call void @weak_foo()
+ call void @internal_foo()
+ call i32 @ext_baz()
+ ret void
+}
+
+; -fpie for local global data tests should be added here
+
+!llvm.module.flags = !{!0, !1}
+!0 = !{i32 1, !"PIC Level", i32 1}
+!1 = !{i32 1, !"PIE Level", i32 1}
diff --git a/llvm/test/CodeGen/M68k/CodeModel/large-static.ll b/llvm/test/CodeGen/M68k/CodeModel/large-static.ll
new file mode 100644
index 00000000000000..fb38cd9582bd13
--- /dev/null
+++ b/llvm/test/CodeGen/M68k/CodeModel/large-static.ll
@@ -0,0 +1,180 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
+; RUN: llc < %s -O2 -mtriple=m68k -verify-machineinstrs \
+; RUN: -code-model=large -relocation-model=static \
+; RUN: | FileCheck %s
+
+ at ptr = external global ptr
+ at dst = external global i32
+ at src = external global i32
+
+define void @test0() nounwind {
+; CHECK-LABEL: test0:
+; CHECK: ; %bb.0: ; %entry
+; CHECK-NEXT: move.l #dst, ptr
+; CHECK-NEXT: move.l src, dst
+; CHECK-NEXT: rts
+entry:
+ store ptr @dst, ptr @ptr
+ %tmp.s = load i32, ptr @src
+ store i32 %tmp.s, ptr @dst
+ ret void
+}
+
+ at ptr2 = global ptr null
+ at dst2 = global i32 0
+ at src2 = global i32 0
+
+define void @test1() nounwind {
+; CHECK-LABEL: test1:
+; CHECK: ; %bb.0: ; %entry
+; CHECK-NEXT: move.l #dst2, ptr2
+; CHECK-NEXT: move.l src2, dst2
+; CHECK-NEXT: rts
+entry:
+ store ptr @dst2, ptr @ptr2
+ %tmp.s = load i32, ptr @src2
+ store i32 %tmp.s, ptr @dst2
+ ret void
+}
+
+declare ptr @malloc(i32)
+
+define void @test2() nounwind {
+; CHECK-LABEL: test2:
+; CHECK: ; %bb.0: ; %entry
+; CHECK-NEXT: suba.l #4, %sp
+; CHECK-NEXT: move.l #40, (%sp)
+; CHECK-NEXT: jsr malloc
+; CHECK-NEXT: adda.l #4, %sp
+; CHECK-NEXT: rts
+entry:
+ %ptr = call ptr @malloc(i32 40)
+ ret void
+}
+
+ at pfoo = external global ptr
+declare ptr @afoo(...)
+
+
+define void @test3() nounwind {
+; CHECK-LABEL: test3:
+; CHECK: ; %bb.0: ; %entry
+; CHECK-NEXT: suba.l #4, %sp
+; CHECK-NEXT: jsr afoo
+; CHECK-NEXT: move.l %a0, pfoo
+; CHECK-NEXT: jsr (%a0)
+; CHECK-NEXT: adda.l #4, %sp
+; CHECK-NEXT: rts
+entry:
+ %tmp = call ptr(...) @afoo()
+ store ptr %tmp, ptr @pfoo
+ %tmp1 = load ptr, ptr @pfoo
+ call void(...) %tmp1()
+ ret void
+}
+
+declare void @foo(...)
+
+define void @test4() nounwind {
+; CHECK-LABEL: test4:
+; CHECK: ; %bb.0: ; %entry
+; CHECK-NEXT: suba.l #4, %sp
+; CHECK-NEXT: jsr foo
+; CHECK-NEXT: adda.l #4, %sp
+; CHECK-NEXT: rts
+entry:
+ call void(...) @foo()
+ ret void
+}
+
+ at ptr6 = internal global ptr null
+ at dst6 = internal global i32 0
+ at src6 = internal global i32 0
+
+define void @test5() nounwind {
+; CHECK-LABEL: test5:
+; CHECK: ; %bb.0: ; %entry
+; CHECK-NEXT: move.l #dst6, ptr6
+; CHECK-NEXT: move.l src6, dst6
+; CHECK-NEXT: rts
+entry:
+ store ptr @dst6, ptr @ptr6
+ %tmp.s = load i32, ptr @src6
+ store i32 %tmp.s, ptr @dst6
+ ret void
+}
+
+define void @test7(i32 %n.u) nounwind {
+; CHECK-LABEL: test7:
+; CHECK: ; %bb.0: ; %entry
+; CHECK-NEXT: move.l (4,%sp), %d0
+; CHECK-NEXT: add.l #-1, %d0
+; CHECK-NEXT: move.l %d0, %d1
+; CHECK-NEXT: sub.l #12, %d1
+; CHECK-NEXT: bhi .LBB6_12
+; CHECK-NEXT: ; %bb.1: ; %entry
+; CHECK-NEXT: lsl.l #2, %d0
+; CHECK-NEXT: move.l #.LJTI6_0, %a0
+; CHECK-NEXT: move.l (0,%a0,%d0), %a0
+; CHECK-NEXT: jmp (%a0)
+; CHECK-NEXT: .LBB6_12: ; %bb2
+; CHECK-NEXT: bra foo6 ; TAILCALL
+; CHECK-NEXT: .LBB6_3: ; %bb5
+; CHECK-NEXT: bra foo5 ; TAILCALL
+; CHECK-NEXT: .LBB6_5: ; %bb1
+; CHECK-NEXT: bra foo2 ; TAILCALL
+; CHECK-NEXT: .LBB6_2: ; %bb
+; CHECK-NEXT: bra foo1 ; TAILCALL
+; CHECK-NEXT: .LBB6_9: ; %bb4
+; CHECK-NEXT: bra foo4 ; TAILCALL
+; CHECK-NEXT: .LBB6_8: ; %bb3
+; CHECK-NEXT: bra foo3 ; TAILCALL
+entry:
+ 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 ]
+bb:
+ tail call void(...) @foo1()
+ ret void
+bb1:
+ tail call void(...) @foo2()
+ ret void
+bb2:
+ tail call void(...) @foo6()
+ ret void
+bb3:
+ tail call void(...) @foo3()
+ ret void
+bb4:
+ tail call void(...) @foo4()
+ ret void
+bb5:
+ tail call void(...) @foo5()
+ ret void
+bb6:
+ tail call void(...) @foo1()
+ ret void
+bb7:
+ tail call void(...) @foo2()
+ ret void
+bb8:
+ tail call void(...) @foo6()
+ ret void
+bb9:
+ tail call void(...) @foo3()
+ ret void
+bb10:
+ tail call void(...) @foo4()
+ ret void
+bb11:
+ tail call void(...) @foo5()
+ ret void
+bb12:
+ tail call void(...) @foo6()
+ ret void
+}
+
+declare void @foo1(...)
+declare void @foo2(...)
+declare void @foo6(...)
+declare void @foo3(...)
+declare void @foo4(...)
+declare void @foo5(...)
More information about the llvm-commits
mailing list