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

Nemanja Ivanovic via llvm-commits llvm-commits at lists.llvm.org
Tue Dec 12 03:51:45 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);
----------------
nemanjai wrote:

The final instruction is indeed written in `RISCV::relocate()`. While we technically don't need to add the immediate here (i.e. we could just write a zero), I figured there is no harm in putting it in there - I don't know if there is any code path where this is needed.

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


More information about the llvm-commits mailing list