]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
ifcvt: Handle lowpart subregs if noce_emit_cmove fails in noce_try_cond_zero_arith...
authorAndrew Pinski <andrew.pinski@oss.qualcomm.com>
Fri, 26 Dec 2025 20:07:26 +0000 (12:07 -0800)
committerAndrew Pinski <andrew.pinski@oss.qualcomm.com>
Mon, 29 Dec 2025 18:27:40 +0000 (10:27 -0800)
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 <andrew.pinski@oss.qualcomm.com>
gcc/ifcvt.cc

index 562775165a2f8cc61d50a4a864f94da228c201d6..2b8f68a9b415531c1e9bb3a75250198b8866f119 100644 (file)
@@ -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;