Skip to content

Commit

Permalink
Relax a GOT load into a PC-relative address materialization
Browse files Browse the repository at this point in the history
  • Loading branch information
rui314 committed Sep 19, 2023
1 parent 9ee10ba commit 5a6c9b4
Showing 1 changed file with 26 additions and 0 deletions.
26 changes: 26 additions & 0 deletions elf/arch-riscv.cc
Original file line number Diff line number Diff line change
Expand Up @@ -364,6 +364,32 @@ void InputSection<E>::apply_reloc_alloc(Context<E> &ctx, u8 *base) {
break;
}
case R_RISCV_GOT_HI20:
if (ctx.arg.relax &&
sym.is_pcrel_linktime_const(ctx) &&
i + 2 < rels.size() &&
rels[i + 1].r_type == R_RISCV_PCREL_LO12_I &&
rels[i + 1].r_offset == rels[i].r_offset + 4 &&
file.symbols[rels[i + 1].r_sym]->value == r_offset &&
rels[i + 2].r_type == R_RISCV_RELAX) {
// AUIPC + LD is used to load a value from a GOT slot. If the
// value is actually a PC-relative link-time constant, we can
// rewrite AUIPC + LD with AUIPC + ADDI to eliminate the memory
// load.
i64 val = S + A - P;
i64 rd1 = get_rd(rel.r_offset);
i64 rd2 = get_rd(rel.r_offset + 4);

if ((i32)val == val && rd1 == rd2) {
// auipc <reg>, %hi20(val)
write_utype(loc, val);

// addi <reg>, <reg>, %lo12(val)
*(ul32 *)(loc + 4) = 0b0010011 | (rd1 << 15) | (rd1 << 7);
write_itype(loc + 4, val);
i += 2;
break;
}
}
write_utype(loc, G + GOT + A - P);
break;
case R_RISCV_TLS_GOT_HI20:
Expand Down

0 comments on commit 5a6c9b4

Please sign in to comment.