> 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
