Hi, PR78695 demonstrates a bug in swap analysis where we assume that a data-flow definition contains a nonzero insn_info. This assumption is wrong at least when -fstack-protector is in effect, as the definition of the base register of the stack protector is not associated with any insn. This patch fixes the problem in the obvious way.
Bootstrapped and tested on powerpc64le-unknown-linux-gnu with no regressions. Is this ok for trunk? The problem was introduced in GCC 7, so no backports are needed. Thanks, Bill [gcc] 2016-12-11 Bill Schmidt <wschm...@linux.vnet.ibm.com> PR target/78695 * config/rs6000/rs6000.c (find_alignment_op): Discard from consideration any definition that doesn't have an associated insn. [gcc/testsuite] 2016-12-11 Bill Schmidt <wschm...@linux.vnet.ibm.com> PR target/78695 * gcc.target/powerpc/swaps-stack-protector.c: New test. Index: gcc/config/rs6000/rs6000.c =================================================================== --- gcc/config/rs6000/rs6000.c (revision 243506) +++ gcc/config/rs6000/rs6000.c (working copy) @@ -41433,6 +41433,12 @@ find_alignment_op (rtx_insn *insn, rtx base_reg) if (!base_def_link || base_def_link->next) break; + /* With stack-protector code enabled, and possibly in other + circumstances, there may not be an associated insn for + the def. */ + if (!base_def_link->ref->base.insn_info) + break; + rtx_insn *and_insn = DF_REF_INSN (base_def_link->ref); and_operation = alignment_mask (and_insn); if (and_operation != 0) Index: gcc/testsuite/gcc.target/powerpc/swaps-stack-protector.c =================================================================== --- gcc/testsuite/gcc.target/powerpc/swaps-stack-protector.c (revision 0) +++ gcc/testsuite/gcc.target/powerpc/swaps-stack-protector.c (working copy) @@ -0,0 +1,16 @@ +/* { dg-do compile } */ +/* { dg-options "-fstack-protector -O3" } */ + +/* PR78695: This code used to ICE in rs6000.c:find_alignment_op because + the stack protector address definition isn't associated with an insn. */ + +void *a(); +long b() { + char c[1]; + char *d = a(), *e = c; + long f = e ? b(e) : 0; + if (f > 54) + f = 1; + while (f--) + *d++ = *e++; +}