From: Kyrylo Tkachov <[email protected]>

noce_convert_multiple_sets keys its dependency information by destination
register number.  Hard registers can have overlapping definitions in
different modes.  An exact RTL replacement cannot represent the value from a
partial or mode-changing definition.

Reject hard-register destinations in the block eligibility check.  Assert
the resulting pseudo-only invariant when dependency information is
initialized.

Add an RTL execution test with mixed-mode hard-register definitions.  It
verifies that the block remains unconverted.

Bootstrapped and regtested on aarch64-none-linux-gnu and
x86_64-pc-linux-gnu.

gcc/ChangeLog:

        PR rtl-optimization/126184
        * ifcvt.cc (init_noce_multiple_sets_info): Assert that destinations
        are pseudos.
        (bb_ok_for_noce_convert_multiple_sets): Reject hard-register
        destinations.

gcc/testsuite/ChangeLog:

        PR rtl-optimization/126184
        * gcc.target/aarch64/pr126184-2.c: New test.

Signed-off-by: Kyrylo Tkachov <[email protected]>
---
 gcc/ifcvt.cc                                  | 14 ++--
 gcc/testsuite/gcc.target/aarch64/pr126184-2.c | 75 +++++++++++++++++++
 2 files changed, 84 insertions(+), 5 deletions(-)
 create mode 100644 gcc/testsuite/gcc.target/aarch64/pr126184-2.c

diff --git a/gcc/ifcvt.cc b/gcc/ifcvt.cc
index 1df5d54efa3..2da85a868d7 100644
--- a/gcc/ifcvt.cc
+++ b/gcc/ifcvt.cc
@@ -4225,7 +4225,7 @@ init_noce_multiple_sets_info (basic_block bb,
       rtx src = SET_SRC (set);
       rtx dest = SET_DEST (set);
 
-      gcc_checking_assert (REG_P (dest));
+      gcc_checking_assert (REG_P (dest) && !HARD_REGISTER_P (dest));
       info->need_cmov = bitmap_bit_p (bb_live_out, REGNO (dest));
 
       /* Check if the current SET's source is the same
@@ -4270,10 +4270,14 @@ bb_ok_for_noce_convert_multiple_sets (basic_block 
test_bb, unsigned *cost)
       rtx dest = SET_DEST (set);
       rtx src = SET_SRC (set);
 
-      /* Do not handle anything involving memory loads/stores since it might
-        violate data-race-freedom guarantees.  Make sure we can force SRC
-        to a register as that may be needed in try_emit_cmove_seq.  */
-      if (!REG_P (dest) || contains_mem_rtx_p (src)
+      /* Dependency rewiring is keyed by register number, so restrict
+        destinations to pseudos.  Hard-register definitions can overlap
+        without having the same mode.  Do not handle anything involving
+        memory loads/stores since it might violate data-race-freedom
+        guarantees.  Make sure we can force SRC to a register as that may
+        be needed in try_emit_cmove_seq.  */
+      if (!REG_P (dest) || HARD_REGISTER_P (dest)
+         || contains_mem_rtx_p (src)
          || !noce_can_force_operand (src))
        return false;
 
diff --git a/gcc/testsuite/gcc.target/aarch64/pr126184-2.c 
b/gcc/testsuite/gcc.target/aarch64/pr126184-2.c
new file mode 100644
index 00000000000..5e027466041
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/pr126184-2.c
@@ -0,0 +1,75 @@
+/* PR rtl-optimization/126184 */
+/* { dg-do run } */
+/* { dg-options "-O2 --param=max-rtl-if-conversion-unpredictable-cost=100 
-fdump-rtl-ce1" } */
+
+/* Mixed-mode hard-register definitions cannot be rewired through a single
+   temporary.  Verify that the multi-set conversion rejects the block.  */
+
+unsigned long long __RTL (startwith ("ce1"))
+f (unsigned long long c, unsigned long long x, unsigned long long y)
+{
+(function "f"
+  (param "c" (DECL_RTL (reg/v:DI x4 [ c ]))
+             (DECL_RTL_INCOMING (reg/v:DI x0 [ c ])))
+  (param "x" (DECL_RTL (reg/v:DI <1> [ x ]))
+             (DECL_RTL_INCOMING (reg/v:DI x1 [ x ])))
+  (param "y" (DECL_RTL (reg/v:DI <2> [ y ]))
+             (DECL_RTL_INCOMING (reg/v:DI x2 [ y ])))
+  (insn-chain
+    (block 2
+      (edge-from entry (flags "FALLTHRU"))
+      (cnote 1 [bb 2] NOTE_INSN_BASIC_BLOCK)
+      (cinsn 2 (set (reg/v:DI x4 [ c ]) (reg:DI x0)))
+      (cinsn 3 (set (reg/v:DI <1> [ x ]) (reg:DI x1)))
+      (cinsn 4 (set (reg/v:DI <2> [ y ]) (reg:DI x2)))
+      (cinsn 5 (set (reg:DI <3>)
+                    (plus:DI (reg/v:DI <1>) (const_int 11))))
+      (cinsn 6 (set (reg:DI <4>)
+                    (plus:DI (reg/v:DI <2>) (const_int -2))))
+      (cinsn 7 (set (reg:CC cc)
+                    (compare:CC (reg/v:DI x4) (const_int 0))))
+      (cjump_insn 8 (set (pc)
+        (if_then_else (eq (reg:CC cc) (const_int 0))
+                      (label_ref 30) (pc))))
+      (edge-to 3 (flags "FALLTHRU"))
+      (edge-to 4)
+    )
+    (block 3
+      (edge-from 2 (flags "FALLTHRU"))
+      (cnote 9 [bb 3] NOTE_INSN_BASIC_BLOCK)
+      (cinsn 10 (set (reg/v:DI x4 [ c ])
+                     (plus:DI (reg/v:DI <1>) (const_int 1))))
+      (cinsn 11 (set (reg:DI <3>)
+                     (plus:DI (reg/v:DI x4) (reg/v:DI <2>))))
+      (cinsn 12 (set (reg:SI x4) (const_int 26)))
+      (cinsn 13 (set (reg:DI <4>)
+                     (plus:DI (reg/v:DI x4) (reg/v:DI <1>))))
+      (edge-to 4 (flags "FALLTHRU"))
+    )
+    (block 4
+      (edge-from 2)
+      (edge-from 3 (flags "FALLTHRU"))
+      (clabel 30 2)
+      (cnote 31 [bb 4] NOTE_INSN_BASIC_BLOCK)
+      (cinsn 32 (set (reg:DI <5>)
+                     (plus:DI (reg:DI <3>) (reg:DI <4>))))
+      (cinsn 33 (set (reg/i:DI x0) (reg:DI <5>)))
+      (cinsn 34 (use (reg/i:DI x0)))
+      (edge-to exit (flags "FALLTHRU"))
+    )
+  )
+  (crtl (return_rtx (reg/i:DI x0)))
+)
+}
+
+int
+main (void)
+{
+  if (f (7, 13, 17) != 70)
+    __builtin_abort ();
+  if (f (0, 13, 17) != 39)
+    __builtin_abort ();
+  return 0;
+}
+
+/* { dg-final { scan-rtl-dump-not "if-conversion succeeded through 
noce_convert_multiple_sets" "ce1" } } */
-- 
2.50.1 (Apple Git-155)

Reply via email to