[llvm-branch-commits] [llvm] [llvm][LoongArch] Add PC-relative address materialization using pcadd instructions (PR #175358)

via llvm-branch-commits llvm-branch-commits at lists.llvm.org
Sat Jan 10 08:59:14 PST 2026


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-backend-loongarch

Author: hev (heiher)

<details>
<summary>Changes</summary>

This patch adds support for PC-relative address materialization using pcadd-class relocations, covering the HI20/LO12 pair and their GOT and TLS variants (IE, LD, GD, and DESC).

Link: https://gcc.gnu.org/pipermail/gcc-patches/2025-December/703312.html

---

Patch is 115.87 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/175358.diff


32 Files Affected:

- (modified) llvm/lib/Target/LoongArch/AsmParser/LoongArchAsmParser.cpp (+133-27) 
- (modified) llvm/lib/Target/LoongArch/LoongArchExpandPseudoInsts.cpp (+153-54) 
- (modified) llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp (+14-4) 
- (modified) llvm/lib/Target/LoongArch/LoongArchInstrInfo.cpp (+40-16) 
- (modified) llvm/lib/Target/LoongArch/LoongArchInstrInfo.td (+5-1) 
- (modified) llvm/lib/Target/LoongArch/LoongArchMCInstLower.cpp (+39) 
- (modified) llvm/lib/Target/LoongArch/LoongArchMergeBaseOffset.cpp (+39-16) 
- (modified) llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchBaseInfo.h (+12) 
- (modified) llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCAsmInfo.cpp (+36) 
- (modified) llvm/test/CodeGen/LoongArch/block-address.ll (+7-5) 
- (modified) llvm/test/CodeGen/LoongArch/branch-relaxation-spill-32.ll (+5-4) 
- (modified) llvm/test/CodeGen/LoongArch/branch-relaxation.ll (+3-2) 
- (modified) llvm/test/CodeGen/LoongArch/calling-conv-ilp32d.ll (+24-16) 
- (modified) llvm/test/CodeGen/LoongArch/code-models.ll (+149-90) 
- (modified) llvm/test/CodeGen/LoongArch/ctlz-cttz-ctpop.ll (+12-8) 
- (modified) llvm/test/CodeGen/LoongArch/double-imm.ll (+42-28) 
- (modified) llvm/test/CodeGen/LoongArch/float-imm.ll (+9-6) 
- (modified) llvm/test/CodeGen/LoongArch/global-address.ll (+12-8) 
- (modified) llvm/test/CodeGen/LoongArch/inline-asm-constraint-f.ll (+3-2) 
- (modified) llvm/test/CodeGen/LoongArch/inline-asm-constraint-m.ll (+11-7) 
- (modified) llvm/test/CodeGen/LoongArch/ir-instruction/load-store.ll (+14-10) 
- (modified) llvm/test/CodeGen/LoongArch/machinelicm-address-pseudos.ll (+15-10) 
- (modified) llvm/test/CodeGen/LoongArch/merge-base-offset.ll (+132-89) 
- (modified) llvm/test/CodeGen/LoongArch/numeric-reg-names.ll (+3-2) 
- (modified) llvm/test/CodeGen/LoongArch/stack-protector-target.ll (+11-8) 
- (modified) llvm/test/CodeGen/LoongArch/tls-models.ll (+27-18) 
- (modified) llvm/test/CodeGen/LoongArch/unaligned-memcpy-inline.ll (+3-2) 
- (modified) llvm/test/CodeGen/LoongArch/vector-fp-imm.ll (+6-4) 
- (modified) llvm/test/ExecutionEngine/JITLink/LoongArch/ELF_reloc_addsub.s (+5-2) 
- (modified) llvm/test/MC/LoongArch/Basic/Integer/invalid.s (+2-2) 
- (modified) llvm/test/tools/UpdateTestChecks/update_llc_test_checks/Inputs/loongarch_generated_funcs.ll.generated.expected (+3-2) 
- (modified) llvm/test/tools/UpdateTestChecks/update_llc_test_checks/Inputs/loongarch_generated_funcs.ll.nogenerated.expected (+3-2) 


``````````diff
diff --git a/llvm/lib/Target/LoongArch/AsmParser/LoongArchAsmParser.cpp b/llvm/lib/Target/LoongArch/AsmParser/LoongArchAsmParser.cpp
index fa545f740b529..965d2e24919c6 100644
--- a/llvm/lib/Target/LoongArch/AsmParser/LoongArchAsmParser.cpp
+++ b/llvm/lib/Target/LoongArch/AsmParser/LoongArchAsmParser.cpp
@@ -38,6 +38,7 @@ class LoongArchAsmParser : public MCTargetAsmParser {
 
   SMLoc getLoc() const { return getParser().getTok().getLoc(); }
   bool is64Bit() const { return getSTI().hasFeature(LoongArch::Feature64Bit); }
+  bool has32S() const { return getSTI().hasFeature(LoongArch::Feature32S); }
   LoongArchTargetStreamer &getTargetStreamer() {
     assert(getParser().getStreamer().getTargetStreamer() &&
            "do not have a target streamer");
@@ -328,8 +329,13 @@ class LoongArchOperand : public MCParsedAsmOperand {
     bool IsValidKind =
         VK == LoongArchMCExpr::VK_None || VK == ELF::R_LARCH_PCALA_LO12 ||
         VK == ELF::R_LARCH_GOT_PC_LO12 || VK == ELF::R_LARCH_TLS_IE_PC_LO12 ||
-        VK == ELF::R_LARCH_TLS_LE_LO12_R ||
-        VK == ELF::R_LARCH_TLS_DESC_PC_LO12 || VK == ELF::R_LARCH_TLS_DESC_LD;
+        VK == ELF::R_LARCH_TLS_LE_LO12_R || VK == ELF::R_LARCH_TLS_DESC_LD ||
+        VK == ELF::R_LARCH_TLS_DESC_PC_LO12 || VK == ELF::R_LARCH_PCADD_LO12 ||
+        VK == ELF::R_LARCH_GOT_PCADD_LO12 ||
+        VK == ELF::R_LARCH_TLS_IE_PCADD_LO12 ||
+        VK == ELF::R_LARCH_TLS_LD_PCADD_LO12 ||
+        VK == ELF::R_LARCH_TLS_GD_PCADD_LO12 ||
+        VK == ELF::R_LARCH_TLS_DESC_PCADD_LO12;
     return IsConstantImm
                ? isInt<12>(Imm) && IsValidKind
                : LoongArchAsmParser::classifySymbolRef(getImm(), VK) &&
@@ -463,6 +469,27 @@ class LoongArchOperand : public MCParsedAsmOperand {
                      IsValidKind;
   }
 
+  bool isSImm20pcaddu12i() const {
+    if (!isImm())
+      return false;
+
+    int64_t Imm;
+    LoongArchMCExpr::Specifier VK = LoongArchMCExpr::VK_None;
+    bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
+    bool IsValidKind =
+        VK == LoongArchMCExpr::VK_None || VK == ELF::R_LARCH_CALL30 ||
+        VK == ELF::R_LARCH_PCADD_HI20 || VK == ELF::R_LARCH_GOT_PCADD_HI20 ||
+        VK == ELF::R_LARCH_TLS_IE_PCADD_HI20 ||
+        VK == ELF::R_LARCH_TLS_LD_PCADD_HI20 ||
+        VK == ELF::R_LARCH_TLS_GD_PCADD_HI20 ||
+        VK == ELF::R_LARCH_TLS_DESC_PCADD_HI20;
+
+    return IsConstantImm
+               ? isInt<20>(Imm) && IsValidKind
+               : LoongArchAsmParser::classifySymbolRef(getImm(), VK) &&
+                     IsValidKind;
+  }
+
   bool isSImm20pcaddu18i() const {
     if (!isImm())
       return false;
@@ -869,6 +896,7 @@ void LoongArchAsmParser::emitLAInstSeq(MCRegister DestReg, MCRegister TmpReg,
                                        SMLoc IDLoc, MCStreamer &Out,
                                        bool RelaxHint) {
   MCContext &Ctx = getContext();
+  MCSymbol *PCALabel = nullptr;
   for (LoongArchAsmParser::Inst &Inst : Insts) {
     unsigned Opc = Inst.Opc;
     auto VK = LoongArchMCExpr::Specifier(Inst.Specifier);
@@ -877,6 +905,10 @@ void LoongArchAsmParser::emitLAInstSeq(MCRegister DestReg, MCRegister TmpReg,
     switch (Opc) {
     default:
       llvm_unreachable("unexpected opcode");
+    case LoongArch::PCADDU12I:
+      PCALabel = Ctx.createNamedTempSymbol("pcadd_hi");
+      Out.emitLabel(PCALabel);
+      LLVM_FALLTHROUGH;
     case LoongArch::PCALAU12I:
     case LoongArch::LU12I_W:
       Out.emitInstruction(MCInstBuilder(Opc).addReg(DestReg).addExpr(LE),
@@ -898,6 +930,18 @@ void LoongArchAsmParser::emitLAInstSeq(MCRegister DestReg, MCRegister TmpReg,
                                 .addExpr(LE),
                             getSTI());
         continue;
+      } else if (VK == ELF::R_LARCH_PCADD_LO12 ||
+                 VK == ELF::R_LARCH_GOT_PCADD_LO12 ||
+                 VK == ELF::R_LARCH_TLS_IE_PCADD_LO12 ||
+                 VK == ELF::R_LARCH_TLS_LD_PCADD_LO12 ||
+                 VK == ELF::R_LARCH_TLS_GD_PCADD_LO12 ||
+                 VK == ELF::R_LARCH_TLS_DESC_PCADD_LO12) {
+        Out.emitInstruction(
+            MCInstBuilder(Opc).addReg(DestReg).addReg(DestReg).addExpr(
+                LoongArchMCExpr::create(MCSymbolRefExpr::create(PCALabel, Ctx),
+                                        VK, Ctx, RelaxHint)),
+            getSTI());
+        continue;
       }
       Out.emitInstruction(
           MCInstBuilder(Opc).addReg(DestReg).addReg(DestReg).addExpr(LE),
@@ -977,17 +1021,27 @@ void LoongArchAsmParser::emitLoadAddressAbs(MCInst &Inst, SMLoc IDLoc,
 void LoongArchAsmParser::emitLoadAddressPcrel(MCInst &Inst, SMLoc IDLoc,
                                               MCStreamer &Out) {
   // la.pcrel $rd, sym
-  // expands to:
+  //
+  // for la32r expands to:
+  // .Lpcadd_hi:
+  //   pcaddu12i $rd, %pcadd_hi20(sym)
+  //   addi.w    $rd, rd, %pcadd_lo12(.Lpcadd_hi)
+  //
+  // for la32s and la64 expands to:
   //   pcalau12i $rd, %pc_hi20(sym)
   //   addi.w/d  $rd, rd, %pc_lo12(sym)
   MCRegister DestReg = Inst.getOperand(0).getReg();
   const MCExpr *Symbol = Inst.getOperand(1).getExpr();
   InstSeq Insts;
+  unsigned PCAI = has32S() ? LoongArch::PCALAU12I : LoongArch::PCADDU12I;
   unsigned ADDI = is64Bit() ? LoongArch::ADDI_D : LoongArch::ADDI_W;
+  unsigned PCAIRel =
+      has32S() ? ELF::R_LARCH_PCALA_HI20 : ELF::R_LARCH_PCADD_HI20;
+  unsigned ADDIRel =
+      has32S() ? ELF::R_LARCH_PCALA_LO12 : ELF::R_LARCH_PCADD_LO12;
 
-  Insts.push_back(
-      LoongArchAsmParser::Inst(LoongArch::PCALAU12I, ELF::R_LARCH_PCALA_HI20));
-  Insts.push_back(LoongArchAsmParser::Inst(ADDI, ELF::R_LARCH_PCALA_LO12));
+  Insts.push_back(LoongArchAsmParser::Inst(PCAI, PCAIRel));
+  Insts.push_back(LoongArchAsmParser::Inst(ADDI, ADDIRel));
 
   emitLAInstSeq(DestReg, DestReg, Symbol, Insts, IDLoc, Out,
                 /*RelaxHint=*/true);
@@ -1026,7 +1080,12 @@ void LoongArchAsmParser::emitLoadAddressGot(MCInst &Inst, SMLoc IDLoc,
   MCRegister DestReg = Inst.getOperand(0).getReg();
   const MCExpr *Symbol = Inst.getOperand(1).getExpr();
   InstSeq Insts;
+  unsigned PCAI = has32S() ? LoongArch::PCALAU12I : LoongArch::PCADDU12I;
   unsigned LD = is64Bit() ? LoongArch::LD_D : LoongArch::LD_W;
+  unsigned PCAIRel =
+      has32S() ? ELF::R_LARCH_GOT_PC_HI20 : ELF::R_LARCH_GOT_PCADD_HI20;
+  unsigned LDRel =
+      has32S() ? ELF::R_LARCH_GOT_PC_LO12 : ELF::R_LARCH_GOT_PCADD_LO12;
 
   if (getSTI().hasFeature(LoongArch::LaGlobalWithAbs)) {
     // with feature: +la-glabal-with-abs
@@ -1056,12 +1115,16 @@ void LoongArchAsmParser::emitLoadAddressGot(MCInst &Inst, SMLoc IDLoc,
     emitLAInstSeq(DestReg, DestReg, Symbol, Insts, IDLoc, Out);
     return;
   }
-  // expands to:
+  // for la32r expands to:
+  // .Lpcadd_hi:
+  //   pcaddu12i $rd, %got_pcadd_hi20(sym)
+  //   ld.w      $rd, $rd, %got_pcadd_lo12(.Lpcadd_hi)
+  //
+  // for la32s and la64 expands to:
   //   pcalau12i $rd, %got_pc_hi20(sym)
   //   ld.w/d    $rd, $rd, %got_pc_lo12(sym)
-  Insts.push_back(
-      LoongArchAsmParser::Inst(LoongArch::PCALAU12I, ELF::R_LARCH_GOT_PC_HI20));
-  Insts.push_back(LoongArchAsmParser::Inst(LD, ELF::R_LARCH_GOT_PC_LO12));
+  Insts.push_back(LoongArchAsmParser::Inst(PCAI, PCAIRel));
+  Insts.push_back(LoongArchAsmParser::Inst(LD, LDRel));
 
   emitLAInstSeq(DestReg, DestReg, Symbol, Insts, IDLoc, Out,
                 /*RelaxHint=*/true);
@@ -1118,7 +1181,12 @@ void LoongArchAsmParser::emitLoadAddressTLSIE(MCInst &Inst, SMLoc IDLoc,
   MCRegister DestReg = Inst.getOperand(0).getReg();
   const MCExpr *Symbol = Inst.getOperand(1).getExpr();
   InstSeq Insts;
+  unsigned PCAI = has32S() ? LoongArch::PCALAU12I : LoongArch::PCADDU12I;
   unsigned LD = is64Bit() ? LoongArch::LD_D : LoongArch::LD_W;
+  unsigned PCAIRel =
+      has32S() ? ELF::R_LARCH_TLS_IE_PC_HI20 : ELF::R_LARCH_TLS_IE_PCADD_HI20;
+  unsigned LDRel =
+      has32S() ? ELF::R_LARCH_TLS_IE_PC_LO12 : ELF::R_LARCH_TLS_IE_PCADD_LO12;
 
   if (getSTI().hasFeature(LoongArch::LaGlobalWithAbs)) {
     // with feature: +la-glabal-with-abs
@@ -1149,12 +1217,16 @@ void LoongArchAsmParser::emitLoadAddressTLSIE(MCInst &Inst, SMLoc IDLoc,
     return;
   }
 
-  // expands to:
+  // for la32r expands to:
+  // .Lpcadd_hi:
+  //   pcaddu12i $rd, %ie_pcadd_hi20(sym)
+  //   ld.w      $rd, $rd, %ie_pcadd_lo12(.Lpcadd_hi)
+  //
+  // for la32s and la64 expands to:
   //   pcalau12i $rd, %ie_pc_hi20(sym)
   //   ld.w/d    $rd, $rd, %ie_pc_lo12(sym)
-  Insts.push_back(LoongArchAsmParser::Inst(LoongArch::PCALAU12I,
-                                           ELF::R_LARCH_TLS_IE_PC_HI20));
-  Insts.push_back(LoongArchAsmParser::Inst(LD, ELF::R_LARCH_TLS_IE_PC_LO12));
+  Insts.push_back(LoongArchAsmParser::Inst(PCAI, PCAIRel));
+  Insts.push_back(LoongArchAsmParser::Inst(LD, LDRel));
 
   emitLAInstSeq(DestReg, DestReg, Symbol, Insts, IDLoc, Out,
                 /*RelaxHint=*/true);
@@ -1193,7 +1265,12 @@ void LoongArchAsmParser::emitLoadAddressTLSLD(MCInst &Inst, SMLoc IDLoc,
   MCRegister DestReg = Inst.getOperand(0).getReg();
   const MCExpr *Symbol = Inst.getOperand(1).getExpr();
   InstSeq Insts;
+  unsigned PCAI = has32S() ? LoongArch::PCALAU12I : LoongArch::PCADDU12I;
   unsigned ADDI = is64Bit() ? LoongArch::ADDI_D : LoongArch::ADDI_W;
+  unsigned PCAIRel =
+      has32S() ? ELF::R_LARCH_TLS_LD_PC_HI20 : ELF::R_LARCH_TLS_LD_PCADD_HI20;
+  unsigned ADDIRel =
+      has32S() ? ELF::R_LARCH_GOT_PC_LO12 : ELF::R_LARCH_TLS_LD_PCADD_LO12;
 
   if (getSTI().hasFeature(LoongArch::LaGlobalWithAbs)) {
     // with feature: +la-glabal-with-abs
@@ -1221,12 +1298,16 @@ void LoongArchAsmParser::emitLoadAddressTLSLD(MCInst &Inst, SMLoc IDLoc,
     return;
   }
 
-  // expands to:
+  // for la32r expands to:
+  // .Lpcadd_hi:
+  //   pcaddu12i $rd, %ld_pcadd_hi20(sym)
+  //   addi.w    $rd, $rd, %ld_pcadd_lo12(.Lpcadd_hi)
+  //
+  // for la32s and la64 expands to:
   //   pcalau12i $rd, %ld_pc_hi20(sym)
   //   addi.w/d  $rd, $rd, %got_pc_lo12(sym)
-  Insts.push_back(LoongArchAsmParser::Inst(LoongArch::PCALAU12I,
-                                           ELF::R_LARCH_TLS_LD_PC_HI20));
-  Insts.push_back(LoongArchAsmParser::Inst(ADDI, ELF::R_LARCH_GOT_PC_LO12));
+  Insts.push_back(LoongArchAsmParser::Inst(PCAI, PCAIRel));
+  Insts.push_back(LoongArchAsmParser::Inst(ADDI, ADDIRel));
 
   emitLAInstSeq(DestReg, DestReg, Symbol, Insts, IDLoc, Out,
                 /*RelaxHint=*/true);
@@ -1265,7 +1346,12 @@ void LoongArchAsmParser::emitLoadAddressTLSGD(MCInst &Inst, SMLoc IDLoc,
   MCRegister DestReg = Inst.getOperand(0).getReg();
   const MCExpr *Symbol = Inst.getOperand(1).getExpr();
   InstSeq Insts;
+  unsigned PCAI = has32S() ? LoongArch::PCALAU12I : LoongArch::PCADDU12I;
   unsigned ADDI = is64Bit() ? LoongArch::ADDI_D : LoongArch::ADDI_W;
+  unsigned PCAIRel =
+      has32S() ? ELF::R_LARCH_TLS_GD_PC_HI20 : ELF::R_LARCH_TLS_GD_PCADD_HI20;
+  unsigned ADDIRel =
+      has32S() ? ELF::R_LARCH_GOT_PC_LO12 : ELF::R_LARCH_TLS_GD_PCADD_LO12;
 
   if (getSTI().hasFeature(LoongArch::LaGlobalWithAbs)) {
     // with feature: +la-glabal-with-abs
@@ -1293,12 +1379,16 @@ void LoongArchAsmParser::emitLoadAddressTLSGD(MCInst &Inst, SMLoc IDLoc,
     return;
   }
 
-  // expands to:
+  // for la32r expands to:
+  // .Lpcadd_hi:
+  //   pcaddu12i $rd, %gd_pcadd_hi20(sym)
+  //   addi.w    $rd, $rd, %gd_pcadd_lo12(.Lpcadd_hi)
+  //
+  // for la32s and la64 expands to:
   //   pcalau12i $rd, %gd_pc_hi20(sym)
   //   addi.w/d  $rd, $rd, %got_pc_lo12(sym)
-  Insts.push_back(LoongArchAsmParser::Inst(LoongArch::PCALAU12I,
-                                           ELF::R_LARCH_TLS_GD_PC_HI20));
-  Insts.push_back(LoongArchAsmParser::Inst(ADDI, ELF::R_LARCH_GOT_PC_LO12));
+  Insts.push_back(LoongArchAsmParser::Inst(PCAI, PCAIRel));
+  Insts.push_back(LoongArchAsmParser::Inst(ADDI, ADDIRel));
 
   emitLAInstSeq(DestReg, DestReg, Symbol, Insts, IDLoc, Out,
                 /*RelaxHint=*/true);
@@ -1336,8 +1426,13 @@ void LoongArchAsmParser::emitLoadAddressTLSDesc(MCInst &Inst, SMLoc IDLoc,
   // la.tls.desc $rd, sym
   MCRegister DestReg = Inst.getOperand(0).getReg();
   const MCExpr *Symbol = Inst.getOperand(1).getExpr();
+  unsigned PCAI = has32S() ? LoongArch::PCALAU12I : LoongArch::PCADDU12I;
   unsigned ADDI = is64Bit() ? LoongArch::ADDI_D : LoongArch::ADDI_W;
   unsigned LD = is64Bit() ? LoongArch::LD_D : LoongArch::LD_W;
+  unsigned PCAIRel = has32S() ? ELF::R_LARCH_TLS_DESC_PC_HI20
+                              : ELF::R_LARCH_TLS_DESC_PCADD_HI20;
+  unsigned ADDIRel = has32S() ? ELF::R_LARCH_TLS_DESC_PC_LO12
+                              : ELF::R_LARCH_TLS_DESC_PCADD_LO12;
   InstSeq Insts;
 
   if (getSTI().hasFeature(LoongArch::LaGlobalWithAbs)) {
@@ -1375,15 +1470,20 @@ void LoongArchAsmParser::emitLoadAddressTLSDesc(MCInst &Inst, SMLoc IDLoc,
     return;
   }
 
-  // expands to:
+  // for la32r expands to:
+  // .Lpcadd_hi:
+  //   pcaddu12i $rd, %desc_pcadd_hi20(sym)
+  //   addi.w    $rd, $rd, %desc_pcadd_lo12(.Lpcadd_hi)
+  //   ld.w      $ra, $rd, %desc_ld(sym)
+  //   jirl      $ra, $ra, %desc_call(sym)
+  //
+  // for la32s and la64 expands to:
   //   pcalau12i $rd, %desc_pc_hi20(sym)
   //   addi.w/d  $rd, $rd, %desc_pc_lo12(sym)
   //   ld.w/d    $ra, $rd, %desc_ld(sym)
   //   jirl      $ra, $ra, %desc_call(sym)
-  Insts.push_back(LoongArchAsmParser::Inst(LoongArch::PCALAU12I,
-                                           ELF::R_LARCH_TLS_DESC_PC_HI20));
-  Insts.push_back(
-      LoongArchAsmParser::Inst(ADDI, ELF::R_LARCH_TLS_DESC_PC_LO12));
+  Insts.push_back(LoongArchAsmParser::Inst(PCAI, PCAIRel));
+  Insts.push_back(LoongArchAsmParser::Inst(ADDI, ADDIRel));
   Insts.push_back(LoongArchAsmParser::Inst(LD, ELF::R_LARCH_TLS_DESC_LD));
   Insts.push_back(
       LoongArchAsmParser::Inst(LoongArch::JIRL, ELF::R_LARCH_TLS_DESC_CALL));
@@ -1874,6 +1974,12 @@ bool LoongArchAsmParser::matchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
         /*Upper=*/(1 << 19) - 1,
         "operand must be a symbol with modifier (e.g. %pc_hi20) or an integer "
         "in the range");
+  case Match_InvalidSImm20pcaddu12i:
+    return generateImmOutOfRangeError(
+        Operands, ErrorInfo, /*Lower=*/-(1 << 19),
+        /*Upper=*/(1 << 19) - 1,
+        "operand must be a symbol with modifier (e.g. %pcadd_hi20) or an "
+        "integer in the range");
   case Match_InvalidSImm20pcaddu18i:
     return generateImmOutOfRangeError(
         Operands, ErrorInfo, /*Lower=*/-(1 << 19),
diff --git a/llvm/lib/Target/LoongArch/LoongArchExpandPseudoInsts.cpp b/llvm/lib/Target/LoongArch/LoongArchExpandPseudoInsts.cpp
index 6cef279c6131c..b3167174454a3 100644
--- a/llvm/lib/Target/LoongArch/LoongArchExpandPseudoInsts.cpp
+++ b/llvm/lib/Target/LoongArch/LoongArchExpandPseudoInsts.cpp
@@ -57,11 +57,11 @@ class LoongArchPreRAExpandPseudo : public MachineFunctionPass {
   bool expandMBB(MachineBasicBlock &MBB);
   bool expandMI(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
                 MachineBasicBlock::iterator &NextMBBI);
-  bool expandPcalau12iInstPair(MachineBasicBlock &MBB,
+  bool expandPcaxxu12iInstPair(MachineBasicBlock &MBB,
                                MachineBasicBlock::iterator MBBI,
                                MachineBasicBlock::iterator &NextMBBI,
-                               unsigned FlagsHi, unsigned SecondOpcode,
-                               unsigned FlagsLo);
+                               unsigned OpcodeHi, unsigned OpcodeLo,
+                               unsigned FlagsHi, unsigned FlagsLo);
   bool expandLargeAddressLoad(MachineBasicBlock &MBB,
                               MachineBasicBlock::iterator MBBI,
                               MachineBasicBlock::iterator &NextMBBI,
@@ -177,10 +177,10 @@ bool LoongArchPreRAExpandPseudo::expandMI(
   return false;
 }
 
-bool LoongArchPreRAExpandPseudo::expandPcalau12iInstPair(
+bool LoongArchPreRAExpandPseudo::expandPcaxxu12iInstPair(
     MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
-    MachineBasicBlock::iterator &NextMBBI, unsigned FlagsHi,
-    unsigned SecondOpcode, unsigned FlagsLo) {
+    MachineBasicBlock::iterator &NextMBBI, unsigned OpcodeHi, unsigned OpcodeLo,
+    unsigned FlagsHi, unsigned FlagsLo) {
   MachineFunction *MF = MBB.getParent();
   MachineInstr &MI = *MBBI;
   DebugLoc DL = MI.getDebugLoc();
@@ -193,13 +193,24 @@ bool LoongArchPreRAExpandPseudo::expandPcalau12iInstPair(
       MF->getRegInfo().createVirtualRegister(&LoongArch::GPRRegClass);
   MachineOperand &Symbol = MI.getOperand(1);
 
-  BuildMI(MBB, MBBI, DL, TII->get(LoongArch::PCALAU12I), ScratchReg)
-      .addDisp(Symbol, 0, LoongArchII::encodeFlags(FlagsHi, EnableRelax));
+  MachineInstr *FirstMI =
+      BuildMI(MBB, MBBI, DL, TII->get(OpcodeHi), ScratchReg)
+          .addDisp(Symbol, 0, LoongArchII::encodeFlags(FlagsHi, EnableRelax));
 
-  MachineInstr *SecondMI =
-      BuildMI(MBB, MBBI, DL, TII->get(SecondOpcode), DestReg)
-          .addReg(ScratchReg)
-          .addDisp(Symbol, 0, LoongArchII::encodeFlags(FlagsLo, EnableRelax));
+  MachineInstr *SecondMI = nullptr;
+  FlagsLo = LoongArchII::encodeFlags(FlagsLo, EnableRelax);
+
+  if (OpcodeHi == LoongArch::PCALAU12I) {
+    SecondMI = BuildMI(MBB, MBBI, DL, TII->get(OpcodeLo), DestReg)
+                   .addReg(ScratchReg)
+                   .addDisp(Symbol, 0, FlagsLo);
+  } else {
+    MCSymbol *PCAddSymbol = MF->getContext().createNamedTempSymbol("pcadd_hi");
+    FirstMI->setPreInstrSymbol(*MF, PCAddSymbol);
+    SecondMI = BuildMI(MBB, MBBI, DL, TII->get(OpcodeLo), DestReg)
+                   .addReg(ScratchReg)
+                   .addSym(PCAddSymbol, FlagsLo);
+  }
 
   if (MI.hasOneMemOperand())
     SecondMI->addMemOperand(*MF, *MI.memoperands_begin());
@@ -321,13 +332,26 @@ bool LoongArchPreRAExpandPseudo::expandLoadAddressPcrel(
                                   LoongArchII::MO_PCREL_LO);
 
   // Code Sequence:
-  // pcalau12i $rd, %pc_hi20(sym)
-  // addi.w/d $rd, $rd, %pc_lo12(sym)
+  //
+  // for la32r expands to:
+  // .Lpcadd_hi:
+  //   pcaddu12i $rd, %pcadd_hi20(sym)
+  //   addi.w    $rd, $rd, %pcadd_lo12(.Lpcadd_hi)
+  //
+  // for la32s and la64 expands to:
+  //   pcalau12i $rd, %pc_hi20(sym)
+  //   addi.w/d  $rd, $rd, %pc_lo12(sym)
   MachineFunction *MF = MBB.getParent();
   const auto &STI = MF->getSubtarget<LoongArchSubtarget>();
-  unsigned SecondOpcode = STI.is64Bit() ? LoongArch::ADDI_D : LoongArch::ADDI_W;
-  return expandPcalau12iInstPair(MBB, MBBI, NextMBBI, LoongArchII::MO_PCREL_HI,
-                                 SecondOpcode, LoongArchII::MO_PCREL_LO);
+  bool Has32S = STI.hasFeature(LoongArch::Feature32S);
+  unsigned OpcodeHi = Has32S ? LoongArch::PCALAU12I : LoongArch::PCADDU12I;
+  unsigned OpcodeLo = STI.is64Bit() ? LoongArch::ADDI_D : LoongArch::ADDI_W;
+  unsigned FlagsHi =
+      Has32S ? LoongArchII::MO_PCREL_HI : LoongArchII::MO_PCADD_HI;
+  unsigned FlagsLo =
+      Has32S ? LoongArchII::MO_PCREL_LO : LoongArchII::MO_PCADD_LO;
+  return expandPcaxxu12iInstPair(MBB, MBBI, NextMBBI, OpcodeHi, OpcodeLo,
+                                 FlagsHi, FlagsLo);
 }
 
 bool LoongArchPreRAExpandPseudo::expandLoadAddressGot(
@@ -340,13 +364,26 @@ bool LoongArchPreRAExpandPseudo::expandLoadAddressGot(
                                   LoongArchII::MO_GOT_PC_HI);
 
   // Code Sequence:
-  // pcalau12i $rd, %got_pc_hi20(sym)
-  // ld.w/d $rd, $rd, %got_pc_lo12(sym)
+  //
+  // for la32r expands to:
+  // .Lpcadd_hi:
+  //   pcaddu12i $rd, %got_pcadd_hi20(sym)
+  //   ld.w      $rd, $rd, %got_pcadd_lo12(.Lpcadd_hi)
+  //
+  // for la32s and la64 expands to:
+  //   pcalau12i $rd, %got_pc_hi20(sym)
+  //   ld.w/d    $rd, $rd, %got_pc_lo12(sym)
   MachineFunction *MF = MBB.getParent();
   const auto &STI = MF->getSubtarget<LoongArchSubtarget>();
-  unsigned SecondOpcode = STI.is64Bit() ? LoongArch::LD_D : LoongArch::LD_W;
-  return expandPcalau12iInstPair(MBB, MBBI, NextMBBI, LoongArchII::MO_GOT_PC_HI,
-                                 SecondOpcode, LoongArchII::MO_GOT_PC_LO);
+  bool Has32S = STI.hasFeature(LoongArch::Feature32S);
+  unsigned OpcodeHi = Has32S ? LoongArch::PCALAU12I : LoongArch::PCADDU12I;
+  unsigned OpcodeLo = STI.is64Bit() ? LoongArch::LD_D : LoongArch::LD_W;
+  unsigned FlagsHi =
+      Has32S ? LoongArchII::MO_GOT_PC_HI : LoongArchII::MO_GOT_PCADD_HI;
+  unsigned FlagsLo =
+      Has32S ? LoongArchII::MO_GOT_PC_LO ...
[truncated]

``````````

</details>


https://github.com/llvm/llvm-project/pull/175358


More information about the llvm-branch-commits mailing list