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(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(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(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@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@plt - pc >> 12 = 0x1234520 - 0x1274670 >> 12 = -65 +## lo18 = foo@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@tprel = st_value(a) = 0x8 # b@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::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(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(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(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(0xfff); - uint64_t PCPage = FixupAddress & ~static_cast(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(FixupPtr)); - Value += ((TargetAddress + Addend) & 0x3f); - *FixupPtr = (*FixupPtr & 0xc0) | (static_cast(Value) & 0x3f); - break; - } - case Add8: { - int64_t Value = - TargetAddress + *(reinterpret_cast(FixupPtr)) + Addend; - *FixupPtr = static_cast(Value); - break; - } - case Add16: { - int64_t Value = - TargetAddress + support::endian::read16le(FixupPtr) + Addend; - *(little16_t *)FixupPtr = static_cast(Value); - break; - } - case Add32: { - int64_t Value = - TargetAddress + support::endian::read32le(FixupPtr) + Addend; - *(little32_t *)FixupPtr = static_cast(Value); - break; - } - case Add64: { - int64_t Value = - TargetAddress + support::endian::read64le(FixupPtr) + Addend; - *(little64_t *)FixupPtr = static_cast(Value); - break; - } - case AddUleb128: { - const uint32_t Maxcount = 1 + 64 / 7; - uint32_t Count; - const char *Error = nullptr; - uint64_t Orig = decodeULEB128((reinterpret_cast(FixupPtr)), - &Count, nullptr, &Error); - - if (Count > Maxcount || (Count == Maxcount && Error)) - return make_error( - "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(FixupPtr)), Count); - break; - } - case Sub6: { - int64_t Value = *(reinterpret_cast(FixupPtr)); - Value -= ((TargetAddress + Addend) & 0x3f); - *FixupPtr = (*FixupPtr & 0xc0) | (static_cast(Value) & 0x3f); - break; - } - case Sub8: { - int64_t Value = - *(reinterpret_cast(FixupPtr)) - TargetAddress - Addend; - *FixupPtr = static_cast(Value); - break; - } - case Sub16: { - int64_t Value = - support::endian::read16le(FixupPtr) - TargetAddress - Addend; - *(little16_t *)FixupPtr = static_cast(Value); - break; - } - case Sub32: { - int64_t Value = - support::endian::read32le(FixupPtr) - TargetAddress - Addend; - *(little32_t *)FixupPtr = static_cast(Value); - break; - } - case Sub64: { - int64_t Value = - support::endian::read64le(FixupPtr) - TargetAddress - Addend; - *(little64_t *)FixupPtr = static_cast(Value); - break; - } - case SubUleb128: { - const uint32_t Maxcount = 1 + 64 / 7; - uint32_t Count; - const char *Error = nullptr; - uint64_t Orig = decodeULEB128((reinterpret_cast(FixupPtr)), - &Count, nullptr, &Error); - - if (Count > Maxcount || (Count == Maxcount && Error)) - return make_error( - "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(FixupPtr)), Count); - break; - } - case AlignRelaxable: - // Ignore when the relaxation pass did not run - break; - default: - return make_error( - "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 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 { case RequestGOTAndTransformToPageOffset12: KindToSet = PageOffset12; break; + case RequestGOTAndTransformToPCAdd20: + KindToSet = PCAdd20; + break; default: return false; } @@ -669,7 +512,8 @@ class PLTTableManager : public TableManager { 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(std::unique_ptr Ctx, std::unique_ptr 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, 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 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("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::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(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(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(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(0xfff); + uint64_t PCPage = FixupAddress & ~static_cast(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(FixupPtr)); + Value += ((TargetAddress + Addend) & 0x3f); + *FixupPtr = (*FixupPtr & 0xc0) | (static_cast(Value) & 0x3f); + break; + } + case Add8: { + int64_t Value = TargetAddress + + *(reinterpret_cast(FixupPtr)) + Addend; + *FixupPtr = static_cast(Value); + break; + } + case Add16: { + int64_t Value = + TargetAddress + support::endian::read16le(FixupPtr) + Addend; + *(little16_t *)FixupPtr = static_cast(Value); + break; + } + case Add32: { + int64_t Value = + TargetAddress + support::endian::read32le(FixupPtr) + Addend; + *(little32_t *)FixupPtr = static_cast(Value); + break; + } + case Add64: { + int64_t Value = + TargetAddress + support::endian::read64le(FixupPtr) + Addend; + *(little64_t *)FixupPtr = static_cast(Value); + break; + } + case AddUleb128: { + const uint32_t Maxcount = 1 + 64 / 7; + uint32_t Count; + const char *Error = nullptr; + uint64_t Orig = + decodeULEB128((reinterpret_cast(FixupPtr)), &Count, + nullptr, &Error); + + if (Count > Maxcount || (Count == Maxcount && Error)) + return make_error( + "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(FixupPtr)), Count); + break; + } + case Sub6: { + int64_t Value = *(reinterpret_cast(FixupPtr)); + Value -= ((TargetAddress + Addend) & 0x3f); + *FixupPtr = (*FixupPtr & 0xc0) | (static_cast(Value) & 0x3f); + break; + } + case Sub8: { + int64_t Value = *(reinterpret_cast(FixupPtr)) - + TargetAddress - Addend; + *FixupPtr = static_cast(Value); + break; + } + case Sub16: { + int64_t Value = + support::endian::read16le(FixupPtr) - TargetAddress - Addend; + *(little16_t *)FixupPtr = static_cast(Value); + break; + } + case Sub32: { + int64_t Value = + support::endian::read32le(FixupPtr) - TargetAddress - Addend; + *(little32_t *)FixupPtr = static_cast(Value); + break; + } + case Sub64: { + int64_t Value = + support::endian::read64le(FixupPtr) - TargetAddress - Addend; + *(little64_t *)FixupPtr = static_cast(Value); + break; + } + case SubUleb128: { + const uint32_t Maxcount = 1 + 64 / 7; + uint32_t Count; + const char *Error = nullptr; + uint64_t Orig = + decodeULEB128((reinterpret_cast(FixupPtr)), &Count, + nullptr, &Error); + + if (Count > Maxcount || (Count == Maxcount && Error)) + return make_error( + "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(FixupPtr)), Count); + break; + } + case AlignRelaxable: + // Ignore when the relaxation pass did not run + break; + default: + return make_error( + "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 { 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 { 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( 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(); - 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(); - 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(); - 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(); - 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(); - 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(); - 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(); + 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().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(); + 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(0x94), 0x02, static_cast(0x80), - 0x28, // ld.d $t8, $t8, %pageoff12(imm) + 0x28, // ld.w $t8, $t8, %pcadd12(.Lpcadd_hi) static_cast(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(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)); }