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

Reply via email to