https://gcc.gnu.org/bugzilla/show_bug.cgi?id=125557

--- Comment #17 from GCC Commits <cvs-commit at gcc dot gnu.org> ---
The master branch has been updated by Kyrylo Tkachov <[email protected]>:

https://gcc.gnu.org/g:62a6880758d410758f43b08cad9fa9d159ec8583

commit r17-3867-g62a6880758d410758f43b08cad9fa9d159ec8583
Author: Kyrylo Tkachov <[email protected]>
Date:   Sat Jul 18 01:16:02 2026 +0200

    ifcvt: Extend noce_convert_multiple_sets to diamonds [PR125557]

    noce_convert_multiple_sets handles multi-set IF-THEN-JOIN regions but not
    IF-THEN-ELSE-JOIN diamonds.  After GIMPLE factors a value shared by both
    arms, such a diamond can still define several live-out values and retain a
    data-dependent branch.

    Validate both arms with the existing multiple-set checks and collect the
    distinct pseudo destinations that they define and that are live out. 
Choose
    as primary an arm with at least two such destinations whose bitmap is a
    superset of the secondary arm's bitmap.  This leaves single-result diamonds
    to the existing specialized transforms.

    For each live-out destination, also classify the raw source of its last RTL
    definition in the arm.  A constant is a non-register source.  Require at
    least one destination shared by both arms to have a non-register final
source
    in at least one arm.  This allows one arm to forward a value that the other
    arm computes.  The classification is deliberately not transitive through
    arm-local register copies.

    Evaluate each secondary-arm SET_SRC in original instruction order into a
    fresh pseudo with copy_to_mode_reg.  Rewire reads of earlier secondary
    definitions to their temporaries and preserve each SET's source location.
    When the secondary arm defines a primary destination more than once, use
the
    temporary for its last definition as the alternate value.  Use the incoming
    value if the secondary arm does not define that destination.

    The secondary arm now executes unconditionally.  Limit its instruction
count
    with MAX_CONDITIONAL_EXECUTE.  This preserves target policies such as Arm's
    short IT restriction.

    Either CFG arm may be primary.  When the branch-target arm is primary, swap
    the arms in a local noce_if_info and reverse the select orientation. 
Reject
    secondary speculation that modifies canonical condition inputs.  When it
    clobbers a reusable condition-code comparison, stop sharing the comparison
    and form later conditional moves from the canonical condition,
    rematerializing comparisons as needed.

    In outline, convert

      secondary:
        (set advance secondary_advance)
      primary:
        (set next primary_next)
        (set advance primary_advance)

    to

      (set secondary_tmp secondary_advance)
      (set next
           (if_then_else primary_p primary_next incoming_next))
      (set advance
           (if_then_else primary_p primary_advance secondary_tmp))

    where primary_p selects the primary arm.

    The existing simple conditional-move handling owns assignments whose
sources
    are constants or registers.  Factor that operand classification into
    noce_simple_cmove_operand_p and use it in both paths.  Apply the
    dependency-aware diamond conversion only when at least one arm contains a
    non-simple source.  All-simple diamonds therefore continue through the
    existing handling, while register-copy permutations that it cannot safely
    convert retain their branch.

    For speed, weight arm costs by edge probability.  For size, sum them.  The
    target noce_conversion_profitable_p hook retains the final profitability
    decision.

    Add execution and code-generation tests for symmetric and asymmetric
    diamonds, arm dependencies, repeated definitions, unmatched live-outs,
    condition-code clobbers, both arm orientations, constant-only fallback, the
    all-simple ownership boundary, and mixed forwarding and computed arms.

    With this patch the Snappy hot loop for decompression is if-converted
    and gives a 20% improvement on aarch64.

    Bootstrapped and tested on aarch64-none-linux-gnu and x86_64-linux.

    gcc/ChangeLog:

            PR tree-optimization/125557
            * ifcvt.cc: Include "explow.h".
            (noce_simple_cmove_operand_p): New function.
            (noce_try_cmove): Use it.
            (noce_convert_multiple_sets): Handle diamond CFG cleanup.
            (noce_convert_multiple_sets_1): Evaluate secondary-arm values in
fresh
            pseudos, preserve their source locations, and use their final
values
            as conditional-move inputs.  Use copy_to_mode_reg.  Reject
secondary
            sequences that modify condition inputs and handle condition-code
            clobbers.
            (bb_ok_for_noce_convert_multiple_sets): Add REQUIRE_MULTIPLE,
            LIVE_OUT_DESTS, HAS_NON_SIMPLE_SRC, NONREG_LIVE_OUT_DESTS, and
            INSN_COUNT.  Record distinct live-out destinations, non-simple
sources,
            the raw source class of each final live-out definition, and the
number
            of active sets.
            (noce_process_if_block): Recognize and cost multi-set diamonds. 
Choose
            the compatible primary arm from the validated live-out
destinations.
            Require a shared destination with a non-register final source in at
least
            one arm.  Limit unconditional secondary-arm evaluation with
            MAX_CONDITIONAL_EXECUTE.  Defer all-simple diamonds to existing
            conditional-move handling.
            (check_cond_move_block): Use noce_simple_cmove_operand_p.

    gcc/testsuite/ChangeLog:

            PR tree-optimization/125557
            * gcc.c-torture/execute/ifcvt-diamond-1.c: New test.
            * gcc.target/aarch64/ifcvt_multiple_sets_diamond.c: New test.
            * gcc.target/aarch64/ifcvt_multiple_sets_diamond_2.c: New test.
            * gcc.target/aarch64/ifcvt_multiple_sets_diamond_3.c: New test.
            * gcc.target/aarch64/ifcvt_multiple_sets_diamond_4.c: New test.
            * gcc.target/aarch64/ifcvt_multiple_sets_diamond_5.c: New test.
            * gcc.target/aarch64/ifcvt_multiple_sets_diamond_9.c: New test.
            * gcc.target/aarch64/ifcvt_multiple_sets_diamond_10.c: New test.
            * gcc.target/i386/ifcvt-multiple-sets-diamond-1.c: New test.

    Signed-off-by: Kyrylo Tkachov <[email protected]>

Reply via email to