Hi! Returning c from avoid_constant_pool_reference for constant pool references is only fine if the modes match and offset is zero, otherwise if the offset is sane, we can try to simplify it as subreg. But, returning c for out of bounds offsets is always wrong, and especially if the mode doesn't match, it can results in all kinds of ICEs.
Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk? 2016-08-29 Jakub Jelinek <ja...@redhat.com> PR middle-end/77377 * simplify-rtx.c (avoid_constant_pool_reference): For out of bounds constant pool reference return x instead of c. * gcc.target/i386/pr77377.c: New test. --- gcc/simplify-rtx.c.jj 2016-08-12 17:33:46.000000000 +0200 +++ gcc/simplify-rtx.c 2016-08-29 13:32:38.126859949 +0200 @@ -251,15 +251,14 @@ avoid_constant_pool_reference (rtx x) /* If we're accessing the constant in a different mode than it was originally stored, attempt to fix that up via subreg simplifications. If that fails we have no choice but to return the original memory. */ - if ((offset != 0 || cmode != GET_MODE (x)) - && offset >= 0 && offset < GET_MODE_SIZE (cmode)) + if (offset == 0 && cmode == GET_MODE (x)) + return c; + else if (offset >= 0 && offset < GET_MODE_SIZE (cmode)) { rtx tem = simplify_subreg (GET_MODE (x), c, cmode, offset); if (tem && CONSTANT_P (tem)) return tem; } - else - return c; } return x; --- gcc/testsuite/gcc.target/i386/pr77377.c.jj 2016-08-29 13:39:01.707328239 +0200 +++ gcc/testsuite/gcc.target/i386/pr77377.c 2016-08-29 13:38:55.901396832 +0200 @@ -0,0 +1,6 @@ +/* PR middle-end/77377 */ +/* { dg-do compile } */ +/* { dg-options "-O3 -msse" } */ +/* { dg-additional-options "-fpic" { target fpic } } */ + +#include "../../c-c++-common/pr59037.c" Jakub