From: Stefan Schulze Frielinghaus <[email protected]>
For the attached test we end up during IRA with
6: r99:DI=`s'
REG_EQUIV `s'
7: {[`b']=asm_operands;
[const(`s'+0x4)]=asm_operands;
[`a']=asm_operands;clobber flags:CC;}
REG_DEAD r99:DI
REG_UNUSED flags:CC
where r99 is used in each asm_operands
(mem/c:SI (plus:DI (reg/f:DI 99)
(const_int 4 [0x4])) [2 s.d+0 S4 A32])
This in turn means that we hit multiple times the very same insn while
iterating over all uses of r99 which in the end triggers the assert.
This patch relaxes the assert since what we want to ensure here is that
a register is not used by multiple insns since otherwise we cannot
trivially move or delete the definition.
PR rtl-optimization/125173
gcc/ChangeLog:
* ira.cc (combine_and_move_insns): Allow multiple uses within
an insn.
gcc/testsuite/ChangeLog:
* gcc.dg/pr125173-1.c: New test.
---
Notes:
Bootstrapped and regtested on
- aarch64-unknown-linux-gnu
- powerpc64le-unknown-linux-gnu
- s390x-ibm-linux-gnu
- x86_64-pc-linux-gnu
Ok for mainline?
gcc/ira.cc | 12 +++++++++++-
gcc/testsuite/gcc.dg/pr125173-1.c | 17 +++++++++++++++++
2 files changed, 28 insertions(+), 1 deletion(-)
create mode 100644 gcc/testsuite/gcc.dg/pr125173-1.c
diff --git a/gcc/ira.cc b/gcc/ira.cc
index 85c7ec419b3..821dbf0e445 100644
--- a/gcc/ira.cc
+++ b/gcc/ira.cc
@@ -3982,6 +3982,7 @@ combine_and_move_insns (void)
continue;
rtx_insn *use_insn = 0;
+ bool multiple_insns = false;
for (df_ref use = DF_REG_USE_CHAIN (regno);
use;
use = DF_REF_NEXT_REG (use))
@@ -3989,11 +3990,20 @@ combine_and_move_insns (void)
{
if (DEBUG_INSN_P (DF_REF_INSN (use)))
continue;
- gcc_assert (!use_insn);
+ if (use_insn && DF_REF_INSN (use) != use_insn)
+ {
+ multiple_insns = true;
+ break;
+ }
use_insn = DF_REF_INSN (use);
}
gcc_assert (use_insn);
+ /* If a register is used by more than one insn, we cannot trivially move
+ or delete the definition anymore. */
+ if (multiple_insns)
+ continue;
+
/* Don't substitute into jumps. indirect_jump_optimize does
this for anything we are prepared to handle. */
if (JUMP_P (use_insn))
diff --git a/gcc/testsuite/gcc.dg/pr125173-1.c
b/gcc/testsuite/gcc.dg/pr125173-1.c
new file mode 100644
index 00000000000..5f66b24fcb0
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr125173-1.c
@@ -0,0 +1,17 @@
+/* { dg-do compile } */
+/* { dg-options "-O1 -fno-fuse-ops-with-volatile-access -fno-forward-propagate
--param=max-cse-insns=0" } */
+
+int a;
+volatile short b;
+
+struct
+{
+ char c;
+ int d;
+} s;
+
+void
+foo ()
+{
+ __asm__ ("":"+m" (b), "+m" (s.d), "+m" (a));
+}
--
2.53.0