[lld] [llvm] [LoongArch] Add reloc types for LA32R/LA32S (PR #146499)
via llvm-commits
llvm-commits at lists.llvm.org
Tue Jul 1 03:01:50 PDT 2025
https://github.com/heiher created https://github.com/llvm/llvm-project/pull/146499
Link: https://github.com/loongson/la-abi-specs/pull/16
Link: https://sourceware.org/pipermail/binutils/2025-April/140730.html
>From 0a256be184a2d1c770e6252322fbb36dcc3c883e Mon Sep 17 00:00:00 2001
From: WANG Rui <wangrui at loongson.cn>
Date: Tue, 13 May 2025 17:08:54 +0800
Subject: [PATCH] [LoongArch] Add reloc types for LA32R/LA32S
Link: https://github.com/loongson/la-abi-specs/pull/16
Link: https://sourceware.org/pipermail/binutils/2025-April/140730.html
---
lld/ELF/Arch/LoongArch.cpp | 38 +++
lld/ELF/InputSection.cpp | 60 ++++
lld/ELF/Relocations.cpp | 2 +-
lld/ELF/Relocations.h | 1 +
lld/test/ELF/loongarch-call30.s | 64 ++++
lld/test/ELF/loongarch-relax-align.s | 4 +-
lld/test/ELF/loongarch-relax-emit-relocs.s | 2 +-
...loongarch-relax-pc-hi20-lo12-got-symbols.s | 4 +-
lld/test/ELF/loongarch-relax-pc-hi20-lo12.s | 2 +-
lld/test/ELF/loongarch-tls-gd-edge-case.s | 4 +-
lld/test/ELF/loongarch-tls-ie.s | 19 +-
.../llvm/BinaryFormat/ELFRelocs/LoongArch.def | 11 +
.../llvm/ExecutionEngine/JITLink/loongarch.h | 316 +++++-------------
.../ExecutionEngine/JITLink/ELF_loongarch.cpp | 315 ++++++++++++++++-
.../lib/ExecutionEngine/JITLink/loongarch.cpp | 8 +-
.../AsmParser/LoongArchAsmParser.cpp | 185 ++++++++--
.../LoongArch/LoongArchExpandPseudoInsts.cpp | 205 ++++++++----
.../LoongArch/LoongArchISelLowering.cpp | 19 +-
.../Target/LoongArch/LoongArchInstrInfo.cpp | 50 ++-
.../Target/LoongArch/LoongArchInstrInfo.td | 29 +-
.../Target/LoongArch/LoongArchMCInstLower.cpp | 21 ++
.../LoongArch/LoongArchMergeBaseOffset.cpp | 42 ++-
.../LoongArch/LoongArchTargetMachine.cpp | 2 +-
.../MCTargetDesc/LoongArchBaseInfo.h | 6 +
.../MCTargetDesc/LoongArchELFObjectWriter.cpp | 3 +
.../MCTargetDesc/LoongArchMCAsmInfo.cpp | 18 +
llvm/test/CodeGen/LoongArch/block-address.ll | 12 +-
.../LoongArch/branch-relaxation-spill-32.ll | 9 +-
.../CodeGen/LoongArch/branch-relaxation.ll | 5 +-
.../CodeGen/LoongArch/calling-conv-half.ll | 180 ++++++----
.../CodeGen/LoongArch/calling-conv-ilp32d.ll | 70 ++--
llvm/test/CodeGen/LoongArch/code-models.ll | 239 ++++++++-----
.../test/CodeGen/LoongArch/ctlz-cttz-ctpop.ll | 20 +-
llvm/test/CodeGen/LoongArch/double-imm.ll | 5 +-
llvm/test/CodeGen/LoongArch/float-imm.ll | 5 +-
.../LoongArch/fsqrt-reciprocal-estimate.ll | 265 ++++++++-------
llvm/test/CodeGen/LoongArch/global-address.ll | 20 +-
.../LoongArch/inline-asm-constraint-f.ll | 5 +-
.../LoongArch/inline-asm-constraint-m.ll | 10 +-
.../ir-instruction/double-convert.ll | 10 +-
.../LoongArch/ir-instruction/float-convert.ll | 15 +-
.../LoongArch/ir-instruction/load-store.ll | 24 +-
.../LoongArch/machinelicm-address-pseudos.ll | 15 +-
.../CodeGen/LoongArch/merge-base-offset.ll | 221 +++++++-----
.../CodeGen/LoongArch/numeric-reg-names.ll | 5 +-
llvm/test/CodeGen/LoongArch/tls-models.ll | 35 +-
.../LoongArch/unaligned-memcpy-inline.ll | 5 +-
llvm/test/CodeGen/LoongArch/vector-fp-imm.ll | 105 +++---
.../JITLink/LoongArch/ELF_reloc_addsub.s | 7 +-
.../test/MC/LoongArch/Basic/Integer/invalid.s | 4 +-
...arch_generated_funcs.ll.generated.expected | 5 +-
...ch_generated_funcs.ll.nogenerated.expected | 5 +-
.../ELF/reloc-types-loongarch64.test | 2 +
.../ExecutionEngine/JITLink/StubsTests.cpp | 16 +-
llvm/unittests/Object/ELFTest.cpp | 2 +
55 files changed, 1816 insertions(+), 935 deletions(-)
create mode 100644 lld/test/ELF/loongarch-call30.s
diff --git a/lld/ELF/Arch/LoongArch.cpp b/lld/ELF/Arch/LoongArch.cpp
index 3c4ad53af1b51..fa79c8df39f1b 100644
--- a/lld/ELF/Arch/LoongArch.cpp
+++ b/lld/ELF/Arch/LoongArch.cpp
@@ -161,6 +161,10 @@ static uint32_t setJ5(uint32_t insn, uint32_t imm) {
return (insn & 0xfffffc1f) | (extractBits(imm, 4, 0) << 5);
}
+static uint32_t setK10(uint32_t insn, uint32_t imm) {
+ return (insn & 0xffc003ff) | (extractBits(imm, 9, 0) << 10);
+}
+
static uint32_t setK12(uint32_t insn, uint32_t imm) {
return (insn & 0xffc003ff) | (extractBits(imm, 11, 0) << 10);
}
@@ -416,6 +420,8 @@ RelExpr LoongArch::getRelExpr(const RelType type, const Symbol &s,
// [1]: https://sourceware.org/git/?p=glibc.git;a=commitdiff;h=9f482b73f41a9a1bbfb173aad0733d1c824c788a
// [2]: https://github.com/loongson/la-abi-specs/pull/3
return isJirl(read32le(loc)) ? R_PLT : R_ABS;
+ case R_LARCH_PCADD_LO12_I:
+ return RE_LOONGARCH_PC_INDIRECT;
case R_LARCH_TLS_DTPREL32:
case R_LARCH_TLS_DTPREL64:
return R_DTPREL;
@@ -446,10 +452,12 @@ RelExpr LoongArch::getRelExpr(const RelType type, const Symbol &s,
case R_LARCH_32_PCREL:
case R_LARCH_64_PCREL:
case R_LARCH_PCREL20_S2:
+ case R_LARCH_PCADD_HI20:
return R_PC;
case R_LARCH_B16:
case R_LARCH_B21:
case R_LARCH_B26:
+ case R_LARCH_CALL30:
case R_LARCH_CALL36:
return R_PLT_PC;
case R_LARCH_GOT_PC_HI20:
@@ -459,6 +467,9 @@ RelExpr LoongArch::getRelExpr(const RelType type, const Symbol &s,
case R_LARCH_TLS_IE64_PC_LO20:
case R_LARCH_TLS_IE64_PC_HI12:
return RE_LOONGARCH_GOT_PAGE_PC;
+ case R_LARCH_PCADD_GOT_HI20:
+ case R_LARCH_PCADD_TLS_IE_HI20:
+ return R_GOT_PC;
case R_LARCH_GOT_PC_LO12:
case R_LARCH_TLS_IE_PC_LO12:
return RE_LOONGARCH_GOT;
@@ -522,6 +533,7 @@ RelExpr LoongArch::getRelExpr(const RelType type, const Symbol &s,
case R_LARCH_TLS_DESC_LO12:
case R_LARCH_TLS_DESC64_LO20:
case R_LARCH_TLS_DESC64_HI12:
+ case R_LARCH_PCADD_TLS_DESC_HI20:
return R_TLSDESC;
case R_LARCH_TLS_DESC_CALL:
return R_TLSDESC_CALL;
@@ -605,6 +617,22 @@ void LoongArch::relocate(uint8_t *loc, const Relocation &rel,
write32le(loc, setD10k16(read32le(loc), val >> 2));
return;
+ case R_LARCH_CALL30: {
+ // This relocation is designed for adjacent pcaddu12i+jirl pairs that
+ // are patched in one time.
+ // The relocation range is [-4G, +4G) (of course must be 4-byte aligned).
+ if ((int64_t)val != llvm::SignExtend64(val, 32))
+ reportRangeError(ctx, loc, rel, Twine(val), llvm::minIntN(32),
+ llvm::maxIntN(32));
+ checkAlignment(ctx, loc, val, 4, rel);
+ uint32_t hi20 = extractBits(val, 31, 12);
+ // Despite the name, the lower part is actually 12 bits with 4-byte aligned.
+ uint32_t lo10 = extractBits(val, 11, 2);
+ write32le(loc, setJ20(read32le(loc), hi20));
+ write32le(loc + 4, setK10(read32le(loc + 4), lo10));
+ return;
+ }
+
case R_LARCH_CALL36: {
// This relocation is designed for adjacent pcaddu18i+jirl pairs that
// are patched in one time. Because of sign extension of these insns'
@@ -648,6 +676,7 @@ void LoongArch::relocate(uint8_t *loc, const Relocation &rel,
case R_LARCH_TLS_LE_LO12_R:
case R_LARCH_TLS_DESC_PC_LO12:
case R_LARCH_TLS_DESC_LO12:
+ case R_LARCH_PCADD_LO12_I:
write32le(loc, setK12(read32le(loc), extractBits(val, 11, 0)));
return;
@@ -667,6 +696,15 @@ void LoongArch::relocate(uint8_t *loc, const Relocation &rel,
case R_LARCH_TLS_DESC_HI20:
write32le(loc, setJ20(read32le(loc), extractBits(val, 31, 12)));
return;
+ case R_LARCH_PCADD_HI20:
+ case R_LARCH_PCADD_GOT_HI20:
+ case R_LARCH_PCADD_TLS_IE_HI20:
+ case R_LARCH_PCADD_TLS_DESC_HI20: {
+ uint64_t hi = val + 0x800;
+ checkInt(ctx, loc, SignExtend64(hi, 32) >> 12, 20, rel);
+ write32le(loc, setJ20(read32le(loc), extractBits(hi, 31, 12)));
+ return;
+ }
case R_LARCH_TLS_LE_HI20_R:
write32le(loc, setJ20(read32le(loc), extractBits(val + 0x800, 31, 12)));
return;
diff --git a/lld/ELF/InputSection.cpp b/lld/ELF/InputSection.cpp
index f8786265029e8..777209d5b20cf 100644
--- a/lld/ELF/InputSection.cpp
+++ b/lld/ELF/InputSection.cpp
@@ -713,6 +713,61 @@ static Relocation *getRISCVPCRelHi20(Ctx &ctx, const InputSectionBase *loSec,
return nullptr;
}
+// For RE_LARCH_PC_INDIRECT (R_LARCH_PCADD_LO12_I), the symbol actually
+// points the corresponding R_LARCH_PCADD_*_HI20 relocation, and the target VA
+// is calculated using PCADD_HI20's symbol.
+//
+// This function returns the R_LARCH_PCADD_*_HI20 relocation from the
+// R_LARCH_PCADD_LO12 relocation.
+static Relocation *getLoongArchPCAddHi20(Ctx &ctx,
+ const InputSectionBase *loSec,
+ const Relocation &loReloc) {
+ int64_t addend = loReloc.addend;
+ Symbol *sym = loReloc.sym;
+
+ const Defined *d = cast<Defined>(sym);
+ if (!d->section) {
+ Err(ctx) << loSec->getLocation(loReloc.offset)
+ << ": R_LARCH_PCADD_LO12 relocation points to an absolute symbol: "
+ << sym->getName();
+ return nullptr;
+ }
+ InputSection *hiSec = cast<InputSection>(d->section);
+
+ if (hiSec != loSec)
+ Err(ctx) << loSec->getLocation(loReloc.offset)
+ << ": R_LARCH_PCADD_LO12 relocation points to a symbol '"
+ << sym->getName() << "' in a different section '" << hiSec->name
+ << "'";
+
+ if (addend != 0)
+ Warn(ctx) << loSec->getLocation(loReloc.offset)
+ << ": non-zero addend in R_LARCH_PCADD_LO12 relocation to "
+ << hiSec->getObjMsg(d->value) << " is ignored";
+
+ // Relocations are sorted by offset, so we can use std::equal_range to do
+ // binary search.
+ Relocation hiReloc;
+ hiReloc.offset = d->value + addend;
+ auto range =
+ std::equal_range(hiSec->relocs().begin(), hiSec->relocs().end(), hiReloc,
+ [](const Relocation &lhs, const Relocation &rhs) {
+ return lhs.offset < rhs.offset;
+ });
+
+ for (auto it = range.first; it != range.second; ++it)
+ if (it->type == R_LARCH_PCADD_HI20 || it->type == R_LARCH_PCADD_GOT_HI20 ||
+ it->type == R_LARCH_PCADD_TLS_IE_HI20 ||
+ it->type == R_LARCH_PCADD_TLS_DESC_HI20)
+ return &*it;
+
+ Err(ctx) << loSec->getLocation(loReloc.offset)
+ << ": R_LARCH_PCADD_LO12 relocation points to "
+ << hiSec->getObjMsg(d->value)
+ << " without an associated R_LARCH_PCADD_HI20 relocation";
+ return nullptr;
+}
+
// A TLS symbol's virtual address is relative to the TLS segment. Add a
// target-specific adjustment to produce a thread-pointer-relative offset.
static int64_t getTlsTpOffset(Ctx &ctx, const Symbol &s) {
@@ -884,6 +939,11 @@ uint64_t InputSectionBase::getRelocTargetVA(Ctx &ctx, const Relocation &r,
return getRelocTargetVA(ctx, *hiRel, r.sym->getVA(ctx));
return 0;
}
+ case RE_LOONGARCH_PC_INDIRECT: {
+ if (const Relocation *hiRel = getLoongArchPCAddHi20(ctx, this, r))
+ return getRelocTargetVA(ctx, *hiRel, r.sym->getVA(ctx, a));
+ return 0;
+ }
case RE_LOONGARCH_PAGE_PC:
return getLoongArchPageDelta(r.sym->getVA(ctx, a), p, r.type);
case R_PC:
diff --git a/lld/ELF/Relocations.cpp b/lld/ELF/Relocations.cpp
index 43f19186f0981..5b12f40c8d5fc 100644
--- a/lld/ELF/Relocations.cpp
+++ b/lld/ELF/Relocations.cpp
@@ -210,7 +210,7 @@ static bool isRelExpr(RelExpr expr) {
return oneof<R_PC, R_GOTREL, R_GOTPLTREL, RE_ARM_PCA, RE_MIPS_GOTREL,
RE_PPC64_CALL, RE_PPC64_RELAX_TOC, RE_AARCH64_PAGE_PC,
R_RELAX_GOT_PC, RE_RISCV_PC_INDIRECT, RE_PPC64_RELAX_GOT_PC,
- RE_LOONGARCH_PAGE_PC>(expr);
+ RE_LOONGARCH_PAGE_PC, RE_LOONGARCH_PC_INDIRECT>(expr);
}
static RelExpr toPlt(RelExpr expr) {
diff --git a/lld/ELF/Relocations.h b/lld/ELF/Relocations.h
index d2a77bc953109..3213c9387606e 100644
--- a/lld/ELF/Relocations.h
+++ b/lld/ELF/Relocations.h
@@ -129,6 +129,7 @@ enum RelExpr {
// also reused for TLS, making the semantics differ from other architectures.
RE_LOONGARCH_GOT,
RE_LOONGARCH_GOT_PAGE_PC,
+ RE_LOONGARCH_PC_INDIRECT,
RE_LOONGARCH_TLSGD_PAGE_PC,
RE_LOONGARCH_TLSDESC_PAGE_PC,
};
diff --git a/lld/test/ELF/loongarch-call30.s b/lld/test/ELF/loongarch-call30.s
new file mode 100644
index 0000000000000..907e8704e908b
--- /dev/null
+++ b/lld/test/ELF/loongarch-call30.s
@@ -0,0 +1,64 @@
+# REQUIRES: loongarch
+
+# RUN: rm -rf %t && split-file %s %t
+# RUN: llvm-mc --filetype=obj --triple=loongarch32-unknown-elf %t/a.s -o %t/a.o
+
+# RUN: ld.lld %t/a.o --section-start=.text=0x20010 --section-start=.sec.foo=0x21020 -o %t/exe1
+# RUN: llvm-objdump --no-show-raw-insn -d %t/exe1 | FileCheck --match-full-lines %s --check-prefix=EXE1
+## hi20 = target - pc >> 12 = 0x21020 - 0x20010 >> 12 = 1
+## lo12 = target - pc & (1 << 12) - 1 = 0x21020 - 0x20010 & 0xfff = 16
+# EXE1: 20010: pcaddu12i $t0, 1
+# EXE1-NEXT: 20014: jirl $zero, $t0, 16
+
+# RUN: ld.lld %t/a.o --section-start=.text=0x20010 --section-start=.sec.foo=0x21820 -o %t/exe2
+# RUN: llvm-objdump --no-show-raw-insn -d %t/exe2 | FileCheck --match-full-lines %s --check-prefix=EXE2
+## hi20 = target - pc >> 12 = 0x21820 - 0x20010 >> 12 = 1
+## lo12 = target - pc & (1 << 12) - 1 = 0x21820 - 0x20010 & 0xfff = 2064
+# EXE2: 20010: pcaddu12i $t0, 1
+# EXE2-NEXT: 20014: jirl $zero, $t0, 2064
+
+# RUN: ld.lld %t/a.o -shared -T %t/a.t -o %t/a.so
+# RUN: llvm-readelf -x .got.plt %t/a.so | FileCheck --check-prefix=GOTPLT %s
+# RUN: llvm-objdump -d --no-show-raw-insn %t/a.so | FileCheck --check-prefix=SO %s
+## PLT should be present in this case.
+# SO: Disassembly of section .plt:
+# SO: <.plt>:
+## foo at plt:
+# SO: 1234520: pcaddu12i $t3, 64{{$}}
+# SO-NEXT: ld.w $t3, $t3, 444{{$}}
+# SO-NEXT: jirl $t1, $t3, 0
+# SO-NEXT: nop
+
+# SO: Disassembly of section .text:
+# SO: <_start>:
+## hi20 = foo at plt - pc >> 12 = 0x1234520 - 0x1274670 >> 12 = -65
+## lo18 = foo at plt - pc & (1 << 12) - 1 = 0x1234520 - 0x1274670 & 0xfff = 3760
+# SO-NEXT: pcaddu12i $t0, -65{{$}}
+# SO-NEXT: jirl $zero, $t0, 3760{{$}}
+
+# GOTPLT: section '.got.plt':
+# GOTPLT-NEXT: 0x012746d4 00000000 00000000 00452301
+
+## Impossible case in reality becasue all LoongArch instructions are fixed 4-bytes long.
+# RUN: not ld.lld %t/a.o --section-start=.text=0x20000 --section-start=.sec.foo=0x40001 -o /dev/null 2>&1 | \
+# RUN: FileCheck -DFILE=%t/a.o --check-prefix=ERROR-ALIGN %s
+# ERROR-ALIGN: error: [[FILE]]:(.text+0x0): improper alignment for relocation R_LARCH_CALL30: 0x20001 is not aligned to 4 bytes
+
+#--- a.t
+SECTIONS {
+ .plt 0x1234500: { *(.plt) }
+ .text 0x1274670: { *(.text) }
+}
+
+#--- a.s
+.text
+.global _start
+_start:
+ .reloc ., R_LARCH_CALL30, foo
+ pcaddu12i $t0, 0
+ jirl $zero, $t0, 0
+
+.section .sec.foo,"awx"
+.global foo
+foo:
+ ret
diff --git a/lld/test/ELF/loongarch-relax-align.s b/lld/test/ELF/loongarch-relax-align.s
index 79353f2a3be47..b9da1322a8c00 100644
--- a/lld/test/ELF/loongarch-relax-align.s
+++ b/lld/test/ELF/loongarch-relax-align.s
@@ -1,7 +1,7 @@
# REQUIRES: loongarch
-# RUN: llvm-mc --filetype=obj --triple=loongarch32 --mattr=+relax %s -o %t.32.o
-# RUN: llvm-mc --filetype=obj --triple=loongarch64 --mattr=+relax %s -o %t.64.o
+# RUN: llvm-mc --filetype=obj --triple=loongarch32 --mattr=+32s,+relax %s -o %t.32.o
+# RUN: llvm-mc --filetype=obj --triple=loongarch64 --mattr=+32s,+relax %s -o %t.64.o
# RUN: ld.lld --section-start=.text=0x10000 --section-start=.text2=0x20000 -e 0 %t.32.o -o %t.32
# RUN: ld.lld --section-start=.text=0x10000 --section-start=.text2=0x20000 -e 0 %t.64.o -o %t.64
# RUN: ld.lld --section-start=.text=0x10000 --section-start=.text2=0x20000 -e 0 --no-relax %t.32.o -o %t.32n
diff --git a/lld/test/ELF/loongarch-relax-emit-relocs.s b/lld/test/ELF/loongarch-relax-emit-relocs.s
index 909b65075a695..6e1e85c004439 100644
--- a/lld/test/ELF/loongarch-relax-emit-relocs.s
+++ b/lld/test/ELF/loongarch-relax-emit-relocs.s
@@ -1,7 +1,7 @@
# REQUIRES: loongarch
## Test that we can handle --emit-relocs while relaxing.
-# RUN: llvm-mc --filetype=obj --triple=loongarch32 --mattr=+relax %s -o %t.32.o
+# RUN: llvm-mc --filetype=obj --triple=loongarch32 --mattr=+32s,+relax %s -o %t.32.o
# RUN: llvm-mc --filetype=obj --triple=loongarch64 --mattr=+relax --defsym ELF64=1 %s -o %t.64.o
# RUN: ld.lld -Ttext=0x10000 -section-start=.got=0x20000 --emit-relocs %t.32.o -o %t.32
# RUN: ld.lld -Ttext=0x10000 -section-start=.got=0x20000 --emit-relocs %t.64.o -o %t.64
diff --git a/lld/test/ELF/loongarch-relax-pc-hi20-lo12-got-symbols.s b/lld/test/ELF/loongarch-relax-pc-hi20-lo12-got-symbols.s
index f37de8e3b7c83..fe243397af346 100644
--- a/lld/test/ELF/loongarch-relax-pc-hi20-lo12-got-symbols.s
+++ b/lld/test/ELF/loongarch-relax-pc-hi20-lo12-got-symbols.s
@@ -4,9 +4,9 @@
# REQUIRES: loongarch
# RUN: rm -rf %t && split-file %s %t && cd %t
-# RUN: llvm-mc --filetype=obj --triple=loongarch32 -mattr=+relax symbols.s -o symbols.32.o
+# RUN: llvm-mc --filetype=obj --triple=loongarch32 -mattr=+32s,+relax symbols.s -o symbols.32.o
# RUN: llvm-mc --filetype=obj --triple=loongarch64 -mattr=+relax symbols.s -o symbols.64.o
-# RUN: llvm-mc --filetype=obj --triple=loongarch32 -mattr=+relax abs.s -o abs.32.o
+# RUN: llvm-mc --filetype=obj --triple=loongarch32 -mattr=+32s,+relax abs.s -o abs.32.o
# RUN: llvm-mc --filetype=obj --triple=loongarch64 -mattr=+relax abs.s -o abs.64.o
# RUN: ld.lld --shared -Tlinker.t symbols.32.o abs.32.o -o symbols.32.so
diff --git a/lld/test/ELF/loongarch-relax-pc-hi20-lo12.s b/lld/test/ELF/loongarch-relax-pc-hi20-lo12.s
index a417d89e9fa2e..a1d6c0f7eec73 100644
--- a/lld/test/ELF/loongarch-relax-pc-hi20-lo12.s
+++ b/lld/test/ELF/loongarch-relax-pc-hi20-lo12.s
@@ -1,6 +1,6 @@
# REQUIRES: loongarch
-# RUN: llvm-mc --filetype=obj --triple=loongarch32 -mattr=+relax %s -o %t.32.o
+# RUN: llvm-mc --filetype=obj --triple=loongarch32 -mattr=+32s,+relax %s -o %t.32.o
# RUN: llvm-mc --filetype=obj --triple=loongarch64 -mattr=+relax %s -o %t.64.o
# RUN: ld.lld --section-start=.text=0x10000 --section-start=.data=0x14000 %t.32.o -o %t.32
diff --git a/lld/test/ELF/loongarch-tls-gd-edge-case.s b/lld/test/ELF/loongarch-tls-gd-edge-case.s
index 9f25f10c73b44..cfa65f91aebb8 100644
--- a/lld/test/ELF/loongarch-tls-gd-edge-case.s
+++ b/lld/test/ELF/loongarch-tls-gd-edge-case.s
@@ -24,8 +24,8 @@
# LA64-REL-NEXT: 00000000000203a8 0000000200000009 R_LARCH_TLS_DTPREL64 0000000000000000 y + 0
# LA64-REL-NEXT: 00000000000203b0 000000020000000b R_LARCH_TLS_TPREL64 0000000000000000 y + 0
-# LA32: 101d4: pcalau12i $a0, 16
-# LA32-NEXT: ld.w $a0, $a0, 580
+# LA32: 101d4: pcaddu12i $a0, 16
+# LA32-NEXT: ld.w $a0, $a0, 112
# LA32-NEXT: pcalau12i $a1, 16
# LA32-NEXT: addi.w $a1, $a1, 572
diff --git a/lld/test/ELF/loongarch-tls-ie.s b/lld/test/ELF/loongarch-tls-ie.s
index ddfd9c976cb9b..84e6672e31e05 100644
--- a/lld/test/ELF/loongarch-tls-ie.s
+++ b/lld/test/ELF/loongarch-tls-ie.s
@@ -41,11 +41,11 @@
## LA32:
## &.got[0] - . = 0x20214 - 0x101a4: 0x10 pages, page offset 0x214
## &.got[1] - . = 0x20218 - 0x101b0: 0x10 pages, page offset 0x218
-# IE32: 101a4: pcalau12i $a4, 16
-# IE32-NEXT: ld.w $a4, $a4, 532
+# IE32: 101a4: pcaddu12i $a4, 16
+# IE32-NEXT: ld.w $a4, $a4, 112
# IE32-NEXT: add.w $a4, $a4, $tp
-# IE32-NEXT: 101b0: pcalau12i $a5, 16
-# IE32-NEXT: ld.w $a5, $a5, 536
+# IE32: 101b0: pcaddu12i $a5, 16
+# IE32-NEXT: ld.w $a5, $a5, 104
# IE32-NEXT: add.w $a5, $a5, $tp
## LA64:
@@ -62,15 +62,16 @@
# a at tprel = st_value(a) = 0x8
# b at tprel = st_value(a) = 0xc
-# LE32-GOT: could not find section '.got'
+# LE32-GOT: section '.got':
+# LE32-GOT-NEXT: 0x0003012c 08000000 0c000000
# LE64-GOT: could not find section '.got'
## LA32:
-# LE32: 200d4: nop
-# LE32-NEXT: ori $a4, $zero, 8
+# LE32: 20114: pcaddu12i $a4, 16
+# LE32-NEXT: ld.w $a4, $a4, 24
# LE32-NEXT: add.w $a4, $a4, $tp
-# LE32-NEXT: 200e0: nop
-# LE32-NEXT: ori $a5, $zero, 12
+# LE32: 20120: pcaddu12i $a5, 16
+# LE32-NEXT: ld.w $a5, $a5, 16
# LE32-NEXT: add.w $a5, $a5, $tp
## LA64:
diff --git a/llvm/include/llvm/BinaryFormat/ELFRelocs/LoongArch.def b/llvm/include/llvm/BinaryFormat/ELFRelocs/LoongArch.def
index 4859057abcbb9..ee5f6ed8c89b4 100644
--- a/llvm/include/llvm/BinaryFormat/ELFRelocs/LoongArch.def
+++ b/llvm/include/llvm/BinaryFormat/ELFRelocs/LoongArch.def
@@ -149,3 +149,14 @@ ELF_RELOC(R_LARCH_TLS_LE_LO12_R, 123)
ELF_RELOC(R_LARCH_TLS_LD_PCREL20_S2, 124)
ELF_RELOC(R_LARCH_TLS_GD_PCREL20_S2, 125)
ELF_RELOC(R_LARCH_TLS_DESC_PCREL20_S2, 126)
+
+// Relocs added in ELF for the LoongArchâ„¢ Architecture v2025????, part of the
+// v2.40 LoongArch ABI specs.
+//
+// Spec addition: https://github.com/loongson/la-abi-specs/pull/16
+ELF_RELOC(R_LARCH_CALL30, 127)
+ELF_RELOC(R_LARCH_PCADD_HI20, 128)
+ELF_RELOC(R_LARCH_PCADD_GOT_HI20, 129)
+ELF_RELOC(R_LARCH_PCADD_TLS_IE_HI20, 130)
+ELF_RELOC(R_LARCH_PCADD_TLS_DESC_HI20, 131)
+ELF_RELOC(R_LARCH_PCADD_LO12_I, 132)
diff --git a/llvm/include/llvm/ExecutionEngine/JITLink/loongarch.h b/llvm/include/llvm/ExecutionEngine/JITLink/loongarch.h
index 04c5a67ac4fe3..1d9038a6fe2d8 100644
--- a/llvm/include/llvm/ExecutionEngine/JITLink/loongarch.h
+++ b/llvm/include/llvm/ExecutionEngine/JITLink/loongarch.h
@@ -170,6 +170,30 @@ enum EdgeKind_loongarch : Edge::Kind {
///
PageOffset12,
+ /// The upper 20 bits of the offset from the fixup to the target.
+ ///
+ /// Fixup expression:
+ /// Fixup <- (Target + Addend - Fixup + 0x800) >> 12 : int20
+ ///
+ /// Notes:
+ /// For PCADDU12I fixups.
+ ///
+ /// Errors:
+ /// - The result of the fixup expression must fit into an int20 otherwise an
+ /// out-of-range error will be returned.
+ ///
+ PCAdd20,
+
+ /// The lower 12 bits of the offset from the paired PCADDU12I (the initial
+ /// target) to the final target it points to.
+ ///
+ /// Typically used to fix up ADDI/LD_W/LD_D immediates.
+ ///
+ /// Fixup expression:
+ /// Fixup <- (FinalTarget - InitialTarget) & 0xfff : int12
+ ///
+ PCAdd12,
+
/// A GOT entry getter/constructor, transformed to Page20 pointing at the GOT
/// entry for the original target.
///
@@ -206,6 +230,49 @@ enum EdgeKind_loongarch : Edge::Kind {
///
RequestGOTAndTransformToPageOffset12,
+ /// A GOT entry getter/constructor, transformed to PCAdd20 pointing at the GOT
+ /// entry for the original target.
+ ///
+ /// Indicates that this edge should be transformed into a PCAdd20 targeting
+ /// the GOT entry for the edge's current target, maintaining the same addend.
+ /// A GOT entry for the target should be created if one does not already
+ /// exist.
+ ///
+ /// Edges of this kind are usually handled by a GOT/PLT builder pass inserted
+ /// by default.
+ ///
+ /// Fixup expression:
+ /// NONE
+ ///
+ /// Errors:
+ /// - *ASSERTION* Failure to handle edges of this kind prior to the fixup
+ /// phase will result in an assert/unreachable during the fixup phase.
+ ///
+ RequestGOTAndTransformToPCAdd20,
+
+ /// A 30-bit PC-relative call.
+ ///
+ /// Represents a PC-relative call to a target within [-4G, +4G)
+ /// The target must be 4-byte aligned. For adjacent pcaddu12i+jirl
+ /// instruction pairs.
+ ///
+ /// Fixup expression:
+ /// Fixup <- (Target - Fixup + Addend) >> 2 : int30
+ ///
+ /// Notes:
+ /// The '30' in the name refers to the number operand bits and follows the
+ /// naming convention used by the corresponding ELF relocations. Since the low
+ /// two bits must be zero (because of the 4-byte alignment of the target) the
+ /// operand is effectively a signed 32-bit number.
+ ///
+ /// Errors:
+ /// - The result of the unshifted part of the fixup expression must be
+ /// 4-byte aligned otherwise an alignment error will be returned.
+ /// - The result of the fixup expression must fit into an int30 otherwise an
+ /// out-of-range error will be returned.
+ ///
+ Call30PCRel,
+
/// A 36-bit PC-relative call.
///
/// Represents a PC-relative call to a target within [-128G - 0x20000, +128G
@@ -330,238 +397,6 @@ inline uint32_t extractBits(uint64_t Val, unsigned Hi, unsigned Lo) {
return Hi == 63 ? Val >> Lo : (Val & ((((uint64_t)1 << (Hi + 1)) - 1))) >> Lo;
}
-/// Apply fixup expression for edge to block content.
-inline Error applyFixup(LinkGraph &G, Block &B, const Edge &E) {
- using namespace support;
-
- char *BlockWorkingMem = B.getAlreadyMutableContent().data();
- char *FixupPtr = BlockWorkingMem + E.getOffset();
- uint64_t FixupAddress = (B.getAddress() + E.getOffset()).getValue();
- uint64_t TargetAddress = E.getTarget().getAddress().getValue();
- int64_t Addend = E.getAddend();
-
- switch (E.getKind()) {
- case Pointer64:
- *(ulittle64_t *)FixupPtr = TargetAddress + Addend;
- break;
- case Pointer32: {
- uint64_t Value = TargetAddress + Addend;
- if (Value > std::numeric_limits<uint32_t>::max())
- return makeTargetOutOfRangeError(G, B, E);
- *(ulittle32_t *)FixupPtr = Value;
- break;
- }
- case Branch16PCRel: {
- int64_t Value = TargetAddress - FixupAddress + Addend;
-
- if (!isInt<18>(Value))
- return makeTargetOutOfRangeError(G, B, E);
-
- if (!isShiftedInt<16, 2>(Value))
- return makeAlignmentError(orc::ExecutorAddr(FixupAddress), Value, 4, E);
-
- uint32_t RawInstr = *(little32_t *)FixupPtr;
- uint32_t Imm = static_cast<uint32_t>(Value >> 2);
- uint32_t Imm15_0 = extractBits(Imm, /*Hi=*/15, /*Lo=*/0) << 10;
- *(little32_t *)FixupPtr = RawInstr | Imm15_0;
- break;
- }
- case Branch21PCRel: {
- int64_t Value = TargetAddress - FixupAddress + Addend;
-
- if (!isInt<23>(Value))
- return makeTargetOutOfRangeError(G, B, E);
-
- if (!isShiftedInt<21, 2>(Value))
- return makeAlignmentError(orc::ExecutorAddr(FixupAddress), Value, 4, E);
-
- uint32_t RawInstr = *(little32_t *)FixupPtr;
- uint32_t Imm = static_cast<uint32_t>(Value >> 2);
- uint32_t Imm15_0 = extractBits(Imm, /*Hi=*/15, /*Lo=*/0) << 10;
- uint32_t Imm20_16 = extractBits(Imm, /*Hi=*/20, /*Lo=*/16);
- *(little32_t *)FixupPtr = RawInstr | Imm15_0 | Imm20_16;
- break;
- }
- case Branch26PCRel: {
- int64_t Value = TargetAddress - FixupAddress + Addend;
-
- if (!isInt<28>(Value))
- return makeTargetOutOfRangeError(G, B, E);
-
- if (!isShiftedInt<26, 2>(Value))
- return makeAlignmentError(orc::ExecutorAddr(FixupAddress), Value, 4, E);
-
- uint32_t RawInstr = *(little32_t *)FixupPtr;
- uint32_t Imm = static_cast<uint32_t>(Value >> 2);
- uint32_t Imm15_0 = extractBits(Imm, /*Hi=*/15, /*Lo=*/0) << 10;
- uint32_t Imm25_16 = extractBits(Imm, /*Hi=*/25, /*Lo=*/16);
- *(little32_t *)FixupPtr = RawInstr | Imm15_0 | Imm25_16;
- break;
- }
- case Delta32: {
- int64_t Value = TargetAddress - FixupAddress + Addend;
-
- if (!isInt<32>(Value))
- return makeTargetOutOfRangeError(G, B, E);
- *(little32_t *)FixupPtr = Value;
- break;
- }
- case NegDelta32: {
- int64_t Value = FixupAddress - TargetAddress + Addend;
- if (!isInt<32>(Value))
- return makeTargetOutOfRangeError(G, B, E);
- *(little32_t *)FixupPtr = Value;
- break;
- }
- case Delta64:
- *(little64_t *)FixupPtr = TargetAddress - FixupAddress + Addend;
- break;
- case Page20: {
- uint64_t Target = TargetAddress + Addend;
- uint64_t TargetPage =
- (Target + (Target & 0x800)) & ~static_cast<uint64_t>(0xfff);
- uint64_t PCPage = FixupAddress & ~static_cast<uint64_t>(0xfff);
-
- int64_t PageDelta = TargetPage - PCPage;
- if (!isInt<32>(PageDelta))
- return makeTargetOutOfRangeError(G, B, E);
-
- uint32_t RawInstr = *(little32_t *)FixupPtr;
- uint32_t Imm31_12 = extractBits(PageDelta, /*Hi=*/31, /*Lo=*/12) << 5;
- *(little32_t *)FixupPtr = RawInstr | Imm31_12;
- break;
- }
- case PageOffset12: {
- uint64_t TargetOffset = (TargetAddress + Addend) & 0xfff;
-
- uint32_t RawInstr = *(ulittle32_t *)FixupPtr;
- uint32_t Imm11_0 = TargetOffset << 10;
- *(ulittle32_t *)FixupPtr = RawInstr | Imm11_0;
- break;
- }
- case Call36PCRel: {
- int64_t Value = TargetAddress - FixupAddress + Addend;
-
- if ((Value + 0x20000) != llvm::SignExtend64(Value + 0x20000, 38))
- return makeTargetOutOfRangeError(G, B, E);
-
- if (!isShiftedInt<36, 2>(Value))
- return makeAlignmentError(orc::ExecutorAddr(FixupAddress), Value, 4, E);
-
- uint32_t Pcaddu18i = *(little32_t *)FixupPtr;
- uint32_t Hi20 = extractBits(Value + (1 << 17), /*Hi=*/37, /*Lo=*/18) << 5;
- *(little32_t *)FixupPtr = Pcaddu18i | Hi20;
- uint32_t Jirl = *(little32_t *)(FixupPtr + 4);
- uint32_t Lo16 = extractBits(Value, /*Hi=*/17, /*Lo=*/2) << 10;
- *(little32_t *)(FixupPtr + 4) = Jirl | Lo16;
- break;
- }
- case Add6: {
- int64_t Value = *(reinterpret_cast<const int8_t *>(FixupPtr));
- Value += ((TargetAddress + Addend) & 0x3f);
- *FixupPtr = (*FixupPtr & 0xc0) | (static_cast<int8_t>(Value) & 0x3f);
- break;
- }
- case Add8: {
- int64_t Value =
- TargetAddress + *(reinterpret_cast<const int8_t *>(FixupPtr)) + Addend;
- *FixupPtr = static_cast<int8_t>(Value);
- break;
- }
- case Add16: {
- int64_t Value =
- TargetAddress + support::endian::read16le(FixupPtr) + Addend;
- *(little16_t *)FixupPtr = static_cast<int16_t>(Value);
- break;
- }
- case Add32: {
- int64_t Value =
- TargetAddress + support::endian::read32le(FixupPtr) + Addend;
- *(little32_t *)FixupPtr = static_cast<int32_t>(Value);
- break;
- }
- case Add64: {
- int64_t Value =
- TargetAddress + support::endian::read64le(FixupPtr) + Addend;
- *(little64_t *)FixupPtr = static_cast<int64_t>(Value);
- break;
- }
- case AddUleb128: {
- const uint32_t Maxcount = 1 + 64 / 7;
- uint32_t Count;
- const char *Error = nullptr;
- uint64_t Orig = decodeULEB128((reinterpret_cast<const uint8_t *>(FixupPtr)),
- &Count, nullptr, &Error);
-
- if (Count > Maxcount || (Count == Maxcount && Error))
- return make_error<JITLinkError>(
- "0x" + llvm::utohexstr(orc::ExecutorAddr(FixupAddress).getValue()) +
- ": extra space for uleb128");
-
- uint64_t Mask = Count < Maxcount ? (1ULL << 7 * Count) - 1 : -1ULL;
- encodeULEB128((Orig + TargetAddress + Addend) & Mask,
- (reinterpret_cast<uint8_t *>(FixupPtr)), Count);
- break;
- }
- case Sub6: {
- int64_t Value = *(reinterpret_cast<const int8_t *>(FixupPtr));
- Value -= ((TargetAddress + Addend) & 0x3f);
- *FixupPtr = (*FixupPtr & 0xc0) | (static_cast<int8_t>(Value) & 0x3f);
- break;
- }
- case Sub8: {
- int64_t Value =
- *(reinterpret_cast<const int8_t *>(FixupPtr)) - TargetAddress - Addend;
- *FixupPtr = static_cast<int8_t>(Value);
- break;
- }
- case Sub16: {
- int64_t Value =
- support::endian::read16le(FixupPtr) - TargetAddress - Addend;
- *(little16_t *)FixupPtr = static_cast<int16_t>(Value);
- break;
- }
- case Sub32: {
- int64_t Value =
- support::endian::read32le(FixupPtr) - TargetAddress - Addend;
- *(little32_t *)FixupPtr = static_cast<int32_t>(Value);
- break;
- }
- case Sub64: {
- int64_t Value =
- support::endian::read64le(FixupPtr) - TargetAddress - Addend;
- *(little64_t *)FixupPtr = static_cast<int64_t>(Value);
- break;
- }
- case SubUleb128: {
- const uint32_t Maxcount = 1 + 64 / 7;
- uint32_t Count;
- const char *Error = nullptr;
- uint64_t Orig = decodeULEB128((reinterpret_cast<const uint8_t *>(FixupPtr)),
- &Count, nullptr, &Error);
-
- if (Count > Maxcount || (Count == Maxcount && Error))
- return make_error<JITLinkError>(
- "0x" + llvm::utohexstr(orc::ExecutorAddr(FixupAddress).getValue()) +
- ": extra space for uleb128");
-
- uint64_t Mask = Count < Maxcount ? (1ULL << 7 * Count) - 1 : -1ULL;
- encodeULEB128((Orig - TargetAddress - Addend) & Mask,
- (reinterpret_cast<uint8_t *>(FixupPtr)), Count);
- break;
- }
- case AlignRelaxable:
- // Ignore when the relaxation pass did not run
- break;
- default:
- return make_error<JITLinkError>(
- "In graph " + G.getName() + ", section " + B.getSection().getName() +
- " unsupported edge kind " + getEdgeKindName(E.getKind()));
- }
-
- return Error::success();
-}
-
/// loongarch null pointer content.
LLVM_ABI extern const char NullPointerContent[8];
inline ArrayRef<char> getGOTEntryBlockContent(LinkGraph &G) {
@@ -612,9 +447,14 @@ inline Symbol &createAnonymousPointerJumpStub(LinkGraph &G,
Symbol &PointerSymbol) {
Block &StubContentBlock = G.createContentBlock(
StubSection, getStubBlockContent(G), orc::ExecutorAddr(), 4, 0);
- StubContentBlock.addEdge(Page20, 0, PointerSymbol, 0);
- StubContentBlock.addEdge(PageOffset12, 4, PointerSymbol, 0);
- return G.addAnonymousSymbol(StubContentBlock, 0, StubEntrySize, true, false);
+ Symbol &StubSymbol =
+ G.addAnonymousSymbol(StubContentBlock, 0, StubEntrySize, true, false);
+ StubContentBlock.addEdge(G.getPointerSize() == 8 ? Page20 : PCAdd20, 0,
+ PointerSymbol, 0);
+ StubContentBlock.addEdge(G.getPointerSize() == 8 ? PageOffset12 : PCAdd12, 4,
+ G.getPointerSize() == 8 ? PointerSymbol : StubSymbol,
+ 0);
+ return StubSymbol;
}
/// Global Offset Table Builder.
@@ -631,6 +471,9 @@ class GOTTableManager : public TableManager<GOTTableManager> {
case RequestGOTAndTransformToPageOffset12:
KindToSet = PageOffset12;
break;
+ case RequestGOTAndTransformToPCAdd20:
+ KindToSet = PCAdd20;
+ break;
default:
return false;
}
@@ -669,7 +512,8 @@ class PLTTableManager : public TableManager<PLTTableManager> {
static StringRef getSectionName() { return "$__STUBS"; }
bool visitEdge(LinkGraph &G, Block *B, Edge &E) {
- if ((E.getKind() == Branch26PCRel || E.getKind() == Call36PCRel) &&
+ if ((E.getKind() == Branch26PCRel || E.getKind() == Call36PCRel ||
+ E.getKind() == Call30PCRel) &&
!E.getTarget().isDefined()) {
DEBUG_WITH_TYPE("jitlink", {
dbgs() << " Fixing " << G.getEdgeKindName(E.getKind()) << " edge at "
diff --git a/llvm/lib/ExecutionEngine/JITLink/ELF_loongarch.cpp b/llvm/lib/ExecutionEngine/JITLink/ELF_loongarch.cpp
index f23fb346c55f9..aa9deaf7a04c0 100644
--- a/llvm/lib/ExecutionEngine/JITLink/ELF_loongarch.cpp
+++ b/llvm/lib/ExecutionEngine/JITLink/ELF_loongarch.cpp
@@ -37,11 +37,314 @@ class ELFJITLinker_loongarch : public JITLinker<ELFJITLinker_loongarch> {
ELFJITLinker_loongarch(std::unique_ptr<JITLinkContext> Ctx,
std::unique_ptr<LinkGraph> G,
PassConfiguration PassConfig)
- : JITLinker(std::move(Ctx), std::move(G), std::move(PassConfig)) {}
+ : JITLinker(std::move(Ctx), std::move(G), std::move(PassConfig)) {
+ JITLinkerBase::getPassConfig().PostAllocationPasses.push_back(
+ [this](LinkGraph &G) { return gatherLoongArchPCAdd20(G); });
+ }
private:
+ DenseMap<std::pair<const Block *, orc::ExecutorAddrDiff>, const Edge *>
+ RelPCAdd20Map;
+
+ Error gatherLoongArchPCAdd20(LinkGraph &G) {
+ for (Block *B : G.blocks())
+ for (Edge &E : B->edges())
+ if (E.getKind() == PCAdd20)
+ RelPCAdd20Map[{B, E.getOffset()}] = &E;
+
+ return Error::success();
+ }
+
+ Expected<const Edge &> getLoongArchPCAdd20(const Edge &E) const {
+ using namespace loongarch;
+ assert((E.getKind() == PCAdd12) &&
+ "Can only have high relocation for PCAdd12");
+
+ const Symbol &Sym = E.getTarget();
+ const Block &B = Sym.getBlock();
+ orc::ExecutorAddrDiff Offset = Sym.getOffset() + E.getAddend();
+
+ auto It = RelPCAdd20Map.find({&B, Offset});
+ if (It != RelPCAdd20Map.end())
+ return *It->second;
+
+ return make_error<JITLinkError>("No PCAdd20 relocation type be found "
+ "for PCAdd12 relocation type");
+ }
+
Error applyFixup(LinkGraph &G, Block &B, const Edge &E) const {
- return loongarch::applyFixup(G, B, E);
+ using namespace support;
+
+ char *BlockWorkingMem = B.getAlreadyMutableContent().data();
+ char *FixupPtr = BlockWorkingMem + E.getOffset();
+ uint64_t FixupAddress = (B.getAddress() + E.getOffset()).getValue();
+ uint64_t TargetAddress = E.getTarget().getAddress().getValue();
+ int64_t Addend = E.getAddend();
+
+ switch (E.getKind()) {
+ case Pointer64:
+ *(ulittle64_t *)FixupPtr = TargetAddress + Addend;
+ break;
+ case Pointer32: {
+ uint64_t Value = TargetAddress + Addend;
+ if (Value > std::numeric_limits<uint32_t>::max())
+ return makeTargetOutOfRangeError(G, B, E);
+ *(ulittle32_t *)FixupPtr = Value;
+ break;
+ }
+ case Branch16PCRel: {
+ int64_t Value = TargetAddress - FixupAddress + Addend;
+
+ if (!isInt<18>(Value))
+ return makeTargetOutOfRangeError(G, B, E);
+
+ if (!isShiftedInt<16, 2>(Value))
+ return makeAlignmentError(orc::ExecutorAddr(FixupAddress), Value, 4, E);
+
+ uint32_t RawInstr = *(little32_t *)FixupPtr;
+ uint32_t Imm = static_cast<uint32_t>(Value >> 2);
+ uint32_t Imm15_0 = extractBits(Imm, /*Hi=*/15, /*Lo=*/0) << 10;
+ *(little32_t *)FixupPtr = RawInstr | Imm15_0;
+ break;
+ }
+ case Branch21PCRel: {
+ int64_t Value = TargetAddress - FixupAddress + Addend;
+
+ if (!isInt<23>(Value))
+ return makeTargetOutOfRangeError(G, B, E);
+
+ if (!isShiftedInt<21, 2>(Value))
+ return makeAlignmentError(orc::ExecutorAddr(FixupAddress), Value, 4, E);
+
+ uint32_t RawInstr = *(little32_t *)FixupPtr;
+ uint32_t Imm = static_cast<uint32_t>(Value >> 2);
+ uint32_t Imm15_0 = extractBits(Imm, /*Hi=*/15, /*Lo=*/0) << 10;
+ uint32_t Imm20_16 = extractBits(Imm, /*Hi=*/20, /*Lo=*/16);
+ *(little32_t *)FixupPtr = RawInstr | Imm15_0 | Imm20_16;
+ break;
+ }
+ case Branch26PCRel: {
+ int64_t Value = TargetAddress - FixupAddress + Addend;
+
+ if (!isInt<28>(Value))
+ return makeTargetOutOfRangeError(G, B, E);
+
+ if (!isShiftedInt<26, 2>(Value))
+ return makeAlignmentError(orc::ExecutorAddr(FixupAddress), Value, 4, E);
+
+ uint32_t RawInstr = *(little32_t *)FixupPtr;
+ uint32_t Imm = static_cast<uint32_t>(Value >> 2);
+ uint32_t Imm15_0 = extractBits(Imm, /*Hi=*/15, /*Lo=*/0) << 10;
+ uint32_t Imm25_16 = extractBits(Imm, /*Hi=*/25, /*Lo=*/16);
+ *(little32_t *)FixupPtr = RawInstr | Imm15_0 | Imm25_16;
+ break;
+ }
+ case Delta32: {
+ int64_t Value = TargetAddress - FixupAddress + Addend;
+
+ if (!isInt<32>(Value))
+ return makeTargetOutOfRangeError(G, B, E);
+ *(little32_t *)FixupPtr = Value;
+ break;
+ }
+ case NegDelta32: {
+ int64_t Value = FixupAddress - TargetAddress + Addend;
+ if (!isInt<32>(Value))
+ return makeTargetOutOfRangeError(G, B, E);
+ *(little32_t *)FixupPtr = Value;
+ break;
+ }
+ case Delta64:
+ *(little64_t *)FixupPtr = TargetAddress - FixupAddress + Addend;
+ break;
+ case Page20: {
+ uint64_t Target = TargetAddress + Addend;
+ uint64_t TargetPage =
+ (Target + (Target & 0x800)) & ~static_cast<uint64_t>(0xfff);
+ uint64_t PCPage = FixupAddress & ~static_cast<uint64_t>(0xfff);
+
+ int64_t PageDelta = TargetPage - PCPage;
+ if (!isInt<32>(PageDelta))
+ return makeTargetOutOfRangeError(G, B, E);
+
+ uint32_t RawInstr = *(little32_t *)FixupPtr;
+ uint32_t Imm31_12 = extractBits(PageDelta, /*Hi=*/31, /*Lo=*/12) << 5;
+ *(little32_t *)FixupPtr = RawInstr | Imm31_12;
+ break;
+ }
+ case PageOffset12: {
+ uint64_t TargetOffset = (TargetAddress + Addend) & 0xfff;
+
+ uint32_t RawInstr = *(ulittle32_t *)FixupPtr;
+ uint32_t Imm11_0 = TargetOffset << 10;
+ *(ulittle32_t *)FixupPtr = RawInstr | Imm11_0;
+ break;
+ }
+ case PCAdd20: {
+ uint64_t Target = TargetAddress + Addend;
+ int64_t Delta = Target - FixupAddress + 0x800;
+
+ if (!isInt<32>(Delta))
+ return makeTargetOutOfRangeError(G, B, E);
+
+ uint32_t RawInstr = *(little32_t *)FixupPtr;
+ uint32_t Imm31_12 = extractBits(Delta, /*Hi=*/31, /*Lo=*/12) << 5;
+ *(little32_t *)FixupPtr = RawInstr | Imm31_12;
+ break;
+ }
+ case PCAdd12: {
+ auto RelPCAdd20 = getLoongArchPCAdd20(E);
+ if (!RelPCAdd20)
+ return RelPCAdd20.takeError();
+ int64_t Delta =
+ (RelPCAdd20->getTarget().getAddress() + RelPCAdd20->getAddend()) -
+ (E.getTarget().getAddress() + E.getAddend());
+
+ uint32_t RawInstr = *(ulittle32_t *)FixupPtr;
+ uint32_t Imm11_0 = extractBits(Delta, /*Hi=*/11, /*Lo=*/0) << 10;
+ *(ulittle32_t *)FixupPtr = RawInstr | Imm11_0;
+ break;
+ }
+ case Call30PCRel: {
+ int64_t Value = TargetAddress - FixupAddress + Addend;
+
+ if (Value != llvm::SignExtend64(Value, 32))
+ return makeTargetOutOfRangeError(G, B, E);
+
+ if (!isShiftedInt<30, 2>(Value))
+ return makeAlignmentError(orc::ExecutorAddr(FixupAddress), Value, 4, E);
+
+ uint32_t Pcaddu12i = *(little32_t *)FixupPtr;
+ uint32_t Hi20 = extractBits(Value + (1 << 17), /*Hi=*/31, /*Lo=*/12) << 5;
+ *(little32_t *)FixupPtr = Pcaddu12i | Hi20;
+ uint32_t Jirl = *(little32_t *)(FixupPtr + 4);
+ uint32_t Lo10 = extractBits(Value, /*Hi=*/11, /*Lo=*/2) << 10;
+ *(little32_t *)(FixupPtr + 4) = Jirl | Lo10;
+ break;
+ }
+ case Call36PCRel: {
+ int64_t Value = TargetAddress - FixupAddress + Addend;
+
+ if ((Value + 0x20000) != llvm::SignExtend64(Value + 0x20000, 38))
+ return makeTargetOutOfRangeError(G, B, E);
+
+ if (!isShiftedInt<36, 2>(Value))
+ return makeAlignmentError(orc::ExecutorAddr(FixupAddress), Value, 4, E);
+
+ uint32_t Pcaddu18i = *(little32_t *)FixupPtr;
+ uint32_t Hi20 = extractBits(Value + (1 << 17), /*Hi=*/37, /*Lo=*/18) << 5;
+ *(little32_t *)FixupPtr = Pcaddu18i | Hi20;
+ uint32_t Jirl = *(little32_t *)(FixupPtr + 4);
+ uint32_t Lo16 = extractBits(Value, /*Hi=*/17, /*Lo=*/2) << 10;
+ *(little32_t *)(FixupPtr + 4) = Jirl | Lo16;
+ break;
+ }
+ case Add6: {
+ int64_t Value = *(reinterpret_cast<const int8_t *>(FixupPtr));
+ Value += ((TargetAddress + Addend) & 0x3f);
+ *FixupPtr = (*FixupPtr & 0xc0) | (static_cast<int8_t>(Value) & 0x3f);
+ break;
+ }
+ case Add8: {
+ int64_t Value = TargetAddress +
+ *(reinterpret_cast<const int8_t *>(FixupPtr)) + Addend;
+ *FixupPtr = static_cast<int8_t>(Value);
+ break;
+ }
+ case Add16: {
+ int64_t Value =
+ TargetAddress + support::endian::read16le(FixupPtr) + Addend;
+ *(little16_t *)FixupPtr = static_cast<int16_t>(Value);
+ break;
+ }
+ case Add32: {
+ int64_t Value =
+ TargetAddress + support::endian::read32le(FixupPtr) + Addend;
+ *(little32_t *)FixupPtr = static_cast<int32_t>(Value);
+ break;
+ }
+ case Add64: {
+ int64_t Value =
+ TargetAddress + support::endian::read64le(FixupPtr) + Addend;
+ *(little64_t *)FixupPtr = static_cast<int64_t>(Value);
+ break;
+ }
+ case AddUleb128: {
+ const uint32_t Maxcount = 1 + 64 / 7;
+ uint32_t Count;
+ const char *Error = nullptr;
+ uint64_t Orig =
+ decodeULEB128((reinterpret_cast<const uint8_t *>(FixupPtr)), &Count,
+ nullptr, &Error);
+
+ if (Count > Maxcount || (Count == Maxcount && Error))
+ return make_error<JITLinkError>(
+ "0x" + llvm::utohexstr(orc::ExecutorAddr(FixupAddress).getValue()) +
+ ": extra space for uleb128");
+
+ uint64_t Mask = Count < Maxcount ? (1ULL << 7 * Count) - 1 : -1ULL;
+ encodeULEB128((Orig + TargetAddress + Addend) & Mask,
+ (reinterpret_cast<uint8_t *>(FixupPtr)), Count);
+ break;
+ }
+ case Sub6: {
+ int64_t Value = *(reinterpret_cast<const int8_t *>(FixupPtr));
+ Value -= ((TargetAddress + Addend) & 0x3f);
+ *FixupPtr = (*FixupPtr & 0xc0) | (static_cast<int8_t>(Value) & 0x3f);
+ break;
+ }
+ case Sub8: {
+ int64_t Value = *(reinterpret_cast<const int8_t *>(FixupPtr)) -
+ TargetAddress - Addend;
+ *FixupPtr = static_cast<int8_t>(Value);
+ break;
+ }
+ case Sub16: {
+ int64_t Value =
+ support::endian::read16le(FixupPtr) - TargetAddress - Addend;
+ *(little16_t *)FixupPtr = static_cast<int16_t>(Value);
+ break;
+ }
+ case Sub32: {
+ int64_t Value =
+ support::endian::read32le(FixupPtr) - TargetAddress - Addend;
+ *(little32_t *)FixupPtr = static_cast<int32_t>(Value);
+ break;
+ }
+ case Sub64: {
+ int64_t Value =
+ support::endian::read64le(FixupPtr) - TargetAddress - Addend;
+ *(little64_t *)FixupPtr = static_cast<int64_t>(Value);
+ break;
+ }
+ case SubUleb128: {
+ const uint32_t Maxcount = 1 + 64 / 7;
+ uint32_t Count;
+ const char *Error = nullptr;
+ uint64_t Orig =
+ decodeULEB128((reinterpret_cast<const uint8_t *>(FixupPtr)), &Count,
+ nullptr, &Error);
+
+ if (Count > Maxcount || (Count == Maxcount && Error))
+ return make_error<JITLinkError>(
+ "0x" + llvm::utohexstr(orc::ExecutorAddr(FixupAddress).getValue()) +
+ ": extra space for uleb128");
+
+ uint64_t Mask = Count < Maxcount ? (1ULL << 7 * Count) - 1 : -1ULL;
+ encodeULEB128((Orig - TargetAddress - Addend) & Mask,
+ (reinterpret_cast<uint8_t *>(FixupPtr)), Count);
+ break;
+ }
+ case AlignRelaxable:
+ // Ignore when the relaxation pass did not run
+ break;
+ default:
+ return make_error<JITLinkError>(
+ "In graph " + G.getName() + ", section " + B.getSection().getName() +
+ " unsupported edge kind " + getEdgeKindName(E.getKind()));
+ }
+
+ return Error::success();
}
};
@@ -304,6 +607,8 @@ class ELFLinkGraphBuilder_loongarch : public ELFLinkGraphBuilder<ELFT> {
return RequestGOTAndTransformToPage20;
case ELF::R_LARCH_GOT_PC_LO12:
return RequestGOTAndTransformToPageOffset12;
+ case ELF::R_LARCH_CALL30:
+ return Call30PCRel;
case ELF::R_LARCH_CALL36:
return Call36PCRel;
case ELF::R_LARCH_ADD6:
@@ -332,6 +637,12 @@ class ELFLinkGraphBuilder_loongarch : public ELFLinkGraphBuilder<ELFT> {
return SubUleb128;
case ELF::R_LARCH_ALIGN:
return AlignRelaxable;
+ case ELF::R_LARCH_PCADD_HI20:
+ return PCAdd20;
+ case ELF::R_LARCH_PCADD_LO12_I:
+ return PCAdd12;
+ case ELF::R_LARCH_PCADD_GOT_HI20:
+ return RequestGOTAndTransformToPCAdd20;
}
return make_error<JITLinkError>(
diff --git a/llvm/lib/ExecutionEngine/JITLink/loongarch.cpp b/llvm/lib/ExecutionEngine/JITLink/loongarch.cpp
index 55389adb31b60..d6f0d8db0efb4 100644
--- a/llvm/lib/ExecutionEngine/JITLink/loongarch.cpp
+++ b/llvm/lib/ExecutionEngine/JITLink/loongarch.cpp
@@ -28,8 +28,8 @@ const uint8_t LA64StubContent[StubEntrySize] = {
};
const uint8_t LA32StubContent[StubEntrySize] = {
- 0x14, 0x00, 0x00, 0x1a, // pcalau12i $t8, %page20(imm)
- 0x94, 0x02, 0x80, 0x28, // ld.w $t8, $t8, %pageoff12(imm)
+ 0x14, 0x00, 0x00, 0x1c, // pcaddu12i $t8, %pcadd20(imm)
+ 0x94, 0x02, 0x80, 0x28, // ld.w $t8, $t8, %pcadd12(.Lpcadd_hi)
0x80, 0x02, 0x00, 0x4c // jr $t8
};
@@ -49,8 +49,12 @@ const char *getEdgeKindName(Edge::Kind K) {
KIND_NAME_CASE(Branch26PCRel)
KIND_NAME_CASE(Page20)
KIND_NAME_CASE(PageOffset12)
+ KIND_NAME_CASE(PCAdd20)
+ KIND_NAME_CASE(PCAdd12)
KIND_NAME_CASE(RequestGOTAndTransformToPage20)
KIND_NAME_CASE(RequestGOTAndTransformToPageOffset12)
+ KIND_NAME_CASE(RequestGOTAndTransformToPCAdd20)
+ KIND_NAME_CASE(Call30PCRel)
KIND_NAME_CASE(Call36PCRel)
KIND_NAME_CASE(Add6)
KIND_NAME_CASE(Add8)
diff --git a/llvm/lib/Target/LoongArch/AsmParser/LoongArchAsmParser.cpp b/llvm/lib/Target/LoongArch/AsmParser/LoongArchAsmParser.cpp
index 5be4713b349ee..0f0dbdd8f41fb 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");
@@ -171,6 +172,10 @@ class LoongArchAsmParser : public MCTargetAsmParser {
// Helper to emit pseudo instruction "li.w/d $rd, $imm".
void emitLoadImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);
+ // Helper to emit pseudo instruction "call30 sym" or "tail36 $rj, sym".
+ void emitFuncCall30(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
+ bool IsTailCall);
+
// Helper to emit pseudo instruction "call36 sym" or "tail36 $rj, sym".
void emitFuncCall36(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
bool IsTailCall);
@@ -328,7 +333,7 @@ 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_LE_LO12_R || VK == ELF::R_LARCH_PCADD_LO12_I ||
VK == ELF::R_LARCH_TLS_DESC_PC_LO12 || VK == ELF::R_LARCH_TLS_DESC_LD;
return IsConstantImm
? isInt<12>(Imm) && IsValidKind
@@ -371,7 +376,7 @@ class LoongArchOperand : public MCParsedAsmOperand {
VK == ELF::R_LARCH_PCALA_LO12 || VK == ELF::R_LARCH_GOT_LO12 ||
VK == ELF::R_LARCH_GOT_PC_LO12 || VK == ELF::R_LARCH_TLS_LE_LO12 ||
VK == ELF::R_LARCH_TLS_IE_LO12 || VK == ELF::R_LARCH_TLS_IE_PC_LO12 ||
- VK == ELF::R_LARCH_TLS_DESC_LO12;
+ VK == ELF::R_LARCH_TLS_DESC_LO12 || VK == ELF::R_LARCH_PCADD_LO12_I;
return IsConstantImm
? isUInt<12>(Imm) && IsValidKind
: LoongArchAsmParser::classifySymbolRef(getImm(), VK) &&
@@ -394,7 +399,8 @@ class LoongArchOperand : public MCParsedAsmOperand {
bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
bool IsValidKind =
VK == LoongArchMCExpr::VK_None || VK == ELF::R_LARCH_B16 ||
- VK == ELF::R_LARCH_PCALA_LO12 || VK == ELF::R_LARCH_TLS_DESC_CALL;
+ VK == ELF::R_LARCH_PCALA_LO12 || VK == ELF::R_LARCH_TLS_DESC_CALL ||
+ VK == ELF::R_LARCH_PCADD_LO12_I;
return IsConstantImm
? isShiftedInt<16, 2>(Imm) && IsValidKind
: LoongArchAsmParser::classifySymbolRef(getImm(), VK) &&
@@ -463,6 +469,25 @@ 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_PCADD_GOT_HI20 ||
+ VK == ELF::R_LARCH_PCADD_TLS_IE_HI20 ||
+ VK == ELF::R_LARCH_PCADD_TLS_DESC_HI20;
+
+ return IsConstantImm
+ ? isInt<20>(Imm) && IsValidKind
+ : LoongArchAsmParser::classifySymbolRef(getImm(), VK) &&
+ IsValidKind;
+ }
+
bool isSImm20pcaddu18i() const {
if (!isImm())
return false;
@@ -869,6 +894,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 +903,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 +928,13 @@ void LoongArchAsmParser::emitLAInstSeq(MCRegister DestReg, MCRegister TmpReg,
.addExpr(LE),
getSTI());
continue;
+ } else if (VK == ELF::R_LARCH_PCADD_LO12_I) {
+ 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),
@@ -917,6 +954,17 @@ void LoongArchAsmParser::emitLAInstSeq(MCRegister DestReg, MCRegister TmpReg,
getSTI());
break;
case LoongArch::ADDI_D:
+ if (VK == ELF::R_LARCH_PCADD_LO12_I) {
+ Out.emitInstruction(
+ MCInstBuilder(Opc)
+ .addReg(TmpReg)
+ .addReg(DestReg == TmpReg ? TmpReg : LoongArch::R0)
+ .addExpr(LoongArchMCExpr::create(
+ MCSymbolRefExpr::create(PCALabel, Ctx), VK, Ctx,
+ RelaxHint)),
+ getSTI());
+ continue;
+ }
Out.emitInstruction(
MCInstBuilder(Opc)
.addReg(TmpReg)
@@ -975,20 +1023,30 @@ 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)
+ // addi.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_I;
- 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);
+ /*RelaxHint=*/has32S());
}
void LoongArchAsmParser::emitLoadAddressPcrelLarge(MCInst &Inst, SMLoc IDLoc,
@@ -1024,7 +1082,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_PCADD_GOT_HI20;
+ unsigned LDRel =
+ has32S() ? ELF::R_LARCH_GOT_PC_LO12 : ELF::R_LARCH_PCADD_LO12_I;
if (getSTI().hasFeature(LoongArch::LaGlobalWithAbs)) {
// with feature: +la-glabal-with-abs
@@ -1054,15 +1117,19 @@ 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, %pcadd_got_hi20(sym)
+ // ld.w $rd, $rd, %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));
+ // ld.d $rd, $rd, %got_pc_lo12(sym)
+ Insts.push_back(LoongArchAsmParser::Inst(PCAI, PCAIRel));
+ Insts.push_back(LoongArchAsmParser::Inst(LD, LDRel));
emitLAInstSeq(DestReg, DestReg, Symbol, Insts, IDLoc, Out,
- /*RelaxHint=*/true);
+ /*RelaxHint=*/has32S());
}
void LoongArchAsmParser::emitLoadAddressGotLarge(MCInst &Inst, SMLoc IDLoc,
@@ -1116,7 +1183,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_PCADD_TLS_IE_HI20;
+ unsigned LDRel =
+ has32S() ? ELF::R_LARCH_TLS_IE_PC_LO12 : ELF::R_LARCH_PCADD_LO12_I;
if (getSTI().hasFeature(LoongArch::LaGlobalWithAbs)) {
// with feature: +la-glabal-with-abs
@@ -1147,15 +1219,19 @@ void LoongArchAsmParser::emitLoadAddressTLSIE(MCInst &Inst, SMLoc IDLoc,
return;
}
- // expands to:
+ // for la32r expands to:
+ // .Lpcadd_hi:
+ // pcaddu12i $rd, %pcadd_ie_hi20(sym)
+ // ld.w $rd, $rd, %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));
+ // ld.d $rd, $rd, %ie_pc_lo12(sym)
+ Insts.push_back(LoongArchAsmParser::Inst(PCAI, PCAIRel));
+ Insts.push_back(LoongArchAsmParser::Inst(LD, LDRel));
emitLAInstSeq(DestReg, DestReg, Symbol, Insts, IDLoc, Out,
- /*RelaxHint=*/true);
+ /*RelaxHint=*/has32S());
}
void LoongArchAsmParser::emitLoadAddressTLSIELarge(MCInst &Inst, SMLoc IDLoc,
@@ -1334,8 +1410,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_PCADD_TLS_DESC_HI20;
+ unsigned ADDIRel =
+ has32S() ? ELF::R_LARCH_TLS_DESC_PC_LO12 : ELF::R_LARCH_PCADD_LO12_I;
InstSeq Insts;
if (getSTI().hasFeature(LoongArch::LaGlobalWithAbs)) {
@@ -1373,21 +1454,26 @@ void LoongArchAsmParser::emitLoadAddressTLSDesc(MCInst &Inst, SMLoc IDLoc,
return;
}
- // expands to:
+ // for la32r expands to:
+ // .Lpcadd_hi:
+ // pcaddu12i $rd, %pcadd_desc_hi20(sym)
+ // addi.w $rd, $rd, %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)
+ // addi.d $rd, $rd, %desc_pc_lo12(sym)
+ // ld.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));
emitLAInstSeq(DestReg, DestReg, Symbol, Insts, IDLoc, Out,
- /*RelaxHint=*/true);
+ /*RelaxHint=*/has32S());
}
void LoongArchAsmParser::emitLoadAddressTLSDescLarge(MCInst &Inst, SMLoc IDLoc,
@@ -1463,6 +1549,35 @@ void LoongArchAsmParser::emitLoadImm(MCInst &Inst, SMLoc IDLoc,
}
}
+void LoongArchAsmParser::emitFuncCall30(MCInst &Inst, SMLoc IDLoc,
+ MCStreamer &Out, bool IsTailCall) {
+ // call30 sym
+ // expands to:
+ // pcaddu12i $ra, %call30(sym)
+ // jirl $ra, $ra, 0
+ //
+ // tail30 $rj, sym
+ // expands to:
+ // pcaddu12i $rj, %call30(sym)
+ // jirl $r0, $rj, 0
+ MCRegister ScratchReg =
+ IsTailCall ? Inst.getOperand(0).getReg() : MCRegister(LoongArch::R1);
+ const MCExpr *Sym =
+ IsTailCall ? Inst.getOperand(1).getExpr() : Inst.getOperand(0).getExpr();
+ const LoongArchMCExpr *LE = LoongArchMCExpr::create(
+ Sym, ELF::R_LARCH_CALL30, getContext(), /*RelaxHint=*/true);
+
+ Out.emitInstruction(
+ MCInstBuilder(LoongArch::PCADDU12I).addReg(ScratchReg).addExpr(LE),
+ getSTI());
+ Out.emitInstruction(
+ MCInstBuilder(LoongArch::JIRL)
+ .addReg(IsTailCall ? MCRegister(LoongArch::R0) : ScratchReg)
+ .addReg(ScratchReg)
+ .addImm(0),
+ getSTI());
+}
+
void LoongArchAsmParser::emitFuncCall36(MCInst &Inst, SMLoc IDLoc,
MCStreamer &Out, bool IsTailCall) {
// call36 sym
@@ -1546,6 +1661,12 @@ bool LoongArchAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
case LoongArch::PseudoLI_D:
emitLoadImm(Inst, IDLoc, Out);
return false;
+ case LoongArch::PseudoCALL30:
+ emitFuncCall30(Inst, IDLoc, Out, /*IsTailCall=*/false);
+ return false;
+ case LoongArch::PseudoTAIL30:
+ emitFuncCall30(Inst, IDLoc, Out, /*IsTailCall=*/true);
+ return false;
case LoongArch::PseudoCALL36:
emitFuncCall36(Inst, IDLoc, Out, /*IsTailCall=*/false);
return false;
@@ -1847,6 +1968,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 7aef4ab53e4ea..04ccc3b9ff63a 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,29 +177,41 @@ 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();
const auto &STI = MF->getSubtarget<LoongArchSubtarget>();
- bool EnableRelax = STI.hasFeature(LoongArch::FeatureRelax);
+ bool EnableRelax = STI.hasFeature(LoongArch::FeatureRelax) &&
+ OpcodeHi == LoongArch::PCALAU12I;
Register DestReg = MI.getOperand(0).getReg();
Register ScratchReg =
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 +333,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.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 +365,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, %pcadd_got_hi20(sym)
+ // ld.w $rd, $rd, %pcadd_lo12(.Lpcadd_hi)
+ //
+ // for la32s and la64 expands to:
+ // pcalau12i $rd, %got_pc_hi20(sym)
+ // ld.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_PCADD_GOT_HI;
+ unsigned FlagsLo =
+ Has32S ? LoongArchII::MO_GOT_PC_LO : LoongArchII::MO_PCADD_LO;
+ return expandPcaxxu12iInstPair(MBB, MBBI, NextMBBI, OpcodeHi, OpcodeLo,
+ FlagsHi, FlagsLo);
}
bool LoongArchPreRAExpandPseudo::expandLoadAddressTLSLE(
@@ -424,13 +462,26 @@ bool LoongArchPreRAExpandPseudo::expandLoadAddressTLSIE(
LoongArchII::MO_IE_PC_LO);
// Code Sequence:
- // pcalau12i $rd, %ie_pc_hi20(sym)
- // ld.w/d $rd, $rd, %ie_pc_lo12(sym)
+ //
+ // for la32r expands to:
+ // .Lpcadd_hi:
+ // pcaddu12i $rd, %pcadd_ie_hi20(sym)
+ // ld.w $rd, $rd, %pcadd_lo12(.Lpcadd_hi)
+ //
+ // for la32s and la64 expands to:
+ // pcalau12i $rd, %ie_pc_hi20(sym)
+ // ld.d $rd, $rd, %ie_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_IE_PC_HI,
- SecondOpcode, LoongArchII::MO_IE_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_IE_PC_HI : LoongArchII::MO_PCADD_IE_HI;
+ unsigned FlagsLo =
+ Has32S ? LoongArchII::MO_IE_PC_LO : LoongArchII::MO_PCADD_LO;
+ return expandPcaxxu12iInstPair(MBB, MBBI, NextMBBI, OpcodeHi, OpcodeLo,
+ FlagsHi, FlagsLo);
}
bool LoongArchPreRAExpandPseudo::expandLoadAddressTLSLD(
@@ -447,9 +498,10 @@ bool LoongArchPreRAExpandPseudo::expandLoadAddressTLSLD(
// addi.w/d $rd, $rd, %got_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_LD_PC_HI,
- SecondOpcode, LoongArchII::MO_GOT_PC_LO);
+ unsigned OpcodeLo = STI.is64Bit() ? LoongArch::ADDI_D : LoongArch::ADDI_W;
+ return expandPcaxxu12iInstPair(MBB, MBBI, NextMBBI, LoongArch::PCALAU12I,
+ OpcodeLo, LoongArchII::MO_LD_PC_HI,
+ LoongArchII::MO_GOT_PC_LO);
}
bool LoongArchPreRAExpandPseudo::expandLoadAddressTLSGD(
@@ -466,9 +518,10 @@ bool LoongArchPreRAExpandPseudo::expandLoadAddressTLSGD(
// addi.w/d $rd, $rd, %got_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_GD_PC_HI,
- SecondOpcode, LoongArchII::MO_GOT_PC_LO);
+ unsigned OpcodeLo = STI.is64Bit() ? LoongArch::ADDI_D : LoongArch::ADDI_W;
+ return expandPcaxxu12iInstPair(MBB, MBBI, NextMBBI, LoongArch::PCALAU12I,
+ OpcodeLo, LoongArchII::MO_GD_PC_HI,
+ LoongArchII::MO_GOT_PC_LO);
}
bool LoongArchPreRAExpandPseudo::expandLoadAddressTLSDesc(
@@ -479,20 +532,24 @@ bool LoongArchPreRAExpandPseudo::expandLoadAddressTLSDesc(
DebugLoc DL = MI.getDebugLoc();
const auto &STI = MF->getSubtarget<LoongArchSubtarget>();
+ bool Has32S = STI.hasFeature(LoongArch::Feature32S);
+ bool EnableRelax = STI.hasFeature(LoongArch::FeatureRelax) && Has32S;
+ unsigned PCA = Has32S ? LoongArch::PCALAU12I : LoongArch::PCADDU12I;
unsigned ADD = STI.is64Bit() ? LoongArch::ADD_D : LoongArch::ADD_W;
unsigned ADDI = STI.is64Bit() ? LoongArch::ADDI_D : LoongArch::ADDI_W;
unsigned LD = STI.is64Bit() ? LoongArch::LD_D : LoongArch::LD_W;
- bool EnableRelax = STI.hasFeature(LoongArch::FeatureRelax);
+ unsigned MO =
+ Has32S ? LoongArchII::MO_DESC_PC_HI : LoongArchII::MO_PCADD_DESC_HI;
Register DestReg = MI.getOperand(0).getReg();
Register Tmp1Reg =
MF->getRegInfo().createVirtualRegister(&LoongArch::GPRRegClass);
MachineOperand &Symbol = MI.getOperand(Large ? 2 : 1);
- BuildMI(MBB, MBBI, DL, TII->get(LoongArch::PCALAU12I), Tmp1Reg)
- .addDisp(Symbol, 0,
- LoongArchII::encodeFlags(LoongArchII::MO_DESC_PC_HI,
- EnableRelax && !Large));
+ MachineInstr *PCAMI =
+ BuildMI(MBB, MBBI, DL, TII->get(PCA), Tmp1Reg)
+ .addDisp(Symbol, 0,
+ LoongArchII::encodeFlags(MO, EnableRelax && !Large));
if (Large) {
// Code Sequence:
@@ -527,16 +584,35 @@ bool LoongArchPreRAExpandPseudo::expandLoadAddressTLSDesc(
.addReg(Tmp4Reg);
} else {
// Code Sequence:
- // pcalau12i $a0, %desc_pc_hi20(sym)
- // addi.w/d $a0, $a0, %desc_pc_lo12(sym)
- // ld.w/d $ra, $a0, %desc_ld(sym)
- // jirl $ra, $ra, %desc_call(sym)
- // add.w/d $dst, $a0, $tp
- BuildMI(MBB, MBBI, DL, TII->get(ADDI), LoongArch::R4)
- .addReg(Tmp1Reg)
- .addDisp(
- Symbol, 0,
- LoongArchII::encodeFlags(LoongArchII::MO_DESC_PC_LO, EnableRelax));
+ //
+ // for la32r expands to:
+ // .Lpcadd_hi:
+ // pcaddu12i $a0, %pcadd_desc_hi20(sym)
+ // addi.w $a0, $a0, %pcadd_lo12(.Lpcadd_hi)
+ // ld.w $ra, $a0, %desc_ld(sym)
+ // jirl $ra, $ra, %desc_call(sym)
+ // add.w $dst, $a0, $tp
+ //
+ // for la32s and la64 expands to:
+ // pcalau12i $a0, %desc_pc_hi20(sym)
+ // addi.d $a0, $a0, %desc_pc_lo12(sym)
+ // ld.d $ra, $a0, %desc_ld(sym)
+ // jirl $ra, $ra, %desc_call(sym)
+ // add.d $dst, $a0, $tp
+ if (Has32S) {
+ BuildMI(MBB, MBBI, DL, TII->get(ADDI), LoongArch::R4)
+ .addReg(Tmp1Reg)
+ .addDisp(Symbol, 0,
+ LoongArchII::encodeFlags(LoongArchII::MO_DESC_PC_LO,
+ EnableRelax));
+ } else {
+ MCSymbol *PCASymbol = MF->getContext().createNamedTempSymbol("desc_hi");
+ PCAMI->setPreInstrSymbol(*MF, PCASymbol);
+ BuildMI(MBB, MBBI, DL, TII->get(ADDI), LoongArch::R4)
+ .addReg(Tmp1Reg)
+ .addSym(PCASymbol, LoongArchII::encodeFlags(LoongArchII::MO_PCADD_LO,
+ EnableRelax));
+ }
}
BuildMI(MBB, MBBI, DL, TII->get(LD), LoongArch::R1)
@@ -646,8 +722,8 @@ void LoongArchPreRAExpandPseudo::annotateTableJump(
}
};
- // FindDepth = 3, probably sufficient.
- FindJTIMI(&*MBBI, /*FindDepth=*/3);
+ // FindDepth = 4, probably sufficient.
+ FindJTIMI(&*MBBI, /*FindDepth=*/4);
}
class LoongArchExpandPseudo : public MachineFunctionPass {
@@ -784,25 +860,36 @@ bool LoongArchExpandPseudo::expandFunctionCALL(
report_fatal_error("Unexpected code model");
break;
case CodeModel::Medium: {
+ // for la32 expands to:
+ // CALL:
+ // pcaddu12i $ra, %call30(func)
+ // jirl $ra, $ra, 0
+ // TAIL:
+ // pcaddu12i $t8, %call30(func)
+ // jirl $r0, $t8, 0
+ //
+ // for la64 expands to:
// CALL:
- // pcaddu18i $ra, %call36(func)
- // jirl $ra, $ra, 0
+ // pcaddu18i $ra, %call36(func)
+ // jirl $ra, $ra, 0
// TAIL:
- // pcaddu18i $t8, %call36(func)
- // jirl $r0, $t8, 0
+ // pcaddu18i $t8, %call36(func)
+ // jirl $r0, $t8, 0
Opcode =
IsTailCall ? LoongArch::PseudoJIRL_TAIL : LoongArch::PseudoJIRL_CALL;
Register ScratchReg = IsTailCall ? LoongArch::R20 : LoongArch::R1;
- MachineInstrBuilder MIB =
- BuildMI(MBB, MBBI, DL, TII->get(LoongArch::PCADDU18I), ScratchReg);
+ bool Is64Bit = MF->getSubtarget<LoongArchSubtarget>().is64Bit();
+ unsigned PC = Is64Bit ? LoongArch::PCADDU18I : LoongArch::PCADDU12I;
+ unsigned MO = Is64Bit ? LoongArchII::MO_CALL36 : LoongArchII::MO_CALL30;
+ MachineInstrBuilder MIB = BuildMI(MBB, MBBI, DL, TII->get(PC), ScratchReg);
CALL =
BuildMI(MBB, MBBI, DL, TII->get(Opcode)).addReg(ScratchReg).addImm(0);
if (Func.isSymbol())
- MIB.addExternalSymbol(Func.getSymbolName(), LoongArchII::MO_CALL36);
+ MIB.addExternalSymbol(Func.getSymbolName(), MO);
else
- MIB.addDisp(Func, 0, LoongArchII::MO_CALL36);
+ MIB.addDisp(Func, 0, MO);
break;
}
}
diff --git a/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp b/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp
index 7dae4d30d31be..372819e8e30b2 100644
--- a/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp
+++ b/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp
@@ -2812,13 +2812,23 @@ SDValue LoongArchTargetLowering::getAddr(NodeTy *N, SelectionDAG &DAG,
case CodeModel::Small:
case CodeModel::Medium:
if (IsLocal) {
- // This generates the pattern (PseudoLA_PCREL sym), which expands to
- // (addi.w/d (pcalau12i %pc_hi20(sym)) %pc_lo12(sym)).
+ // This generates the pattern (PseudoLA_PCREL sym), which
+ //
+ // for la32r expands to:
+ // (addi.w (pcaddu12i %pcadd_hi20(sym)) %pcadd_lo12(.Lpcadd_hi)).
+ //
+ // for la32s and la64 expands to:
+ // (addi.d (pcalau12i %pc_hi20(sym)) %pc_lo12(sym)).
Load = SDValue(
DAG.getMachineNode(LoongArch::PseudoLA_PCREL, DL, Ty, Addr), 0);
} else {
- // This generates the pattern (PseudoLA_GOT sym), which expands to (ld.w/d
- // (pcalau12i %got_pc_hi20(sym)) %got_pc_lo12(sym)).
+ // This generates the pattern (PseudoLA_GOT sym), which
+ //
+ // for la32r expands to:
+ // (ld.w (pcaddu12i %pcadd_got_hi20(sym)) %pcadd_lo12(.Lpcadd_hi)).
+ //
+ // for la32s and la64 expands to:
+ // (ld.d (pcalau12i %got_pc_hi20(sym)) %got_pc_lo12(sym)).
Load =
SDValue(DAG.getMachineNode(LoongArch::PseudoLA_GOT, DL, Ty, Addr), 0);
}
@@ -7446,7 +7456,6 @@ LoongArchTargetLowering::LowerCall(CallLoweringInfo &CLI,
Op = IsTailCall ? LoongArchISD::TAIL : LoongArchISD::CALL;
break;
case CodeModel::Medium:
- assert(Subtarget.is64Bit() && "Medium code model requires LA64");
Op = IsTailCall ? LoongArchISD::TAIL_MEDIUM : LoongArchISD::CALL_MEDIUM;
break;
case CodeModel::Large:
diff --git a/llvm/lib/Target/LoongArch/LoongArchInstrInfo.cpp b/llvm/lib/Target/LoongArch/LoongArchInstrInfo.cpp
index 26d36f1c5058f..89e6571158735 100644
--- a/llvm/lib/Target/LoongArch/LoongArchInstrInfo.cpp
+++ b/llvm/lib/Target/LoongArch/LoongArchInstrInfo.cpp
@@ -18,6 +18,7 @@
#include "MCTargetDesc/LoongArchMatInt.h"
#include "llvm/CodeGen/RegisterScavenging.h"
#include "llvm/CodeGen/StackMaps.h"
+#include "llvm/MC/MCContext.h"
#include "llvm/MC/MCInstBuilder.h"
using namespace llvm;
@@ -621,30 +622,40 @@ void LoongArchInstrInfo::insertIndirectBranch(MachineBasicBlock &MBB,
const TargetRegisterInfo *TRI = MF->getSubtarget().getRegisterInfo();
LoongArchMachineFunctionInfo *LAFI =
MF->getInfo<LoongArchMachineFunctionInfo>();
+ bool Has32S = STI.hasFeature(LoongArch::Feature32S);
if (!isInt<32>(BrOffset))
report_fatal_error(
"Branch offsets outside of the signed 32-bit range not supported");
Register ScratchReg = MRI.createVirtualRegister(&LoongArch::GPRRegClass);
+ MachineInstr *PCAI = nullptr;
+ MachineInstr *ADDI = nullptr;
auto II = MBB.end();
-
- MachineInstr &PCALAU12I =
- *BuildMI(MBB, II, DL, get(LoongArch::PCALAU12I), ScratchReg)
- .addMBB(&DestBB, LoongArchII::MO_PCREL_HI);
- MachineInstr &ADDI =
- *BuildMI(MBB, II, DL,
- get(STI.is64Bit() ? LoongArch::ADDI_D : LoongArch::ADDI_W),
- ScratchReg)
- .addReg(ScratchReg)
- .addMBB(&DestBB, LoongArchII::MO_PCREL_LO);
+ unsigned ADDIOp = STI.is64Bit() ? LoongArch::ADDI_D : LoongArch::ADDI_W;
+
+ if (Has32S) {
+ PCAI = BuildMI(MBB, II, DL, get(LoongArch::PCALAU12I), ScratchReg)
+ .addMBB(&DestBB, LoongArchII::MO_PCREL_HI);
+ ADDI = BuildMI(MBB, II, DL, get(ADDIOp), ScratchReg)
+ .addReg(ScratchReg)
+ .addMBB(&DestBB, LoongArchII::MO_PCREL_LO);
+ } else {
+ MCSymbol *PCAddSymbol = MF->getContext().createNamedTempSymbol("pcadd_hi");
+ PCAI = BuildMI(MBB, II, DL, get(LoongArch::PCADDU12I), ScratchReg)
+ .addMBB(&DestBB, LoongArchII::MO_PCADD_HI);
+ PCAI->setPreInstrSymbol(*MF, PCAddSymbol);
+ ADDI = BuildMI(MBB, II, DL, get(ADDIOp), ScratchReg)
+ .addReg(ScratchReg)
+ .addSym(PCAddSymbol, LoongArchII::MO_PCADD_LO);
+ }
BuildMI(MBB, II, DL, get(LoongArch::PseudoBRIND))
.addReg(ScratchReg, RegState::Kill)
.addImm(0);
RS->enterBasicBlockEnd(MBB);
Register Scav = RS->scavengeRegisterBackwards(
- LoongArch::GPRRegClass, PCALAU12I.getIterator(), /*RestoreAfter=*/false,
+ LoongArch::GPRRegClass, PCAI->getIterator(), /*RestoreAfter=*/false,
/*SPAdj=*/0, /*AllowSpill=*/false);
if (Scav != LoongArch::NoRegister)
RS->setRegUsed(Scav);
@@ -655,12 +666,13 @@ void LoongArchInstrInfo::insertIndirectBranch(MachineBasicBlock &MBB,
int FrameIndex = LAFI->getBranchRelaxationSpillFrameIndex();
if (FrameIndex == -1)
report_fatal_error("The function size is incorrectly estimated.");
- storeRegToStackSlot(MBB, PCALAU12I, Scav, /*IsKill=*/true, FrameIndex,
+ storeRegToStackSlot(MBB, PCAI, Scav, /*IsKill=*/true, FrameIndex,
&LoongArch::GPRRegClass, TRI, Register());
- TRI->eliminateFrameIndex(std::prev(PCALAU12I.getIterator()),
+ TRI->eliminateFrameIndex(std::prev(PCAI->getIterator()),
/*SpAdj=*/0, /*FIOperandNum=*/1);
- PCALAU12I.getOperand(1).setMBB(&RestoreBB);
- ADDI.getOperand(2).setMBB(&RestoreBB);
+ PCAI->getOperand(1).setMBB(&RestoreBB);
+ if (Has32S)
+ ADDI->getOperand(2).setMBB(&RestoreBB);
loadRegFromStackSlot(RestoreBB, RestoreBB.end(), Scav, FrameIndex,
&LoongArch::GPRRegClass, TRI, Register());
TRI->eliminateFrameIndex(RestoreBB.back(),
@@ -735,6 +747,7 @@ LoongArchInstrInfo::getSerializableDirectMachineOperandTargetFlags() const {
{MO_IE_PC64_HI, "loongarch-ie-pc64-hi"},
{MO_LD_PC_HI, "loongarch-ld-pc-hi"},
{MO_GD_PC_HI, "loongarch-gd-pc-hi"},
+ {MO_CALL30, "loongarch-call30"},
{MO_CALL36, "loongarch-call36"},
{MO_DESC_PC_HI, "loongarch-desc-pc-hi"},
{MO_DESC_PC_LO, "loongarch-desc-pc-lo"},
@@ -744,7 +757,12 @@ LoongArchInstrInfo::getSerializableDirectMachineOperandTargetFlags() const {
{MO_DESC_CALL, "loongarch-desc-call"},
{MO_LE_HI_R, "loongarch-le-hi-r"},
{MO_LE_ADD_R, "loongarch-le-add-r"},
- {MO_LE_LO_R, "loongarch-le-lo-r"}};
+ {MO_LE_LO_R, "loongarch-le-lo-r"},
+ {MO_PCADD_HI, "loongarch-pcadd-hi"},
+ {MO_PCADD_LO, "loongarch-pcadd-lo"},
+ {MO_PCADD_GOT_HI, "loongarch-pcadd-got-hi"},
+ {MO_PCADD_IE_HI, "loongarch-pcadd-ie-hi"},
+ {MO_PCADD_DESC_HI, "loongarch-pcadd-desc-hi"}};
return ArrayRef(TargetFlags);
}
diff --git a/llvm/lib/Target/LoongArch/LoongArchInstrInfo.td b/llvm/lib/Target/LoongArch/LoongArchInstrInfo.td
index 2b94e65cac0e5..18984bab29466 100644
--- a/llvm/lib/Target/LoongArch/LoongArchInstrInfo.td
+++ b/llvm/lib/Target/LoongArch/LoongArchInstrInfo.td
@@ -431,6 +431,10 @@ def simm20_lu32id : SImm20Operand {
let ParserMatchClass = SImmAsmOperand<20, "lu32id">;
}
+def simm20_pcaddu12i : SImm20Operand {
+ let ParserMatchClass = SImmAsmOperand<20, "pcaddu12i">;
+}
+
def simm20_pcaddu18i : SImm20Operand {
let ParserMatchClass = SImmAsmOperand<20, "pcaddu18i">;
}
@@ -808,7 +812,7 @@ def SLT : ALU_3R<0x00120000>;
def SLTU : ALU_3R<0x00128000>;
def SLTI : ALU_2RI12<0x02000000, simm12>;
def SLTUI : ALU_2RI12<0x02400000, simm12>;
-def PCADDU12I : ALU_1RI20<0x1c000000, simm20>;
+def PCADDU12I : ALU_1RI20<0x1c000000, simm20_pcaddu12i>;
def AND : ALU_3R<0x00148000>;
def OR : ALU_3R<0x00150000>;
def NOR : ALU_3R<0x00140000>;
@@ -1602,12 +1606,10 @@ def : Pat<(loongarch_call texternalsym:$func), (PseudoCALL texternalsym:$func)>;
let isCall = 1, Defs = [R1, R20], Size = 8 in
def PseudoCALL_MEDIUM : Pseudo<(outs), (ins bare_symbol:$func)>;
-let Predicates = [IsLA64] in {
def : Pat<(loongarch_call_medium tglobaladdr:$func),
(PseudoCALL_MEDIUM tglobaladdr:$func)>;
def : Pat<(loongarch_call_medium texternalsym:$func),
(PseudoCALL_MEDIUM texternalsym:$func)>;
-} // Predicates = [IsLA64]
// Function call with 'Large' code model.
let isCall = 1, Defs = [R1] in
@@ -1624,10 +1626,9 @@ let isCall = 1, Defs = [R1] in
def PseudoCALLIndirect : Pseudo<(outs), (ins GPR:$rj),
[(loongarch_call GPR:$rj)]>,
PseudoInstExpansion<(JIRL R1, GPR:$rj, 0)>;
-let Predicates = [IsLA64] in {
def : Pat<(loongarch_call_medium GPR:$rj), (PseudoCALLIndirect GPR:$rj)>;
+let Predicates = [IsLA64] in
def : Pat<(loongarch_call_large GPR:$rj), (PseudoCALLIndirect GPR:$rj)>;
-}
let isCall = 1, hasSideEffects = 0, mayStore = 0, mayLoad = 0, Defs = [R1] in
def PseudoJIRL_CALL : Pseudo<(outs), (ins GPR:$rj, simm16_lsl2:$imm16)>,
@@ -1652,12 +1653,10 @@ let isCall = 1, isTerminator = 1, isReturn = 1, isBarrier = 1,
Uses = [R3], Defs = [R20], Size = 8 in
def PseudoTAIL_MEDIUM : Pseudo<(outs), (ins bare_symbol:$dst)>;
-let Predicates = [IsLA64] in {
def : Pat<(loongarch_tail_medium (iPTR tglobaladdr:$dst)),
(PseudoTAIL_MEDIUM tglobaladdr:$dst)>;
def : Pat<(loongarch_tail_medium (iPTR texternalsym:$dst)),
(PseudoTAIL_MEDIUM texternalsym:$dst)>;
-} // Predicates = [IsLA64]
// Tail call with 'Large' code model.
let isCall = 1, isTerminator = 1, isReturn = 1, isBarrier = 1, Uses = [R3] in
@@ -1674,10 +1673,9 @@ let isCall = 1, isTerminator = 1, isReturn = 1, isBarrier = 1, Uses = [R3] in
def PseudoTAILIndirect : Pseudo<(outs), (ins GPRT:$rj),
[(loongarch_tail GPRT:$rj)]>,
PseudoInstExpansion<(JIRL R0, GPR:$rj, 0)>;
-let Predicates = [IsLA64] in {
def : Pat<(loongarch_tail_medium GPR:$rj), (PseudoTAILIndirect GPR:$rj)>;
+let Predicates = [IsLA64] in
def : Pat<(loongarch_tail_large GPR:$rj), (PseudoTAILIndirect GPR:$rj)>;
-}
let isCall = 1, isTerminator = 1, isReturn = 1, isBarrier = 1,
hasSideEffects = 0, mayStore = 0, mayLoad = 0, Uses = [R3] in
@@ -1690,6 +1688,19 @@ def PseudoJIRL_TAIL : Pseudo<(outs), (ins GPR:$rj, simm16_lsl2:$imm16)>,
PseudoInstExpansion<(JIRL R0, GPR:$rj,
simm16_lsl2:$imm16)>;
+/// call30/taill30 macro instructions
+let isCall = 1, isBarrier = 1, isCodeGenOnly = 0, isAsmParserOnly = 1,
+ Defs = [R1], hasSideEffects = 0, mayStore = 0, mayLoad = 0 in
+def PseudoCALL30 : Pseudo<(outs), (ins bare_symbol:$dst), [],
+ "call30", "$dst">,
+ Requires<[IsLA32]>;
+let isCall = 1, isTerminator = 1, isReturn = 1, isBarrier = 1, Uses = [R3],
+ isCodeGenOnly = 0, isAsmParserOnly = 1, hasSideEffects = 0,
+ mayStore = 0, mayLoad = 0 in
+def PseudoTAIL30 : Pseudo<(outs), (ins GPR:$tmp, bare_symbol:$dst), [],
+ "tail30", "$tmp, $dst">,
+ Requires<[IsLA32]>;
+
/// call36/taill36 macro instructions
let isCall = 1, isBarrier = 1, isCodeGenOnly = 0, isAsmParserOnly = 1,
Defs = [R1], hasSideEffects = 0, mayStore = 0, mayLoad = 0 in
diff --git a/llvm/lib/Target/LoongArch/LoongArchMCInstLower.cpp b/llvm/lib/Target/LoongArch/LoongArchMCInstLower.cpp
index 455e6ad7c3ac5..c0815d0e013bb 100644
--- a/llvm/lib/Target/LoongArch/LoongArchMCInstLower.cpp
+++ b/llvm/lib/Target/LoongArch/LoongArchMCInstLower.cpp
@@ -92,6 +92,9 @@ static MCOperand lowerSymbolOperand(const MachineOperand &MO, MCSymbol *Sym,
case LoongArchII::MO_GD_PC_HI:
Kind = ELF::R_LARCH_TLS_GD_PC_HI20;
break;
+ case LoongArchII::MO_CALL30:
+ Kind = ELF::R_LARCH_CALL30;
+ break;
case LoongArchII::MO_CALL36:
Kind = ELF::R_LARCH_CALL36;
break;
@@ -122,6 +125,21 @@ static MCOperand lowerSymbolOperand(const MachineOperand &MO, MCSymbol *Sym,
case LoongArchII::MO_LE_LO_R:
Kind = ELF::R_LARCH_TLS_LE_LO12_R;
break;
+ case LoongArchII::MO_PCADD_HI:
+ Kind = ELF::R_LARCH_PCADD_HI20;
+ break;
+ case LoongArchII::MO_PCADD_LO:
+ Kind = ELF::R_LARCH_PCADD_LO12_I;
+ break;
+ case LoongArchII::MO_PCADD_GOT_HI:
+ Kind = ELF::R_LARCH_PCADD_GOT_HI20;
+ break;
+ case LoongArchII::MO_PCADD_IE_HI:
+ Kind = ELF::R_LARCH_PCADD_TLS_IE_HI20;
+ break;
+ case LoongArchII::MO_PCADD_DESC_HI:
+ Kind = ELF::R_LARCH_PCADD_TLS_DESC_HI20;
+ break;
// TODO: Handle more target-flags.
}
@@ -175,6 +193,9 @@ bool llvm::lowerLoongArchMachineOperandToMCOperand(const MachineOperand &MO,
case MachineOperand::MO_JumpTableIndex:
MCOp = lowerSymbolOperand(MO, AP.GetJTISymbol(MO.getIndex()), AP);
break;
+ case MachineOperand::MO_MCSymbol:
+ MCOp = lowerSymbolOperand(MO, MO.getMCSymbol(), AP);
+ break;
}
return true;
}
diff --git a/llvm/lib/Target/LoongArch/LoongArchMergeBaseOffset.cpp b/llvm/lib/Target/LoongArch/LoongArchMergeBaseOffset.cpp
index f62753356a4dd..0e7abcc948b33 100644
--- a/llvm/lib/Target/LoongArch/LoongArchMergeBaseOffset.cpp
+++ b/llvm/lib/Target/LoongArch/LoongArchMergeBaseOffset.cpp
@@ -79,7 +79,7 @@ INITIALIZE_PASS(LoongArchMergeBaseOffsetOpt, DEBUG_TYPE,
// Detect either of the patterns:
//
// 1. (small/medium):
-// pcalau12i vreg1, %pc_hi20(s)
+// pcaxxu12i vreg1, %pc_hi20(s)
// addi.d vreg2, vreg1, %pc_lo12(s)
//
// 2. (large):
@@ -102,11 +102,13 @@ bool LoongArchMergeBaseOffsetOpt::detectFoldable(MachineInstr &Hi20,
MachineInstr *&Lo20,
MachineInstr *&Hi12,
MachineInstr *&Last) {
- if (Hi20.getOpcode() != LoongArch::PCALAU12I)
+ if (Hi20.getOpcode() != LoongArch::PCALAU12I &&
+ Hi20.getOpcode() != LoongArch::PCADDU12I)
return false;
const MachineOperand &Hi20Op1 = Hi20.getOperand(1);
- if (LoongArchII::getDirectFlags(Hi20Op1) != LoongArchII::MO_PCREL_HI)
+ if (LoongArchII::getDirectFlags(Hi20Op1) != LoongArchII::MO_PCREL_HI &&
+ LoongArchII::getDirectFlags(Hi20Op1) != LoongArchII::MO_PCADD_HI)
return false;
auto isGlobalOrCPIOrBlockAddress = [](const MachineOperand &Op) {
@@ -157,8 +159,10 @@ bool LoongArchMergeBaseOffsetOpt::detectFoldable(MachineInstr &Hi20,
}
const MachineOperand &Lo12Op2 = Lo12->getOperand(2);
- assert(Hi20.getOpcode() == LoongArch::PCALAU12I);
- if (LoongArchII::getDirectFlags(Lo12Op2) != LoongArchII::MO_PCREL_LO ||
+ assert(Hi20.getOpcode() == LoongArch::PCALAU12I ||
+ Hi20.getOpcode() == LoongArch::PCADDU12I);
+ if ((LoongArchII::getDirectFlags(Lo12Op2) != LoongArchII::MO_PCREL_LO &&
+ LoongArchII::getDirectFlags(Lo12Op2) != LoongArchII::MO_PCADD_LO) ||
!(isGlobalOrCPIOrBlockAddress(Lo12Op2) || Lo12Op2.isMCSymbol()) ||
Lo12Op2.getOffset() != 0)
return false;
@@ -258,8 +262,10 @@ void LoongArchMergeBaseOffsetOpt::foldOffset(
MachineInstr *&Hi12, MachineInstr *&Last, MachineInstr &Tail,
int64_t Offset) {
// Put the offset back in Hi and the Lo
+ MachineOperand &Lo12Op2 = Lo12.getOperand(2);
Hi20.getOperand(1).setOffset(Offset);
- Lo12.getOperand(2).setOffset(Offset);
+ if (LoongArchII::getDirectFlags(Lo12Op2) != LoongArchII::MO_PCADD_LO)
+ Lo12Op2.setOffset(Offset);
if (Lo20 && Hi12) {
Lo20->getOperand(2).setOffset(Offset);
Hi12->getOperand(2).setOffset(Offset);
@@ -298,7 +304,7 @@ void LoongArchMergeBaseOffsetOpt::foldOffset(
//
// Base address lowering is of the form:
// 1) pcala:
-// Hi20: pcalau12i vreg1, %pc_hi20(s)
+// Hi20: pcaxxu12i vreg1, %pc_hi20(s)
// +--- Lo12: addi.d vreg2, vreg1, %pc_lo12(s)
// | Lo20: lu32i.d vreg2, %pc64_lo20(s) !
// +--- Hi12: lu52i.d vreg2, vreg2, %pc64_hi12(s) !
@@ -426,7 +432,7 @@ bool LoongArchMergeBaseOffsetOpt::detectAndFoldOffset(MachineInstr &Hi20,
// Look for arithmetic instructions we can get an offset from.
// We might be able to remove the arithmetic instructions by folding the
- // offset into the PCALAU12I+(ADDI/ADDI+LU32I+LU52I) or
+ // offset into the PCAXXU12I+(ADDI/ADDI+LU32I+LU52I) or
// LU12I_W+PseudoAddTPRel+ADDI.
if (!MRI->hasOneUse(DestReg))
return false;
@@ -548,13 +554,13 @@ bool LoongArchMergeBaseOffsetOpt::foldIntoMemoryOps(MachineInstr &Hi20,
//
// 1. (small/medium):
// 1.1. pcala
- // pcalau12i vreg1, %pc_hi20(s)
+ // pcaxxu12i vreg1, %pc_hi20(s)
// addi.d vreg2, vreg1, %pc_lo12(s)
// ld.w vreg3, 8(vreg2)
//
// =>
//
- // pcalau12i vreg1, %pc_hi20(s+8)
+ // pcalxx12i vreg1, %pc_hi20(s+8)
// ld.w vreg3, vreg1, %pc_lo12(s+8)(vreg1)
//
// 1.2. tls-le
@@ -708,13 +714,13 @@ bool LoongArchMergeBaseOffsetOpt::foldIntoMemoryOps(MachineInstr &Hi20,
// be relaxed after being optimized.
//
// For example:
- // pcalau12i $a0, %pc_hi20(symbol)
+ // pcaxxu12i $a0, %pc_hi20(symbol)
// addi.d $a0, $a0, %pc_lo12(symbol)
// ld.w $a0, $a0, 0
//
// =>
//
- // pcalau12i $a0, %pc_hi20(symbol)
+ // pcaxxu12i $a0, %pc_hi20(symbol)
// ld.w $a0, $a0, %pc_lo12(symbol)
//
// Code sequence optimized before can be relax by linker. But after being
@@ -722,12 +728,14 @@ bool LoongArchMergeBaseOffsetOpt::foldIntoMemoryOps(MachineInstr &Hi20,
// carried by them.
Hi20.getOperand(1).setOffset(NewOffset);
MachineOperand &ImmOp = Lo12.getOperand(2);
- ImmOp.setOffset(NewOffset);
+ if (LoongArchII::getDirectFlags(ImmOp) != LoongArchII::MO_PCADD_LO)
+ ImmOp.setOffset(NewOffset);
if (Lo20 && Hi12) {
Lo20->getOperand(2).setOffset(NewOffset);
Hi12->getOperand(2).setOffset(NewOffset);
}
- if (Hi20.getOpcode() == LoongArch::PCALAU12I) {
+ if (Hi20.getOpcode() == LoongArch::PCADDU12I ||
+ Hi20.getOpcode() == LoongArch::PCALAU12I) {
Hi20.getOperand(1).setTargetFlags(
LoongArchII::getDirectFlags(Hi20.getOperand(1)));
ImmOp.setTargetFlags(LoongArchII::getDirectFlags(ImmOp));
@@ -785,7 +793,8 @@ bool LoongArchMergeBaseOffsetOpt::foldIntoMemoryOps(MachineInstr &Hi20,
return true;
}
- if (Hi20.getOpcode() == LoongArch::PCALAU12I) {
+ if (Hi20.getOpcode() == LoongArch::PCADDU12I ||
+ Hi20.getOpcode() == LoongArch::PCALAU12I) {
MRI->replaceRegWith(Lo12.getOperand(0).getReg(),
Hi20.getOperand(0).getReg());
} else if (Hi20.getOpcode() == LoongArch::LU12I_W) {
@@ -812,7 +821,8 @@ bool LoongArchMergeBaseOffsetOpt::runOnMachineFunction(MachineFunction &Fn) {
MachineInstr *Lo20 = nullptr;
MachineInstr *Hi12 = nullptr;
MachineInstr *Last = nullptr;
- if (Hi20.getOpcode() == LoongArch::PCALAU12I) {
+ if (Hi20.getOpcode() == LoongArch::PCADDU12I ||
+ Hi20.getOpcode() == LoongArch::PCALAU12I) {
// Detect foldable pcala code sequence in small/medium/large code model.
if (!detectFoldable(Hi20, Lo12, Lo20, Hi12, Last))
continue;
diff --git a/llvm/lib/Target/LoongArch/LoongArchTargetMachine.cpp b/llvm/lib/Target/LoongArch/LoongArchTargetMachine.cpp
index c36db9c75dd3a..07fe6fcb128fb 100644
--- a/llvm/lib/Target/LoongArch/LoongArchTargetMachine.cpp
+++ b/llvm/lib/Target/LoongArch/LoongArchTargetMachine.cpp
@@ -77,8 +77,8 @@ getEffectiveLoongArchCodeModel(const Triple &TT,
switch (*CM) {
case CodeModel::Small:
- return *CM;
case CodeModel::Medium:
+ return *CM;
case CodeModel::Large:
if (!TT.isArch64Bit())
report_fatal_error("Medium/Large code model requires LA64");
diff --git a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchBaseInfo.h b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchBaseInfo.h
index 833cd06261624..a9bd509fa189a 100644
--- a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchBaseInfo.h
+++ b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchBaseInfo.h
@@ -48,6 +48,7 @@ enum {
MO_IE_PC64_HI,
MO_LD_PC_HI,
MO_GD_PC_HI,
+ MO_CALL30,
MO_CALL36,
MO_DESC_PC_HI,
MO_DESC_PC_LO,
@@ -58,6 +59,11 @@ enum {
MO_LE_HI_R,
MO_LE_ADD_R,
MO_LE_LO_R,
+ MO_PCADD_HI,
+ MO_PCADD_LO,
+ MO_PCADD_GOT_HI,
+ MO_PCADD_IE_HI,
+ MO_PCADD_DESC_HI,
// TODO: Add more flags.
// Used to differentiate between target-specific "direct" flags and "bitmask"
diff --git a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchELFObjectWriter.cpp b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchELFObjectWriter.cpp
index faf3cba59a53c..35d4d4c84f7d9 100644
--- a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchELFObjectWriter.cpp
+++ b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchELFObjectWriter.cpp
@@ -26,6 +26,9 @@ class LoongArchELFObjectWriter : public MCELFObjectTargetWriter {
~LoongArchELFObjectWriter() override;
bool needsRelocateWithSymbol(const MCValue &, unsigned Type) const override {
+ // PCADD_LO12_I must be relocated with a symbol, and its addend must be 0
+ if (Type == ELF::R_LARCH_PCADD_LO12_I)
+ return true;
return EnableRelax;
}
diff --git a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCAsmInfo.cpp b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCAsmInfo.cpp
index 8dc7c88f6e78e..70a29fe72e13f 100644
--- a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCAsmInfo.cpp
+++ b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCAsmInfo.cpp
@@ -96,6 +96,8 @@ static StringRef getLoongArchSpecifierName(uint16_t S) {
return "gd_pc_hi20";
case ELF::R_LARCH_TLS_GD_HI20:
return "gd_hi20";
+ case ELF::R_LARCH_CALL30:
+ return "call30";
case ELF::R_LARCH_CALL36:
return "call36";
case ELF::R_LARCH_TLS_DESC_PC_HI20:
@@ -132,6 +134,16 @@ static StringRef getLoongArchSpecifierName(uint16_t S) {
return "gd_pcrel_20";
case ELF::R_LARCH_TLS_DESC_PCREL20_S2:
return "desc_pcrel_20";
+ case ELF::R_LARCH_PCADD_HI20:
+ return "pcadd_hi20";
+ case ELF::R_LARCH_PCADD_LO12_I:
+ return "pcadd_lo12";
+ case ELF::R_LARCH_PCADD_GOT_HI20:
+ return "pcadd_got_hi20";
+ case ELF::R_LARCH_PCADD_TLS_IE_HI20:
+ return "pcadd_ie_hi20";
+ case ELF::R_LARCH_PCADD_TLS_DESC_HI20:
+ return "pcadd_desc_hi20";
}
}
@@ -173,6 +185,7 @@ LoongArchMCExpr::Specifier LoongArch::parseSpecifier(StringRef name) {
.Case("ld_hi20", ELF::R_LARCH_TLS_LD_HI20)
.Case("gd_pc_hi20", ELF::R_LARCH_TLS_GD_PC_HI20)
.Case("gd_hi20", ELF::R_LARCH_TLS_GD_HI20)
+ .Case("call30", ELF::R_LARCH_CALL30)
.Case("call36", ELF::R_LARCH_CALL36)
.Case("desc_pc_hi20", ELF::R_LARCH_TLS_DESC_PC_HI20)
.Case("desc_pc_lo12", ELF::R_LARCH_TLS_DESC_PC_LO12)
@@ -191,6 +204,11 @@ LoongArchMCExpr::Specifier LoongArch::parseSpecifier(StringRef name) {
.Case("ld_pcrel_20", ELF::R_LARCH_TLS_LD_PCREL20_S2)
.Case("gd_pcrel_20", ELF::R_LARCH_TLS_GD_PCREL20_S2)
.Case("desc_pcrel_20", ELF::R_LARCH_TLS_DESC_PCREL20_S2)
+ .Case("pcadd_hi20", ELF::R_LARCH_PCADD_HI20)
+ .Case("pcadd_lo12", ELF::R_LARCH_PCADD_LO12_I)
+ .Case("pcadd_got_hi20", ELF::R_LARCH_PCADD_GOT_HI20)
+ .Case("pcadd_ie_hi20", ELF::R_LARCH_PCADD_TLS_IE_HI20)
+ .Case("pcadd_desc_hi20", ELF::R_LARCH_PCADD_TLS_DESC_HI20)
.Default(0);
}
diff --git a/llvm/test/CodeGen/LoongArch/block-address.ll b/llvm/test/CodeGen/LoongArch/block-address.ll
index 114cbb73a5125..6b8c8ce93f944 100644
--- a/llvm/test/CodeGen/LoongArch/block-address.ll
+++ b/llvm/test/CodeGen/LoongArch/block-address.ll
@@ -7,11 +7,13 @@
define void @test_blockaddress() nounwind {
; LA32-LABEL: test_blockaddress:
; LA32: # %bb.0:
-; LA32-NEXT: pcalau12i $a0, %pc_hi20(addr)
-; LA32-NEXT: pcalau12i $a1, %pc_hi20(.Ltmp0)
-; LA32-NEXT: addi.w $a1, $a1, %pc_lo12(.Ltmp0)
-; LA32-NEXT: st.w $a1, $a0, %pc_lo12(addr)
-; LA32-NEXT: ld.w $a0, $a0, %pc_lo12(addr)
+; LA32-NEXT: .Lpcadd_hi0:
+; LA32-NEXT: pcaddu12i $a0, %pcadd_hi20(addr)
+; LA32-NEXT: .Lpcadd_hi1:
+; LA32-NEXT: pcaddu12i $a1, %pcadd_hi20(.Ltmp0)
+; LA32-NEXT: addi.w $a1, $a1, %pcadd_lo12(.Lpcadd_hi1)
+; LA32-NEXT: st.w $a1, $a0, %pcadd_lo12(.Lpcadd_hi0)
+; LA32-NEXT: ld.w $a0, $a0, %pcadd_lo12(.Lpcadd_hi0)
; LA32-NEXT: jr $a0
; LA32-NEXT: .Ltmp0: # Block address taken
; LA32-NEXT: .LBB0_1: # %block
diff --git a/llvm/test/CodeGen/LoongArch/branch-relaxation-spill-32.ll b/llvm/test/CodeGen/LoongArch/branch-relaxation-spill-32.ll
index 5c96d5c416b9c..e37863efdf5f3 100644
--- a/llvm/test/CodeGen/LoongArch/branch-relaxation-spill-32.ll
+++ b/llvm/test/CodeGen/LoongArch/branch-relaxation-spill-32.ll
@@ -122,9 +122,10 @@ define void @relax_b28_spill() {
; CHECK-NEXT: #NO_APP
; CHECK-NEXT: beq $s7, $s8, .LBB0_1
; CHECK-NEXT: # %bb.4:
-; CHECK-NEXT: st.w $t8, $sp, 0
-; CHECK-NEXT: pcalau12i $t8, %pc_hi20(.LBB0_5)
-; CHECK-NEXT: addi.w $t8, $t8, %pc_lo12(.LBB0_5)
+; CHECK-NEXT: st.w $t8, $sp, 0 # 4-byte Folded Spill
+; CHECK-NEXT: .Lpcadd_hi0:
+; CHECK-NEXT: pcaddu12i $t8, %pcadd_hi20(.LBB0_5)
+; CHECK-NEXT: addi.w $t8, $t8, %pcadd_lo12(.Lpcadd_hi0)
; CHECK-NEXT: jr $t8
; CHECK-NEXT: .LBB0_1: # %iftrue
; CHECK-NEXT: #APP
@@ -132,7 +133,7 @@ define void @relax_b28_spill() {
; CHECK-NEXT: #NO_APP
; CHECK-NEXT: b .LBB0_3
; CHECK-NEXT: .LBB0_5: # %iffalse
-; CHECK-NEXT: ld.w $t8, $sp, 0
+; CHECK-NEXT: ld.w $t8, $sp, 0 # 4-byte Folded Reload
; CHECK-NEXT: # %bb.2: # %iffalse
; CHECK-NEXT: #APP
; CHECK-NEXT: # reg use $zero
diff --git a/llvm/test/CodeGen/LoongArch/branch-relaxation.ll b/llvm/test/CodeGen/LoongArch/branch-relaxation.ll
index f88603b6c79db..ffeaa5283ada8 100644
--- a/llvm/test/CodeGen/LoongArch/branch-relaxation.ll
+++ b/llvm/test/CodeGen/LoongArch/branch-relaxation.ll
@@ -119,8 +119,9 @@ define i32 @relax_b28(i1 %a) {
; LA32R-NEXT: andi $a0, $a0, 1
; LA32R-NEXT: bne $a0, $zero, .LBB2_1
; LA32R-NEXT: # %bb.3:
-; LA32R-NEXT: pcalau12i $a0, %pc_hi20(.LBB2_2)
-; LA32R-NEXT: addi.w $a0, $a0, %pc_lo12(.LBB2_2)
+; LA32R-NEXT: .Lpcadd_hi0:
+; LA32R-NEXT: pcaddu12i $a0, %pcadd_hi20(.LBB2_2)
+; LA32R-NEXT: addi.w $a0, $a0, %pcadd_lo12(.Lpcadd_hi0)
; LA32R-NEXT: jr $a0
; LA32R-NEXT: .LBB2_1: # %iftrue
; LA32R-NEXT: ori $a0, $zero, 1
diff --git a/llvm/test/CodeGen/LoongArch/calling-conv-half.ll b/llvm/test/CodeGen/LoongArch/calling-conv-half.ll
index c88b67f13d1e7..ee204ff643b35 100644
--- a/llvm/test/CodeGen/LoongArch/calling-conv-half.ll
+++ b/llvm/test/CodeGen/LoongArch/calling-conv-half.ll
@@ -226,8 +226,9 @@ define i32 @caller_half_in_fregs() nounwind {
; LA32F-ILP32D: # %bb.0:
; LA32F-ILP32D-NEXT: addi.w $sp, $sp, -16
; LA32F-ILP32D-NEXT: st.w $ra, $sp, 12 # 4-byte Folded Spill
-; LA32F-ILP32D-NEXT: pcalau12i $a0, %pc_hi20(.LCPI1_0)
-; LA32F-ILP32D-NEXT: fld.s $fa0, $a0, %pc_lo12(.LCPI1_0)
+; LA32F-ILP32D-NEXT: .Lpcadd_hi0:
+; LA32F-ILP32D-NEXT: pcaddu12i $a0, %pcadd_hi20(.LCPI1_0)
+; LA32F-ILP32D-NEXT: fld.s $fa0, $a0, %pcadd_lo12(.Lpcadd_hi0)
; LA32F-ILP32D-NEXT: ori $a0, $zero, 1
; LA32F-ILP32D-NEXT: ori $a1, $zero, 2
; LA32F-ILP32D-NEXT: ori $a2, $zero, 3
@@ -264,8 +265,9 @@ define i32 @caller_half_in_fregs() nounwind {
; LA32D-ILP32D: # %bb.0:
; LA32D-ILP32D-NEXT: addi.w $sp, $sp, -16
; LA32D-ILP32D-NEXT: st.w $ra, $sp, 12 # 4-byte Folded Spill
-; LA32D-ILP32D-NEXT: pcalau12i $a0, %pc_hi20(.LCPI1_0)
-; LA32D-ILP32D-NEXT: fld.s $fa0, $a0, %pc_lo12(.LCPI1_0)
+; LA32D-ILP32D-NEXT: .Lpcadd_hi0:
+; LA32D-ILP32D-NEXT: pcaddu12i $a0, %pcadd_hi20(.LCPI1_0)
+; LA32D-ILP32D-NEXT: fld.s $fa0, $a0, %pcadd_lo12(.Lpcadd_hi0)
; LA32D-ILP32D-NEXT: ori $a0, $zero, 1
; LA32D-ILP32D-NEXT: ori $a1, $zero, 2
; LA32D-ILP32D-NEXT: ori $a2, $zero, 3
@@ -606,22 +608,30 @@ define i32 @caller_half_in_gregs() nounwind {
; LA32F-ILP32D: # %bb.0:
; LA32F-ILP32D-NEXT: addi.w $sp, $sp, -16
; LA32F-ILP32D-NEXT: st.w $ra, $sp, 12 # 4-byte Folded Spill
-; LA32F-ILP32D-NEXT: pcalau12i $a0, %pc_hi20(.LCPI3_0)
-; LA32F-ILP32D-NEXT: fld.s $fa0, $a0, %pc_lo12(.LCPI3_0)
-; LA32F-ILP32D-NEXT: pcalau12i $a0, %pc_hi20(.LCPI3_1)
-; LA32F-ILP32D-NEXT: fld.s $fa1, $a0, %pc_lo12(.LCPI3_1)
-; LA32F-ILP32D-NEXT: pcalau12i $a0, %pc_hi20(.LCPI3_2)
-; LA32F-ILP32D-NEXT: fld.s $fa2, $a0, %pc_lo12(.LCPI3_2)
-; LA32F-ILP32D-NEXT: pcalau12i $a0, %pc_hi20(.LCPI3_3)
-; LA32F-ILP32D-NEXT: fld.s $fa3, $a0, %pc_lo12(.LCPI3_3)
-; LA32F-ILP32D-NEXT: pcalau12i $a0, %pc_hi20(.LCPI3_4)
-; LA32F-ILP32D-NEXT: fld.s $fa4, $a0, %pc_lo12(.LCPI3_4)
-; LA32F-ILP32D-NEXT: pcalau12i $a0, %pc_hi20(.LCPI3_5)
-; LA32F-ILP32D-NEXT: fld.s $fa5, $a0, %pc_lo12(.LCPI3_5)
-; LA32F-ILP32D-NEXT: pcalau12i $a0, %pc_hi20(.LCPI3_6)
-; LA32F-ILP32D-NEXT: fld.s $fa6, $a0, %pc_lo12(.LCPI3_6)
-; LA32F-ILP32D-NEXT: pcalau12i $a0, %pc_hi20(.LCPI3_7)
-; LA32F-ILP32D-NEXT: fld.s $fa7, $a0, %pc_lo12(.LCPI3_7)
+; LA32F-ILP32D-NEXT: .Lpcadd_hi1:
+; LA32F-ILP32D-NEXT: pcaddu12i $a0, %pcadd_hi20(.LCPI3_0)
+; LA32F-ILP32D-NEXT: fld.s $fa0, $a0, %pcadd_lo12(.Lpcadd_hi1)
+; LA32F-ILP32D-NEXT: .Lpcadd_hi2:
+; LA32F-ILP32D-NEXT: pcaddu12i $a0, %pcadd_hi20(.LCPI3_1)
+; LA32F-ILP32D-NEXT: fld.s $fa1, $a0, %pcadd_lo12(.Lpcadd_hi2)
+; LA32F-ILP32D-NEXT: .Lpcadd_hi3:
+; LA32F-ILP32D-NEXT: pcaddu12i $a0, %pcadd_hi20(.LCPI3_2)
+; LA32F-ILP32D-NEXT: fld.s $fa2, $a0, %pcadd_lo12(.Lpcadd_hi3)
+; LA32F-ILP32D-NEXT: .Lpcadd_hi4:
+; LA32F-ILP32D-NEXT: pcaddu12i $a0, %pcadd_hi20(.LCPI3_3)
+; LA32F-ILP32D-NEXT: fld.s $fa3, $a0, %pcadd_lo12(.Lpcadd_hi4)
+; LA32F-ILP32D-NEXT: .Lpcadd_hi5:
+; LA32F-ILP32D-NEXT: pcaddu12i $a0, %pcadd_hi20(.LCPI3_4)
+; LA32F-ILP32D-NEXT: fld.s $fa4, $a0, %pcadd_lo12(.Lpcadd_hi5)
+; LA32F-ILP32D-NEXT: .Lpcadd_hi6:
+; LA32F-ILP32D-NEXT: pcaddu12i $a0, %pcadd_hi20(.LCPI3_5)
+; LA32F-ILP32D-NEXT: fld.s $fa5, $a0, %pcadd_lo12(.Lpcadd_hi6)
+; LA32F-ILP32D-NEXT: .Lpcadd_hi7:
+; LA32F-ILP32D-NEXT: pcaddu12i $a0, %pcadd_hi20(.LCPI3_6)
+; LA32F-ILP32D-NEXT: fld.s $fa6, $a0, %pcadd_lo12(.Lpcadd_hi7)
+; LA32F-ILP32D-NEXT: .Lpcadd_hi8:
+; LA32F-ILP32D-NEXT: pcaddu12i $a0, %pcadd_hi20(.LCPI3_7)
+; LA32F-ILP32D-NEXT: fld.s $fa7, $a0, %pcadd_lo12(.Lpcadd_hi8)
; LA32F-ILP32D-NEXT: lu12i.w $a0, -12
; LA32F-ILP32D-NEXT: ori $a0, $a0, 2176
; LA32F-ILP32D-NEXT: ori $a1, $zero, 10
@@ -656,22 +666,30 @@ define i32 @caller_half_in_gregs() nounwind {
; LA32D-ILP32D: # %bb.0:
; LA32D-ILP32D-NEXT: addi.w $sp, $sp, -16
; LA32D-ILP32D-NEXT: st.w $ra, $sp, 12 # 4-byte Folded Spill
-; LA32D-ILP32D-NEXT: pcalau12i $a0, %pc_hi20(.LCPI3_0)
-; LA32D-ILP32D-NEXT: fld.s $fa0, $a0, %pc_lo12(.LCPI3_0)
-; LA32D-ILP32D-NEXT: pcalau12i $a0, %pc_hi20(.LCPI3_1)
-; LA32D-ILP32D-NEXT: fld.s $fa1, $a0, %pc_lo12(.LCPI3_1)
-; LA32D-ILP32D-NEXT: pcalau12i $a0, %pc_hi20(.LCPI3_2)
-; LA32D-ILP32D-NEXT: fld.s $fa2, $a0, %pc_lo12(.LCPI3_2)
-; LA32D-ILP32D-NEXT: pcalau12i $a0, %pc_hi20(.LCPI3_3)
-; LA32D-ILP32D-NEXT: fld.s $fa3, $a0, %pc_lo12(.LCPI3_3)
-; LA32D-ILP32D-NEXT: pcalau12i $a0, %pc_hi20(.LCPI3_4)
-; LA32D-ILP32D-NEXT: fld.s $fa4, $a0, %pc_lo12(.LCPI3_4)
-; LA32D-ILP32D-NEXT: pcalau12i $a0, %pc_hi20(.LCPI3_5)
-; LA32D-ILP32D-NEXT: fld.s $fa5, $a0, %pc_lo12(.LCPI3_5)
-; LA32D-ILP32D-NEXT: pcalau12i $a0, %pc_hi20(.LCPI3_6)
-; LA32D-ILP32D-NEXT: fld.s $fa6, $a0, %pc_lo12(.LCPI3_6)
-; LA32D-ILP32D-NEXT: pcalau12i $a0, %pc_hi20(.LCPI3_7)
-; LA32D-ILP32D-NEXT: fld.s $fa7, $a0, %pc_lo12(.LCPI3_7)
+; LA32D-ILP32D-NEXT: .Lpcadd_hi1:
+; LA32D-ILP32D-NEXT: pcaddu12i $a0, %pcadd_hi20(.LCPI3_0)
+; LA32D-ILP32D-NEXT: fld.s $fa0, $a0, %pcadd_lo12(.Lpcadd_hi1)
+; LA32D-ILP32D-NEXT: .Lpcadd_hi2:
+; LA32D-ILP32D-NEXT: pcaddu12i $a0, %pcadd_hi20(.LCPI3_1)
+; LA32D-ILP32D-NEXT: fld.s $fa1, $a0, %pcadd_lo12(.Lpcadd_hi2)
+; LA32D-ILP32D-NEXT: .Lpcadd_hi3:
+; LA32D-ILP32D-NEXT: pcaddu12i $a0, %pcadd_hi20(.LCPI3_2)
+; LA32D-ILP32D-NEXT: fld.s $fa2, $a0, %pcadd_lo12(.Lpcadd_hi3)
+; LA32D-ILP32D-NEXT: .Lpcadd_hi4:
+; LA32D-ILP32D-NEXT: pcaddu12i $a0, %pcadd_hi20(.LCPI3_3)
+; LA32D-ILP32D-NEXT: fld.s $fa3, $a0, %pcadd_lo12(.Lpcadd_hi4)
+; LA32D-ILP32D-NEXT: .Lpcadd_hi5:
+; LA32D-ILP32D-NEXT: pcaddu12i $a0, %pcadd_hi20(.LCPI3_4)
+; LA32D-ILP32D-NEXT: fld.s $fa4, $a0, %pcadd_lo12(.Lpcadd_hi5)
+; LA32D-ILP32D-NEXT: .Lpcadd_hi6:
+; LA32D-ILP32D-NEXT: pcaddu12i $a0, %pcadd_hi20(.LCPI3_5)
+; LA32D-ILP32D-NEXT: fld.s $fa5, $a0, %pcadd_lo12(.Lpcadd_hi6)
+; LA32D-ILP32D-NEXT: .Lpcadd_hi7:
+; LA32D-ILP32D-NEXT: pcaddu12i $a0, %pcadd_hi20(.LCPI3_6)
+; LA32D-ILP32D-NEXT: fld.s $fa6, $a0, %pcadd_lo12(.Lpcadd_hi7)
+; LA32D-ILP32D-NEXT: .Lpcadd_hi8:
+; LA32D-ILP32D-NEXT: pcaddu12i $a0, %pcadd_hi20(.LCPI3_7)
+; LA32D-ILP32D-NEXT: fld.s $fa7, $a0, %pcadd_lo12(.Lpcadd_hi8)
; LA32D-ILP32D-NEXT: lu12i.w $a0, -12
; LA32D-ILP32D-NEXT: ori $a0, $a0, 2176
; LA32D-ILP32D-NEXT: ori $a1, $zero, 10
@@ -1110,22 +1128,30 @@ define i32 @caller_half_on_stack() nounwind {
; LA32F-ILP32D-NEXT: st.w $ra, $sp, 12 # 4-byte Folded Spill
; LA32F-ILP32D-NEXT: lu12i.w $a0, -12
; LA32F-ILP32D-NEXT: ori $t0, $a0, 3200
-; LA32F-ILP32D-NEXT: pcalau12i $a0, %pc_hi20(.LCPI5_0)
-; LA32F-ILP32D-NEXT: fld.s $fa0, $a0, %pc_lo12(.LCPI5_0)
-; LA32F-ILP32D-NEXT: pcalau12i $a0, %pc_hi20(.LCPI5_1)
-; LA32F-ILP32D-NEXT: fld.s $fa1, $a0, %pc_lo12(.LCPI5_1)
-; LA32F-ILP32D-NEXT: pcalau12i $a0, %pc_hi20(.LCPI5_2)
-; LA32F-ILP32D-NEXT: fld.s $fa2, $a0, %pc_lo12(.LCPI5_2)
-; LA32F-ILP32D-NEXT: pcalau12i $a0, %pc_hi20(.LCPI5_3)
-; LA32F-ILP32D-NEXT: fld.s $fa3, $a0, %pc_lo12(.LCPI5_3)
-; LA32F-ILP32D-NEXT: pcalau12i $a0, %pc_hi20(.LCPI5_4)
-; LA32F-ILP32D-NEXT: fld.s $fa4, $a0, %pc_lo12(.LCPI5_4)
-; LA32F-ILP32D-NEXT: pcalau12i $a0, %pc_hi20(.LCPI5_5)
-; LA32F-ILP32D-NEXT: fld.s $fa5, $a0, %pc_lo12(.LCPI5_5)
-; LA32F-ILP32D-NEXT: pcalau12i $a0, %pc_hi20(.LCPI5_6)
-; LA32F-ILP32D-NEXT: fld.s $fa6, $a0, %pc_lo12(.LCPI5_6)
-; LA32F-ILP32D-NEXT: pcalau12i $a0, %pc_hi20(.LCPI5_7)
-; LA32F-ILP32D-NEXT: fld.s $fa7, $a0, %pc_lo12(.LCPI5_7)
+; LA32F-ILP32D-NEXT: .Lpcadd_hi9:
+; LA32F-ILP32D-NEXT: pcaddu12i $a0, %pcadd_hi20(.LCPI5_0)
+; LA32F-ILP32D-NEXT: fld.s $fa0, $a0, %pcadd_lo12(.Lpcadd_hi9)
+; LA32F-ILP32D-NEXT: .Lpcadd_hi10:
+; LA32F-ILP32D-NEXT: pcaddu12i $a0, %pcadd_hi20(.LCPI5_1)
+; LA32F-ILP32D-NEXT: fld.s $fa1, $a0, %pcadd_lo12(.Lpcadd_hi10)
+; LA32F-ILP32D-NEXT: .Lpcadd_hi11:
+; LA32F-ILP32D-NEXT: pcaddu12i $a0, %pcadd_hi20(.LCPI5_2)
+; LA32F-ILP32D-NEXT: fld.s $fa2, $a0, %pcadd_lo12(.Lpcadd_hi11)
+; LA32F-ILP32D-NEXT: .Lpcadd_hi12:
+; LA32F-ILP32D-NEXT: pcaddu12i $a0, %pcadd_hi20(.LCPI5_3)
+; LA32F-ILP32D-NEXT: fld.s $fa3, $a0, %pcadd_lo12(.Lpcadd_hi12)
+; LA32F-ILP32D-NEXT: .Lpcadd_hi13:
+; LA32F-ILP32D-NEXT: pcaddu12i $a0, %pcadd_hi20(.LCPI5_4)
+; LA32F-ILP32D-NEXT: fld.s $fa4, $a0, %pcadd_lo12(.Lpcadd_hi13)
+; LA32F-ILP32D-NEXT: .Lpcadd_hi14:
+; LA32F-ILP32D-NEXT: pcaddu12i $a0, %pcadd_hi20(.LCPI5_5)
+; LA32F-ILP32D-NEXT: fld.s $fa5, $a0, %pcadd_lo12(.Lpcadd_hi14)
+; LA32F-ILP32D-NEXT: .Lpcadd_hi15:
+; LA32F-ILP32D-NEXT: pcaddu12i $a0, %pcadd_hi20(.LCPI5_6)
+; LA32F-ILP32D-NEXT: fld.s $fa6, $a0, %pcadd_lo12(.Lpcadd_hi15)
+; LA32F-ILP32D-NEXT: .Lpcadd_hi16:
+; LA32F-ILP32D-NEXT: pcaddu12i $a0, %pcadd_hi20(.LCPI5_7)
+; LA32F-ILP32D-NEXT: fld.s $fa7, $a0, %pcadd_lo12(.Lpcadd_hi16)
; LA32F-ILP32D-NEXT: ori $a0, $zero, 1
; LA32F-ILP32D-NEXT: ori $a1, $zero, 2
; LA32F-ILP32D-NEXT: ori $a2, $zero, 3
@@ -1182,22 +1208,30 @@ define i32 @caller_half_on_stack() nounwind {
; LA32D-ILP32D-NEXT: st.w $ra, $sp, 12 # 4-byte Folded Spill
; LA32D-ILP32D-NEXT: lu12i.w $a0, -12
; LA32D-ILP32D-NEXT: ori $t0, $a0, 3200
-; LA32D-ILP32D-NEXT: pcalau12i $a0, %pc_hi20(.LCPI5_0)
-; LA32D-ILP32D-NEXT: fld.s $fa0, $a0, %pc_lo12(.LCPI5_0)
-; LA32D-ILP32D-NEXT: pcalau12i $a0, %pc_hi20(.LCPI5_1)
-; LA32D-ILP32D-NEXT: fld.s $fa1, $a0, %pc_lo12(.LCPI5_1)
-; LA32D-ILP32D-NEXT: pcalau12i $a0, %pc_hi20(.LCPI5_2)
-; LA32D-ILP32D-NEXT: fld.s $fa2, $a0, %pc_lo12(.LCPI5_2)
-; LA32D-ILP32D-NEXT: pcalau12i $a0, %pc_hi20(.LCPI5_3)
-; LA32D-ILP32D-NEXT: fld.s $fa3, $a0, %pc_lo12(.LCPI5_3)
-; LA32D-ILP32D-NEXT: pcalau12i $a0, %pc_hi20(.LCPI5_4)
-; LA32D-ILP32D-NEXT: fld.s $fa4, $a0, %pc_lo12(.LCPI5_4)
-; LA32D-ILP32D-NEXT: pcalau12i $a0, %pc_hi20(.LCPI5_5)
-; LA32D-ILP32D-NEXT: fld.s $fa5, $a0, %pc_lo12(.LCPI5_5)
-; LA32D-ILP32D-NEXT: pcalau12i $a0, %pc_hi20(.LCPI5_6)
-; LA32D-ILP32D-NEXT: fld.s $fa6, $a0, %pc_lo12(.LCPI5_6)
-; LA32D-ILP32D-NEXT: pcalau12i $a0, %pc_hi20(.LCPI5_7)
-; LA32D-ILP32D-NEXT: fld.s $fa7, $a0, %pc_lo12(.LCPI5_7)
+; LA32D-ILP32D-NEXT: .Lpcadd_hi9:
+; LA32D-ILP32D-NEXT: pcaddu12i $a0, %pcadd_hi20(.LCPI5_0)
+; LA32D-ILP32D-NEXT: fld.s $fa0, $a0, %pcadd_lo12(.Lpcadd_hi9)
+; LA32D-ILP32D-NEXT: .Lpcadd_hi10:
+; LA32D-ILP32D-NEXT: pcaddu12i $a0, %pcadd_hi20(.LCPI5_1)
+; LA32D-ILP32D-NEXT: fld.s $fa1, $a0, %pcadd_lo12(.Lpcadd_hi10)
+; LA32D-ILP32D-NEXT: .Lpcadd_hi11:
+; LA32D-ILP32D-NEXT: pcaddu12i $a0, %pcadd_hi20(.LCPI5_2)
+; LA32D-ILP32D-NEXT: fld.s $fa2, $a0, %pcadd_lo12(.Lpcadd_hi11)
+; LA32D-ILP32D-NEXT: .Lpcadd_hi12:
+; LA32D-ILP32D-NEXT: pcaddu12i $a0, %pcadd_hi20(.LCPI5_3)
+; LA32D-ILP32D-NEXT: fld.s $fa3, $a0, %pcadd_lo12(.Lpcadd_hi12)
+; LA32D-ILP32D-NEXT: .Lpcadd_hi13:
+; LA32D-ILP32D-NEXT: pcaddu12i $a0, %pcadd_hi20(.LCPI5_4)
+; LA32D-ILP32D-NEXT: fld.s $fa4, $a0, %pcadd_lo12(.Lpcadd_hi13)
+; LA32D-ILP32D-NEXT: .Lpcadd_hi14:
+; LA32D-ILP32D-NEXT: pcaddu12i $a0, %pcadd_hi20(.LCPI5_5)
+; LA32D-ILP32D-NEXT: fld.s $fa5, $a0, %pcadd_lo12(.Lpcadd_hi14)
+; LA32D-ILP32D-NEXT: .Lpcadd_hi15:
+; LA32D-ILP32D-NEXT: pcaddu12i $a0, %pcadd_hi20(.LCPI5_6)
+; LA32D-ILP32D-NEXT: fld.s $fa6, $a0, %pcadd_lo12(.Lpcadd_hi15)
+; LA32D-ILP32D-NEXT: .Lpcadd_hi16:
+; LA32D-ILP32D-NEXT: pcaddu12i $a0, %pcadd_hi20(.LCPI5_7)
+; LA32D-ILP32D-NEXT: fld.s $fa7, $a0, %pcadd_lo12(.Lpcadd_hi16)
; LA32D-ILP32D-NEXT: ori $a0, $zero, 1
; LA32D-ILP32D-NEXT: ori $a1, $zero, 2
; LA32D-ILP32D-NEXT: ori $a2, $zero, 3
@@ -1436,8 +1470,9 @@ define half @callee_half_ret() nounwind {
;
; LA32F-ILP32D-LABEL: callee_half_ret:
; LA32F-ILP32D: # %bb.0:
-; LA32F-ILP32D-NEXT: pcalau12i $a0, %pc_hi20(.LCPI6_0)
-; LA32F-ILP32D-NEXT: fld.s $fa0, $a0, %pc_lo12(.LCPI6_0)
+; LA32F-ILP32D-NEXT: .Lpcadd_hi17:
+; LA32F-ILP32D-NEXT: pcaddu12i $a0, %pcadd_hi20(.LCPI6_0)
+; LA32F-ILP32D-NEXT: fld.s $fa0, $a0, %pcadd_lo12(.Lpcadd_hi17)
; LA32F-ILP32D-NEXT: ret
;
; LA32D-ILP32S-LABEL: callee_half_ret:
@@ -1448,8 +1483,9 @@ define half @callee_half_ret() nounwind {
;
; LA32D-ILP32D-LABEL: callee_half_ret:
; LA32D-ILP32D: # %bb.0:
-; LA32D-ILP32D-NEXT: pcalau12i $a0, %pc_hi20(.LCPI6_0)
-; LA32D-ILP32D-NEXT: fld.s $fa0, $a0, %pc_lo12(.LCPI6_0)
+; LA32D-ILP32D-NEXT: .Lpcadd_hi17:
+; LA32D-ILP32D-NEXT: pcaddu12i $a0, %pcadd_hi20(.LCPI6_0)
+; LA32D-ILP32D-NEXT: fld.s $fa0, $a0, %pcadd_lo12(.Lpcadd_hi17)
; LA32D-ILP32D-NEXT: ret
;
; LA64S-LABEL: callee_half_ret:
diff --git a/llvm/test/CodeGen/LoongArch/calling-conv-ilp32d.ll b/llvm/test/CodeGen/LoongArch/calling-conv-ilp32d.ll
index 62c2cc999456c..04f33bf90e910 100644
--- a/llvm/test/CodeGen/LoongArch/calling-conv-ilp32d.ll
+++ b/llvm/test/CodeGen/LoongArch/calling-conv-ilp32d.ll
@@ -65,20 +65,27 @@ define i32 @caller_double_in_gpr_exhausted_fprs() nounwind {
; CHECK: # %bb.0:
; CHECK-NEXT: addi.w $sp, $sp, -16
; CHECK-NEXT: st.w $ra, $sp, 12 # 4-byte Folded Spill
-; CHECK-NEXT: pcalau12i $a0, %pc_hi20(.LCPI3_0)
-; CHECK-NEXT: fld.d $fa1, $a0, %pc_lo12(.LCPI3_0)
-; CHECK-NEXT: pcalau12i $a0, %pc_hi20(.LCPI3_1)
-; CHECK-NEXT: fld.d $fa2, $a0, %pc_lo12(.LCPI3_1)
-; CHECK-NEXT: pcalau12i $a0, %pc_hi20(.LCPI3_2)
-; CHECK-NEXT: fld.d $fa3, $a0, %pc_lo12(.LCPI3_2)
-; CHECK-NEXT: pcalau12i $a0, %pc_hi20(.LCPI3_3)
-; CHECK-NEXT: fld.d $fa4, $a0, %pc_lo12(.LCPI3_3)
-; CHECK-NEXT: pcalau12i $a0, %pc_hi20(.LCPI3_4)
-; CHECK-NEXT: fld.d $fa5, $a0, %pc_lo12(.LCPI3_4)
-; CHECK-NEXT: pcalau12i $a0, %pc_hi20(.LCPI3_5)
-; CHECK-NEXT: fld.d $fa6, $a0, %pc_lo12(.LCPI3_5)
-; CHECK-NEXT: pcalau12i $a0, %pc_hi20(.LCPI3_6)
-; CHECK-NEXT: fld.d $fa7, $a0, %pc_lo12(.LCPI3_6)
+; CHECK-NEXT: .Lpcadd_hi0:
+; CHECK-NEXT: pcaddu12i $a0, %pcadd_hi20(.LCPI3_0)
+; CHECK-NEXT: fld.d $fa1, $a0, %pcadd_lo12(.Lpcadd_hi0)
+; CHECK-NEXT: .Lpcadd_hi1:
+; CHECK-NEXT: pcaddu12i $a0, %pcadd_hi20(.LCPI3_1)
+; CHECK-NEXT: fld.d $fa2, $a0, %pcadd_lo12(.Lpcadd_hi1)
+; CHECK-NEXT: .Lpcadd_hi2:
+; CHECK-NEXT: pcaddu12i $a0, %pcadd_hi20(.LCPI3_2)
+; CHECK-NEXT: fld.d $fa3, $a0, %pcadd_lo12(.Lpcadd_hi2)
+; CHECK-NEXT: .Lpcadd_hi3:
+; CHECK-NEXT: pcaddu12i $a0, %pcadd_hi20(.LCPI3_3)
+; CHECK-NEXT: fld.d $fa4, $a0, %pcadd_lo12(.Lpcadd_hi3)
+; CHECK-NEXT: .Lpcadd_hi4:
+; CHECK-NEXT: pcaddu12i $a0, %pcadd_hi20(.LCPI3_4)
+; CHECK-NEXT: fld.d $fa5, $a0, %pcadd_lo12(.Lpcadd_hi4)
+; CHECK-NEXT: .Lpcadd_hi5:
+; CHECK-NEXT: pcaddu12i $a0, %pcadd_hi20(.LCPI3_5)
+; CHECK-NEXT: fld.d $fa6, $a0, %pcadd_lo12(.Lpcadd_hi5)
+; CHECK-NEXT: .Lpcadd_hi6:
+; CHECK-NEXT: pcaddu12i $a0, %pcadd_hi20(.LCPI3_6)
+; CHECK-NEXT: fld.d $fa7, $a0, %pcadd_lo12(.Lpcadd_hi6)
; CHECK-NEXT: addi.w $a0, $zero, 1
; CHECK-NEXT: movgr2fr.w $fa0, $a0
; CHECK-NEXT: ffint.s.w $fa0, $fa0
@@ -125,20 +132,27 @@ define i32 @caller_double_on_stack_exhausted_fprs_gprs() nounwind {
; CHECK-NEXT: st.w $zero, $sp, 0
; CHECK-NEXT: lu12i.w $a0, 262848
; CHECK-NEXT: st.w $a0, $sp, 12
-; CHECK-NEXT: pcalau12i $a0, %pc_hi20(.LCPI5_0)
-; CHECK-NEXT: fld.d $fa1, $a0, %pc_lo12(.LCPI5_0)
-; CHECK-NEXT: pcalau12i $a0, %pc_hi20(.LCPI5_1)
-; CHECK-NEXT: fld.d $fa2, $a0, %pc_lo12(.LCPI5_1)
-; CHECK-NEXT: pcalau12i $a0, %pc_hi20(.LCPI5_2)
-; CHECK-NEXT: fld.d $fa3, $a0, %pc_lo12(.LCPI5_2)
-; CHECK-NEXT: pcalau12i $a0, %pc_hi20(.LCPI5_3)
-; CHECK-NEXT: fld.d $fa4, $a0, %pc_lo12(.LCPI5_3)
-; CHECK-NEXT: pcalau12i $a0, %pc_hi20(.LCPI5_4)
-; CHECK-NEXT: fld.d $fa5, $a0, %pc_lo12(.LCPI5_4)
-; CHECK-NEXT: pcalau12i $a0, %pc_hi20(.LCPI5_5)
-; CHECK-NEXT: fld.d $fa6, $a0, %pc_lo12(.LCPI5_5)
-; CHECK-NEXT: pcalau12i $a0, %pc_hi20(.LCPI5_6)
-; CHECK-NEXT: fld.d $fa7, $a0, %pc_lo12(.LCPI5_6)
+; CHECK-NEXT: .Lpcadd_hi7:
+; CHECK-NEXT: pcaddu12i $a0, %pcadd_hi20(.LCPI5_0)
+; CHECK-NEXT: fld.d $fa1, $a0, %pcadd_lo12(.Lpcadd_hi7)
+; CHECK-NEXT: .Lpcadd_hi8:
+; CHECK-NEXT: pcaddu12i $a0, %pcadd_hi20(.LCPI5_1)
+; CHECK-NEXT: fld.d $fa2, $a0, %pcadd_lo12(.Lpcadd_hi8)
+; CHECK-NEXT: .Lpcadd_hi9:
+; CHECK-NEXT: pcaddu12i $a0, %pcadd_hi20(.LCPI5_2)
+; CHECK-NEXT: fld.d $fa3, $a0, %pcadd_lo12(.Lpcadd_hi9)
+; CHECK-NEXT: .Lpcadd_hi10:
+; CHECK-NEXT: pcaddu12i $a0, %pcadd_hi20(.LCPI5_3)
+; CHECK-NEXT: fld.d $fa4, $a0, %pcadd_lo12(.Lpcadd_hi10)
+; CHECK-NEXT: .Lpcadd_hi11:
+; CHECK-NEXT: pcaddu12i $a0, %pcadd_hi20(.LCPI5_4)
+; CHECK-NEXT: fld.d $fa5, $a0, %pcadd_lo12(.Lpcadd_hi11)
+; CHECK-NEXT: .Lpcadd_hi12:
+; CHECK-NEXT: pcaddu12i $a0, %pcadd_hi20(.LCPI5_5)
+; CHECK-NEXT: fld.d $fa6, $a0, %pcadd_lo12(.Lpcadd_hi12)
+; CHECK-NEXT: .Lpcadd_hi13:
+; CHECK-NEXT: pcaddu12i $a0, %pcadd_hi20(.LCPI5_6)
+; CHECK-NEXT: fld.d $fa7, $a0, %pcadd_lo12(.Lpcadd_hi13)
; CHECK-NEXT: addi.w $a0, $zero, 1
; CHECK-NEXT: movgr2fr.w $fa0, $a0
; CHECK-NEXT: ffint.s.w $fa0, $fa0
diff --git a/llvm/test/CodeGen/LoongArch/code-models.ll b/llvm/test/CodeGen/LoongArch/code-models.ll
index f4459655e6138..907961d449f38 100644
--- a/llvm/test/CodeGen/LoongArch/code-models.ll
+++ b/llvm/test/CodeGen/LoongArch/code-models.ll
@@ -1,96 +1,146 @@
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
+; RUN: llc --mtriple=loongarch32 -mattr=+d --code-model=small < %s | \
+; RUN: FileCheck --check-prefix=LA32-SMALL %s
+; RUN: llc --mtriple=loongarch32 -mattr=+d --code-model=medium < %s | \
+; RUN: FileCheck --check-prefix=LA32-MEDIUM %s
; RUN: llc --mtriple=loongarch64 -mattr=+d --code-model=small < %s | \
-; RUN: FileCheck --check-prefix=SMALL %s
+; RUN: FileCheck --check-prefix=LA64-SMALL %s
; RUN: llc --mtriple=loongarch64 -mattr=+d --code-model=medium < %s | \
-; RUN: FileCheck --check-prefix=MEDIUM %s
+; RUN: FileCheck --check-prefix=LA64-MEDIUM %s
; RUN: llc --mtriple=loongarch64 -mattr=+d --code-model=large < %s | \
-; RUN: FileCheck --check-prefix=LARGE %s
+; RUN: FileCheck --check-prefix=LA64-LARGE %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 callee
-; SMALL-NEXT: ld.d $ra, $sp, 8 # 8-byte Folded Reload
-; SMALL-NEXT: addi.d $sp, $sp, 16
-; SMALL-NEXT: ret
+; LA32-SMALL-LABEL: call_globaladdress:
+; LA32-SMALL: # %bb.0:
+; LA32-SMALL-NEXT: addi.w $sp, $sp, -16
+; LA32-SMALL-NEXT: st.w $ra, $sp, 12 # 4-byte Folded Spill
+; LA32-SMALL-NEXT: bl callee
+; LA32-SMALL-NEXT: ld.w $ra, $sp, 12 # 4-byte Folded Reload
+; LA32-SMALL-NEXT: addi.w $sp, $sp, 16
+; LA32-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: pcaddu18i $ra, %call36(callee)
-; MEDIUM-NEXT: jirl $ra, $ra, 0
-; MEDIUM-NEXT: ld.d $ra, $sp, 8 # 8-byte Folded Reload
-; MEDIUM-NEXT: addi.d $sp, $sp, 16
-; MEDIUM-NEXT: ret
+; LA32-MEDIUM-LABEL: call_globaladdress:
+; LA32-MEDIUM: # %bb.0:
+; LA32-MEDIUM-NEXT: addi.w $sp, $sp, -16
+; LA32-MEDIUM-NEXT: st.w $ra, $sp, 12 # 4-byte Folded Spill
+; LA32-MEDIUM-NEXT: pcaddu12i $ra, %call30(callee)
+; LA32-MEDIUM-NEXT: jirl $ra, $ra, 0
+; LA32-MEDIUM-NEXT: ld.w $ra, $sp, 12 # 4-byte Folded Reload
+; LA32-MEDIUM-NEXT: addi.w $sp, $sp, 16
+; LA32-MEDIUM-NEXT: ret
;
-; LARGE-LABEL: call_globaladdress:
-; LARGE: # %bb.0:
-; LARGE-NEXT: addi.d $sp, $sp, -16
-; LARGE-NEXT: st.d $ra, $sp, 8 # 8-byte Folded Spill
-; LARGE-NEXT: pcalau12i $a1, %got_pc_hi20(callee)
-; LARGE-NEXT: addi.d $ra, $zero, %got_pc_lo12(callee)
-; LARGE-NEXT: lu32i.d $ra, %got64_pc_lo20(callee)
-; LARGE-NEXT: lu52i.d $ra, $ra, %got64_pc_hi12(callee)
-; LARGE-NEXT: ldx.d $ra, $ra, $a1
-; LARGE-NEXT: jirl $ra, $ra, 0
-; LARGE-NEXT: ld.d $ra, $sp, 8 # 8-byte Folded Reload
-; LARGE-NEXT: addi.d $sp, $sp, 16
-; LARGE-NEXT: ret
+; LA64-SMALL-LABEL: call_globaladdress:
+; LA64-SMALL: # %bb.0:
+; LA64-SMALL-NEXT: addi.d $sp, $sp, -16
+; LA64-SMALL-NEXT: st.d $ra, $sp, 8 # 8-byte Folded Spill
+; LA64-SMALL-NEXT: bl callee
+; LA64-SMALL-NEXT: ld.d $ra, $sp, 8 # 8-byte Folded Reload
+; LA64-SMALL-NEXT: addi.d $sp, $sp, 16
+; LA64-SMALL-NEXT: ret
+;
+; LA64-MEDIUM-LABEL: call_globaladdress:
+; LA64-MEDIUM: # %bb.0:
+; LA64-MEDIUM-NEXT: addi.d $sp, $sp, -16
+; LA64-MEDIUM-NEXT: st.d $ra, $sp, 8 # 8-byte Folded Spill
+; LA64-MEDIUM-NEXT: pcaddu18i $ra, %call36(callee)
+; LA64-MEDIUM-NEXT: jirl $ra, $ra, 0
+; LA64-MEDIUM-NEXT: ld.d $ra, $sp, 8 # 8-byte Folded Reload
+; LA64-MEDIUM-NEXT: addi.d $sp, $sp, 16
+; LA64-MEDIUM-NEXT: ret
+;
+; LA64-LARGE-LABEL: call_globaladdress:
+; LA64-LARGE: # %bb.0:
+; LA64-LARGE-NEXT: addi.d $sp, $sp, -16
+; LA64-LARGE-NEXT: st.d $ra, $sp, 8 # 8-byte Folded Spill
+; LA64-LARGE-NEXT: pcalau12i $a1, %got_pc_hi20(callee)
+; LA64-LARGE-NEXT: addi.d $ra, $zero, %got_pc_lo12(callee)
+; LA64-LARGE-NEXT: lu32i.d $ra, %got64_pc_lo20(callee)
+; LA64-LARGE-NEXT: lu52i.d $ra, $ra, %got64_pc_hi12(callee)
+; LA64-LARGE-NEXT: ldx.d $ra, $ra, $a1
+; LA64-LARGE-NEXT: jirl $ra, $ra, 0
+; LA64-LARGE-NEXT: ld.d $ra, $sp, 8 # 8-byte Folded Reload
+; LA64-LARGE-NEXT: addi.d $sp, $sp, 16
+; LA64-LARGE-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 memset
-; SMALL-NEXT: ld.d $ra, $sp, 8 # 8-byte Folded Reload
-; SMALL-NEXT: addi.d $sp, $sp, 16
-; SMALL-NEXT: ret
+; LA32-SMALL-LABEL: call_external_sym:
+; LA32-SMALL: # %bb.0: # %entry
+; LA32-SMALL-NEXT: addi.w $sp, $sp, -16
+; LA32-SMALL-NEXT: .cfi_def_cfa_offset 16
+; LA32-SMALL-NEXT: st.w $ra, $sp, 12 # 4-byte Folded Spill
+; LA32-SMALL-NEXT: .cfi_offset 1, -4
+; LA32-SMALL-NEXT: ori $a2, $zero, 1000
+; LA32-SMALL-NEXT: move $a1, $zero
+; LA32-SMALL-NEXT: bl memset
+; LA32-SMALL-NEXT: ld.w $ra, $sp, 12 # 4-byte Folded Reload
+; LA32-SMALL-NEXT: addi.w $sp, $sp, 16
+; LA32-SMALL-NEXT: ret
+;
+; LA32-MEDIUM-LABEL: call_external_sym:
+; LA32-MEDIUM: # %bb.0: # %entry
+; LA32-MEDIUM-NEXT: addi.w $sp, $sp, -16
+; LA32-MEDIUM-NEXT: .cfi_def_cfa_offset 16
+; LA32-MEDIUM-NEXT: st.w $ra, $sp, 12 # 4-byte Folded Spill
+; LA32-MEDIUM-NEXT: .cfi_offset 1, -4
+; LA32-MEDIUM-NEXT: ori $a2, $zero, 1000
+; LA32-MEDIUM-NEXT: move $a1, $zero
+; LA32-MEDIUM-NEXT: pcaddu12i $ra, %call30(memset)
+; LA32-MEDIUM-NEXT: jirl $ra, $ra, 0
+; LA32-MEDIUM-NEXT: ld.w $ra, $sp, 12 # 4-byte Folded Reload
+; LA32-MEDIUM-NEXT: addi.w $sp, $sp, 16
+; LA32-MEDIUM-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: pcaddu18i $ra, %call36(memset)
-; MEDIUM-NEXT: jirl $ra, $ra, 0
-; MEDIUM-NEXT: ld.d $ra, $sp, 8 # 8-byte Folded Reload
-; MEDIUM-NEXT: addi.d $sp, $sp, 16
-; MEDIUM-NEXT: ret
+; LA64-SMALL-LABEL: call_external_sym:
+; LA64-SMALL: # %bb.0: # %entry
+; LA64-SMALL-NEXT: addi.d $sp, $sp, -16
+; LA64-SMALL-NEXT: .cfi_def_cfa_offset 16
+; LA64-SMALL-NEXT: st.d $ra, $sp, 8 # 8-byte Folded Spill
+; LA64-SMALL-NEXT: .cfi_offset 1, -8
+; LA64-SMALL-NEXT: ori $a2, $zero, 1000
+; LA64-SMALL-NEXT: move $a1, $zero
+; LA64-SMALL-NEXT: bl memset
+; LA64-SMALL-NEXT: ld.d $ra, $sp, 8 # 8-byte Folded Reload
+; LA64-SMALL-NEXT: addi.d $sp, $sp, 16
+; LA64-SMALL-NEXT: ret
;
-; LARGE-LABEL: call_external_sym:
-; LARGE: # %bb.0: # %entry
-; LARGE-NEXT: addi.d $sp, $sp, -16
-; LARGE-NEXT: .cfi_def_cfa_offset 16
-; LARGE-NEXT: st.d $ra, $sp, 8 # 8-byte Folded Spill
-; LARGE-NEXT: .cfi_offset 1, -8
-; LARGE-NEXT: ori $a2, $zero, 1000
-; LARGE-NEXT: move $a1, $zero
-; LARGE-NEXT: pcalau12i $a3, %got_pc_hi20(memset)
-; LARGE-NEXT: addi.d $ra, $zero, %got_pc_lo12(memset)
-; LARGE-NEXT: lu32i.d $ra, %got64_pc_lo20(memset)
-; LARGE-NEXT: lu52i.d $ra, $ra, %got64_pc_hi12(memset)
-; LARGE-NEXT: ldx.d $ra, $ra, $a3
-; LARGE-NEXT: jirl $ra, $ra, 0
-; LARGE-NEXT: ld.d $ra, $sp, 8 # 8-byte Folded Reload
-; LARGE-NEXT: addi.d $sp, $sp, 16
-; LARGE-NEXT: ret
+; LA64-MEDIUM-LABEL: call_external_sym:
+; LA64-MEDIUM: # %bb.0: # %entry
+; LA64-MEDIUM-NEXT: addi.d $sp, $sp, -16
+; LA64-MEDIUM-NEXT: .cfi_def_cfa_offset 16
+; LA64-MEDIUM-NEXT: st.d $ra, $sp, 8 # 8-byte Folded Spill
+; LA64-MEDIUM-NEXT: .cfi_offset 1, -8
+; LA64-MEDIUM-NEXT: ori $a2, $zero, 1000
+; LA64-MEDIUM-NEXT: move $a1, $zero
+; LA64-MEDIUM-NEXT: pcaddu18i $ra, %call36(memset)
+; LA64-MEDIUM-NEXT: jirl $ra, $ra, 0
+; LA64-MEDIUM-NEXT: ld.d $ra, $sp, 8 # 8-byte Folded Reload
+; LA64-MEDIUM-NEXT: addi.d $sp, $sp, 16
+; LA64-MEDIUM-NEXT: ret
+;
+; LA64-LARGE-LABEL: call_external_sym:
+; LA64-LARGE: # %bb.0: # %entry
+; LA64-LARGE-NEXT: addi.d $sp, $sp, -16
+; LA64-LARGE-NEXT: .cfi_def_cfa_offset 16
+; LA64-LARGE-NEXT: st.d $ra, $sp, 8 # 8-byte Folded Spill
+; LA64-LARGE-NEXT: .cfi_offset 1, -8
+; LA64-LARGE-NEXT: ori $a2, $zero, 1000
+; LA64-LARGE-NEXT: move $a1, $zero
+; LA64-LARGE-NEXT: pcalau12i $a3, %got_pc_hi20(memset)
+; LA64-LARGE-NEXT: addi.d $ra, $zero, %got_pc_lo12(memset)
+; LA64-LARGE-NEXT: lu32i.d $ra, %got64_pc_lo20(memset)
+; LA64-LARGE-NEXT: lu52i.d $ra, $ra, %got64_pc_hi12(memset)
+; LA64-LARGE-NEXT: ldx.d $ra, $ra, $a3
+; LA64-LARGE-NEXT: jirl $ra, $ra, 0
+; LA64-LARGE-NEXT: ld.d $ra, $sp, 8 # 8-byte Folded Reload
+; LA64-LARGE-NEXT: addi.d $sp, $sp, 16
+; LA64-LARGE-NEXT: ret
entry:
call void @llvm.memset.p0.i64(ptr %dst, i8 0, i64 1000, i1 false)
ret void
@@ -99,23 +149,32 @@ entry:
;; Tail call with different codemodel.
declare i32 @callee_tail(i32 %i)
define i32 @caller_tail(i32 %i) nounwind {
-; SMALL-LABEL: caller_tail:
-; SMALL: # %bb.0: # %entry
-; SMALL-NEXT: b callee_tail
+; LA32-SMALL-LABEL: caller_tail:
+; LA32-SMALL: # %bb.0: # %entry
+; LA32-SMALL-NEXT: b callee_tail
+;
+; LA32-MEDIUM-LABEL: caller_tail:
+; LA32-MEDIUM: # %bb.0: # %entry
+; LA32-MEDIUM-NEXT: pcaddu12i $t8, %call30(callee_tail)
+; LA32-MEDIUM-NEXT: jr $t8
+;
+; LA64-SMALL-LABEL: caller_tail:
+; LA64-SMALL: # %bb.0: # %entry
+; LA64-SMALL-NEXT: b callee_tail
;
-; MEDIUM-LABEL: caller_tail:
-; MEDIUM: # %bb.0: # %entry
-; MEDIUM-NEXT: pcaddu18i $t8, %call36(callee_tail)
-; MEDIUM-NEXT: jr $t8
+; LA64-MEDIUM-LABEL: caller_tail:
+; LA64-MEDIUM: # %bb.0: # %entry
+; LA64-MEDIUM-NEXT: pcaddu18i $t8, %call36(callee_tail)
+; LA64-MEDIUM-NEXT: jr $t8
;
-; LARGE-LABEL: caller_tail:
-; LARGE: # %bb.0: # %entry
-; LARGE-NEXT: pcalau12i $a1, %got_pc_hi20(callee_tail)
-; LARGE-NEXT: addi.d $a2, $zero, %got_pc_lo12(callee_tail)
-; LARGE-NEXT: lu32i.d $a2, %got64_pc_lo20(callee_tail)
-; LARGE-NEXT: lu52i.d $a2, $a2, %got64_pc_hi12(callee_tail)
-; LARGE-NEXT: ldx.d $a1, $a2, $a1
-; LARGE-NEXT: jr $a1
+; LA64-LARGE-LABEL: caller_tail:
+; LA64-LARGE: # %bb.0: # %entry
+; LA64-LARGE-NEXT: pcalau12i $a1, %got_pc_hi20(callee_tail)
+; LA64-LARGE-NEXT: addi.d $a2, $zero, %got_pc_lo12(callee_tail)
+; LA64-LARGE-NEXT: lu32i.d $a2, %got64_pc_lo20(callee_tail)
+; LA64-LARGE-NEXT: lu52i.d $a2, $a2, %got64_pc_hi12(callee_tail)
+; LA64-LARGE-NEXT: ldx.d $a1, $a2, $a1
+; LA64-LARGE-NEXT: jr $a1
entry:
%r = tail call i32 @callee_tail(i32 %i)
ret i32 %r
diff --git a/llvm/test/CodeGen/LoongArch/ctlz-cttz-ctpop.ll b/llvm/test/CodeGen/LoongArch/ctlz-cttz-ctpop.ll
index 27be02c50f1c7..384c2d25135ea 100644
--- a/llvm/test/CodeGen/LoongArch/ctlz-cttz-ctpop.ll
+++ b/llvm/test/CodeGen/LoongArch/ctlz-cttz-ctpop.ll
@@ -810,8 +810,9 @@ define i32 @test_cttz_i32(i32 %a) nounwind {
; LA32R-NEXT: ori $a1, $a1, 1329
; LA32R-NEXT: mul.w $a0, $a0, $a1
; LA32R-NEXT: srli.w $a0, $a0, 27
-; LA32R-NEXT: pcalau12i $a1, %pc_hi20(.LCPI14_0)
-; LA32R-NEXT: addi.w $a1, $a1, %pc_lo12(.LCPI14_0)
+; LA32R-NEXT: .Lpcadd_hi0:
+; LA32R-NEXT: pcaddu12i $a1, %pcadd_hi20(.LCPI14_0)
+; LA32R-NEXT: addi.w $a1, $a1, %pcadd_lo12(.Lpcadd_hi0)
; LA32R-NEXT: add.w $a0, $a1, $a0
; LA32R-NEXT: ld.bu $a0, $a0, 0
; LA32R-NEXT: ret
@@ -834,8 +835,9 @@ define i64 @test_cttz_i64(i64 %a) nounwind {
; LA32R: # %bb.0:
; LA32R-NEXT: lu12i.w $a2, 30667
; LA32R-NEXT: ori $a2, $a2, 1329
-; LA32R-NEXT: pcalau12i $a3, %pc_hi20(.LCPI15_0)
-; LA32R-NEXT: addi.w $a3, $a3, %pc_lo12(.LCPI15_0)
+; LA32R-NEXT: .Lpcadd_hi1:
+; LA32R-NEXT: pcaddu12i $a3, %pcadd_hi20(.LCPI15_0)
+; LA32R-NEXT: addi.w $a3, $a3, %pcadd_lo12(.Lpcadd_hi1)
; LA32R-NEXT: bne $a1, $zero, .LBB15_3
; LA32R-NEXT: # %bb.1:
; LA32R-NEXT: ori $a1, $zero, 32
@@ -974,8 +976,9 @@ define i32 @test_not_cttz_i32(i32 %a) nounwind {
; LA32R-NEXT: ori $a1, $a1, 1329
; LA32R-NEXT: mul.w $a0, $a0, $a1
; LA32R-NEXT: srli.w $a0, $a0, 27
-; LA32R-NEXT: pcalau12i $a1, %pc_hi20(.LCPI18_0)
-; LA32R-NEXT: addi.w $a1, $a1, %pc_lo12(.LCPI18_0)
+; LA32R-NEXT: .Lpcadd_hi2:
+; LA32R-NEXT: pcaddu12i $a1, %pcadd_hi20(.LCPI18_0)
+; LA32R-NEXT: addi.w $a1, $a1, %pcadd_lo12(.Lpcadd_hi2)
; LA32R-NEXT: add.w $a0, $a1, $a0
; LA32R-NEXT: ld.bu $a0, $a0, 0
; LA32R-NEXT: ret
@@ -1001,8 +1004,9 @@ define i64 @test_not_cttz_i64(i64 %a) nounwind {
; LA32R-NEXT: nor $a2, $a0, $zero
; LA32R-NEXT: lu12i.w $a3, 30667
; LA32R-NEXT: ori $a3, $a3, 1329
-; LA32R-NEXT: pcalau12i $a4, %pc_hi20(.LCPI19_0)
-; LA32R-NEXT: addi.w $a4, $a4, %pc_lo12(.LCPI19_0)
+; LA32R-NEXT: .Lpcadd_hi3:
+; LA32R-NEXT: pcaddu12i $a4, %pcadd_hi20(.LCPI19_0)
+; LA32R-NEXT: addi.w $a4, $a4, %pcadd_lo12(.Lpcadd_hi3)
; LA32R-NEXT: bne $a5, $zero, .LBB19_3
; LA32R-NEXT: # %bb.1:
; LA32R-NEXT: ori $a1, $zero, 32
diff --git a/llvm/test/CodeGen/LoongArch/double-imm.ll b/llvm/test/CodeGen/LoongArch/double-imm.ll
index fe403ec532d8e..ea0c1766e3d69 100644
--- a/llvm/test/CodeGen/LoongArch/double-imm.ll
+++ b/llvm/test/CodeGen/LoongArch/double-imm.ll
@@ -35,8 +35,9 @@ define double @f64_negative_zero() nounwind {
define double @f64_constant_pi() nounwind {
; LA32-LABEL: f64_constant_pi:
; LA32: # %bb.0:
-; LA32-NEXT: pcalau12i $a0, %pc_hi20(.LCPI2_0)
-; LA32-NEXT: fld.d $fa0, $a0, %pc_lo12(.LCPI2_0)
+; LA32-NEXT: .Lpcadd_hi0:
+; LA32-NEXT: pcaddu12i $a0, %pcadd_hi20(.LCPI2_0)
+; LA32-NEXT: fld.d $fa0, $a0, %pcadd_lo12(.Lpcadd_hi0)
; LA32-NEXT: ret
;
; LA64-LABEL: f64_constant_pi:
diff --git a/llvm/test/CodeGen/LoongArch/float-imm.ll b/llvm/test/CodeGen/LoongArch/float-imm.ll
index 006a9e64b190d..920bff98b1744 100644
--- a/llvm/test/CodeGen/LoongArch/float-imm.ll
+++ b/llvm/test/CodeGen/LoongArch/float-imm.ll
@@ -33,8 +33,9 @@ define float @f32_negative_zero() nounwind {
define float @f32_constant_pi() nounwind {
; LA32-LABEL: f32_constant_pi:
; LA32: # %bb.0:
-; LA32-NEXT: pcalau12i $a0, %pc_hi20(.LCPI2_0)
-; LA32-NEXT: fld.s $fa0, $a0, %pc_lo12(.LCPI2_0)
+; LA32-NEXT: .Lpcadd_hi0:
+; LA32-NEXT: pcaddu12i $a0, %pcadd_hi20(.LCPI2_0)
+; LA32-NEXT: fld.s $fa0, $a0, %pcadd_lo12(.Lpcadd_hi0)
; LA32-NEXT: ret
;
; LA64-LABEL: f32_constant_pi:
diff --git a/llvm/test/CodeGen/LoongArch/fsqrt-reciprocal-estimate.ll b/llvm/test/CodeGen/LoongArch/fsqrt-reciprocal-estimate.ll
index e5c848e0f1542..8f4a1898cb1bc 100644
--- a/llvm/test/CodeGen/LoongArch/fsqrt-reciprocal-estimate.ll
+++ b/llvm/test/CodeGen/LoongArch/fsqrt-reciprocal-estimate.ll
@@ -16,16 +16,18 @@ define float @frsqrt_f32(float %a) nounwind {
;
; LA32F-FRECIPE-LABEL: frsqrt_f32:
; LA32F-FRECIPE: # %bb.0:
-; LA32F-FRECIPE-NEXT: frsqrte.s $fa1, $fa0
-; LA32F-FRECIPE-NEXT: pcalau12i $a0, %pc_hi20(.LCPI0_0)
-; LA32F-FRECIPE-NEXT: fld.s $fa2, $a0, %pc_lo12(.LCPI0_0)
-; LA32F-FRECIPE-NEXT: pcalau12i $a0, %pc_hi20(.LCPI0_1)
-; LA32F-FRECIPE-NEXT: fld.s $fa3, $a0, %pc_lo12(.LCPI0_1)
-; LA32F-FRECIPE-NEXT: fmul.s $fa1, $fa0, $fa1
-; LA32F-FRECIPE-NEXT: fmul.s $fa0, $fa0, $fa1
-; LA32F-FRECIPE-NEXT: fmadd.s $fa0, $fa0, $fa1, $fa2
-; LA32F-FRECIPE-NEXT: fmul.s $fa1, $fa1, $fa3
-; LA32F-FRECIPE-NEXT: fmul.s $fa0, $fa1, $fa0
+; LA32F-FRECIPE-NEXT: frsqrte.s $fa1, $fa0
+; LA32F-FRECIPE-NEXT: .Lpcadd_hi0:
+; LA32F-FRECIPE-NEXT: pcaddu12i $a0, %pcadd_hi20(.LCPI0_0)
+; LA32F-FRECIPE-NEXT: fld.s $fa2, $a0, %pcadd_lo12(.Lpcadd_hi0)
+; LA32F-FRECIPE-NEXT: .Lpcadd_hi1:
+; LA32F-FRECIPE-NEXT: pcaddu12i $a0, %pcadd_hi20(.LCPI0_1)
+; LA32F-FRECIPE-NEXT: fld.s $fa3, $a0, %pcadd_lo12(.Lpcadd_hi1)
+; LA32F-FRECIPE-NEXT: fmul.s $fa1, $fa0, $fa1
+; LA32F-FRECIPE-NEXT: fmul.s $fa0, $fa0, $fa1
+; LA32F-FRECIPE-NEXT: fmadd.s $fa0, $fa0, $fa1, $fa2
+; LA32F-FRECIPE-NEXT: fmul.s $fa1, $fa1, $fa3
+; LA32F-FRECIPE-NEXT: fmul.s $fa0, $fa1, $fa0
; LA32F-FRECIPE-NEXT: ret
;
; LA64D-LABEL: frsqrt_f32:
@@ -541,34 +543,38 @@ define double @sqrt_simplify_before_recip_4_uses_f64(double %x, ptr %p1, ptr %p2
define float @sqrt_simplify_before_recip_3_uses_f32(float %x, ptr %p1, ptr %p2) nounwind {
; LA32F-LABEL: sqrt_simplify_before_recip_3_uses_f32:
; LA32F: # %bb.0:
-; LA32F-NEXT: pcalau12i $a2, %pc_hi20(.LCPI5_0)
-; LA32F-NEXT: fld.s $fa2, $a2, %pc_lo12(.LCPI5_0)
-; LA32F-NEXT: fsqrt.s $fa1, $fa0
-; LA32F-NEXT: frsqrt.s $fa0, $fa0
-; LA32F-NEXT: fdiv.s $fa2, $fa2, $fa1
-; LA32F-NEXT: fst.s $fa0, $a0, 0
-; LA32F-NEXT: fst.s $fa2, $a1, 0
-; LA32F-NEXT: fmov.s $fa0, $fa1
+; LA32F-NEXT: .Lpcadd_hi0:
+; LA32F-NEXT: pcaddu12i $a2, %pcadd_hi20(.LCPI5_0)
+; LA32F-NEXT: fld.s $fa2, $a2, %pcadd_lo12(.Lpcadd_hi0)
+; LA32F-NEXT: fsqrt.s $fa1, $fa0
+; LA32F-NEXT: frsqrt.s $fa0, $fa0
+; LA32F-NEXT: fdiv.s $fa2, $fa2, $fa1
+; LA32F-NEXT: fst.s $fa0, $a0, 0
+; LA32F-NEXT: fst.s $fa2, $a1, 0
+; LA32F-NEXT: fmov.s $fa0, $fa1
; LA32F-NEXT: ret
;
; LA32F-FRECIPE-LABEL: sqrt_simplify_before_recip_3_uses_f32:
; LA32F-FRECIPE: # %bb.0:
-; LA32F-FRECIPE-NEXT: frsqrte.s $fa1, $fa0
-; LA32F-FRECIPE-NEXT: fmul.s $fa1, $fa0, $fa1
-; LA32F-FRECIPE-NEXT: fmul.s $fa2, $fa0, $fa1
-; LA32F-FRECIPE-NEXT: pcalau12i $a2, %pc_hi20(.LCPI5_0)
-; LA32F-FRECIPE-NEXT: fld.s $fa3, $a2, %pc_lo12(.LCPI5_0)
-; LA32F-FRECIPE-NEXT: pcalau12i $a2, %pc_hi20(.LCPI5_1)
-; LA32F-FRECIPE-NEXT: fld.s $fa4, $a2, %pc_lo12(.LCPI5_1)
-; LA32F-FRECIPE-NEXT: pcalau12i $a2, %pc_hi20(.LCPI5_2)
-; LA32F-FRECIPE-NEXT: fld.s $fa5, $a2, %pc_lo12(.LCPI5_2)
-; LA32F-FRECIPE-NEXT: fmadd.s $fa2, $fa2, $fa1, $fa3
-; LA32F-FRECIPE-NEXT: fmul.s $fa1, $fa1, $fa4
-; LA32F-FRECIPE-NEXT: fmul.s $fa1, $fa1, $fa2
-; LA32F-FRECIPE-NEXT: fmul.s $fa2, $fa1, $fa5
-; LA32F-FRECIPE-NEXT: fmul.s $fa0, $fa0, $fa1
-; LA32F-FRECIPE-NEXT: fst.s $fa1, $a0, 0
-; LA32F-FRECIPE-NEXT: fst.s $fa2, $a1, 0
+; LA32F-FRECIPE-NEXT: frsqrte.s $fa1, $fa0
+; LA32F-FRECIPE-NEXT: fmul.s $fa1, $fa0, $fa1
+; LA32F-FRECIPE-NEXT: fmul.s $fa2, $fa0, $fa1
+; LA32F-FRECIPE-NEXT: .Lpcadd_hi2:
+; LA32F-FRECIPE-NEXT: pcaddu12i $a2, %pcadd_hi20(.LCPI5_0)
+; LA32F-FRECIPE-NEXT: fld.s $fa3, $a2, %pcadd_lo12(.Lpcadd_hi2)
+; LA32F-FRECIPE-NEXT: .Lpcadd_hi3:
+; LA32F-FRECIPE-NEXT: pcaddu12i $a2, %pcadd_hi20(.LCPI5_1)
+; LA32F-FRECIPE-NEXT: fld.s $fa4, $a2, %pcadd_lo12(.Lpcadd_hi3)
+; LA32F-FRECIPE-NEXT: .Lpcadd_hi4:
+; LA32F-FRECIPE-NEXT: pcaddu12i $a2, %pcadd_hi20(.LCPI5_2)
+; LA32F-FRECIPE-NEXT: fld.s $fa5, $a2, %pcadd_lo12(.Lpcadd_hi4)
+; LA32F-FRECIPE-NEXT: fmadd.s $fa2, $fa2, $fa1, $fa3
+; LA32F-FRECIPE-NEXT: fmul.s $fa1, $fa1, $fa4
+; LA32F-FRECIPE-NEXT: fmul.s $fa1, $fa1, $fa2
+; LA32F-FRECIPE-NEXT: fmul.s $fa2, $fa1, $fa5
+; LA32F-FRECIPE-NEXT: fmul.s $fa0, $fa0, $fa1
+; LA32F-FRECIPE-NEXT: fst.s $fa1, $a0, 0
+; LA32F-FRECIPE-NEXT: fst.s $fa2, $a1, 0
; LA32F-FRECIPE-NEXT: ret
;
; LA64D-LABEL: sqrt_simplify_before_recip_3_uses_f32:
@@ -613,62 +619,68 @@ define float @sqrt_simplify_before_recip_3_uses_f32(float %x, ptr %p1, ptr %p2)
define float @sqrt_simplify_before_recip_4_uses_f32(float %x, ptr %p1, ptr %p2, ptr %p3) nounwind {
; LA32F-LABEL: sqrt_simplify_before_recip_4_uses_f32:
; LA32F: # %bb.0:
-; LA32F-NEXT: pcalau12i $a3, %pc_hi20(.LCPI6_0)
-; LA32F-NEXT: fld.s $fa2, $a3, %pc_lo12(.LCPI6_0)
-; LA32F-NEXT: pcalau12i $a3, %pc_hi20(.LCPI6_1)
-; LA32F-NEXT: fld.s $fa3, $a3, %pc_lo12(.LCPI6_1)
-; LA32F-NEXT: fsqrt.s $fa1, $fa0
-; LA32F-NEXT: frsqrt.s $fa0, $fa0
-; LA32F-NEXT: fdiv.s $fa2, $fa2, $fa1
-; LA32F-NEXT: fdiv.s $fa3, $fa3, $fa1
-; LA32F-NEXT: fst.s $fa0, $a0, 0
-; LA32F-NEXT: fst.s $fa2, $a1, 0
-; LA32F-NEXT: fst.s $fa3, $a2, 0
-; LA32F-NEXT: fmov.s $fa0, $fa1
+; LA32F-NEXT: .Lpcadd_hi1:
+; LA32F-NEXT: pcaddu12i $a3, %pcadd_hi20(.LCPI6_0)
+; LA32F-NEXT: fld.s $fa2, $a3, %pcadd_lo12(.Lpcadd_hi1)
+; LA32F-NEXT: .Lpcadd_hi2:
+; LA32F-NEXT: pcaddu12i $a3, %pcadd_hi20(.LCPI6_1)
+; LA32F-NEXT: fld.s $fa3, $a3, %pcadd_lo12(.Lpcadd_hi2)
+; LA32F-NEXT: fsqrt.s $fa1, $fa0
+; LA32F-NEXT: frsqrt.s $fa0, $fa0
+; LA32F-NEXT: fdiv.s $fa2, $fa2, $fa1
+; LA32F-NEXT: fdiv.s $fa3, $fa3, $fa1
+; LA32F-NEXT: fst.s $fa0, $a0, 0
+; LA32F-NEXT: fst.s $fa2, $a1, 0
+; LA32F-NEXT: fst.s $fa3, $a2, 0
+; LA32F-NEXT: fmov.s $fa0, $fa1
; LA32F-NEXT: ret
;
; LA32F-FRECIPE-LABEL: sqrt_simplify_before_recip_4_uses_f32:
; LA32F-FRECIPE: # %bb.0:
-; LA32F-FRECIPE-NEXT: pcalau12i $a3, %pc_hi20(.LCPI6_0)
-; LA32F-FRECIPE-NEXT: fld.s $fa1, $a3, %pc_lo12(.LCPI6_0)
-; LA32F-FRECIPE-NEXT: frsqrte.s $fa2, $fa0
-; LA32F-FRECIPE-NEXT: fmul.s $fa2, $fa0, $fa2
-; LA32F-FRECIPE-NEXT: fmul.s $fa3, $fa0, $fa2
-; LA32F-FRECIPE-NEXT: fmadd.s $fa1, $fa3, $fa2, $fa1
-; LA32F-FRECIPE-NEXT: pcalau12i $a3, %pc_hi20(.LCPI6_1)
-; LA32F-FRECIPE-NEXT: fld.s $fa3, $a3, %pc_lo12(.LCPI6_1)
-; LA32F-FRECIPE-NEXT: pcalau12i $a3, %pc_hi20(.LCPI6_2)
-; LA32F-FRECIPE-NEXT: fld.s $fa4, $a3, %pc_lo12(.LCPI6_2)
-; LA32F-FRECIPE-NEXT: pcalau12i $a3, %pc_hi20(.LCPI6_3)
-; LA32F-FRECIPE-NEXT: fld.s $fa5, $a3, %pc_lo12(.LCPI6_3)
-; LA32F-FRECIPE-NEXT: fmul.s $fa2, $fa2, $fa3
-; LA32F-FRECIPE-NEXT: fmul.s $fa1, $fa2, $fa1
-; LA32F-FRECIPE-NEXT: fmul.s $fa2, $fa1, $fa4
-; LA32F-FRECIPE-NEXT: fmul.s $fa3, $fa1, $fa5
-; LA32F-FRECIPE-NEXT: fmul.s $fa0, $fa0, $fa1
-; LA32F-FRECIPE-NEXT: fst.s $fa1, $a0, 0
-; LA32F-FRECIPE-NEXT: fst.s $fa2, $a1, 0
-; LA32F-FRECIPE-NEXT: fst.s $fa3, $a2, 0
+; LA32F-FRECIPE-NEXT: .Lpcadd_hi5:
+; LA32F-FRECIPE-NEXT: pcaddu12i $a3, %pcadd_hi20(.LCPI6_0)
+; LA32F-FRECIPE-NEXT: fld.s $fa1, $a3, %pcadd_lo12(.Lpcadd_hi5)
+; LA32F-FRECIPE-NEXT: frsqrte.s $fa2, $fa0
+; LA32F-FRECIPE-NEXT: fmul.s $fa2, $fa0, $fa2
+; LA32F-FRECIPE-NEXT: fmul.s $fa3, $fa0, $fa2
+; LA32F-FRECIPE-NEXT: fmadd.s $fa1, $fa3, $fa2, $fa1
+; LA32F-FRECIPE-NEXT: .Lpcadd_hi6:
+; LA32F-FRECIPE-NEXT: pcaddu12i $a3, %pcadd_hi20(.LCPI6_1)
+; LA32F-FRECIPE-NEXT: fld.s $fa3, $a3, %pcadd_lo12(.Lpcadd_hi6)
+; LA32F-FRECIPE-NEXT: .Lpcadd_hi7:
+; LA32F-FRECIPE-NEXT: pcaddu12i $a3, %pcadd_hi20(.LCPI6_2)
+; LA32F-FRECIPE-NEXT: fld.s $fa4, $a3, %pcadd_lo12(.Lpcadd_hi7)
+; LA32F-FRECIPE-NEXT: .Lpcadd_hi8:
+; LA32F-FRECIPE-NEXT: pcaddu12i $a3, %pcadd_hi20(.LCPI6_3)
+; LA32F-FRECIPE-NEXT: fld.s $fa5, $a3, %pcadd_lo12(.Lpcadd_hi8)
+; LA32F-FRECIPE-NEXT: fmul.s $fa2, $fa2, $fa3
+; LA32F-FRECIPE-NEXT: fmul.s $fa1, $fa2, $fa1
+; LA32F-FRECIPE-NEXT: fmul.s $fa2, $fa1, $fa4
+; LA32F-FRECIPE-NEXT: fmul.s $fa3, $fa1, $fa5
+; LA32F-FRECIPE-NEXT: fmul.s $fa0, $fa0, $fa1
+; LA32F-FRECIPE-NEXT: fst.s $fa1, $a0, 0
+; LA32F-FRECIPE-NEXT: fst.s $fa2, $a1, 0
+; LA32F-FRECIPE-NEXT: fst.s $fa3, $a2, 0
; LA32F-FRECIPE-NEXT: ret
;
-; LA64D-LABEL: sqrt_simplify_before_recip_4_uses_f32:
-; LA64D: # %bb.0:
-; LA64D-NEXT: pcalau12i $a3, %pc_hi20(.LCPI6_0)
-; LA64D-NEXT: fld.s $fa2, $a3, %pc_lo12(.LCPI6_0)
-; LA64D-NEXT: pcalau12i $a3, %pc_hi20(.LCPI6_1)
-; LA64D-NEXT: fld.s $fa3, $a3, %pc_lo12(.LCPI6_1)
-; LA64D-NEXT: fsqrt.s $fa1, $fa0
-; LA64D-NEXT: frsqrt.s $fa0, $fa0
-; LA64D-NEXT: fdiv.s $fa2, $fa2, $fa1
-; LA64D-NEXT: fdiv.s $fa3, $fa3, $fa1
-; LA64D-NEXT: fst.s $fa0, $a0, 0
-; LA64D-NEXT: fst.s $fa2, $a1, 0
-; LA64D-NEXT: fst.s $fa3, $a2, 0
-; LA64D-NEXT: fmov.s $fa0, $fa1
+; LA64D-LABEL: sqrt_simplify_before_recip_4_uses_f32:
+; LA64D: # %bb.0:
+; LA64D-NEXT: pcalau12i $a3, %pc_hi20(.LCPI6_0)
+; LA64D-NEXT: fld.s $fa2, $a3, %pc_lo12(.LCPI6_0)
+; LA64D-NEXT: pcalau12i $a3, %pc_hi20(.LCPI6_1)
+; LA64D-NEXT: fld.s $fa3, $a3, %pc_lo12(.LCPI6_1)
+; LA64D-NEXT: fsqrt.s $fa1, $fa0
+; LA64D-NEXT: frsqrt.s $fa0, $fa0
+; LA64D-NEXT: fdiv.s $fa2, $fa2, $fa1
+; LA64D-NEXT: fdiv.s $fa3, $fa3, $fa1
+; LA64D-NEXT: fst.s $fa0, $a0, 0
+; LA64D-NEXT: fst.s $fa2, $a1, 0
+; LA64D-NEXT: fst.s $fa3, $a2, 0
+; LA64D-NEXT: fmov.s $fa0, $fa1
; LA64D-NEXT: ret
;
-; LA64D-FRECIPE-LABEL: sqrt_simplify_before_recip_4_uses_f32:
-; LA64D-FRECIPE: # %bb.0:
+; LA64D-FRECIPE-LABEL: sqrt_simplify_before_recip_4_uses_f32:
+; LA64D-FRECIPE: # %bb.0:
; LA64D-FRECIPE-NEXT: frsqrte.s $fa1, $fa0
; LA64D-FRECIPE-NEXT: fmul.s $fa1, $fa0, $fa1
; LA64D-FRECIPE-NEXT: fmul.s $fa2, $fa0, $fa1
@@ -688,7 +700,6 @@ define float @sqrt_simplify_before_recip_4_uses_f32(float %x, ptr %p1, ptr %p2,
; LA64D-FRECIPE-NEXT: fst.s $fa2, $a1, 0
; LA64D-FRECIPE-NEXT: fst.s $fa3, $a2, 0
; LA64D-FRECIPE-NEXT: ret
-;
%sqrt = tail call fast float @llvm.sqrt.f32(float %x)
%rsqrt = fdiv fast float 1.0, %sqrt
%r1 = fdiv fast float 42.0, %sqrt
@@ -703,55 +714,61 @@ define float @sqrt_simplify_before_recip_4_uses_f32(float %x, ptr %p1, ptr %p2,
define float @sqrt_simplify_before_recip_3_uses_order_f32(float %x, ptr %p1, ptr %p2) nounwind {
; LA32F-LABEL: sqrt_simplify_before_recip_3_uses_order_f32:
; LA32F: # %bb.0:
-; LA32F-NEXT: pcalau12i $a2, %pc_hi20(.LCPI7_0)
-; LA32F-NEXT: fld.s $fa1, $a2, %pc_lo12(.LCPI7_0)
-; LA32F-NEXT: pcalau12i $a2, %pc_hi20(.LCPI7_1)
-; LA32F-NEXT: fld.s $fa2, $a2, %pc_lo12(.LCPI7_1)
-; LA32F-NEXT: fsqrt.s $fa0, $fa0
-; LA32F-NEXT: fdiv.s $fa1, $fa1, $fa0
-; LA32F-NEXT: fdiv.s $fa2, $fa2, $fa0
-; LA32F-NEXT: fst.s $fa1, $a0, 0
-; LA32F-NEXT: fst.s $fa2, $a1, 0
+; LA32F-NEXT: .Lpcadd_hi3:
+; LA32F-NEXT: pcaddu12i $a2, %pcadd_hi20(.LCPI7_0)
+; LA32F-NEXT: fld.s $fa1, $a2, %pcadd_lo12(.Lpcadd_hi3)
+; LA32F-NEXT: .Lpcadd_hi4:
+; LA32F-NEXT: pcaddu12i $a2, %pcadd_hi20(.LCPI7_1)
+; LA32F-NEXT: fld.s $fa2, $a2, %pcadd_lo12(.Lpcadd_hi4)
+; LA32F-NEXT: fsqrt.s $fa0, $fa0
+; LA32F-NEXT: fdiv.s $fa1, $fa1, $fa0
+; LA32F-NEXT: fdiv.s $fa2, $fa2, $fa0
+; LA32F-NEXT: fst.s $fa1, $a0, 0
+; LA32F-NEXT: fst.s $fa2, $a1, 0
; LA32F-NEXT: ret
;
; LA32F-FRECIPE-LABEL: sqrt_simplify_before_recip_3_uses_order_f32:
; LA32F-FRECIPE: # %bb.0:
-; LA32F-FRECIPE-NEXT: frsqrte.s $fa1, $fa0
-; LA32F-FRECIPE-NEXT: pcalau12i $a2, %pc_hi20(.LCPI7_0)
-; LA32F-FRECIPE-NEXT: fld.s $fa2, $a2, %pc_lo12(.LCPI7_0)
-; LA32F-FRECIPE-NEXT: pcalau12i $a2, %pc_hi20(.LCPI7_1)
-; LA32F-FRECIPE-NEXT: fld.s $fa3, $a2, %pc_lo12(.LCPI7_1)
-; LA32F-FRECIPE-NEXT: fmul.s $fa1, $fa0, $fa1
-; LA32F-FRECIPE-NEXT: fmul.s $fa4, $fa0, $fa1
-; LA32F-FRECIPE-NEXT: fmadd.s $fa2, $fa4, $fa1, $fa2
-; LA32F-FRECIPE-NEXT: fmul.s $fa1, $fa1, $fa3
-; LA32F-FRECIPE-NEXT: pcalau12i $a2, %pc_hi20(.LCPI7_2)
-; LA32F-FRECIPE-NEXT: fld.s $fa3, $a2, %pc_lo12(.LCPI7_2)
-; LA32F-FRECIPE-NEXT: pcalau12i $a2, %pc_hi20(.LCPI7_3)
-; LA32F-FRECIPE-NEXT: fld.s $fa4, $a2, %pc_lo12(.LCPI7_3)
-; LA32F-FRECIPE-NEXT: fmul.s $fa1, $fa1, $fa2
-; LA32F-FRECIPE-NEXT: fmul.s $fa0, $fa0, $fa1
-; LA32F-FRECIPE-NEXT: fmul.s $fa2, $fa1, $fa3
-; LA32F-FRECIPE-NEXT: fmul.s $fa1, $fa1, $fa4
-; LA32F-FRECIPE-NEXT: fst.s $fa2, $a0, 0
-; LA32F-FRECIPE-NEXT: fst.s $fa1, $a1, 0
+; LA32F-FRECIPE-NEXT: frsqrte.s $fa1, $fa0
+; LA32F-FRECIPE-NEXT: .Lpcadd_hi9:
+; LA32F-FRECIPE-NEXT: pcaddu12i $a2, %pcadd_hi20(.LCPI7_0)
+; LA32F-FRECIPE-NEXT: fld.s $fa2, $a2, %pcadd_lo12(.Lpcadd_hi9)
+; LA32F-FRECIPE-NEXT: .Lpcadd_hi10:
+; LA32F-FRECIPE-NEXT: pcaddu12i $a2, %pcadd_hi20(.LCPI7_1)
+; LA32F-FRECIPE-NEXT: fld.s $fa3, $a2, %pcadd_lo12(.Lpcadd_hi10)
+; LA32F-FRECIPE-NEXT: fmul.s $fa1, $fa0, $fa1
+; LA32F-FRECIPE-NEXT: fmul.s $fa4, $fa0, $fa1
+; LA32F-FRECIPE-NEXT: fmadd.s $fa2, $fa4, $fa1, $fa2
+; LA32F-FRECIPE-NEXT: fmul.s $fa1, $fa1, $fa3
+; LA32F-FRECIPE-NEXT: .Lpcadd_hi11:
+; LA32F-FRECIPE-NEXT: pcaddu12i $a2, %pcadd_hi20(.LCPI7_2)
+; LA32F-FRECIPE-NEXT: fld.s $fa3, $a2, %pcadd_lo12(.Lpcadd_hi11)
+; LA32F-FRECIPE-NEXT: .Lpcadd_hi12:
+; LA32F-FRECIPE-NEXT: pcaddu12i $a2, %pcadd_hi20(.LCPI7_3)
+; LA32F-FRECIPE-NEXT: fld.s $fa4, $a2, %pcadd_lo12(.Lpcadd_hi12)
+; LA32F-FRECIPE-NEXT: fmul.s $fa1, $fa1, $fa2
+; LA32F-FRECIPE-NEXT: fmul.s $fa0, $fa0, $fa1
+; LA32F-FRECIPE-NEXT: fmul.s $fa2, $fa1, $fa3
+; LA32F-FRECIPE-NEXT: fmul.s $fa1, $fa1, $fa4
+; LA32F-FRECIPE-NEXT: fst.s $fa2, $a0, 0
+; LA32F-FRECIPE-NEXT: fst.s $fa1, $a1, 0
; LA32F-FRECIPE-NEXT: ret
;
-; LA64D-LABEL: sqrt_simplify_before_recip_3_uses_order_f32:
-; LA64D: # %bb.0:
-; LA64D-NEXT: pcalau12i $a2, %pc_hi20(.LCPI7_0)
-; LA64D-NEXT: fld.s $fa1, $a2, %pc_lo12(.LCPI7_0)
-; LA64D-NEXT: pcalau12i $a2, %pc_hi20(.LCPI7_1)
-; LA64D-NEXT: fld.s $fa2, $a2, %pc_lo12(.LCPI7_1)
-; LA64D-NEXT: fsqrt.s $fa0, $fa0
-; LA64D-NEXT: fdiv.s $fa1, $fa1, $fa0
-; LA64D-NEXT: fdiv.s $fa2, $fa2, $fa0
-; LA64D-NEXT: fst.s $fa1, $a0, 0
-; LA64D-NEXT: fst.s $fa2, $a1, 0
+; LA64D-LABEL: sqrt_simplify_before_recip_3_uses_order_f32:
+; LA64D: # %bb.0:
+; LA64D-NEXT: pcalau12i $a2, %pc_hi20(.LCPI7_0)
+; LA64D-NEXT: fld.s $fa1, $a2, %pc_lo12(.LCPI7_0)
+; LA64D-NEXT: pcalau12i $a2, %pc_hi20(.LCPI7_1)
+; LA64D-NEXT: fld.s $fa2, $a2, %pc_lo12(.LCPI7_1)
+; LA64D-NEXT: fsqrt.s $fa0, $fa0
+; LA64D-NEXT: fdiv.s $fa1, $fa1, $fa0
+; LA64D-NEXT: fdiv.s $fa2, $fa2, $fa0
+; LA64D-NEXT: fst.s $fa1, $a0, 0
+; LA64D-NEXT: fst.s $fa2, $a1, 0
; LA64D-NEXT: ret
;
-; LA64D-FRECIPE-LABEL: sqrt_simplify_before_recip_3_uses_order_f32:
-; LA64D-FRECIPE: # %bb.0:
+; LA64D-FRECIPE-LABEL: sqrt_simplify_before_recip_3_uses_order_f32:
+; LA64D-FRECIPE: # %bb.0:
; LA64D-FRECIPE-NEXT: frsqrte.s $fa1, $fa0
; LA64D-FRECIPE-NEXT: fmul.s $fa1, $fa0, $fa1
; LA64D-FRECIPE-NEXT: fmul.s $fa2, $fa0, $fa1
diff --git a/llvm/test/CodeGen/LoongArch/global-address.ll b/llvm/test/CodeGen/LoongArch/global-address.ll
index 89ea48c3b1cbf..8098c225564ee 100644
--- a/llvm/test/CodeGen/LoongArch/global-address.ll
+++ b/llvm/test/CodeGen/LoongArch/global-address.ll
@@ -12,20 +12,24 @@
define void @foo() nounwind {
; LA32NOPIC-LABEL: foo:
; LA32NOPIC: # %bb.0:
-; LA32NOPIC-NEXT: pcalau12i $a0, %got_pc_hi20(G)
-; LA32NOPIC-NEXT: ld.w $a0, $a0, %got_pc_lo12(G)
+; LA32NOPIC-NEXT: .Lpcadd_hi0:
+; LA32NOPIC-NEXT: pcaddu12i $a0, %pcadd_got_hi20(G)
+; LA32NOPIC-NEXT: ld.w $a0, $a0, %pcadd_lo12(.Lpcadd_hi0)
; LA32NOPIC-NEXT: ld.w $zero, $a0, 0
-; LA32NOPIC-NEXT: pcalau12i $a0, %pc_hi20(g)
-; LA32NOPIC-NEXT: ld.w $zero, $a0, %pc_lo12(g)
+; LA32NOPIC-NEXT: .Lpcadd_hi1:
+; LA32NOPIC-NEXT: pcaddu12i $a0, %pcadd_hi20(g)
+; LA32NOPIC-NEXT: ld.w $zero, $a0, %pcadd_lo12(.Lpcadd_hi1)
; LA32NOPIC-NEXT: ret
;
; LA32PIC-LABEL: foo:
; LA32PIC: # %bb.0:
-; LA32PIC-NEXT: pcalau12i $a0, %got_pc_hi20(G)
-; LA32PIC-NEXT: ld.w $a0, $a0, %got_pc_lo12(G)
+; LA32PIC-NEXT: .Lpcadd_hi0:
+; LA32PIC-NEXT: pcaddu12i $a0, %pcadd_got_hi20(G)
+; LA32PIC-NEXT: ld.w $a0, $a0, %pcadd_lo12(.Lpcadd_hi0)
; LA32PIC-NEXT: ld.w $zero, $a0, 0
-; LA32PIC-NEXT: pcalau12i $a0, %pc_hi20(.Lg$local)
-; LA32PIC-NEXT: ld.w $zero, $a0, %pc_lo12(.Lg$local)
+; LA32PIC-NEXT: .Lpcadd_hi1:
+; LA32PIC-NEXT: pcaddu12i $a0, %pcadd_hi20(.Lg$local)
+; LA32PIC-NEXT: ld.w $zero, $a0, %pcadd_lo12(.Lpcadd_hi1)
; LA32PIC-NEXT: ret
;
; LA64NOPIC-LABEL: foo:
diff --git a/llvm/test/CodeGen/LoongArch/inline-asm-constraint-f.ll b/llvm/test/CodeGen/LoongArch/inline-asm-constraint-f.ll
index c1d75ddd32803..b5f1c23a95207 100644
--- a/llvm/test/CodeGen/LoongArch/inline-asm-constraint-f.ll
+++ b/llvm/test/CodeGen/LoongArch/inline-asm-constraint-f.ll
@@ -9,8 +9,9 @@
define double @constraint_f_double(double %a) nounwind {
; LA32-LABEL: constraint_f_double:
; LA32: # %bb.0:
-; LA32-NEXT: pcalau12i $a0, %pc_hi20(gd)
-; LA32-NEXT: fld.d $fa1, $a0, %pc_lo12(gd)
+; LA32-NEXT: .Lpcadd_hi0:
+; LA32-NEXT: pcaddu12i $a0, %pcadd_hi20(gd)
+; LA32-NEXT: fld.d $fa1, $a0, %pcadd_lo12(.Lpcadd_hi0)
; LA32-NEXT: #APP
; LA32-NEXT: fadd.d $fa0, $fa0, $fa1
; LA32-NEXT: #NO_APP
diff --git a/llvm/test/CodeGen/LoongArch/inline-asm-constraint-m.ll b/llvm/test/CodeGen/LoongArch/inline-asm-constraint-m.ll
index 565ccdbe6880f..59117683c1f08 100644
--- a/llvm/test/CodeGen/LoongArch/inline-asm-constraint-m.ll
+++ b/llvm/test/CodeGen/LoongArch/inline-asm-constraint-m.ll
@@ -147,9 +147,10 @@ define i32 @m_offset_2048(ptr %p) nounwind {
define i32 @m_addr_pcrel() nounwind {
; LA32-LABEL: m_addr_pcrel:
; LA32: # %bb.0:
-; LA32-NEXT: pcalau12i $a1, %pc_hi20(g_i32)
+; LA32-NEXT: .Lpcadd_hi0:
+; LA32-NEXT: pcaddu12i $a1, %pcadd_hi20(g_i32)
; LA32-NEXT: #APP
-; LA32-NEXT: ld.w $a0, $a1, %pc_lo12(g_i32)
+; LA32-NEXT: ld.w $a0, $a1, %pcadd_lo12(.Lpcadd_hi00)
; LA32-NEXT: #NO_APP
; LA32-NEXT: ret
;
@@ -167,8 +168,9 @@ define i32 @m_addr_pcrel() nounwind {
define i32 @m_addr_should_not_fold() nounwind {
; LA32-LABEL: m_addr_should_not_fold:
; LA32: # %bb.0:
-; LA32-NEXT: pcalau12i $a0, %pc_hi20(g_i32)
-; LA32-NEXT: addi.w $a1, $a0, %pc_lo12(g_i32)
+; LA32-NEXT: .Lpcadd_hi1:
+; LA32-NEXT: pcaddu12i $a0, %pcadd_hi20(g_i32)
+; LA32-NEXT: addi.w $a1, $a0, %pcadd_lo12(.Lpcadd_hi1)
; LA32-NEXT: #APP
; LA32-NEXT: ld.w $a0, $a1, 0
; LA32-NEXT: #NO_APP
diff --git a/llvm/test/CodeGen/LoongArch/ir-instruction/double-convert.ll b/llvm/test/CodeGen/LoongArch/ir-instruction/double-convert.ll
index 0b82ea220d7fb..1950eaf247967 100644
--- a/llvm/test/CodeGen/LoongArch/ir-instruction/double-convert.ll
+++ b/llvm/test/CodeGen/LoongArch/ir-instruction/double-convert.ll
@@ -116,8 +116,9 @@ define i32 @convert_double_to_i32(double %a) nounwind {
define i32 @convert_double_to_u32(double %a) nounwind {
; LA32-LABEL: convert_double_to_u32:
; LA32: # %bb.0:
-; LA32-NEXT: pcalau12i $a0, %pc_hi20(.LCPI7_0)
-; LA32-NEXT: fld.d $fa1, $a0, %pc_lo12(.LCPI7_0)
+; LA32-NEXT: .Lpcadd_hi0:
+; LA32-NEXT: pcaddu12i $a0, %pcadd_hi20(.LCPI7_0)
+; LA32-NEXT: fld.d $fa1, $a0, %pcadd_lo12(.Lpcadd_hi0)
; LA32-NEXT: fcmp.clt.d $fcc0, $fa0, $fa1
; LA32-NEXT: movcf2gr $a0, $fcc0
; LA32-NEXT: bne $a0, $zero, .LBB7_2
@@ -232,8 +233,9 @@ define double @convert_u32_to_double(i32 %a) nounwind {
; LA32-NEXT: st.w $a1, $sp, 12
; LA32-NEXT: st.w $a0, $sp, 8
; LA32-NEXT: fld.d $fa0, $sp, 8
-; LA32-NEXT: pcalau12i $a0, %pc_hi20(.LCPI12_0)
-; LA32-NEXT: fld.d $fa1, $a0, %pc_lo12(.LCPI12_0)
+; LA32-NEXT: .Lpcadd_hi1:
+; LA32-NEXT: pcaddu12i $a0, %pcadd_hi20(.LCPI12_0)
+; LA32-NEXT: fld.d $fa1, $a0, %pcadd_lo12(.Lpcadd_hi1)
; LA32-NEXT: fsub.d $fa0, $fa0, $fa1
; LA32-NEXT: addi.w $sp, $sp, 16
; LA32-NEXT: ret
diff --git a/llvm/test/CodeGen/LoongArch/ir-instruction/float-convert.ll b/llvm/test/CodeGen/LoongArch/ir-instruction/float-convert.ll
index 413702b006b1b..92e4e0b19d7cc 100644
--- a/llvm/test/CodeGen/LoongArch/ir-instruction/float-convert.ll
+++ b/llvm/test/CodeGen/LoongArch/ir-instruction/float-convert.ll
@@ -181,8 +181,9 @@ define zeroext i16 @convert_float_to_u16(float %a) nounwind {
define i32 @convert_float_to_u32(float %a) nounwind {
; LA32F-LABEL: convert_float_to_u32:
; LA32F: # %bb.0:
-; LA32F-NEXT: pcalau12i $a0, %pc_hi20(.LCPI6_0)
-; LA32F-NEXT: fld.s $fa1, $a0, %pc_lo12(.LCPI6_0)
+; LA32F-NEXT: .Lpcadd_hi0:
+; LA32F-NEXT: pcaddu12i $a0, %pcadd_hi20(.LCPI6_0)
+; LA32F-NEXT: fld.s $fa1, $a0, %pcadd_lo12(.Lpcadd_hi0)
; LA32F-NEXT: fcmp.clt.s $fcc0, $fa0, $fa1
; LA32F-NEXT: movcf2gr $a0, $fcc0
; LA32F-NEXT: bne $a0, $zero, .LBB6_2
@@ -200,8 +201,9 @@ define i32 @convert_float_to_u32(float %a) nounwind {
;
; LA32D-LABEL: convert_float_to_u32:
; LA32D: # %bb.0:
-; LA32D-NEXT: pcalau12i $a0, %pc_hi20(.LCPI6_0)
-; LA32D-NEXT: fld.s $fa1, $a0, %pc_lo12(.LCPI6_0)
+; LA32D-NEXT: .Lpcadd_hi0:
+; LA32D-NEXT: pcaddu12i $a0, %pcadd_hi20(.LCPI6_0)
+; LA32D-NEXT: fld.s $fa1, $a0, %pcadd_lo12(.Lpcadd_hi0)
; LA32D-NEXT: fcmp.clt.s $fcc0, $fa0, $fa1
; LA32D-NEXT: movcf2gr $a0, $fcc0
; LA32D-NEXT: bne $a0, $zero, .LBB6_2
@@ -503,8 +505,9 @@ define float @convert_u32_to_float(i32 %a) nounwind {
; LA32D-NEXT: st.w $a1, $sp, 12
; LA32D-NEXT: st.w $a0, $sp, 8
; LA32D-NEXT: fld.d $fa0, $sp, 8
-; LA32D-NEXT: pcalau12i $a0, %pc_hi20(.LCPI14_0)
-; LA32D-NEXT: fld.d $fa1, $a0, %pc_lo12(.LCPI14_0)
+; LA32D-NEXT: .Lpcadd_hi1:
+; LA32D-NEXT: pcaddu12i $a0, %pcadd_hi20(.LCPI14_0)
+; LA32D-NEXT: fld.d $fa1, $a0, %pcadd_lo12(.Lpcadd_hi1)
; LA32D-NEXT: fsub.d $fa0, $fa0, $fa1
; LA32D-NEXT: fcvt.s.d $fa0, $fa0
; LA32D-NEXT: addi.w $sp, $sp, 16
diff --git a/llvm/test/CodeGen/LoongArch/ir-instruction/load-store.ll b/llvm/test/CodeGen/LoongArch/ir-instruction/load-store.ll
index 18ba4810cfb72..1679659a8823b 100644
--- a/llvm/test/CodeGen/LoongArch/ir-instruction/load-store.ll
+++ b/llvm/test/CodeGen/LoongArch/ir-instruction/load-store.ll
@@ -13,10 +13,11 @@
define i32 @load_store_global() nounwind {
; LA32RNOPIC-LABEL: load_store_global:
; LA32RNOPIC: # %bb.0:
-; LA32RNOPIC-NEXT: pcalau12i $a1, %pc_hi20(G)
-; LA32RNOPIC-NEXT: ld.w $a0, $a1, %pc_lo12(G)
+; LA32RNOPIC-NEXT: .Lpcadd_hi0:
+; LA32RNOPIC-NEXT: pcaddu12i $a1, %pcadd_hi20(G)
+; LA32RNOPIC-NEXT: ld.w $a0, $a1, %pcadd_lo12(.Lpcadd_hi0)
; LA32RNOPIC-NEXT: addi.w $a0, $a0, 1
-; LA32RNOPIC-NEXT: st.w $a0, $a1, %pc_lo12(G)
+; LA32RNOPIC-NEXT: st.w $a0, $a1, %pcadd_lo12(.Lpcadd_hi0)
; LA32RNOPIC-NEXT: ret
;
; LA32SNOPIC-LABEL: load_store_global:
@@ -29,10 +30,11 @@ define i32 @load_store_global() nounwind {
;
; LA32RPIC-LABEL: load_store_global:
; LA32RPIC: # %bb.0:
-; LA32RPIC-NEXT: pcalau12i $a1, %pc_hi20(.LG$local)
-; LA32RPIC-NEXT: ld.w $a0, $a1, %pc_lo12(.LG$local)
+; LA32RPIC-NEXT: .Lpcadd_hi0:
+; LA32RPIC-NEXT: pcaddu12i $a1, %pcadd_hi20(.LG$local)
+; LA32RPIC-NEXT: ld.w $a0, $a1, %pcadd_lo12(.Lpcadd_hi0)
; LA32RPIC-NEXT: addi.w $a0, $a0, 1
-; LA32RPIC-NEXT: st.w $a0, $a1, %pc_lo12(.LG$local)
+; LA32RPIC-NEXT: st.w $a0, $a1, %pcadd_lo12(.Lpcadd_hi0)
; LA32RPIC-NEXT: ret
;
; LA32SPIC-LABEL: load_store_global:
@@ -67,8 +69,9 @@ define i32 @load_store_global() nounwind {
define i32 @load_store_global_array(i32 %a) nounwind {
; LA32RNOPIC-LABEL: load_store_global_array:
; LA32RNOPIC: # %bb.0:
-; LA32RNOPIC-NEXT: pcalau12i $a1, %pc_hi20(arr)
-; LA32RNOPIC-NEXT: addi.w $a2, $a1, %pc_lo12(arr)
+; LA32RNOPIC-NEXT: .Lpcadd_hi1:
+; LA32RNOPIC-NEXT: pcaddu12i $a1, %pcadd_hi20(arr)
+; LA32RNOPIC-NEXT: addi.w $a2, $a1, %pcadd_lo12(.Lpcadd_hi1)
; LA32RNOPIC-NEXT: ld.w $a1, $a2, 0
; LA32RNOPIC-NEXT: st.w $a0, $a2, 0
; LA32RNOPIC-NEXT: ld.w $zero, $a2, 36
@@ -89,8 +92,9 @@ define i32 @load_store_global_array(i32 %a) nounwind {
;
; LA32RPIC-LABEL: load_store_global_array:
; LA32RPIC: # %bb.0:
-; LA32RPIC-NEXT: pcalau12i $a1, %pc_hi20(.Larr$local)
-; LA32RPIC-NEXT: addi.w $a2, $a1, %pc_lo12(.Larr$local)
+; LA32RPIC-NEXT: .Lpcadd_hi1:
+; LA32RPIC-NEXT: pcaddu12i $a1, %pcadd_hi20(.Larr$local)
+; LA32RPIC-NEXT: addi.w $a2, $a1, %pcadd_lo12(.Lpcadd_hi1)
; LA32RPIC-NEXT: ld.w $a1, $a2, 0
; LA32RPIC-NEXT: st.w $a0, $a2, 0
; LA32RPIC-NEXT: ld.w $zero, $a2, 36
diff --git a/llvm/test/CodeGen/LoongArch/machinelicm-address-pseudos.ll b/llvm/test/CodeGen/LoongArch/machinelicm-address-pseudos.ll
index 06edb736e0435..a2d5e84c719a7 100644
--- a/llvm/test/CodeGen/LoongArch/machinelicm-address-pseudos.ll
+++ b/llvm/test/CodeGen/LoongArch/machinelicm-address-pseudos.ll
@@ -14,11 +14,12 @@ define void @test_la_pcrel(i32 signext %n) {
; LA32-LABEL: test_la_pcrel:
; LA32: # %bb.0: # %entry
; LA32-NEXT: move $a1, $zero
-; LA32-NEXT: pcalau12i $a2, %pc_hi20(l)
+; LA32-NEXT: .Lpcadd_hi0:
+; LA32-NEXT: pcaddu12i $a2, %pcadd_hi20(l)
; LA32-NEXT: .p2align 4, , 16
; LA32-NEXT: .LBB0_1: # %loop
; LA32-NEXT: # =>This Inner Loop Header: Depth=1
-; LA32-NEXT: ld.w $zero, $a2, %pc_lo12(l)
+; LA32-NEXT: ld.w $zero, $a2, %pcadd_lo12(.Lpcadd_hi0)
; LA32-NEXT: addi.w $a1, $a1, 1
; LA32-NEXT: blt $a1, $a0, .LBB0_1
; LA32-NEXT: # %bb.2: # %ret
@@ -71,8 +72,9 @@ ret:
define void @test_la_got(i32 signext %n) {
; LA32-LABEL: test_la_got:
; LA32: # %bb.0: # %entry
-; LA32-NEXT: pcalau12i $a1, %got_pc_hi20(g)
-; LA32-NEXT: ld.w $a1, $a1, %got_pc_lo12(g)
+; LA32-NEXT: .Lpcadd_hi1:
+; LA32-NEXT: pcaddu12i $a1, %pcadd_got_hi20(g)
+; LA32-NEXT: ld.w $a1, $a1, %pcadd_lo12(.Lpcadd_hi1)
; LA32-NEXT: move $a2, $zero
; LA32-NEXT: .p2align 4, , 16
; LA32-NEXT: .LBB1_1: # %loop
@@ -132,8 +134,9 @@ ret:
define void @test_la_tls_ie(i32 signext %n) {
; LA32-LABEL: test_la_tls_ie:
; LA32: # %bb.0: # %entry
-; LA32-NEXT: pcalau12i $a1, %ie_pc_hi20(ie)
-; LA32-NEXT: ld.w $a2, $a1, %ie_pc_lo12(ie)
+; LA32-NEXT: .Lpcadd_hi2:
+; LA32-NEXT: pcaddu12i $a1, %pcadd_ie_hi20(ie)
+; LA32-NEXT: ld.w $a2, $a1, %pcadd_lo12(.Lpcadd_hi2)
; LA32-NEXT: move $a1, $zero
; LA32-NEXT: add.w $a2, $a2, $tp
; LA32-NEXT: .p2align 4, , 16
diff --git a/llvm/test/CodeGen/LoongArch/merge-base-offset.ll b/llvm/test/CodeGen/LoongArch/merge-base-offset.ll
index 2af206699d4ad..6ac311e251060 100644
--- a/llvm/test/CodeGen/LoongArch/merge-base-offset.ll
+++ b/llvm/test/CodeGen/LoongArch/merge-base-offset.ll
@@ -11,8 +11,9 @@
define dso_local signext i8 @load_s8() nounwind {
; LA32-LABEL: load_s8:
; LA32: # %bb.0: # %entry
-; LA32-NEXT: pcalau12i $a0, %pc_hi20(g_i8)
-; LA32-NEXT: ld.b $a0, $a0, %pc_lo12(g_i8)
+; LA32-NEXT: .Lpcadd_hi0:
+; LA32-NEXT: pcaddu12i $a0, %pcadd_hi20(g_i8)
+; LA32-NEXT: ld.b $a0, $a0, %pcadd_lo12(.Lpcadd_hi0)
; LA32-NEXT: ret
;
; LA64-LABEL: load_s8:
@@ -37,8 +38,9 @@ entry:
define dso_local zeroext i8 @load_u8() nounwind {
; LA32-LABEL: load_u8:
; LA32: # %bb.0: # %entry
-; LA32-NEXT: pcalau12i $a0, %pc_hi20(g_i8)
-; LA32-NEXT: ld.bu $a0, $a0, %pc_lo12(g_i8)
+; LA32-NEXT: .Lpcadd_hi1:
+; LA32-NEXT: pcaddu12i $a0, %pcadd_hi20(g_i8)
+; LA32-NEXT: ld.bu $a0, $a0, %pcadd_lo12(.Lpcadd_hi1)
; LA32-NEXT: ret
;
; LA64-LABEL: load_u8:
@@ -63,9 +65,10 @@ entry:
define dso_local void @store_i8() nounwind {
; LA32-LABEL: store_i8:
; LA32: # %bb.0: # %entry
-; LA32-NEXT: pcalau12i $a0, %pc_hi20(g_i8)
+; LA32-NEXT: .Lpcadd_hi2:
+; LA32-NEXT: pcaddu12i $a0, %pcadd_hi20(g_i8)
; LA32-NEXT: ori $a1, $zero, 1
-; LA32-NEXT: st.b $a1, $a0, %pc_lo12(g_i8)
+; LA32-NEXT: st.b $a1, $a0, %pcadd_lo12(.Lpcadd_hi2)
; LA32-NEXT: ret
;
; LA64-LABEL: store_i8:
@@ -94,8 +97,9 @@ entry:
define dso_local signext i16 @load_s16() nounwind {
; LA32-LABEL: load_s16:
; LA32: # %bb.0: # %entry
-; LA32-NEXT: pcalau12i $a0, %pc_hi20(g_i16)
-; LA32-NEXT: ld.h $a0, $a0, %pc_lo12(g_i16)
+; LA32-NEXT: .Lpcadd_hi3:
+; LA32-NEXT: pcaddu12i $a0, %pcadd_hi20(g_i16)
+; LA32-NEXT: ld.h $a0, $a0, %pcadd_lo12(.Lpcadd_hi3)
; LA32-NEXT: ret
;
; LA64-LABEL: load_s16:
@@ -120,8 +124,9 @@ entry:
define dso_local zeroext i16 @load_u16() nounwind {
; LA32-LABEL: load_u16:
; LA32: # %bb.0: # %entry
-; LA32-NEXT: pcalau12i $a0, %pc_hi20(g_i16)
-; LA32-NEXT: ld.hu $a0, $a0, %pc_lo12(g_i16)
+; LA32-NEXT: .Lpcadd_hi4:
+; LA32-NEXT: pcaddu12i $a0, %pcadd_hi20(g_i16)
+; LA32-NEXT: ld.hu $a0, $a0, %pcadd_lo12(.Lpcadd_hi4)
; LA32-NEXT: ret
;
; LA64-LABEL: load_u16:
@@ -146,9 +151,10 @@ entry:
define dso_local void @store_i16() nounwind {
; LA32-LABEL: store_i16:
; LA32: # %bb.0: # %entry
-; LA32-NEXT: pcalau12i $a0, %pc_hi20(g_i16)
+; LA32-NEXT: .Lpcadd_hi5:
+; LA32-NEXT: pcaddu12i $a0, %pcadd_hi20(g_i16)
; LA32-NEXT: ori $a1, $zero, 1
-; LA32-NEXT: st.h $a1, $a0, %pc_lo12(g_i16)
+; LA32-NEXT: st.h $a1, $a0, %pcadd_lo12(.Lpcadd_hi5)
; LA32-NEXT: ret
;
; LA64-LABEL: store_i16:
@@ -177,8 +183,9 @@ entry:
define dso_local signext i32 @load_s32() nounwind {
; LA32-LABEL: load_s32:
; LA32: # %bb.0: # %entry
-; LA32-NEXT: pcalau12i $a0, %pc_hi20(g_i32)
-; LA32-NEXT: ld.w $a0, $a0, %pc_lo12(g_i32)
+; LA32-NEXT: .Lpcadd_hi6:
+; LA32-NEXT: pcaddu12i $a0, %pcadd_hi20(g_i32)
+; LA32-NEXT: ld.w $a0, $a0, %pcadd_lo12(.Lpcadd_hi6)
; LA32-NEXT: ret
;
; LA64-LABEL: load_s32:
@@ -203,8 +210,9 @@ entry:
define dso_local zeroext i32 @load_u32() nounwind {
; LA32-LABEL: load_u32:
; LA32: # %bb.0: # %entry
-; LA32-NEXT: pcalau12i $a0, %pc_hi20(g_i32)
-; LA32-NEXT: ld.w $a0, $a0, %pc_lo12(g_i32)
+; LA32-NEXT: .Lpcadd_hi7:
+; LA32-NEXT: pcaddu12i $a0, %pcadd_hi20(g_i32)
+; LA32-NEXT: ld.w $a0, $a0, %pcadd_lo12(.Lpcadd_hi7)
; LA32-NEXT: ret
;
; LA64-LABEL: load_u32:
@@ -229,9 +237,10 @@ entry:
define dso_local void @store_i32() nounwind {
; LA32-LABEL: store_i32:
; LA32: # %bb.0: # %entry
-; LA32-NEXT: pcalau12i $a0, %pc_hi20(g_i32)
+; LA32-NEXT: .Lpcadd_hi8:
+; LA32-NEXT: pcaddu12i $a0, %pcadd_hi20(g_i32)
; LA32-NEXT: ori $a1, $zero, 1
-; LA32-NEXT: st.w $a1, $a0, %pc_lo12(g_i32)
+; LA32-NEXT: st.w $a1, $a0, %pcadd_lo12(.Lpcadd_hi8)
; LA32-NEXT: ret
;
; LA64-LABEL: store_i32:
@@ -260,8 +269,9 @@ entry:
define dso_local i64 @load_i64() nounwind {
; LA32-LABEL: load_i64:
; LA32: # %bb.0: # %entry
-; LA32-NEXT: pcalau12i $a0, %pc_hi20(g_i64)
-; LA32-NEXT: addi.w $a1, $a0, %pc_lo12(g_i64)
+; LA32-NEXT: .Lpcadd_hi9:
+; LA32-NEXT: pcaddu12i $a0, %pcadd_hi20(g_i64)
+; LA32-NEXT: addi.w $a1, $a0, %pcadd_lo12(.Lpcadd_hi9)
; LA32-NEXT: ld.w $a0, $a1, 0
; LA32-NEXT: ld.w $a1, $a1, 4
; LA32-NEXT: ret
@@ -288,8 +298,9 @@ entry:
define dso_local void @store_i64() nounwind {
; LA32-LABEL: store_i64:
; LA32: # %bb.0: # %entry
-; LA32-NEXT: pcalau12i $a0, %pc_hi20(g_i64)
-; LA32-NEXT: addi.w $a0, $a0, %pc_lo12(g_i64)
+; LA32-NEXT: .Lpcadd_hi10:
+; LA32-NEXT: pcaddu12i $a0, %pcadd_hi20(g_i64)
+; LA32-NEXT: addi.w $a0, $a0, %pcadd_lo12(.Lpcadd_hi10)
; LA32-NEXT: st.w $zero, $a0, 4
; LA32-NEXT: ori $a1, $zero, 1
; LA32-NEXT: st.w $a1, $a0, 0
@@ -321,8 +332,9 @@ entry:
define dso_local float @load_f32() nounwind {
; LA32-LABEL: load_f32:
; LA32: # %bb.0: # %entry
-; LA32-NEXT: pcalau12i $a0, %pc_hi20(g_f32)
-; LA32-NEXT: fld.s $fa0, $a0, %pc_lo12(g_f32)
+; LA32-NEXT: .Lpcadd_hi11:
+; LA32-NEXT: pcaddu12i $a0, %pcadd_hi20(g_f32)
+; LA32-NEXT: fld.s $fa0, $a0, %pcadd_lo12(.Lpcadd_hi11)
; LA32-NEXT: ret
;
; LA64-LABEL: load_f32:
@@ -347,9 +359,10 @@ entry:
define dso_local void @store_f32() nounwind {
; LA32-LABEL: store_f32:
; LA32: # %bb.0: # %entry
-; LA32-NEXT: pcalau12i $a0, %pc_hi20(g_f32)
+; LA32-NEXT: .Lpcadd_hi12:
+; LA32-NEXT: pcaddu12i $a0, %pcadd_hi20(g_f32)
; LA32-NEXT: lu12i.w $a1, 260096
-; LA32-NEXT: st.w $a1, $a0, %pc_lo12(g_f32)
+; LA32-NEXT: st.w $a1, $a0, %pcadd_lo12(.Lpcadd_hi12)
; LA32-NEXT: ret
;
; LA64-LABEL: store_f32:
@@ -378,8 +391,9 @@ entry:
define dso_local double @load_f64() nounwind {
; LA32-LABEL: load_f64:
; LA32: # %bb.0: # %entry
-; LA32-NEXT: pcalau12i $a0, %pc_hi20(g_f64)
-; LA32-NEXT: fld.d $fa0, $a0, %pc_lo12(g_f64)
+; LA32-NEXT: .Lpcadd_hi13:
+; LA32-NEXT: pcaddu12i $a0, %pcadd_hi20(g_f64)
+; LA32-NEXT: fld.d $fa0, $a0, %pcadd_lo12(.Lpcadd_hi13)
; LA32-NEXT: ret
;
; LA64-LABEL: load_f64:
@@ -404,9 +418,10 @@ entry:
define dso_local void @store_f64() nounwind {
; LA32-LABEL: store_f64:
; LA32: # %bb.0: # %entry
-; LA32-NEXT: pcalau12i $a0, %pc_hi20(g_f64)
+; LA32-NEXT: .Lpcadd_hi14:
+; LA32-NEXT: pcaddu12i $a0, %pcadd_hi20(g_f64)
; LA32-NEXT: vldi $vr0, -912
-; LA32-NEXT: fst.d $fa0, $a0, %pc_lo12(g_f64)
+; LA32-NEXT: fst.d $fa0, $a0, %pcadd_lo12(.Lpcadd_hi14)
; LA32-NEXT: ret
;
; LA64-LABEL: store_f64:
@@ -435,8 +450,9 @@ entry:
define dso_local void @store_multi() nounwind {
; LA32-LABEL: store_multi:
; LA32: # %bb.0: # %entry
-; LA32-NEXT: pcalau12i $a0, %pc_hi20(g_m64)
-; LA32-NEXT: addi.w $a0, $a0, %pc_lo12(g_m64)
+; LA32-NEXT: .Lpcadd_hi15:
+; LA32-NEXT: pcaddu12i $a0, %pcadd_hi20(g_m64)
+; LA32-NEXT: addi.w $a0, $a0, %pcadd_lo12(.Lpcadd_hi15)
; LA32-NEXT: st.w $zero, $a0, 4
; LA32-NEXT: ori $a1, $zero, 1
; LA32-NEXT: st.w $a1, $a0, 0
@@ -476,9 +492,10 @@ entry:
define dso_local void @store_sf32() nounwind {
; LA32-LABEL: store_sf32:
; LA32: # %bb.0: # %entry
-; LA32-NEXT: pcalau12i $a0, %pc_hi20(g_sf32)
-; LA32-NEXT: fld.s $fa0, $a0, %pc_lo12(g_sf32)
-; LA32-NEXT: fst.s $fa0, $a0, %pc_lo12(g_sf32)
+; LA32-NEXT: .Lpcadd_hi16:
+; LA32-NEXT: pcaddu12i $a0, %pcadd_hi20(g_sf32)
+; LA32-NEXT: fld.s $fa0, $a0, %pcadd_lo12(.Lpcadd_hi16)
+; LA32-NEXT: fst.s $fa0, $a0, %pcadd_lo12(.Lpcadd_hi16)
; LA32-NEXT: ret
;
; LA64-LABEL: store_sf32:
@@ -508,9 +525,10 @@ entry:
define dso_local void @store_sf64() nounwind {
; LA32-LABEL: store_sf64:
; LA32: # %bb.0: # %entry
-; LA32-NEXT: pcalau12i $a0, %pc_hi20(g_sf64)
-; LA32-NEXT: fld.d $fa0, $a0, %pc_lo12(g_sf64)
-; LA32-NEXT: fst.d $fa0, $a0, %pc_lo12(g_sf64)
+; LA32-NEXT: .Lpcadd_hi17:
+; LA32-NEXT: pcaddu12i $a0, %pcadd_hi20(g_sf64)
+; LA32-NEXT: fld.d $fa0, $a0, %pcadd_lo12(.Lpcadd_hi17)
+; LA32-NEXT: fst.d $fa0, $a0, %pcadd_lo12(.Lpcadd_hi17)
; LA32-NEXT: ret
;
; LA64-LABEL: store_sf64:
@@ -541,10 +559,12 @@ entry:
define dso_local void @copy_i32x4() nounwind {
; LA32-LABEL: copy_i32x4:
; LA32: # %bb.0: # %entry
-; LA32-NEXT: pcalau12i $a0, %pc_hi20(g_i32x4_src)
-; LA32-NEXT: vld $vr0, $a0, %pc_lo12(g_i32x4_src)
-; LA32-NEXT: pcalau12i $a0, %pc_hi20(g_i32x4_dst)
-; LA32-NEXT: vst $vr0, $a0, %pc_lo12(g_i32x4_dst)
+; LA32-NEXT: .Lpcadd_hi18:
+; LA32-NEXT: pcaddu12i $a0, %pcadd_hi20(g_i32x4_src)
+; LA32-NEXT: vld $vr0, $a0, %pcadd_lo12(.Lpcadd_hi18)
+; LA32-NEXT: .Lpcadd_hi19:
+; LA32-NEXT: pcaddu12i $a0, %pcadd_hi20(g_i32x4_dst)
+; LA32-NEXT: vst $vr0, $a0, %pcadd_lo12(.Lpcadd_hi19)
; LA32-NEXT: ret
;
; LA64-LABEL: copy_i32x4:
@@ -580,10 +600,12 @@ entry:
define dso_local void @copy_i32x8() nounwind {
; LA32-LABEL: copy_i32x8:
; LA32: # %bb.0: # %entry
-; LA32-NEXT: pcalau12i $a0, %pc_hi20(g_i32x8_src)
-; LA32-NEXT: xvld $xr0, $a0, %pc_lo12(g_i32x8_src)
-; LA32-NEXT: pcalau12i $a0, %pc_hi20(g_i32x8_dst)
-; LA32-NEXT: xvst $xr0, $a0, %pc_lo12(g_i32x8_dst)
+; LA32-NEXT: .Lpcadd_hi20:
+; LA32-NEXT: pcaddu12i $a0, %pcadd_hi20(g_i32x8_src)
+; LA32-NEXT: xvld $xr0, $a0, %pcadd_lo12(.Lpcadd_hi20)
+; LA32-NEXT: .Lpcadd_hi21:
+; LA32-NEXT: pcaddu12i $a0, %pcadd_hi20(g_i32x8_dst)
+; LA32-NEXT: xvst $xr0, $a0, %pcadd_lo12(.Lpcadd_hi21)
; LA32-NEXT: ret
;
; LA64-LABEL: copy_i32x8:
@@ -618,10 +640,12 @@ entry:
define void @copy_i8_to_i8x16() {
; LA32-LABEL: copy_i8_to_i8x16:
; LA32: # %bb.0: # %entry
-; LA32-NEXT: pcalau12i $a0, %pc_hi20(g_i8)
-; LA32-NEXT: vldrepl.b $vr0, $a0, %pc_lo12(g_i8)
-; LA32-NEXT: pcalau12i $a0, %pc_hi20(g_i8x16)
-; LA32-NEXT: vst $vr0, $a0, %pc_lo12(g_i8x16)
+; LA32-NEXT: .Lpcadd_hi22:
+; LA32-NEXT: pcaddu12i $a0, %pcadd_hi20(g_i8)
+; LA32-NEXT: vldrepl.b $vr0, $a0, %pcadd_lo12(.Lpcadd_hi22)
+; LA32-NEXT: .Lpcadd_hi23:
+; LA32-NEXT: pcaddu12i $a0, %pcadd_hi20(g_i8x16)
+; LA32-NEXT: vst $vr0, $a0, %pcadd_lo12(.Lpcadd_hi23)
; LA32-NEXT: ret
;
; LA64-LABEL: copy_i8_to_i8x16:
@@ -657,10 +681,12 @@ entry:
define void @copy_i8_to_i8x32() {
; LA32-LABEL: copy_i8_to_i8x32:
; LA32: # %bb.0: # %entry
-; LA32-NEXT: pcalau12i $a0, %pc_hi20(g_i8)
-; LA32-NEXT: xvldrepl.b $xr0, $a0, %pc_lo12(g_i8)
-; LA32-NEXT: pcalau12i $a0, %pc_hi20(g_i8x32)
-; LA32-NEXT: xvst $xr0, $a0, %pc_lo12(g_i8x32)
+; LA32-NEXT: .Lpcadd_hi24:
+; LA32-NEXT: pcaddu12i $a0, %pcadd_hi20(g_i8)
+; LA32-NEXT: xvldrepl.b $xr0, $a0, %pcadd_lo12(.Lpcadd_hi24)
+; LA32-NEXT: .Lpcadd_hi25:
+; LA32-NEXT: pcaddu12i $a0, %pcadd_hi20(g_i8x32)
+; LA32-NEXT: xvst $xr0, $a0, %pcadd_lo12(.Lpcadd_hi25)
; LA32-NEXT: ret
;
; LA64-LABEL: copy_i8_to_i8x32:
@@ -696,8 +722,9 @@ entry:
define dso_local void @rmw() nounwind {
; LA32-LABEL: rmw:
; LA32: # %bb.0: # %entry
-; LA32-NEXT: pcalau12i $a0, %pc_hi20(g_rmw)
-; LA32-NEXT: addi.w $a0, $a0, %pc_lo12(g_rmw)
+; LA32-NEXT: .Lpcadd_hi26:
+; LA32-NEXT: pcaddu12i $a0, %pcadd_hi20(g_rmw)
+; LA32-NEXT: addi.w $a0, $a0, %pcadd_lo12(.Lpcadd_hi26)
; LA32-NEXT: ld.w $a1, $a0, 0
; LA32-NEXT: ld.w $a2, $a0, 4
; LA32-NEXT: addi.w $a1, $a1, 1
@@ -737,9 +764,10 @@ entry:
define dso_local void @store_a32() nounwind {
; LA32-LABEL: store_a32:
; LA32: # %bb.0: # %entry
-; LA32-NEXT: pcalau12i $a0, %pc_hi20(g_a32+4096)
+; LA32-NEXT: .Lpcadd_hi27:
+; LA32-NEXT: pcaddu12i $a0, %pcadd_hi20(g_a32+4096)
; LA32-NEXT: ori $a1, $zero, 1
-; LA32-NEXT: st.w $a1, $a0, %pc_lo12(g_a32+4096)
+; LA32-NEXT: st.w $a1, $a0, %pcadd_lo12(.Lpcadd_hi27)
; LA32-NEXT: ret
;
; LA64-LABEL: store_a32:
@@ -766,8 +794,9 @@ entry:
define dso_local void @store_a32_2() nounwind {
; LA32-LABEL: store_a32_2:
; LA32: # %bb.0: # %entry
-; LA32-NEXT: pcalau12i $a0, %pc_hi20(g_a32)
-; LA32-NEXT: addi.w $a0, $a0, %pc_lo12(g_a32)
+; LA32-NEXT: .Lpcadd_hi28:
+; LA32-NEXT: pcaddu12i $a0, %pcadd_hi20(g_a32)
+; LA32-NEXT: addi.w $a0, $a0, %pcadd_lo12(.Lpcadd_hi28)
; LA32-NEXT: lu12i.w $a1, 1
; LA32-NEXT: add.w $a2, $a0, $a1
; LA32-NEXT: ori $a3, $zero, 1
@@ -809,13 +838,14 @@ entry:
define dso_local void @control_flow_with_mem_access() nounwind {
; LA32-LABEL: control_flow_with_mem_access:
; LA32: # %bb.0: # %entry
-; LA32-NEXT: pcalau12i $a0, %pc_hi20(g_a32+4)
-; LA32-NEXT: ld.w $a1, $a0, %pc_lo12(g_a32+4)
+; LA32-NEXT: .Lpcadd_hi29:
+; LA32-NEXT: pcaddu12i $a0, %pcadd_hi20(g_a32+4)
+; LA32-NEXT: ld.w $a1, $a0, %pcadd_lo12(.Lpcadd_hi29)
; LA32-NEXT: ori $a2, $zero, 1
; LA32-NEXT: blt $a1, $a2, .LBB25_2
; LA32-NEXT: # %bb.1: # %if.then
; LA32-NEXT: ori $a1, $zero, 10
-; LA32-NEXT: st.w $a1, $a0, %pc_lo12(g_a32+4)
+; LA32-NEXT: st.w $a1, $a0, %pcadd_lo12(.Lpcadd_hi29)
; LA32-NEXT: .LBB25_2: # %if.end
; LA32-NEXT: ret
;
@@ -867,8 +897,9 @@ define dso_local ptr @load_ba_1() nounwind {
; LA32: # %bb.0: # %entry
; LA32-NEXT: .Ltmp0: # Block address taken
; LA32-NEXT: # %bb.1: # %label
-; LA32-NEXT: pcalau12i $a0, %pc_hi20(.Ltmp0)
-; LA32-NEXT: ld.w $a0, $a0, %pc_lo12(.Ltmp0)
+; LA32-NEXT: .Lpcadd_hi30:
+; LA32-NEXT: pcaddu12i $a0, %pcadd_hi20(.Ltmp0)
+; LA32-NEXT: ld.w $a0, $a0, %pcadd_lo12(.Lpcadd_hi30)
; LA32-NEXT: ret
;
; LA64-LABEL: load_ba_1:
@@ -901,8 +932,9 @@ define dso_local ptr @load_ba_2() nounwind {
; LA32: # %bb.0: # %entry
; LA32-NEXT: .Ltmp1: # Block address taken
; LA32-NEXT: # %bb.1: # %label
-; LA32-NEXT: pcalau12i $a0, %pc_hi20(.Ltmp1+8)
-; LA32-NEXT: ld.w $a0, $a0, %pc_lo12(.Ltmp1+8)
+; LA32-NEXT: .Lpcadd_hi31:
+; LA32-NEXT: pcaddu12i $a0, %pcadd_hi20(.Ltmp1+8)
+; LA32-NEXT: ld.w $a0, $a0, %pcadd_lo12(.Lpcadd_hi31)
; LA32-NEXT: ret
;
; LA64-LABEL: load_ba_2:
@@ -935,8 +967,9 @@ label:
define dso_local ptr @load_addr_offset_1() nounwind {
; LA32-LABEL: load_addr_offset_1:
; LA32: # %bb.0: # %entry
-; LA32-NEXT: pcalau12i $a0, %pc_hi20(g_a64+8)
-; LA32-NEXT: addi.w $a0, $a0, %pc_lo12(g_a64+8)
+; LA32-NEXT: .Lpcadd_hi32:
+; LA32-NEXT: pcaddu12i $a0, %pcadd_hi20(g_a64+8)
+; LA32-NEXT: addi.w $a0, $a0, %pcadd_lo12(.Lpcadd_hi32)
; LA32-NEXT: ret
;
; LA64-LABEL: load_addr_offset_1:
@@ -960,8 +993,9 @@ entry:
define dso_local ptr @load_addr_offset_257() nounwind {
; LA32-LABEL: load_addr_offset_257:
; LA32: # %bb.0: # %entry
-; LA32-NEXT: pcalau12i $a0, %pc_hi20(g_a64+2056)
-; LA32-NEXT: addi.w $a0, $a0, %pc_lo12(g_a64+2056)
+; LA32-NEXT: .Lpcadd_hi33:
+; LA32-NEXT: pcaddu12i $a0, %pcadd_hi20(g_a64+2056)
+; LA32-NEXT: addi.w $a0, $a0, %pcadd_lo12(.Lpcadd_hi33)
; LA32-NEXT: ret
;
; LA64-LABEL: load_addr_offset_257:
@@ -985,8 +1019,9 @@ entry:
define dso_local ptr @load_addr_offset_1048576() nounwind {
; LA32-LABEL: load_addr_offset_1048576:
; LA32: # %bb.0: # %entry
-; LA32-NEXT: pcalau12i $a0, %pc_hi20(g_a64+8388608)
-; LA32-NEXT: addi.w $a0, $a0, %pc_lo12(g_a64+8388608)
+; LA32-NEXT: .Lpcadd_hi34:
+; LA32-NEXT: pcaddu12i $a0, %pcadd_hi20(g_a64+8388608)
+; LA32-NEXT: addi.w $a0, $a0, %pcadd_lo12(.Lpcadd_hi34)
; LA32-NEXT: ret
;
; LA64-LABEL: load_addr_offset_1048576:
@@ -1010,8 +1045,9 @@ entry:
define dso_local ptr @load_addr_offset_1048577() nounwind {
; LA32-LABEL: load_addr_offset_1048577:
; LA32: # %bb.0: # %entry
-; LA32-NEXT: pcalau12i $a0, %pc_hi20(g_a64+8388616)
-; LA32-NEXT: addi.w $a0, $a0, %pc_lo12(g_a64+8388616)
+; LA32-NEXT: .Lpcadd_hi35:
+; LA32-NEXT: pcaddu12i $a0, %pcadd_hi20(g_a64+8388616)
+; LA32-NEXT: addi.w $a0, $a0, %pcadd_lo12(.Lpcadd_hi35)
; LA32-NEXT: ret
;
; LA64-LABEL: load_addr_offset_1048577:
@@ -1035,8 +1071,9 @@ entry:
define dso_local ptr @load_addr_offset_268432896() nounwind {
; LA32-LABEL: load_addr_offset_268432896:
; LA32: # %bb.0: # %entry
-; LA32-NEXT: pcalau12i $a0, %pc_hi20(g_a64+2147463168)
-; LA32-NEXT: addi.w $a0, $a0, %pc_lo12(g_a64+2147463168)
+; LA32-NEXT: .Lpcadd_hi36:
+; LA32-NEXT: pcaddu12i $a0, %pcadd_hi20(g_a64+2147463168)
+; LA32-NEXT: addi.w $a0, $a0, %pcadd_lo12(.Lpcadd_hi36)
; LA32-NEXT: ret
;
; LA64-LABEL: load_addr_offset_268432896:
@@ -1060,8 +1097,9 @@ entry:
define dso_local ptr @load_addr_offset_268432897() nounwind {
; LA32-LABEL: load_addr_offset_268432897:
; LA32: # %bb.0: # %entry
-; LA32-NEXT: pcalau12i $a0, %pc_hi20(g_a64+2147463176)
-; LA32-NEXT: addi.w $a0, $a0, %pc_lo12(g_a64+2147463176)
+; LA32-NEXT: .Lpcadd_hi37:
+; LA32-NEXT: pcaddu12i $a0, %pcadd_hi20(g_a64+2147463176)
+; LA32-NEXT: addi.w $a0, $a0, %pcadd_lo12(.Lpcadd_hi37)
; LA32-NEXT: ret
;
; LA64-LABEL: load_addr_offset_268432897:
@@ -1085,8 +1123,9 @@ entry:
define dso_local ptr @load_addr_offset_281474439839744() nounwind {
; LA32-LABEL: load_addr_offset_281474439839744:
; LA32: # %bb.0: # %entry
-; LA32-NEXT: pcalau12i $a0, %pc_hi20(g_a64)
-; LA32-NEXT: addi.w $a0, $a0, %pc_lo12(g_a64)
+; LA32-NEXT: .Lpcadd_hi38:
+; LA32-NEXT: pcaddu12i $a0, %pcadd_hi20(g_a64)
+; LA32-NEXT: addi.w $a0, $a0, %pcadd_lo12(.Lpcadd_hi38)
; LA32-NEXT: ret
;
; LA64-LABEL: load_addr_offset_281474439839744:
@@ -1113,8 +1152,9 @@ entry:
define dso_local ptr @load_addr_offset_248792680471040() nounwind {
; LA32-LABEL: load_addr_offset_248792680471040:
; LA32: # %bb.0: # %entry
-; LA32-NEXT: pcalau12i $a0, %pc_hi20(g_a64+2059194368)
-; LA32-NEXT: addi.w $a0, $a0, %pc_lo12(g_a64+2059194368)
+; LA32-NEXT: .Lpcadd_hi39:
+; LA32-NEXT: pcaddu12i $a0, %pcadd_hi20(g_a64+2059194368)
+; LA32-NEXT: addi.w $a0, $a0, %pcadd_lo12(.Lpcadd_hi39)
; LA32-NEXT: ret
;
; LA64-LABEL: load_addr_offset_248792680471040:
@@ -1141,8 +1181,9 @@ entry:
define dso_local ptr @load_addr_offset_9380351707272() nounwind {
; LA32-LABEL: load_addr_offset_9380351707272:
; LA32: # %bb.0: # %entry
-; LA32-NEXT: pcalau12i $a0, %pc_hi20(g_a64+1145062464)
-; LA32-NEXT: addi.w $a0, $a0, %pc_lo12(g_a64+1145062464)
+; LA32-NEXT: .Lpcadd_hi40:
+; LA32-NEXT: pcaddu12i $a0, %pcadd_hi20(g_a64+1145062464)
+; LA32-NEXT: addi.w $a0, $a0, %pcadd_lo12(.Lpcadd_hi40)
; LA32-NEXT: ret
;
; LA64-LABEL: load_addr_offset_9380351707272:
@@ -1170,8 +1211,9 @@ entry:
define dso_local ptr @load_addr_offset_562949953421312() nounwind {
; LA32-LABEL: load_addr_offset_562949953421312:
; LA32: # %bb.0: # %entry
-; LA32-NEXT: pcalau12i $a0, %pc_hi20(g_a64)
-; LA32-NEXT: addi.w $a0, $a0, %pc_lo12(g_a64)
+; LA32-NEXT: .Lpcadd_hi41:
+; LA32-NEXT: pcaddu12i $a0, %pcadd_hi20(g_a64)
+; LA32-NEXT: addi.w $a0, $a0, %pcadd_lo12(.Lpcadd_hi41)
; LA32-NEXT: ret
;
; LA64-LABEL: load_addr_offset_562949953421312:
@@ -1197,8 +1239,9 @@ entry:
define dso_local ptr @load_addr_offset_614749556925924693() nounwind {
; LA32-LABEL: load_addr_offset_614749556925924693:
; LA32: # %bb.0: # %entry
-; LA32-NEXT: pcalau12i $a0, %pc_hi20(g_a64+858794664)
-; LA32-NEXT: addi.w $a0, $a0, %pc_lo12(g_a64+858794664)
+; LA32-NEXT: .Lpcadd_hi42:
+; LA32-NEXT: pcaddu12i $a0, %pcadd_hi20(g_a64+858794664)
+; LA32-NEXT: addi.w $a0, $a0, %pcadd_lo12(.Lpcadd_hi42)
; LA32-NEXT: ret
;
; LA64-LABEL: load_addr_offset_614749556925924693:
diff --git a/llvm/test/CodeGen/LoongArch/numeric-reg-names.ll b/llvm/test/CodeGen/LoongArch/numeric-reg-names.ll
index 73f4dbbbdd026..38de4564c3d3f 100644
--- a/llvm/test/CodeGen/LoongArch/numeric-reg-names.ll
+++ b/llvm/test/CodeGen/LoongArch/numeric-reg-names.ll
@@ -15,8 +15,9 @@ define i32 @main() {
; LA32-NEXT: .cfi_def_cfa_offset 16
; LA32-NEXT: st.w $r1, $r3, 12 # 4-byte Folded Spill
; LA32-NEXT: .cfi_offset 1, -4
-; LA32-NEXT: pcalau12i $r4, %pc_hi20(.str_1)
-; LA32-NEXT: addi.w $r4, $r4, %pc_lo12(.str_1)
+; LA32-NEXT: .Lpcadd_hi0:
+; LA32-NEXT: pcaddu12i $r4, %pcadd_hi20(.str_1)
+; LA32-NEXT: addi.w $r4, $r4, %pcadd_lo12(.Lpcadd_hi0)
; LA32-NEXT: bl printf
; LA32-NEXT: move $r4, $r0
; LA32-NEXT: ld.w $r1, $r3, 12 # 4-byte Folded Reload
diff --git a/llvm/test/CodeGen/LoongArch/tls-models.ll b/llvm/test/CodeGen/LoongArch/tls-models.ll
index 50d994fb85327..675d34dcafc04 100644
--- a/llvm/test/CodeGen/LoongArch/tls-models.ll
+++ b/llvm/test/CodeGen/LoongArch/tls-models.ll
@@ -68,8 +68,9 @@ define ptr @f1() nounwind {
;
; LA32NOPIC-LABEL: f1:
; LA32NOPIC: # %bb.0: # %entry
-; LA32NOPIC-NEXT: pcalau12i $a0, %ie_pc_hi20(unspecified)
-; LA32NOPIC-NEXT: ld.w $a0, $a0, %ie_pc_lo12(unspecified)
+; LA32NOPIC-NEXT: .Lpcadd_hi0:
+; LA32NOPIC-NEXT: pcaddu12i $a0, %pcadd_ie_hi20(unspecified)
+; LA32NOPIC-NEXT: ld.w $a0, $a0, %pcadd_lo12(.Lpcadd_hi0)
; LA32NOPIC-NEXT: add.w $a0, $a0, $tp
; LA32NOPIC-NEXT: ret
;
@@ -94,8 +95,9 @@ define ptr @f1() nounwind {
; LA32DESC: # %bb.0: # %entry
; LA32DESC-NEXT: addi.w $sp, $sp, -16
; LA32DESC-NEXT: st.w $ra, $sp, 12 # 4-byte Folded Spill
-; LA32DESC-NEXT: pcalau12i $a0, %desc_pc_hi20(unspecified)
-; LA32DESC-NEXT: addi.w $a0, $a0, %desc_pc_lo12(unspecified)
+; LA32DESC-NEXT: .Ldesc_hi0:
+; LA32DESC-NEXT: pcaddu12i $a0, %pcadd_desc_hi20(unspecified)
+; LA32DESC-NEXT: addi.w $a0, $a0, %pcadd_lo12(.Ldesc_hi0)
; LA32DESC-NEXT: ld.w $ra, $a0, %desc_ld(unspecified)
; LA32DESC-NEXT: jirl $ra, $ra, %desc_call(unspecified)
; LA32DESC-NEXT: add.w $a0, $a0, $tp
@@ -182,8 +184,9 @@ define ptr @f2() nounwind {
;
; LA32NOPIC-LABEL: f2:
; LA32NOPIC: # %bb.0: # %entry
-; LA32NOPIC-NEXT: pcalau12i $a0, %ie_pc_hi20(ld)
-; LA32NOPIC-NEXT: ld.w $a0, $a0, %ie_pc_lo12(ld)
+; LA32NOPIC-NEXT: .Lpcadd_hi1:
+; LA32NOPIC-NEXT: pcaddu12i $a0, %pcadd_ie_hi20(ld)
+; LA32NOPIC-NEXT: ld.w $a0, $a0, %pcadd_lo12(.Lpcadd_hi1)
; LA32NOPIC-NEXT: add.w $a0, $a0, $tp
; LA32NOPIC-NEXT: ret
;
@@ -208,8 +211,9 @@ define ptr @f2() nounwind {
; LA32DESC: # %bb.0: # %entry
; LA32DESC-NEXT: addi.w $sp, $sp, -16
; LA32DESC-NEXT: st.w $ra, $sp, 12 # 4-byte Folded Spill
-; LA32DESC-NEXT: pcalau12i $a0, %desc_pc_hi20(ld)
-; LA32DESC-NEXT: addi.w $a0, $a0, %desc_pc_lo12(ld)
+; LA32DESC-NEXT: .Ldesc_hi1:
+; LA32DESC-NEXT: pcaddu12i $a0, %pcadd_desc_hi20(ld)
+; LA32DESC-NEXT: addi.w $a0, $a0, %pcadd_lo12(.Ldesc_hi1)
; LA32DESC-NEXT: ld.w $ra, $a0, %desc_ld(ld)
; LA32DESC-NEXT: jirl $ra, $ra, %desc_call(ld)
; LA32DESC-NEXT: add.w $a0, $a0, $tp
@@ -254,8 +258,9 @@ entry:
define ptr @f3() nounwind {
; LA32PIC-LABEL: f3:
; LA32PIC: # %bb.0: # %entry
-; LA32PIC-NEXT: pcalau12i $a0, %ie_pc_hi20(ie)
-; LA32PIC-NEXT: ld.w $a0, $a0, %ie_pc_lo12(ie)
+; LA32PIC-NEXT: .Lpcadd_hi0:
+; LA32PIC-NEXT: pcaddu12i $a0, %pcadd_ie_hi20(ie)
+; LA32PIC-NEXT: ld.w $a0, $a0, %pcadd_lo12(.Lpcadd_hi0)
; LA32PIC-NEXT: add.w $a0, $a0, $tp
; LA32PIC-NEXT: ret
;
@@ -278,8 +283,9 @@ define ptr @f3() nounwind {
;
; LA32NOPIC-LABEL: f3:
; LA32NOPIC: # %bb.0: # %entry
-; LA32NOPIC-NEXT: pcalau12i $a0, %ie_pc_hi20(ie)
-; LA32NOPIC-NEXT: ld.w $a0, $a0, %ie_pc_lo12(ie)
+; LA32NOPIC-NEXT: .Lpcadd_hi2:
+; LA32NOPIC-NEXT: pcaddu12i $a0, %pcadd_ie_hi20(ie)
+; LA32NOPIC-NEXT: ld.w $a0, $a0, %pcadd_lo12(.Lpcadd_hi2)
; LA32NOPIC-NEXT: add.w $a0, $a0, $tp
; LA32NOPIC-NEXT: ret
;
@@ -302,8 +308,9 @@ define ptr @f3() nounwind {
;
; LA32DESC-LABEL: f3:
; LA32DESC: # %bb.0: # %entry
-; LA32DESC-NEXT: pcalau12i $a0, %ie_pc_hi20(ie)
-; LA32DESC-NEXT: ld.w $a0, $a0, %ie_pc_lo12(ie)
+; LA32DESC-NEXT: .Lpcadd_hi0:
+; LA32DESC-NEXT: pcaddu12i $a0, %pcadd_ie_hi20(ie)
+; LA32DESC-NEXT: ld.w $a0, $a0, %pcadd_lo12(.Lpcadd_hi0)
; LA32DESC-NEXT: add.w $a0, $a0, $tp
; LA32DESC-NEXT: ret
;
diff --git a/llvm/test/CodeGen/LoongArch/unaligned-memcpy-inline.ll b/llvm/test/CodeGen/LoongArch/unaligned-memcpy-inline.ll
index 925fdf3d60646..38b17241cbe28 100644
--- a/llvm/test/CodeGen/LoongArch/unaligned-memcpy-inline.ll
+++ b/llvm/test/CodeGen/LoongArch/unaligned-memcpy-inline.ll
@@ -102,8 +102,9 @@ define void @t3() {
; LA32: # %bb.0: # %entry
; LA32-NEXT: addi.w $sp, $sp, -64
; LA32-NEXT: .cfi_def_cfa_offset 64
-; LA32-NEXT: pcalau12i $a0, %pc_hi20(.L.str)
-; LA32-NEXT: addi.w $a0, $a0, %pc_lo12(.L.str)
+; LA32-NEXT: .Lpcadd_hi0:
+; LA32-NEXT: pcaddu12i $a0, %pcadd_hi20(.L.str)
+; LA32-NEXT: addi.w $a0, $a0, %pcadd_lo12(.Lpcadd_hi0)
; LA32-NEXT: ld.h $a1, $a0, 20
; LA32-NEXT: ld.w $a2, $a0, 16
; LA32-NEXT: st.h $a1, $sp, 20
diff --git a/llvm/test/CodeGen/LoongArch/vector-fp-imm.ll b/llvm/test/CodeGen/LoongArch/vector-fp-imm.ll
index 285527fca11cf..b18c62cc9979e 100644
--- a/llvm/test/CodeGen/LoongArch/vector-fp-imm.ll
+++ b/llvm/test/CodeGen/LoongArch/vector-fp-imm.ll
@@ -84,8 +84,9 @@ define void @test_f2(ptr %P, ptr %S) nounwind {
; LA32F-NEXT: fld.s $fa0, $a0, 4
; LA32F-NEXT: fld.s $fa1, $a0, 0
; LA32F-NEXT: addi.w $a0, $zero, 1
-; LA32F-NEXT: pcalau12i $a2, %pc_hi20(.LCPI1_0)
-; LA32F-NEXT: fld.s $fa2, $a2, %pc_lo12(.LCPI1_0)
+; LA32F-NEXT: .Lpcadd_hi0:
+; LA32F-NEXT: pcaddu12i $a2, %pcadd_hi20(.LCPI1_0)
+; LA32F-NEXT: fld.s $fa2, $a2, %pcadd_lo12(.Lpcadd_hi0)
; LA32F-NEXT: movgr2fr.w $fa3, $a0
; LA32F-NEXT: ffint.s.w $fa3, $fa3
; LA32F-NEXT: fadd.s $fa1, $fa1, $fa3
@@ -99,8 +100,9 @@ define void @test_f2(ptr %P, ptr %S) nounwind {
; LA32D-NEXT: fld.s $fa0, $a0, 4
; LA32D-NEXT: fld.s $fa1, $a0, 0
; LA32D-NEXT: addi.w $a0, $zero, 1
-; LA32D-NEXT: pcalau12i $a2, %pc_hi20(.LCPI1_0)
-; LA32D-NEXT: fld.s $fa2, $a2, %pc_lo12(.LCPI1_0)
+; LA32D-NEXT: .Lpcadd_hi0:
+; LA32D-NEXT: pcaddu12i $a2, %pcadd_hi20(.LCPI1_0)
+; LA32D-NEXT: fld.s $fa2, $a2, %pcadd_lo12(.Lpcadd_hi0)
; LA32D-NEXT: movgr2fr.w $fa3, $a0
; LA32D-NEXT: ffint.s.w $fa3, $fa3
; LA32D-NEXT: fadd.s $fa1, $fa1, $fa3
@@ -150,12 +152,15 @@ define void @test_f4(ptr %P, ptr %S) nounwind {
; LA32F-NEXT: addi.w $a0, $zero, 1
; LA32F-NEXT: movgr2fr.w $fa4, $a0
; LA32F-NEXT: ffint.s.w $fa4, $fa4
-; LA32F-NEXT: pcalau12i $a0, %pc_hi20(.LCPI2_0)
-; LA32F-NEXT: fld.s $fa5, $a0, %pc_lo12(.LCPI2_0)
-; LA32F-NEXT: pcalau12i $a0, %pc_hi20(.LCPI2_1)
-; LA32F-NEXT: fld.s $fa6, $a0, %pc_lo12(.LCPI2_1)
-; LA32F-NEXT: pcalau12i $a0, %pc_hi20(.LCPI2_2)
-; LA32F-NEXT: fld.s $fa7, $a0, %pc_lo12(.LCPI2_2)
+; LA32F-NEXT: .Lpcadd_hi1:
+; LA32F-NEXT: pcaddu12i $a0, %pcadd_hi20(.LCPI2_0)
+; LA32F-NEXT: fld.s $fa5, $a0, %pcadd_lo12(.Lpcadd_hi1)
+; LA32F-NEXT: .Lpcadd_hi2:
+; LA32F-NEXT: pcaddu12i $a0, %pcadd_hi20(.LCPI2_1)
+; LA32F-NEXT: fld.s $fa6, $a0, %pcadd_lo12(.Lpcadd_hi2)
+; LA32F-NEXT: .Lpcadd_hi3:
+; LA32F-NEXT: pcaddu12i $a0, %pcadd_hi20(.LCPI2_2)
+; LA32F-NEXT: fld.s $fa7, $a0, %pcadd_lo12(.Lpcadd_hi3)
; LA32F-NEXT: fadd.s $fa3, $fa3, $fa4
; LA32F-NEXT: fadd.s $fa2, $fa2, $fa5
; LA32F-NEXT: fadd.s $fa1, $fa1, $fa6
@@ -175,12 +180,15 @@ define void @test_f4(ptr %P, ptr %S) nounwind {
; LA32D-NEXT: addi.w $a0, $zero, 1
; LA32D-NEXT: movgr2fr.w $fa4, $a0
; LA32D-NEXT: ffint.s.w $fa4, $fa4
-; LA32D-NEXT: pcalau12i $a0, %pc_hi20(.LCPI2_0)
-; LA32D-NEXT: fld.s $fa5, $a0, %pc_lo12(.LCPI2_0)
-; LA32D-NEXT: pcalau12i $a0, %pc_hi20(.LCPI2_1)
-; LA32D-NEXT: fld.s $fa6, $a0, %pc_lo12(.LCPI2_1)
-; LA32D-NEXT: pcalau12i $a0, %pc_hi20(.LCPI2_2)
-; LA32D-NEXT: fld.s $fa7, $a0, %pc_lo12(.LCPI2_2)
+; LA32D-NEXT: .Lpcadd_hi1:
+; LA32D-NEXT: pcaddu12i $a0, %pcadd_hi20(.LCPI2_0)
+; LA32D-NEXT: fld.s $fa5, $a0, %pcadd_lo12(.Lpcadd_hi1)
+; LA32D-NEXT: .Lpcadd_hi2:
+; LA32D-NEXT: pcaddu12i $a0, %pcadd_hi20(.LCPI2_1)
+; LA32D-NEXT: fld.s $fa6, $a0, %pcadd_lo12(.Lpcadd_hi2)
+; LA32D-NEXT: .Lpcadd_hi3:
+; LA32D-NEXT: pcaddu12i $a0, %pcadd_hi20(.LCPI2_2)
+; LA32D-NEXT: fld.s $fa7, $a0, %pcadd_lo12(.Lpcadd_hi3)
; LA32D-NEXT: fadd.s $fa3, $fa3, $fa4
; LA32D-NEXT: fadd.s $fa2, $fa2, $fa5
; LA32D-NEXT: fadd.s $fa1, $fa1, $fa6
@@ -235,12 +243,15 @@ define void @test_f8(ptr %P, ptr %S) nounwind {
; LA32F: # %bb.0:
; LA32F-NEXT: addi.w $a2, $zero, 1
; LA32F-NEXT: movgr2fr.w $fa0, $a2
-; LA32F-NEXT: pcalau12i $a2, %pc_hi20(.LCPI3_0)
-; LA32F-NEXT: fld.s $fa1, $a2, %pc_lo12(.LCPI3_0)
-; LA32F-NEXT: pcalau12i $a2, %pc_hi20(.LCPI3_1)
-; LA32F-NEXT: fld.s $fa2, $a2, %pc_lo12(.LCPI3_1)
-; LA32F-NEXT: pcalau12i $a2, %pc_hi20(.LCPI3_2)
-; LA32F-NEXT: fld.s $fa3, $a2, %pc_lo12(.LCPI3_2)
+; LA32F-NEXT: .Lpcadd_hi4:
+; LA32F-NEXT: pcaddu12i $a2, %pcadd_hi20(.LCPI3_0)
+; LA32F-NEXT: fld.s $fa1, $a2, %pcadd_lo12(.Lpcadd_hi4)
+; LA32F-NEXT: .Lpcadd_hi5:
+; LA32F-NEXT: pcaddu12i $a2, %pcadd_hi20(.LCPI3_1)
+; LA32F-NEXT: fld.s $fa2, $a2, %pcadd_lo12(.Lpcadd_hi5)
+; LA32F-NEXT: .Lpcadd_hi6:
+; LA32F-NEXT: pcaddu12i $a2, %pcadd_hi20(.LCPI3_2)
+; LA32F-NEXT: fld.s $fa3, $a2, %pcadd_lo12(.Lpcadd_hi6)
; LA32F-NEXT: fld.s $fa4, $a0, 28
; LA32F-NEXT: fld.s $fa5, $a0, 24
; LA32F-NEXT: fld.s $fa6, $a0, 12
@@ -272,12 +283,15 @@ define void @test_f8(ptr %P, ptr %S) nounwind {
; LA32D: # %bb.0:
; LA32D-NEXT: addi.w $a2, $zero, 1
; LA32D-NEXT: movgr2fr.w $fa0, $a2
-; LA32D-NEXT: pcalau12i $a2, %pc_hi20(.LCPI3_0)
-; LA32D-NEXT: fld.s $fa1, $a2, %pc_lo12(.LCPI3_0)
-; LA32D-NEXT: pcalau12i $a2, %pc_hi20(.LCPI3_1)
-; LA32D-NEXT: fld.s $fa2, $a2, %pc_lo12(.LCPI3_1)
-; LA32D-NEXT: pcalau12i $a2, %pc_hi20(.LCPI3_2)
-; LA32D-NEXT: fld.s $fa3, $a2, %pc_lo12(.LCPI3_2)
+; LA32D-NEXT: .Lpcadd_hi4:
+; LA32D-NEXT: pcaddu12i $a2, %pcadd_hi20(.LCPI3_0)
+; LA32D-NEXT: fld.s $fa1, $a2, %pcadd_lo12(.Lpcadd_hi4)
+; LA32D-NEXT: .Lpcadd_hi5:
+; LA32D-NEXT: pcaddu12i $a2, %pcadd_hi20(.LCPI3_1)
+; LA32D-NEXT: fld.s $fa2, $a2, %pcadd_lo12(.Lpcadd_hi5)
+; LA32D-NEXT: .Lpcadd_hi6:
+; LA32D-NEXT: pcaddu12i $a2, %pcadd_hi20(.LCPI3_2)
+; LA32D-NEXT: fld.s $fa3, $a2, %pcadd_lo12(.Lpcadd_hi6)
; LA32D-NEXT: fld.s $fa4, $a0, 28
; LA32D-NEXT: fld.s $fa5, $a0, 24
; LA32D-NEXT: fld.s $fa6, $a0, 12
@@ -405,8 +419,9 @@ define void @test_d2(ptr %P, ptr %S) nounwind {
; LA32D-NEXT: fld.d $fa1, $a0, 0
; LA32D-NEXT: addi.w $a0, $zero, 1
; LA32D-NEXT: movgr2fr.w $fa2, $a0
-; LA32D-NEXT: pcalau12i $a0, %pc_hi20(.LCPI4_0)
-; LA32D-NEXT: fld.d $fa3, $a0, %pc_lo12(.LCPI4_0)
+; LA32D-NEXT: .Lpcadd_hi7:
+; LA32D-NEXT: pcaddu12i $a0, %pcadd_hi20(.LCPI4_0)
+; LA32D-NEXT: fld.d $fa3, $a0, %pcadd_lo12(.Lpcadd_hi7)
; LA32D-NEXT: ffint.s.w $fa2, $fa2
; LA32D-NEXT: fcvt.d.s $fa2, $fa2
; LA32D-NEXT: fadd.d $fa1, $fa1, $fa2
@@ -536,12 +551,15 @@ define void @test_d4(ptr %P, ptr %S) nounwind {
; LA32D-NEXT: movgr2fr.w $fa4, $a0
; LA32D-NEXT: ffint.s.w $fa4, $fa4
; LA32D-NEXT: fcvt.d.s $fa4, $fa4
-; LA32D-NEXT: pcalau12i $a0, %pc_hi20(.LCPI5_0)
-; LA32D-NEXT: fld.d $fa5, $a0, %pc_lo12(.LCPI5_0)
-; LA32D-NEXT: pcalau12i $a0, %pc_hi20(.LCPI5_1)
-; LA32D-NEXT: fld.d $fa6, $a0, %pc_lo12(.LCPI5_1)
-; LA32D-NEXT: pcalau12i $a0, %pc_hi20(.LCPI5_2)
-; LA32D-NEXT: fld.d $fa7, $a0, %pc_lo12(.LCPI5_2)
+; LA32D-NEXT: .Lpcadd_hi8:
+; LA32D-NEXT: pcaddu12i $a0, %pcadd_hi20(.LCPI5_0)
+; LA32D-NEXT: fld.d $fa5, $a0, %pcadd_lo12(.Lpcadd_hi8)
+; LA32D-NEXT: .Lpcadd_hi9:
+; LA32D-NEXT: pcaddu12i $a0, %pcadd_hi20(.LCPI5_1)
+; LA32D-NEXT: fld.d $fa6, $a0, %pcadd_lo12(.Lpcadd_hi9)
+; LA32D-NEXT: .Lpcadd_hi10:
+; LA32D-NEXT: pcaddu12i $a0, %pcadd_hi20(.LCPI5_2)
+; LA32D-NEXT: fld.d $fa7, $a0, %pcadd_lo12(.Lpcadd_hi10)
; LA32D-NEXT: fadd.d $fa3, $fa3, $fa4
; LA32D-NEXT: fadd.d $fa2, $fa2, $fa5
; LA32D-NEXT: fadd.d $fa1, $fa1, $fa6
@@ -750,12 +768,15 @@ define void @test_d8(ptr %P, ptr %S) nounwind {
; LA32D: # %bb.0:
; LA32D-NEXT: addi.w $a2, $zero, 1
; LA32D-NEXT: movgr2fr.w $fa0, $a2
-; LA32D-NEXT: pcalau12i $a2, %pc_hi20(.LCPI6_0)
-; LA32D-NEXT: fld.d $fa1, $a2, %pc_lo12(.LCPI6_0)
-; LA32D-NEXT: pcalau12i $a2, %pc_hi20(.LCPI6_1)
-; LA32D-NEXT: fld.d $fa2, $a2, %pc_lo12(.LCPI6_1)
-; LA32D-NEXT: pcalau12i $a2, %pc_hi20(.LCPI6_2)
-; LA32D-NEXT: fld.d $fa3, $a2, %pc_lo12(.LCPI6_2)
+; LA32D-NEXT: .Lpcadd_hi11:
+; LA32D-NEXT: pcaddu12i $a2, %pcadd_hi20(.LCPI6_0)
+; LA32D-NEXT: fld.d $fa1, $a2, %pcadd_lo12(.Lpcadd_hi11)
+; LA32D-NEXT: .Lpcadd_hi12:
+; LA32D-NEXT: pcaddu12i $a2, %pcadd_hi20(.LCPI6_1)
+; LA32D-NEXT: fld.d $fa2, $a2, %pcadd_lo12(.Lpcadd_hi12)
+; LA32D-NEXT: .Lpcadd_hi13:
+; LA32D-NEXT: pcaddu12i $a2, %pcadd_hi20(.LCPI6_2)
+; LA32D-NEXT: fld.d $fa3, $a2, %pcadd_lo12(.Lpcadd_hi13)
; LA32D-NEXT: fld.d $fa4, $a0, 56
; LA32D-NEXT: fld.d $fa5, $a0, 48
; LA32D-NEXT: fld.d $fa6, $a0, 24
diff --git a/llvm/test/ExecutionEngine/JITLink/LoongArch/ELF_reloc_addsub.s b/llvm/test/ExecutionEngine/JITLink/LoongArch/ELF_reloc_addsub.s
index 86e3008ef4094..d9d03efab30d3 100644
--- a/llvm/test/ExecutionEngine/JITLink/LoongArch/ELF_reloc_addsub.s
+++ b/llvm/test/ExecutionEngine/JITLink/LoongArch/ELF_reloc_addsub.s
@@ -1,5 +1,5 @@
# RUN: rm -rf %t && mkdir -p %t
-# RUN: llvm-mc --triple=loongarch32 -mattr=+relax --filetype=obj \
+# RUN: llvm-mc --triple=loongarch32 -mattr=+32s,+relax --filetype=obj \
# RUN: -o %t/la32_reloc_addsub.o %s
# RUN: llvm-jitlink --noexec --check %s %t/la32_reloc_addsub.o \
# RUN: --slab-allocate=1Mb --slab-address=0x1000 --slab-page-size=0x4000
@@ -27,7 +27,10 @@ main:
.L0:
# Referencing named_data symbol to avoid the following relocations be
# skipped. This macro instruction will be expand to two instructions
-# (pcalau12i + ld.w/d).
+# 32bit:
+# (pcaddu12i + ld.w)
+# 64bit:
+# (pcalau12i + ld.d)
la.global $t0, named_data
.L1:
diff --git a/llvm/test/MC/LoongArch/Basic/Integer/invalid.s b/llvm/test/MC/LoongArch/Basic/Integer/invalid.s
index 08a131d4d43f9..edc9352cd3949 100644
--- a/llvm/test/MC/LoongArch/Basic/Integer/invalid.s
+++ b/llvm/test/MC/LoongArch/Basic/Integer/invalid.s
@@ -98,9 +98,9 @@ bgeu $a0, $a0, 0x1FFFF
jirl $a0, $a0, 0x20000
# CHECK: :[[#@LINE-1]]:16: error: operand must be a symbol with modifier (e.g. %b16) or an integer in the range [-131072, 131068]
-## simm20
+## simm20_pcaddu12i
pcaddu12i $a0, 0x80000
-# CHECK: :[[#@LINE-1]]:16: error: immediate must be an integer in the range [-524288, 524287]
+# CHECK: :[[#@LINE-1]]:16: error: operand must be a symbol with modifier (e.g. %pcadd_hi20) or an integer in the range [-524288, 524287]
## simm20_pcaddi
pcaddi $a0, -0x80001
diff --git a/llvm/test/tools/UpdateTestChecks/update_llc_test_checks/Inputs/loongarch_generated_funcs.ll.generated.expected b/llvm/test/tools/UpdateTestChecks/update_llc_test_checks/Inputs/loongarch_generated_funcs.ll.generated.expected
index eda7e771c128b..c2f5f345624bc 100644
--- a/llvm/test/tools/UpdateTestChecks/update_llc_test_checks/Inputs/loongarch_generated_funcs.ll.generated.expected
+++ b/llvm/test/tools/UpdateTestChecks/update_llc_test_checks/Inputs/loongarch_generated_funcs.ll.generated.expected
@@ -121,7 +121,8 @@ attributes #0 = { noredzone nounwind ssp uwtable "frame-pointer"="all" }
; CHECK-NEXT: addi.w $fp, $sp, 32
; CHECK-NEXT: .cfi_def_cfa 22, 0
; CHECK-NEXT: st.w $zero, $fp, -12
-; CHECK-NEXT: pcalau12i $a0, %pc_hi20(x)
+; CHECK-NEXT: .Lpcadd_hi0:
+; CHECK-NEXT: pcaddu12i $a0, %pcadd_hi20(x)
; CHECK-NEXT: ori $a1, $zero, 1
; CHECK-NEXT: st.w $a1, $fp, -16
; CHECK-NEXT: ori $a2, $zero, 2
@@ -130,7 +131,7 @@ attributes #0 = { noredzone nounwind ssp uwtable "frame-pointer"="all" }
; CHECK-NEXT: st.w $a3, $fp, -24
; CHECK-NEXT: ori $a4, $zero, 4
; CHECK-NEXT: st.w $a4, $fp, -28
-; CHECK-NEXT: st.w $a1, $a0, %pc_lo12(x)
+; CHECK-NEXT: st.w $a1, $a0, %pcadd_lo12(.Lpcadd_hi0)
; CHECK-NEXT: #APP
; CHECK-NEXT: #NO_APP
; CHECK-NEXT: st.w $a1, $fp, -16
diff --git a/llvm/test/tools/UpdateTestChecks/update_llc_test_checks/Inputs/loongarch_generated_funcs.ll.nogenerated.expected b/llvm/test/tools/UpdateTestChecks/update_llc_test_checks/Inputs/loongarch_generated_funcs.ll.nogenerated.expected
index aab63fa7176c1..1ab256f6fa268 100644
--- a/llvm/test/tools/UpdateTestChecks/update_llc_test_checks/Inputs/loongarch_generated_funcs.ll.nogenerated.expected
+++ b/llvm/test/tools/UpdateTestChecks/update_llc_test_checks/Inputs/loongarch_generated_funcs.ll.nogenerated.expected
@@ -98,7 +98,8 @@ define dso_local i32 @main() #0 {
; CHECK-NEXT: addi.w $fp, $sp, 32
; CHECK-NEXT: .cfi_def_cfa 22, 0
; CHECK-NEXT: st.w $zero, $fp, -12
-; CHECK-NEXT: pcalau12i $a0, %pc_hi20(x)
+; CHECK-NEXT: .Lpcadd_hi0:
+; CHECK-NEXT: pcaddu12i $a0, %pcadd_hi20(x)
; CHECK-NEXT: ori $a1, $zero, 1
; CHECK-NEXT: st.w $a1, $fp, -16
; CHECK-NEXT: ori $a2, $zero, 2
@@ -107,7 +108,7 @@ define dso_local i32 @main() #0 {
; CHECK-NEXT: st.w $a3, $fp, -24
; CHECK-NEXT: ori $a4, $zero, 4
; CHECK-NEXT: st.w $a4, $fp, -28
-; CHECK-NEXT: st.w $a1, $a0, %pc_lo12(x)
+; CHECK-NEXT: st.w $a1, $a0, %pcadd_lo12(.Lpcadd_hi0)
; CHECK-NEXT: #APP
; CHECK-NEXT: #NO_APP
; CHECK-NEXT: st.w $a1, $fp, -16
diff --git a/llvm/test/tools/llvm-readobj/ELF/reloc-types-loongarch64.test b/llvm/test/tools/llvm-readobj/ELF/reloc-types-loongarch64.test
index 26c4e8f5ca846..0f74db8d5ddae 100644
--- a/llvm/test/tools/llvm-readobj/ELF/reloc-types-loongarch64.test
+++ b/llvm/test/tools/llvm-readobj/ELF/reloc-types-loongarch64.test
@@ -119,6 +119,7 @@
# CHECK: Type: R_LARCH_TLS_LD_PCREL20_S2 (124)
# CHECK: Type: R_LARCH_TLS_GD_PCREL20_S2 (125)
# CHECK: Type: R_LARCH_TLS_DESC_PCREL20_S2 (126)
+# CHECK: Type: R_LARCH_CALL30 (127)
--- !ELF
FileHeader:
@@ -245,3 +246,4 @@ Sections:
- Type: R_LARCH_TLS_LD_PCREL20_S2
- Type: R_LARCH_TLS_GD_PCREL20_S2
- Type: R_LARCH_TLS_DESC_PCREL20_S2
+ - Type: R_LARCH_CALL30
diff --git a/llvm/unittests/ExecutionEngine/JITLink/StubsTests.cpp b/llvm/unittests/ExecutionEngine/JITLink/StubsTests.cpp
index 643ea6754f2d1..fe03f27ec1abf 100644
--- a/llvm/unittests/ExecutionEngine/JITLink/StubsTests.cpp
+++ b/llvm/unittests/ExecutionEngine/JITLink/StubsTests.cpp
@@ -119,11 +119,11 @@ TEST(StubsTest, StubsGeneration_loongarch32) {
0x14,
0x00,
0x00,
- 0x1a, // pcalau12i $t8, %page20(imm)
+ 0x1c, // pcaddu12i $t8, %pcadd20(imm)
static_cast<char>(0x94),
0x02,
static_cast<char>(0x80),
- 0x28, // ld.d $t8, $t8, %pageoff12(imm)
+ 0x28, // ld.w $t8, $t8, %pcadd12(.Lpcadd_hi)
static_cast<char>(0x80),
0x02,
0x00,
@@ -137,12 +137,12 @@ TEST(StubsTest, StubsGeneration_loongarch32) {
EXPECT_EQ(std::distance(StubSym.getBlock().edges().begin(),
StubSym.getBlock().edges().end()),
2U);
- auto &PageHighEdge = *StubSym.getBlock().edges().begin();
- auto &PageLowEdge = *++StubSym.getBlock().edges().begin();
- EXPECT_EQ(PageHighEdge.getKind(), loongarch::Page20);
- EXPECT_EQ(&PageHighEdge.getTarget(), &PointerSym);
- EXPECT_EQ(PageLowEdge.getKind(), loongarch::PageOffset12);
- EXPECT_EQ(&PageLowEdge.getTarget(), &PointerSym);
+ auto &HighEdge = *StubSym.getBlock().edges().begin();
+ auto &LowEdge = *++StubSym.getBlock().edges().begin();
+ EXPECT_EQ(HighEdge.getKind(), loongarch::PCAdd20);
+ EXPECT_EQ(&HighEdge.getTarget(), &PointerSym);
+ EXPECT_EQ(LowEdge.getKind(), loongarch::PCAdd12);
+ EXPECT_EQ(&LowEdge.getTarget(), &StubSym);
EXPECT_EQ(StubSym.getBlock().getContent(),
ArrayRef<char>(PointerJumpStubContent));
}
diff --git a/llvm/unittests/Object/ELFTest.cpp b/llvm/unittests/Object/ELFTest.cpp
index faf855c09cfe8..499eacb58bb36 100644
--- a/llvm/unittests/Object/ELFTest.cpp
+++ b/llvm/unittests/Object/ELFTest.cpp
@@ -247,6 +247,8 @@ TEST(ELFTest, getELFRelocationTypeNameForLoongArch) {
getELFRelocationTypeName(EM_LOONGARCH, R_LARCH_SUB_ULEB128));
EXPECT_EQ("R_LARCH_64_PCREL",
getELFRelocationTypeName(EM_LOONGARCH, R_LARCH_64_PCREL));
+ EXPECT_EQ("R_LARCH_CALL30",
+ getELFRelocationTypeName(EM_LOONGARCH, R_LARCH_CALL30));
EXPECT_EQ("R_LARCH_CALL36",
getELFRelocationTypeName(EM_LOONGARCH, R_LARCH_CALL36));
}
More information about the llvm-commits
mailing list