The ICE in PR93974 is caused by a bug in decompose address not being able to handle Altivec addresses the use AND: to strip off the bottom address bits. Rather than modify lra-constraints.c or rtlanal.c to solve this generic problem this late in the release cycle, I have decided to fix this in target code by defining the TARGET_CANNOT_SUBSTITUTE_MEM_EQUIV_P target hook to reject mems with Altivec addresses from being used as equivalent expressions. I think this is fine, since Altivec addresses are legacy addresses. I have confirmed the following patch fixes the ICE and that we still get the same code generated for the test case below, that we got before my PR93658 patch.
This passed bootstrap and regression testing on powerpc64le-linux with no regressions. Ok for mainline? Peter gcc/ PR rtl-optimization/93974 * config/rs6000/rs6000.c (TARGET_CANNOT_SUBSTITUTE_MEM_EQUIV_P): Define. (rs6000_cannot_substitute_mem_equiv_p): New function. gcc/testsuite/ PR rtl-optimization/93974 * g++.dg/pr93974.C: New test. diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c index 4defc1ab52b..a723503b4dc 100644 --- a/gcc/config/rs6000/rs6000.c +++ b/gcc/config/rs6000/rs6000.c @@ -1734,6 +1734,9 @@ static const struct attribute_spec rs6000_attribute_table[] = #undef TARGET_MANGLE_DECL_ASSEMBLER_NAME #define TARGET_MANGLE_DECL_ASSEMBLER_NAME rs6000_mangle_decl_assembler_name + +#undef TARGET_CANNOT_SUBSTITUTE_MEM_EQUIV_P +#define TARGET_CANNOT_SUBSTITUTE_MEM_EQUIV_P rs6000_cannot_substitute_mem_equiv_p /* Processor table. */ @@ -26375,6 +26378,22 @@ rs6000_predict_doloop_p (struct loop *loop) return true; } +/* Implement TARGET_CANNOT_SUBSTITUTE_MEM_EQUIV_P. */ + +static bool +rs6000_cannot_substitute_mem_equiv_p (rtx mem) +{ + gcc_assert (MEM_P (mem)); + + /* curr_insn_transform()'s handling of subregs cannot handle altivec AND: + type addresses, so don't allow MEMs with those address types to be + substituted as an equivalent expression. See PR93974 for details. */ + if (GET_CODE (XEXP (mem, 0)) == AND) + return true; + + return false; +} + struct gcc_target targetm = TARGET_INITIALIZER; #include "gt-rs6000.h" diff --git a/gcc/testsuite/g++.dg/pr93974.C b/gcc/testsuite/g++.dg/pr93974.C new file mode 100644 index 00000000000..ea5f2f817c1 --- /dev/null +++ b/gcc/testsuite/g++.dg/pr93974.C @@ -0,0 +1,27 @@ +/* { dg-do compile { target { powerpc*-*-linux* } } } */ +/* { dg-require-effective-target powerpc_p8vector_ok } */ +/* { dg-options "-mdejagnu-cpu=power8 -O3 -fstack-protector-strong" } */ + +class a { + double b[2]; +public: + a(); +}; + +class c { +public: + typedef a d; + d m_fn1() { + a e; + return e; + } +}; +template <typename f> void operator+(f, typename f::d); +void g() { + c connector; + for (;;) { + c cut; + a h = cut.m_fn1(); + connector + h; + } +}