Hi, The problem here is lra_substitute_pseudo calls gen_rtx_SUBREG with a VOIDmode (const_int) argument but really it should not be calling gen_rtx_SUBREG directly instead it should be using gen_lowpart_if_possible. This patch fixes that and adds a testcase that had happened on x86_64.
OK? I bootstrapped and tested this on both aarch64-linux-gnu and x86_64-linux-gnu with no regression on either. Thanks, Andrew Pinski ChangeLog: * lra.c (lra_substitute_pseudo): Use gen_lowpart_if_possible instead of gen_rtx_SUBREG/gen_lowpart_SUBREG. testsuite/ChangeLog: * gcc.dg/pr64061.c: New testcase.
Index: testsuite/gcc.dg/pr64061.c =================================================================== --- testsuite/gcc.dg/pr64061.c (revision 0) +++ testsuite/gcc.dg/pr64061.c (revision 0) @@ -0,0 +1,20 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -g -fno-dce -fno-tree-dce" } */ +extern void *buf; + +extern void bar (void); + +int +foo (int i) +{ + int j = 0; + if (__builtin_setjmp (buf) == 0) + { + while (1) + { + j = 1; + bar (); + } + } + return j ? i : 0; +} Index: lra.c =================================================================== --- lra.c (revision 218071) +++ lra.c (working copy) @@ -1807,13 +1807,7 @@ lra_substitute_pseudo (rtx *loc, int old machine_mode inner_mode = GET_MODE (new_reg); if (mode != inner_mode) - { - if (GET_MODE_SIZE (mode) >= GET_MODE_SIZE (inner_mode) - || ! SCALAR_INT_MODE_P (inner_mode)) - new_reg = gen_rtx_SUBREG (mode, new_reg, 0); - else - new_reg = gen_lowpart_SUBREG (mode, new_reg); - } + new_reg = gen_lowpart_if_possible (mode, new_reg); *loc = new_reg; return true; }