Skip to content

Commit 882ddab

Browse files
committed
[LoongArch] Generate PCALAU12I + JIRL instruction pair for medium codemodel
In LoongArch, when `CodeModel=Medium`, it just increases the jumping ability of function calls relative to PC, from 2^28 to 2^32. Depends on D137393 Reviewed By: SixWeining Differential Revision: https://reviews.llvm.org/D137394
1 parent 05baf68 commit 882ddab

File tree

3 files changed

+87
-1
lines changed

3 files changed

+87
-1
lines changed

llvm/lib/Target/LoongArch/LoongArchExpandPseudoInsts.cpp

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -254,14 +254,32 @@ bool LoongArchPreRAExpandPseudo::expandFunctionCALL(
254254
const MachineOperand &Func = MI.getOperand(0);
255255
MachineInstrBuilder CALL;
256256

257-
// TODO: CodeModel::Medium
258257
switch (MF->getTarget().getCodeModel()) {
259258
default:
260259
report_fatal_error("Unsupported code model");
261260
break;
262261
case CodeModel::Small: // Default CodeModel.
263262
CALL = BuildMI(MBB, MBBI, DL, TII->get(LoongArch::BL)).add(Func);
264263
break;
264+
case CodeModel::Medium: {
265+
// pcalau12i $ra, %pc_hi20(func)
266+
// jirl $ra, $ra, %pc_lo12(func)
267+
MachineInstrBuilder MIB =
268+
BuildMI(MBB, MBBI, DL, TII->get(LoongArch::PCALAU12I), LoongArch::R1);
269+
CALL = BuildMI(MBB, MBBI, DL, TII->get(LoongArch::PseudoJIRL_CALL))
270+
.addReg(LoongArch::R1);
271+
if (Func.isSymbol()) {
272+
const char *FnName = Func.getSymbolName();
273+
MIB.addExternalSymbol(FnName, LoongArchII::MO_PCREL_HI);
274+
CALL.addExternalSymbol(FnName, LoongArchII::MO_PCREL_LO);
275+
break;
276+
}
277+
assert(Func.isGlobal() && "Expected a GlobalValue at this time");
278+
const GlobalValue *GV = Func.getGlobal();
279+
MIB.addGlobalAddress(GV, 0, LoongArchII::MO_PCREL_HI);
280+
CALL.addGlobalAddress(GV, 0, LoongArchII::MO_PCREL_LO);
281+
break;
282+
}
265283
}
266284

267285
// Transfer implicit operands.

llvm/lib/Target/LoongArch/LoongArchInstrInfo.td

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -944,6 +944,11 @@ def PseudoCALLIndirect : Pseudo<(outs), (ins GPR:$rj),
944944
[(loongarch_call GPR:$rj)]>,
945945
PseudoInstExpansion<(JIRL R1, GPR:$rj, 0)>;
946946

947+
let isCall = 1, Defs = [R1] in
948+
def PseudoJIRL_CALL : Pseudo<(outs), (ins GPR:$rj, simm16_lsl2:$imm16)>,
949+
PseudoInstExpansion<(JIRL R1, GPR:$rj,
950+
simm16_lsl2:$imm16)>;
951+
947952
let isBarrier = 1, isReturn = 1, isTerminator = 1 in
948953
def PseudoRET : Pseudo<(outs), (ins), [(loongarch_ret)]>,
949954
PseudoInstExpansion<(JIRL R0, R1, 0)>;
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
2+
; RUN: llc --mtriple=loongarch64 --code-model=small < %s | \
3+
; RUN: FileCheck --check-prefix=SMALL %s
4+
; RUN: llc --mtriple=loongarch64 --code-model=medium < %s | \
5+
; RUN: FileCheck --check-prefix=MEDIUM %s
6+
7+
declare void @llvm.memset.p0.i64(ptr, i8, i64, i1)
8+
declare i32 @callee(i32)
9+
10+
define i32 @call_globaladdress(i32 %a) nounwind {
11+
; SMALL-LABEL: call_globaladdress:
12+
; SMALL: # %bb.0:
13+
; SMALL-NEXT: addi.d $sp, $sp, -16
14+
; SMALL-NEXT: st.d $ra, $sp, 8 # 8-byte Folded Spill
15+
; SMALL-NEXT: bl %plt(callee)
16+
; SMALL-NEXT: ld.d $ra, $sp, 8 # 8-byte Folded Reload
17+
; SMALL-NEXT: addi.d $sp, $sp, 16
18+
; SMALL-NEXT: ret
19+
;
20+
; MEDIUM-LABEL: call_globaladdress:
21+
; MEDIUM: # %bb.0:
22+
; MEDIUM-NEXT: addi.d $sp, $sp, -16
23+
; MEDIUM-NEXT: st.d $ra, $sp, 8 # 8-byte Folded Spill
24+
; MEDIUM-NEXT: pcalau12i $ra, %pc_hi20(callee)
25+
; MEDIUM-NEXT: jirl $ra, $ra, %pc_lo12(callee)
26+
; MEDIUM-NEXT: ld.d $ra, $sp, 8 # 8-byte Folded Reload
27+
; MEDIUM-NEXT: addi.d $sp, $sp, 16
28+
; MEDIUM-NEXT: ret
29+
%1 = call i32 @callee(i32 %a)
30+
ret i32 %1
31+
}
32+
33+
define void @call_external_sym(ptr %dst) {
34+
; SMALL-LABEL: call_external_sym:
35+
; SMALL: # %bb.0: # %entry
36+
; SMALL-NEXT: addi.d $sp, $sp, -16
37+
; SMALL-NEXT: .cfi_def_cfa_offset 16
38+
; SMALL-NEXT: st.d $ra, $sp, 8 # 8-byte Folded Spill
39+
; SMALL-NEXT: .cfi_offset 1, -8
40+
; SMALL-NEXT: ori $a2, $zero, 1000
41+
; SMALL-NEXT: move $a1, $zero
42+
; SMALL-NEXT: bl %plt(memset)
43+
; SMALL-NEXT: ld.d $ra, $sp, 8 # 8-byte Folded Reload
44+
; SMALL-NEXT: addi.d $sp, $sp, 16
45+
; SMALL-NEXT: ret
46+
;
47+
; MEDIUM-LABEL: call_external_sym:
48+
; MEDIUM: # %bb.0: # %entry
49+
; MEDIUM-NEXT: addi.d $sp, $sp, -16
50+
; MEDIUM-NEXT: .cfi_def_cfa_offset 16
51+
; MEDIUM-NEXT: st.d $ra, $sp, 8 # 8-byte Folded Spill
52+
; MEDIUM-NEXT: .cfi_offset 1, -8
53+
; MEDIUM-NEXT: ori $a2, $zero, 1000
54+
; MEDIUM-NEXT: move $a1, $zero
55+
; MEDIUM-NEXT: pcalau12i $ra, %pc_hi20(memset)
56+
; MEDIUM-NEXT: jirl $ra, $ra, %pc_lo12(memset)
57+
; MEDIUM-NEXT: ld.d $ra, $sp, 8 # 8-byte Folded Reload
58+
; MEDIUM-NEXT: addi.d $sp, $sp, 16
59+
; MEDIUM-NEXT: ret
60+
entry:
61+
call void @llvm.memset.p0.i64(ptr %dst, i8 0, i64 1000, i1 false)
62+
ret void
63+
}

0 commit comments

Comments
 (0)