Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 50 additions & 4 deletions llvm/lib/Target/M68k/M68kSubtarget.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
// ---------------------+------------+------------+------------+-------------
Expand All @@ -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
Expand All @@ -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
Expand Down Expand Up @@ -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;
}
}
}
}

Expand Down Expand Up @@ -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;
}
}
}

Expand All @@ -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;
Expand Down
2 changes: 0 additions & 2 deletions llvm/lib/Target/M68k/M68kTargetMachine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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");
}
Expand Down
205 changes: 205 additions & 0 deletions llvm/test/CodeGen/M68k/CodeModel/large-pic.ll
Original file line number Diff line number Diff line change
@@ -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

@ptr = external global ptr
@dst = external global i32
@src = external global i32

define void @test0() nounwind {
; CHECK-LABEL: test0:
; CHECK: ; %bb.0: ; %entry
; CHECK-NEXT: lea (_GLOBAL_OFFSET_TABLE_@GOTPCREL,%pc), %a0
; CHECK-NEXT: move.l %a0, %a1
; CHECK-NEXT: adda.l #dst@GOTOFF, %a1
; CHECK-NEXT: move.l #ptr@GOTOFF, %d0
; CHECK-NEXT: move.l %a1, (0,%a0,%d0)
; CHECK-NEXT: move.l #src@GOTOFF, %d0
; CHECK-NEXT: move.l #dst@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
}

@ptr2 = global ptr null
@dst2 = global i32 0
@src2 = global i32 0

define void @test1() nounwind {
; CHECK-LABEL: test1:
; CHECK: ; %bb.0: ; %entry
; CHECK-NEXT: lea (_GLOBAL_OFFSET_TABLE_@GOTPCREL,%pc), %a0
; CHECK-NEXT: move.l %a0, %a1
; CHECK-NEXT: adda.l #dst2@GOTOFF, %a1
; CHECK-NEXT: move.l #ptr2@GOTOFF, %d0
; CHECK-NEXT: move.l %a1, (0,%a0,%d0)
; CHECK-NEXT: move.l #src2@GOTOFF, %d0
; CHECK-NEXT: move.l #dst2@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@PLT,%pc)
; CHECK-NEXT: adda.l #4, %sp
; CHECK-NEXT: rts
entry:
%ptr = call ptr @malloc(i32 40)
ret void
}

@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_@GOTPCREL,%pc), %a2
; CHECK-NEXT: jsr (afoo@PLT,%pc)
; CHECK-NEXT: move.l #pfoo@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@PLT,%pc)
; CHECK-NEXT: adda.l #4, %sp
; CHECK-NEXT: rts
entry:
call void(...) @foo()
ret void
}

@ptr6 = internal global ptr null
@dst6 = internal global i32 0
@src6 = internal global i32 0

define void @test5() nounwind {
; CHECK-LABEL: test5:
; CHECK: ; %bb.0: ; %entry
; CHECK-NEXT: lea (_GLOBAL_OFFSET_TABLE_@GOTPCREL,%pc), %a0
; CHECK-NEXT: move.l %a0, %a1
; CHECK-NEXT: adda.l #dst6@GOTOFF, %a1
; CHECK-NEXT: move.l #ptr6@GOTOFF, %d0
; CHECK-NEXT: move.l %a1, (0,%a0,%d0)
; CHECK-NEXT: move.l #src6@GOTOFF, %d0
; CHECK-NEXT: move.l #dst6@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_@GOTPCREL,%pc), %a0
; CHECK-NEXT: lsl.l #2, %d0
; CHECK-NEXT: move.l %a0, %a1
; CHECK-NEXT: adda.l #.LJTI6_0@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@PLT ; TAILCALL
; CHECK-NEXT: .LBB6_3: ; %bb5
; CHECK-NEXT: bra foo5@PLT ; TAILCALL
; CHECK-NEXT: .LBB6_5: ; %bb1
; CHECK-NEXT: bra foo2@PLT ; TAILCALL
; CHECK-NEXT: .LBB6_2: ; %bb
; CHECK-NEXT: bra foo1@PLT ; TAILCALL
; CHECK-NEXT: .LBB6_9: ; %bb4
; CHECK-NEXT: bra foo4@PLT ; TAILCALL
; CHECK-NEXT: .LBB6_8: ; %bb3
; CHECK-NEXT: bra foo3@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(...)
Loading