Hi! With -O1 -m32 -mpreferred-stack-boundary=2 -msseregparm -msse the following testcase ICEs, because the stack realignment code isn't aware of the DFmode value that possibly needs spilling (on i?86/x86_64 the cost code is saying that extending load from SFmode memory into DFmode constant is for free, which is the case for i387 stack, but not when the target is a SSE register).
Fixed by forcing the value first into a pseudo, where gen_reg_rtx takes care of telling the stack realignment code about it. Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk? 2014-02-12 Jakub Jelinek <ja...@redhat.com> PR target/43546 * expr.c (compress_float_constant): If x is a hard register, extend into a pseudo and then move to x. * gcc.target/i386/pr43546.c: New test. --- gcc/expr.c.jj 2014-02-11 18:45:28.000000000 +0100 +++ gcc/expr.c 2014-02-12 12:43:48.829403526 +0100 @@ -3726,12 +3726,21 @@ compress_float_constant (rtx x, rtx y) into a new pseudo. This constant may be used in different modes, and if not, combine will put things back together for us. */ trunc_y = force_reg (srcmode, trunc_y); - emit_unop_insn (ic, x, trunc_y, UNKNOWN); + + /* If x is a hard register, perform the extension into a pseudo, + so that e.g. stack realignment code is aware of it. */ + rtx target = x; + if (REG_P (x) && HARD_REGISTER_P (x)) + target = gen_reg_rtx (dstmode); + + emit_unop_insn (ic, target, trunc_y, UNKNOWN); last_insn = get_last_insn (); - if (REG_P (x)) + if (REG_P (target)) set_unique_reg_note (last_insn, REG_EQUAL, y); + if (target != x) + return emit_move_insn (x, target); return last_insn; } --- gcc/testsuite/gcc.target/i386/pr43546.c.jj 2014-02-12 12:51:08.029131223 +0100 +++ gcc/testsuite/gcc.target/i386/pr43546.c 2014-02-12 12:50:49.000000000 +0100 @@ -0,0 +1,12 @@ +/* PR target/43546 */ +/* { dg-do compile } */ +/* { dg-options "-O1" } */ +/* { dg-additional-options "-mpreferred-stack-boundary=2 -msseregparm -msse" { target ia32 } } */ + +extern void bar (double); + +void +foo (void) +{ + bar (1.0); +} Jakub