On 8/31/26 11:38 PM, [email protected] wrote:
From: Kyrylo Tkachov <[email protected]>

The diamond conversion currently requires one arm's live-out destinations
to contain the other's.  This rejects diamonds in which the arms update
different values, although a destination can keep its incoming value on the
path that does not assign it.

For example, convert

   then:                    else:
     x = a;                   z = c;
     y = b;                   w = d;

to

   z_tmp = c;
   w_tmp = d;
   x = cond ? a : x;
   y = cond ? b : y;
   z = cond ? z : z_tmp;
   w = cond ? w : w_tmp;

Build the metadata for both arms once.  Append an output entry for the last
else definition of each live-out destination that the then arm does not
define.  The existing conditional-move loop then selects between the else
temporary and the incoming value for these entries.  It continues to select
between the then and else values for shared entries.

Form the union of the live-out destinations and permit arm-only destinations
and one-set arms.  Do not restrict partially overlapping sets based on the
source of a shared destination.  Keep the CFG arm order and evaluate the else
arm into temporaries.  Include the complete live-out union and the appended
output entries in the conversion limit.

Add execution and code-generation tests for disjoint and partially
overlapping outputs, one-set arms, cross-arm incoming values, repeated
definitions, condition inputs, unequal output counts, condition-code
clobbers, and the final output limit.

Bootstrapped and tested on aarch64-none-linux-gnu.
Ok fro trunk?
Thanks,
Kyrill

gcc/ChangeLog:

        PR tree-optimization/125557
        * ifcvt.cc (noce_convert_multiple_sets): Build metadata for both arms.
        Append entries for else-only live-out destinations, enforce the final
        output limit, and preserve the then-arm source location.
        (noce_convert_multiple_sets_1): Consume the unified output metadata.
        Select incoming values for destinations defined by only one arm.
        (init_noce_multiple_sets_info): Initialize stable metadata fields.
        (bb_ok_for_noce_convert_multiple_sets): Remove final-source
        classification.
        (noce_process_if_block): Form the union of the arm live-outs, accept
        arm-only destinations and one-set arms without a shared-source gate, and
        keep the CFG arm order.

gcc/testsuite/ChangeLog:

        PR tree-optimization/125557
        * gcc.target/aarch64/ifcvt_multiple_sets_diamond_4.c: Test disjoint,
        partially overlapping, and one-set outputs.
        * gcc.target/aarch64/ifcvt_multiple_sets_diamond_5.c: Update expected
        code generation for the fixed arm order.
        * gcc.target/aarch64/ifcvt_multiple_sets_diamond_6.c: New test.
        * gcc.target/aarch64/ifcvt_multiple_sets_diamond_7.c: New test.
        * gcc.target/i386/ifcvt-multiple-sets-diamond-1.c: Test disjoint outputs
        with a condition-code clobber.

Co-authored-by: Cui Lili <[email protected]>
Signed-off-by: Kyrylo Tkachov <[email protected]>
OK.

Jeff

Reply via email to