> On 2 Sep 2026, at 17:10, Jeff Law <[email protected]> wrote:
> 
> 
> 
> On 8/31/26 11:38 PM, [email protected] wrote:
>> From: Kyrylo Tkachov <[email protected]>
>> 
>> 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.
>> Ok for trunk?
>> Thanks,
>> Kyrill
>> 
>> 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]>
> Thanks for your patience.  This is OK for the trunk.
> 

Thanks very much! I pushed it.
Will be on the lookout for any regression reports.
Kyrill

> Jeff


Reply via email to