From: Andrew Pinski Date: Fri, 26 Dec 2025 20:07:26 +0000 (-0800) Subject: ifcvt: Handle lowpart subregs if noce_emit_cmove fails in noce_try_cond_zero_arith... X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=92f2a86794ad88d773b102c753e13be1b6f05ff9;p=thirdparty%2Fgcc.git ifcvt: Handle lowpart subregs if noce_emit_cmove fails in noce_try_cond_zero_arith [PR123308] This fixes up a missed optimization regression for riscv in ifcvt after r16-6350-g9e61a171244110. The problem is noce_emit_cmove will fail for QImode. This can show up when dealing with shifts and the right hand side is `(subreg:QI (reg:DI) lowpart)`. Trying first for the subreg mode fails so the need to try to unwrap the subreg and try for the full mode. This fixes test_ShiftLeft_eqz in gcc.target/riscv/zicond_ifcvt_opt.c. Bootstrapped and tested on x86_64-linux-gnu. PR rtl-optimization/123308 gcc/ChangeLog: * ifcvt.cc (noce_try_cond_zero_arith): If noce_emit_cmove fails for a lowpart subreg case, then try the full reg cmove and take the lowpart subreg afterwards. Signed-off-by: Andrew Pinski --- diff --git a/gcc/ifcvt.cc b/gcc/ifcvt.cc index 562775165a2..2b8f68a9b41 100644 --- a/gcc/ifcvt.cc +++ b/gcc/ifcvt.cc @@ -3207,6 +3207,28 @@ noce_try_cond_zero_arith (struct noce_if_info *if_info) XEXP (cond, 0), XEXP (cond, 1), op != AND ? XEXP (a, 1) : const0_rtx, op != AND ? const0_rtx : XEXP (a, 0)); + if (!target) + { + end_sequence (); + rtx tmp = XEXP (a, op != AND); + /* If the cmove fails and this was a lowpart subreg, + then try the reg part and then putting back the lowpart + afterwards. */ + if (GET_CODE (tmp) != SUBREG || !subreg_lowpart_p (tmp)) + return false; + start_sequence (); + + tmp = SUBREG_REG (tmp); + target = gen_reg_rtx (GET_MODE (tmp)); + target = noce_emit_cmove (if_info, target, code, + XEXP (cond, 0), XEXP (cond, 1), + op != AND ? tmp : const0_rtx, + op != AND ? const0_rtx : tmp); + if (!target) + goto end_seq_n_fail; + target = rtl_hooks.gen_lowpart_no_emit (GET_MODE (XEXP (a, op != AND)), target); + gcc_assert (target); + } if (!target) goto end_seq_n_fail;