[LoongArch] Generate PCALAU12I + JIRL instruction pair for medium codemodel
authorwanglei <wanglei@loongson.cn>
Fri, 11 Nov 2022 10:13:52 +0000 (18:13 +0800)
committerwanglei <wanglei@loongson.cn>
Fri, 11 Nov 2022 10:26:51 +0000 (18:26 +0800)
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

llvm/lib/Target/LoongArch/LoongArchExpandPseudoInsts.cpp
llvm/lib/Target/LoongArch/LoongArchInstrInfo.td
llvm/test/CodeGen/LoongArch/codemodel-medium.ll [new file with mode: 0644]

index 86c5e07..2aa2140 100644 (file)
@@ -254,7 +254,6 @@ bool LoongArchPreRAExpandPseudo::expandFunctionCALL(
   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 @@ bool LoongArchPreRAExpandPseudo::expandFunctionCALL(
   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.
index cfd726f..2a8fc40 100644 (file)
@@ -944,6 +944,11 @@ def PseudoCALLIndirect : Pseudo<(outs), (ins GPR:$rj),
                                 [(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 (file)
index 0000000..aad38bb
--- /dev/null
@@ -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
+}