On 9/13/26 12:24 AM, Dominic P wrote:
reload_cse_regs_1 records an implicit set on the edges of a conditional
branch that tests an equality, so cselib knows the compared register holds
the compared value in the block the edge enters (PR107455). It reads the
condition out of the jump pattern, so it works only where the jump carries
the comparison: riscv and mips branches, aarch64 cbz, Thumb-1 cbz
(gcc.target/riscv/pr107455-1.c and -2.c). Where the comparison is a
separate insn the jump tests a MODE_CC register and no implicit set is made.
Use get_condition, which finds the comparison through the cc register, and
take the edge polarity from the returned code. get_condition reverses the
condition only for a LABEL_REF else arm, so a jump with a return in one arm
(frv and ia64 *return_false) would give the other edge's condition; reject
jumps whose target is not a label.
Record the equivalence only where the block sets the register to that value,
the redundancy the implicit set exists to remove. That is a profitability
choice, not a correctness condition: every equivalence is true, but
unguarded it also reaches reload_cse_simplify_set, which at equal cost
prefers a register to a constant (postreload.cc:452); with a register known
to hold the constant that rewrites literal operands, and the lost fusions
and cross-jumps cost more than the removed sets save: a bcmrpi_defconfig
kernel at -O2 for arm1176 grows 3128 bytes of .text unguarded and shrinks
224 guarded. Of the 783 kernel objects the unguarded change alters, 42
still change with the guard. Teaching that tie-break to ignore a value
known only through an implicit set would remove the guard, but it changes
the rule for every target, so it belongs in a separate patch.
On Arm the re-materialised value in a shared early-exit block goes away and
the exit becomes a conditional return:
subs r3, r0, #0 subs r3, r0, #0
bne .L14 bxeq lr
mov r0, #0
bx lr
The core_list_find loop of gcc.target/riscv/pr107455-2.c gets the same
treatment on arm1176.
Bootstrapped and regression tested on x86_64-pc-linux-gnu, where dg.exp and
tree-ssa.exp are identical with and without the patch. Cross tested
like-for-like, the patched cc1 against one relinked from the unpatched
source in the same tree: arm-none-eabi with arm.exp, simd.exp, mve.exp,
advsimd-intrinsics.exp, acle.exp and cmse.exp on the default board and with
-mthumb -mfloat-abi=hard -mtune=cortex-a9 -march=armv7-a
-mfpu=neon-fp-armv8; aarch64-linux-gnu under qemu with aarch64.exp,
vect.exp and tree-ssa.exp. Only the new tests change. gcc.c-torture/execute
under qemu on arm1176 with and without the patch: 1564 tests, same results.
Assisted-by: Claude Opus 5 (Anthropic)
gcc/ChangeLog:
* postreload.cc (reload_cse_regs_1): Find the condition of the
predecessor's conditional branch with get_condition, so a comparison
held in the condition-code register is seen. Reject a jump whose
target is not a label. Record the implicit set only where the block
sets the register to that value.
gcc/testsuite/ChangeLog:
* gcc.target/aarch64/postreload-implicit-set-1.c: New test.
* gcc.target/arm/postreload-implicit-set-1.c: New test.
* gcc.target/arm/postreload-implicit-set-2.c: New test.
* gcc.target/i386/postreload-implicit-set-1.c: New test.
Signed-off-by: Dominic P <[email protected]>
So I didn't even realize this was my code at first glance, but certain
style markers looked like mine and sure enough it was something I added
a while back.
Whether or not to propagate these conditional equivalences is a subject
of debate. We actually started throttling back propagation of these
equivalences in the gimple optimizers a few years back, particularly
obj1 == obj2 equivalences. While there are cases where those
equivalences help, they cause more problems than they're worth,
particularly early in gimple.
Preferring constants over registers is probably a costing decision the
targets need to make in general. The code you reference only triggers
when the costs reported by the target are the same. Your data seems to
indicate that preferring regs as the final tie-breaker to improve code
density may not be good because it hides constants from later passes, at
least in some cases. As you note, tackling that problem seems like an
independent adjustment.
It wasn't clear if you ran the full testsuite or just limited your
testing to dg.exp and tree-ssa.exp. So I threw it into my tester and
let it run on x86_64 and aarch64 where it passed without any regressions.
Pushing to the trunk.
Thanks,
Jeff