In this PR, we have two registers with "replace" set for them. When
processing the first, we delete its setter, which happens to be the only
use of the other register. In the second iteration we then assert that
the other register has a use, which would be reasonable if we hadn't
deleted it.
The following fixes it. Bootstrapped and tested on x86_64-linux, ok?
Bernd
PR rtl-optimization/78669
* ira.c (combine_and_move_insns): When deleting an insn, clear the
replace flag for all used regs in that insn.
PR rtl-optimization/78669
* gcc.target/i386/pr78669.c: New test.
Index: gcc/ira.c
===================================================================
--- gcc/ira.c (revision 242958)
+++ gcc/ira.c (working copy)
@@ -3705,6 +3705,14 @@ combine_and_move_insns (void)
remove_death (regno, use_insn);
SET_REG_N_REFS (regno, 0);
REG_FREQ (regno) = 0;
+ df_ref use;
+ FOR_EACH_INSN_USE (use, def_insn)
+ {
+ unsigned int use_regno = DF_REF_REGNO (use);
+ if (!HARD_REGISTER_NUM_P (use_regno))
+ reg_equiv[use_regno].replace = 0;
+ }
+
delete_insn (def_insn);
reg_equiv[regno].init_insns = NULL;
Index: gcc/testsuite/gcc.target/i386/pr78669.c
===================================================================
--- gcc/testsuite/gcc.target/i386/pr78669.c (nonexistent)
+++ gcc/testsuite/gcc.target/i386/pr78669.c (working copy)
@@ -0,0 +1,27 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target lp64 } */
+/* { dg-options "-Os -fno-tree-ter -mavx512bw " } */
+typedef __int128 u128;
+typedef __int128 v64u128 __attribute__((vector_size(64)));
+
+v64u128 v64u128_g;
+
+static inline v64u128
+baz(v64u128 v64u128_0, v64u128 v64u128_3)
+{
+ v64u128_0 |= (v64u128){} == v64u128_0;
+ v64u128_3 = (v64u128){} >= v64u128_3;
+ return v64u128_0 + v64u128_3;
+}
+
+static void __attribute__((noinline, noclone))
+bar(u128 u128_0, v64u128 v64u128_3)
+{
+ v64u128_g = baz((v64u128){(u128)1 << 64, u128_0}, v64u128_3);
+}
+
+void
+foo(v64u128 v64u128_3)
+{
+ bar(3, v64u128_3);
+}