diff --git a/llvm/lib/Target/LoongArch/LoongArchExpandPseudoInsts.cpp b/llvm/lib/Target/LoongArch/LoongArchExpandPseudoInsts.cpp --- a/llvm/lib/Target/LoongArch/LoongArchExpandPseudoInsts.cpp +++ b/llvm/lib/Target/LoongArch/LoongArchExpandPseudoInsts.cpp @@ -254,7 +254,6 @@ const MachineOperand &Func = MI.getOperand(0); MachineInstrBuilder CALL; - // TODO: CodeModel::Medium switch (MF->getTarget().getCodeModel()) { default: report_fatal_error("Unsupported code model"); @@ -262,6 +261,25 @@ case CodeModel::Small: // Default CodeModel. CALL = BuildMI(MBB, MBBI, DL, TII->get(LoongArch::BL)).add(Func); break; + case CodeModel::Medium: { + // pcalau12i $ra, %pc_hi20(func) + // jirl $ra, $ra, %pc_lo12(func) + MachineInstrBuilder MIB = + BuildMI(MBB, MBBI, DL, TII->get(LoongArch::PCALAU12I), LoongArch::R1); + CALL = BuildMI(MBB, MBBI, DL, TII->get(LoongArch::PseudoJIRL_CALL)) + .addReg(LoongArch::R1); + if (Func.isSymbol()) { + const char *FnName = Func.getSymbolName(); + MIB.addExternalSymbol(FnName, LoongArchII::MO_PCREL_HI); + CALL.addExternalSymbol(FnName, LoongArchII::MO_PCREL_LO); + break; + } + assert(Func.isGlobal() && "Expected a GlobalValue at this time"); + const GlobalValue *GV = Func.getGlobal(); + MIB.addGlobalAddress(GV, 0, LoongArchII::MO_PCREL_HI); + CALL.addGlobalAddress(GV, 0, LoongArchII::MO_PCREL_LO); + break; + } } // Transfer implicit operands. diff --git a/llvm/lib/Target/LoongArch/LoongArchInstrInfo.td b/llvm/lib/Target/LoongArch/LoongArchInstrInfo.td --- a/llvm/lib/Target/LoongArch/LoongArchInstrInfo.td +++ b/llvm/lib/Target/LoongArch/LoongArchInstrInfo.td @@ -937,6 +937,11 @@ [(loongarch_call GPR:$rj)]>, PseudoInstExpansion<(JIRL R1, GPR:$rj, 0)>; +let isCall = 1, Defs = [R1] in +def PseudoJIRL_CALL : Pseudo<(outs), (ins GPR:$rj, simm16_lsl2:$imm16)>, + PseudoInstExpansion<(JIRL R1, GPR:$rj, + simm16_lsl2:$imm16)>; + let isBarrier = 1, isReturn = 1, isTerminator = 1 in def PseudoRET : Pseudo<(outs), (ins), [(loongarch_ret)]>, PseudoInstExpansion<(JIRL R0, R1, 0)>; diff --git a/llvm/test/CodeGen/LoongArch/codemodel-medium.ll b/llvm/test/CodeGen/LoongArch/codemodel-medium.ll new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/LoongArch/codemodel-medium.ll @@ -0,0 +1,63 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc --mtriple=loongarch64 --code-model=small < %s | \ +; RUN: FileCheck --check-prefix=SMALL %s +; RUN: llc --mtriple=loongarch64 --code-model=medium < %s | \ +; RUN: FileCheck --check-prefix=MEDIUM %s + +declare void @llvm.memset.p0.i64(ptr, i8, i64, i1) +declare i32 @callee(i32) + +define i32 @call_globaladdress(i32 %a) nounwind { +; SMALL-LABEL: call_globaladdress: +; SMALL: # %bb.0: +; SMALL-NEXT: addi.d $sp, $sp, -16 +; SMALL-NEXT: st.d $ra, $sp, 8 # 8-byte Folded Spill +; SMALL-NEXT: bl %plt(callee) +; SMALL-NEXT: ld.d $ra, $sp, 8 # 8-byte Folded Reload +; SMALL-NEXT: addi.d $sp, $sp, 16 +; SMALL-NEXT: ret +; +; MEDIUM-LABEL: call_globaladdress: +; MEDIUM: # %bb.0: +; MEDIUM-NEXT: addi.d $sp, $sp, -16 +; MEDIUM-NEXT: st.d $ra, $sp, 8 # 8-byte Folded Spill +; MEDIUM-NEXT: pcalau12i $ra, %pc_hi20(callee) +; MEDIUM-NEXT: jirl $ra, $ra, %pc_lo12(callee) +; MEDIUM-NEXT: ld.d $ra, $sp, 8 # 8-byte Folded Reload +; MEDIUM-NEXT: addi.d $sp, $sp, 16 +; MEDIUM-NEXT: ret + %1 = call i32 @callee(i32 %a) + ret i32 %1 +} + +define void @call_external_sym(ptr %dst) { +; SMALL-LABEL: call_external_sym: +; SMALL: # %bb.0: # %entry +; SMALL-NEXT: addi.d $sp, $sp, -16 +; SMALL-NEXT: .cfi_def_cfa_offset 16 +; SMALL-NEXT: st.d $ra, $sp, 8 # 8-byte Folded Spill +; SMALL-NEXT: .cfi_offset 1, -8 +; SMALL-NEXT: ori $a2, $zero, 1000 +; SMALL-NEXT: move $a1, $zero +; SMALL-NEXT: bl %plt(memset) +; SMALL-NEXT: ld.d $ra, $sp, 8 # 8-byte Folded Reload +; SMALL-NEXT: addi.d $sp, $sp, 16 +; SMALL-NEXT: ret +; +; MEDIUM-LABEL: call_external_sym: +; MEDIUM: # %bb.0: # %entry +; MEDIUM-NEXT: addi.d $sp, $sp, -16 +; MEDIUM-NEXT: .cfi_def_cfa_offset 16 +; MEDIUM-NEXT: st.d $ra, $sp, 8 # 8-byte Folded Spill +; MEDIUM-NEXT: .cfi_offset 1, -8 +; MEDIUM-NEXT: ori $a2, $zero, 1000 +; MEDIUM-NEXT: move $a1, $zero +; MEDIUM-NEXT: pcalau12i $ra, %pc_hi20(memset) +; MEDIUM-NEXT: jirl $ra, $ra, %pc_lo12(memset) +; MEDIUM-NEXT: ld.d $ra, $sp, 8 # 8-byte Folded Reload +; MEDIUM-NEXT: addi.d $sp, $sp, 16 +; MEDIUM-NEXT: ret +entry: + call void @llvm.memset.p0.i64(ptr %dst, i8 0, i64 1000, i1 false) + ret void +}