https://gcc.gnu.org/g:e0a8b636253b21aae0ce4b66348163171322c7f9
commit r16-6747-ge0a8b636253b21aae0ce4b66348163171322c7f9 Author: Andrew Pinski <[email protected]> Date: Fri Jan 9 23:14:22 2026 -0800 ifcvt: Improve `cmp?a&b:a` to try with -1 [PR123312] After the current improvements to ifcvt, on some targets for cmp?a&b:a it is better to produce `(cmp?b:-1) & a` rather than `(!cmp?a:0)|(a & b)`. So this extends noce_try_cond_zero_arith (with a rename to noce_try_cond_arith) to see if `cmp ? a : -1` is cheaper than `!cmp?a:0`. Bootstrapped and tested on x86_64-linux-gnu. PR rtl-optimization/123312 gcc/ChangeLog: * ifcvt.cc (noce_try_cond_zero_arith): Rename to ... (noce_try_cond_arith): This. For AND try `cmp ? a : -1` also to see which one cost less. (noce_process_if_block): Handle the rename. Signed-off-by: Andrew Pinski <[email protected]> Diff: --- gcc/ifcvt.cc | 70 +++++++++++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 58 insertions(+), 12 deletions(-) diff --git a/gcc/ifcvt.cc b/gcc/ifcvt.cc index c029a583e841..0858b3d2f6d6 100644 --- a/gcc/ifcvt.cc +++ b/gcc/ifcvt.cc @@ -790,7 +790,6 @@ static rtx noce_get_alt_condition (struct noce_if_info *, rtx, rtx_insn **); static bool noce_try_minmax (struct noce_if_info *); static bool noce_try_abs (struct noce_if_info *); static bool noce_try_sign_mask (struct noce_if_info *); -static int noce_try_cond_zero_arith (struct noce_if_info *); /* Return the comparison code for reversed condition for IF_INFO, or UNKNOWN if reversing the condition is not possible. */ @@ -3135,10 +3134,15 @@ get_base_reg (rtx exp) tmp = !cond ? y : 0 x = (y & z) | tmp + Also for AND try: + tmp = cond ? z : -1 + x = y op tmp + To see if it is cheaper to produce `!cond ? y : 0` + or `cond ? z : -1`. */ static int -noce_try_cond_zero_arith (struct noce_if_info *if_info) +noce_try_cond_arith (struct noce_if_info *if_info) { rtx target, a, b, a_op0, a_op1; rtx cond = if_info->cond; @@ -3230,27 +3234,69 @@ noce_try_cond_zero_arith (struct noce_if_info *if_info) target = rtl_hooks.gen_lowpart_no_emit (GET_MODE (XEXP (a, op != AND)), target); gcc_assert (target); } - if (!target) - goto end_seq_n_fail; + /* For AND, try `cond ? z : -1` to see if that is cheaper or the same cost. + In some cases it will be cheaper to produce the -1 rather than the 0 case. */ if (op == AND) { + rtx_insn *seq0 = end_sequence (); + unsigned cost0 = seq_cost (seq0, if_info->speed_p); + if (!target) + cost0 = -1u; + + /* Produce `cond ? z : -1`. */ + rtx targetm1; + start_sequence (); + targetm1 = gen_reg_rtx (GET_MODE (XEXP (a, 1))); + targetm1 = noce_emit_cmove (if_info, targetm1, code, + XEXP (cond, 0), XEXP (cond, 1), + XEXP (a, 1), constm1_rtx); + rtx_insn *seqm1 = end_sequence (); + unsigned costm1 = seq_cost (seqm1, if_info->speed_p); + if (!targetm1) + costm1 = -1u; + /* If both fails, then there is no costing to be done. */ + if (!targetm1 && !target) + return false; + + /* If -1 is cheaper or the same cost to producing 0, then use that. */ + if (costm1 <= cost0) + { + push_to_sequence (seqm1); + targetm1 = expand_simple_binop (mode, op, a_op0, targetm1, + if_info->x, 0, OPTAB_WIDEN); + if (targetm1) + { + target = targetm1; + goto success; + } + end_sequence (); + } + if (!target) + return false; + /* For 0 the produce sequence is: + tmp = !cond ? y : 0 + x = (y & z) | tmp */ + push_to_sequence (seq0); rtx a_bin = gen_reg_rtx (mode); noce_emit_move_insn (a_bin, a); target = expand_simple_binop (mode, IOR, a_bin, target, if_info->x, 0, OPTAB_WIDEN); - - } - else - { - target = expand_simple_binop (mode, op, a_op0, target, if_info->x, 0, - OPTAB_WIDEN); + if (!target) + goto end_seq_n_fail; + goto success; } + if (!target) + goto end_seq_n_fail; + + target = expand_simple_binop (mode, op, a_op0, target, if_info->x, 0, + OPTAB_WIDEN); if (!target) goto end_seq_n_fail; +success: if (target != if_info->x) noce_emit_move_insn (if_info->x, target); @@ -3259,7 +3305,7 @@ noce_try_cond_zero_arith (struct noce_if_info *if_info) goto fail; emit_insn_before_setloc (seq, if_info->jump, INSN_LOCATION (if_info->insn_a)); - if_info->transform_name = "noce_try_cond_zero_arith"; + if_info->transform_name = "noce_try_cond_arith"; return true; end_seq_n_fail: @@ -4431,7 +4477,7 @@ noce_process_if_block (struct noce_if_info *if_info) if (noce_try_store_flag_mask (if_info)) goto success; if (HAVE_conditional_move - && noce_try_cond_zero_arith (if_info)) + && noce_try_cond_arith (if_info)) goto success; if (HAVE_conditional_move && noce_try_cmove_arith (if_info))
