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)