https://gcc.gnu.org/bugzilla/show_bug.cgi?id=122118
Longjun Luo <luolongjuna at gmail dot com> changed:
What |Removed |Added
----------------------------------------------------------------------------
CC| |luolongjuna at gmail dot com
--- Comment #9 from Longjun Luo <luolongjuna at gmail dot com> ---
I also ran into this issue in a hot-patching/binary-diffing workflow,
where the extra pointer constant-pool entry adds another relocation for
the tooling to follow. The first function from the original testcase
still reproduces it on current trunk:
static int a, b;
void
init (int *ptrs[])
{
ptrs[0] = &a;
ptrs[1] = &b;
}
With -O2 -fPIE at
d5a8ecb5477a180e614bd6fa1d194dc8d5c8d0fb, GCC emits:
movq .LC0(%rip), %xmm0
leaq b(%rip), %rax
...
.section .data.rel.ro.local,"aw"
.LC0:
.quad a
The pointer slot also adds one R_X86_64_RELATIVE relocation to the final
PIE.
The IRA dump points to calculate_equiv_gains. SLP combines the two
stores into a vec_concat containing two address pseudos with REG_EQUIV
notes. get_equiv_regno returns after finding one such pseudo, and
calculate_equiv_gains invokes it only once per instruction. Only one
pseudo is therefore charged for using its equivalence. The other retains
the gain from removing its initialization and is assigned NO_REGS in this
case.
LRA then substitutes the other pseudo with its SYMBOL_REF. Since the
SSE move cannot consume that directly, the address is forced into the
constant pool. The missed accounting is in generic IRA code, although
the resulting code sequence is target-specific.
This equivalence-costing machinery was introduced by r14-4944
(f55cdce3f8d). The PR112107 follow-up to that commit (4d3d2cdb574)
only changed INSN_P to NONDEBUG_INSN_P and does not affect this case.
I also checked r17-1505 (398bdccce49), which prevents IRA from honoring
equivalences it can already tell LRA will reject on targets using a PIC
register. For this x86-64 -fPIE testcase, I confirmed that
pic_offset_table_rtx is NULL, so that guard does not exclude the
equivalence. Here LRA uses the equivalence; substituting the SYMBOL_REF
ultimately forces it into the constant pool.
As an experiment, I changed calculate_equiv_gains to account once for
each distinct equivalence pseudo in an instruction. The testcase then
uses two RIP-relative LEAs, with no .data.rel.ro.local section or extra
dynamic relocation. A targeted DejaGNU test passes, as do the C
frontend selftests in my non-bootstrap build. I have not run a full
bootstrap or regression test.
The prototype currently walks the RTL pattern again for each distinct
pseudo. Before treating it as a patch, I would want to check whether
this should instead use a single traversal. For now this is only a
local experiment. I have not assigned the PR, but I would be interested
in taking it further if this is the right direction.
Does accounting for every distinct equivalence pseudo here look like
the right fix, or should this be handled elsewhere?