[lld] [lld][LoongArch] Relax R_LARCH_PCALA_HI20 and R_LARCH_PCALA_LO12 (PR #112696)
Lu Weining via llvm-commits
llvm-commits at lists.llvm.org
Thu Oct 17 23:30:56 PDT 2024
================
@@ -744,6 +784,70 @@ void LoongArch::relocate(uint8_t *loc, const Relocation &rel,
}
}
+static bool relaxable(ArrayRef<Relocation> relocs, size_t i) {
+ return i + 1 != relocs.size() && relocs[i + 1].type == R_LARCH_RELAX;
+}
+
+// Returns true if the two instructions corresponding to the i-th reloc
+// entry and the i+2-th reloc entry can apply relaxation. For scenarios
+// with fewer than four reloc entries, e.g., R_ALRCH_CALL36, this function
+// should not be used to make a judgment.
+static bool isPair(ArrayRef<Relocation> relocs, size_t i) {
+ return relaxable(relocs, i) && relaxable(relocs, i + 2) &&
+ relocs[i].offset + 4 == relocs[i + 2].offset;
+}
+
+void LoongArch::relocateAlloc(InputSectionBase &sec, uint8_t *buf) const {
+ const unsigned bits = ctx.arg.is64 ? 64 : 32;
+ uint64_t secAddr = sec.getOutputSection()->addr;
+ if (auto *s = dyn_cast<InputSection>(&sec))
+ secAddr += s->outSecOff;
+ else if (auto *ehIn = dyn_cast<EhInputSection>(&sec))
+ secAddr += ehIn->getParent()->outSecOff;
+ const ArrayRef<Relocation> relocs = sec.relocs();
+ for (size_t i = 0, size = relocs.size(); i != size; ++i) {
+ const Relocation &rel = relocs[i];
+ uint8_t *loc = buf + rel.offset;
+ uint64_t val = SignExtend64(
+ sec.getRelocTargetVA(ctx, rel, secAddr + rel.offset), bits);
+
+ switch (rel.expr) {
+ case R_RELAX_HINT:
+ continue;
+ default:
+ break;
+ }
+ relocate(loc, rel, val);
+ }
+}
+
+// Relax pcalau12i,addi.d => pcaddi.
+static void relaxPcalaAddi(const InputSection &sec, size_t i, uint64_t loc,
+ Relocation &r_hi, uint32_t &remove) {
+ const uint64_t symval =
+ (r_hi.expr == R_LOONGARCH_PLT_PAGE_PC ? r_hi.sym->getPltVA(ctx)
+ : r_hi.sym->getVA()) +
+ r_hi.addend;
+ const int64_t dist = symval - loc;
+ uint32_t pca = read32le(sec.content().data() + r_hi.offset);
+ uint32_t add = read32le(sec.content().data() + r_hi.offset + 4);
+ uint32_t rd = LARCH_GET_RD(pca);
+
+ if (!LARCH_INSN_ADDI_D(add)
+ // Is pcalau12i $rd + addi.d $rd, $rd?
+ || LARCH_GET_RD(add) != rd ||
----------------
SixWeining wrote:
Why `LARCH_GET_RD(add)` must be `rd`?
https://github.com/llvm/llvm-project/pull/112696
More information about the llvm-commits
mailing list