[lld] [RISCV] Compress unrelaxable lui when RVC attribute is present (PR #74715)

Craig Topper via llvm-commits llvm-commits at lists.llvm.org
Mon Dec 11 10:25:30 PST 2023


================
@@ -650,8 +650,32 @@ static void relaxHi20Lo12(const InputSection &sec, size_t i, uint64_t loc,
   if (!gp)
     return;
 
-  if (!isInt<12>(r.sym->getVA(r.addend) - gp->getVA()))
+  if (!isInt<12>(r.sym->getVA(r.addend) - gp->getVA())) {
+    if (r.type != R_RISCV_HI20 || !(getEFlags(sec.file) & EF_RISCV_RVC) ||
+        !isInt<18>(r.sym->getVA(r.addend)))
+      return;
+    // We have a HI20 reloc that fits in 18 bits but not in 12 bits
+    // and compressed instructions are enabled.
+    // Try to compress the lui to a c.lui.
+    const unsigned bits = config->wordsize * 8;
+    uint32_t rd = extractBits(read32le(sec.content().data() + r.offset), 11, 7);
+    uint32_t newInsn = 0x6001 | (rd << 7); // c.lui
+    int64_t imm = SignExtend64(r.sym->getVA(r.addend) + 0x800, bits) >> 12;
+
+    // The high immediate may be outside the range if the low needs to be
+    // negative. So the isInt<18> check above is not sufficient. Also,
+    // rd != 2 for c.lui.
+    if (rd == 2 || !isInt<6>(imm))
+      return;
+    if (imm == 0)
+      newInsn &= 0xDFFF;
+    uint16_t imm17 = extractBits(imm, 5, 5) << 12;
+    uint16_t imm16_12 = extractBits(imm, 4, 0) << 2;
+    remove = 2;
+    sec.relaxAux->relocTypes[i] = R_RISCV_RVC_LUI;
+    sec.relaxAux->writes.push_back(newInsn | imm17 | imm16_12);
----------------
topperc wrote:

Do we know the final address of the global at this point? We're in the middle of shrinking code here, but I don't think the layout hasn't been finalized. That's why R_RISCV_LO12_I and R_RISCV_LO12_S are changed to INTERNAL_R_RISCV_GPREL_I/INTERNAL_R_RISCV_GPREL_S and the rewrite occurs in `RISCV::relocate`

I wonder if you only need to change the opcode to `0x6001 | (rd << 7)` here and let `RISCV::relocate` finish the rewrite?

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


More information about the llvm-commits mailing list