[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