The following fixes an ICE observed with a MEM_REF allows_mem asm
operand.  There's code expecting INDIRECT_REFs that are now never
going to appear.  The following simply treats all tcc_reference
operands the same.

A more conservative approach would be to use INDIRECT_REF || MEM_REF
which would fix this particular testcase, but all non-register typed
kinds of reference trees could appear here and I'm not sure why
former INDIRECT_REFs should be OK to go this path but not say
a.b as we also handle plain DECL_P here albeit with some extra
constraints.  For the VLA case in the PR another spot to adjust
would be || TREE_ADDRESSABLE (type) noting that we also cannot
create a temporary for not constant-sized types.

That said - INDIRECT_REF catched my eye here, this might have
caused quite some extra copies eventually so I did want to fix
that.

Btw, it seems to me the DECL_P case disallowing promoted variables
should only apply to register types which should be SSA names
here unless TREE_ADDRESSABLE in which case we let them through
anyway.  With the same reasoning a generic REFERENCE_CLASS_P
should be OK, not needing such special-casing.

Bootstrap and regtest running on x86_64-unknown-linux-gnu.

OK for trunk?

Thanks,
Richard.

2022-03-09  Richard Biener  <rguent...@suse.de>

        PR middle-end/104786
        * cfgexpand.cc (expand_asm_stmt): Specialize REFERENCE_CLASS_P
        operands rather than INDIRECT_REFs.

        * gcc.dg/pr104786.c: New testcase.
---
 gcc/cfgexpand.cc                | 2 +-
 gcc/testsuite/gcc.dg/pr104786.c | 8 ++++++++
 2 files changed, 9 insertions(+), 1 deletion(-)
 create mode 100644 gcc/testsuite/gcc.dg/pr104786.c

diff --git a/gcc/cfgexpand.cc b/gcc/cfgexpand.cc
index 87536ec7ccd..aaccf1a0906 100644
--- a/gcc/cfgexpand.cc
+++ b/gcc/cfgexpand.cc
@@ -3290,7 +3290,7 @@ expand_asm_stmt (gasm *stmt)
 
       generating_concat_p = 0;
 
-      if ((TREE_CODE (val) == INDIRECT_REF && allows_mem)
+      if ((REFERENCE_CLASS_P (val) && allows_mem)
          || (DECL_P (val)
              && (allows_mem || REG_P (DECL_RTL (val)))
              && ! (REG_P (DECL_RTL (val))
diff --git a/gcc/testsuite/gcc.dg/pr104786.c b/gcc/testsuite/gcc.dg/pr104786.c
new file mode 100644
index 00000000000..3076d236d21
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr104786.c
@@ -0,0 +1,8 @@
+/* { dg-do compile } */
+/* { dg-options "-std=gnu90" } */
+
+void h(void *di, int num)
+{
+  char (*t)[num] = di;
+  __asm__ ("" : "=X"( *t));
+}
-- 
2.34.1

Reply via email to