diff --git a/gcc/ChangeLog b/gcc/ChangeLog index a9202c7fc91..f003eb1ed24 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,19 @@ +2013-12-03 Jakub Jelinek + + PR target/58864 + * dojump.c (save_pending_stack_adjust, restore_pending_stack_adjust): + New functions. + * expr.h (struct saved_pending_stack_adjust): New type. + (save_pending_stack_adjust, restore_pending_stack_adjust): New + prototypes. + * optabs.c (emit_conditional_move): Call save_pending_stack_adjust + and get_last_insn before do_pending_stack_adjust, call + restore_pending_stack_adjust after delete_insns_since. + * expr.c (expand_expr_real_2): Don't call do_pending_stack_adjust + before calling emit_conditional_move. + * expmed.c (expand_sdiv_pow2): Likewise. + * calls.c (expand_call): Use {save,restore}_pending_stack_adjust. + 2013-12-02 Jeff Law PR tree-optimization/59322 diff --git a/gcc/calls.c b/gcc/calls.c index aaba8b983a7..7d6327f28ef 100644 --- a/gcc/calls.c +++ b/gcc/calls.c @@ -2672,8 +2672,7 @@ expand_call (tree exp, rtx target, int ignore) recursion "call". That way we know any adjustment after the tail recursion call can be ignored if we indeed use the tail call expansion. */ - int save_pending_stack_adjust = 0; - int save_stack_pointer_delta = 0; + saved_pending_stack_adjust save; rtx insns; rtx before_call, next_arg_reg, after_args; @@ -2681,8 +2680,7 @@ expand_call (tree exp, rtx target, int ignore) { /* State variables we need to save and restore between iterations. */ - save_pending_stack_adjust = pending_stack_adjust; - save_stack_pointer_delta = stack_pointer_delta; + save_pending_stack_adjust (&save); } if (pass) flags &= ~ECF_SIBCALL; @@ -3438,8 +3436,7 @@ expand_call (tree exp, rtx target, int ignore) /* Restore the pending stack adjustment now that we have finished generating the sibling call sequence. */ - pending_stack_adjust = save_pending_stack_adjust; - stack_pointer_delta = save_stack_pointer_delta; + restore_pending_stack_adjust (&save); /* Prepare arg structure for next iteration. */ for (i = 0; i < num_actuals; i++) diff --git a/gcc/dojump.c b/gcc/dojump.c index 2aef34d307a..73df6d163d5 100644 --- a/gcc/dojump.c +++ b/gcc/dojump.c @@ -96,6 +96,29 @@ do_pending_stack_adjust (void) pending_stack_adjust = 0; } } + +/* Remember pending_stack_adjust/stack_pointer_delta. + To be used around code that may call do_pending_stack_adjust (), + but the generated code could be discarded e.g. using delete_insns_since. */ + +void +save_pending_stack_adjust (saved_pending_stack_adjust *save) +{ + save->x_pending_stack_adjust = pending_stack_adjust; + save->x_stack_pointer_delta = stack_pointer_delta; +} + +/* Restore the saved pending_stack_adjust/stack_pointer_delta. */ + +void +restore_pending_stack_adjust (saved_pending_stack_adjust *save) +{ + if (inhibit_defer_pop == 0) + { + pending_stack_adjust = save->x_pending_stack_adjust; + stack_pointer_delta = save->x_stack_pointer_delta; + } +} /* Expand conditional expressions. */ diff --git a/gcc/expmed.c b/gcc/expmed.c index c5123cbbe81..8e63cd5b5c5 100644 --- a/gcc/expmed.c +++ b/gcc/expmed.c @@ -3736,11 +3736,6 @@ expand_sdiv_pow2 (enum machine_mode mode, rtx op0, HOST_WIDE_INT d) { rtx temp2; - /* ??? emit_conditional_move forces a stack adjustment via - compare_from_rtx so, if the sequence is discarded, it will - be lost. Do it now instead. */ - do_pending_stack_adjust (); - start_sequence (); temp2 = copy_to_mode_reg (mode, op0); temp = expand_binop (mode, add_optab, temp2, gen_int_mode (d - 1, mode), diff --git a/gcc/expr.c b/gcc/expr.c index c0539da250c..4e0e54f25b5 100644 --- a/gcc/expr.c +++ b/gcc/expr.c @@ -8801,12 +8801,6 @@ expand_expr_real_2 (sepops ops, rtx target, enum machine_mode tmode, { rtx insn; - /* ??? Same problem as in expmed.c: emit_conditional_move - forces a stack adjustment via compare_from_rtx, and we - lose the stack adjustment if the sequence we are about - to create is discarded. */ - do_pending_stack_adjust (); - start_sequence (); /* Try to emit the conditional move. */ diff --git a/gcc/expr.h b/gcc/expr.h index a2cd6690bfe..e734ef44016 100644 --- a/gcc/expr.h +++ b/gcc/expr.h @@ -473,6 +473,28 @@ extern void clear_pending_stack_adjust (void); /* Pop any previously-pushed arguments that have not been popped yet. */ extern void do_pending_stack_adjust (void); +/* Struct for saving/restoring of pending_stack_adjust/stack_pointer_delta + values. */ + +struct saved_pending_stack_adjust +{ + /* Saved value of pending_stack_adjust. */ + int x_pending_stack_adjust; + + /* Saved value of stack_pointer_delta. */ + int x_stack_pointer_delta; +}; + +/* Remember pending_stack_adjust/stack_pointer_delta. + To be used around code that may call do_pending_stack_adjust (), + but the generated code could be discarded e.g. using delete_insns_since. */ + +extern void save_pending_stack_adjust (saved_pending_stack_adjust *); + +/* Restore the saved pending_stack_adjust/stack_pointer_delta. */ + +extern void restore_pending_stack_adjust (saved_pending_stack_adjust *); + /* Return the tree node and offset if a given argument corresponds to a string constant. */ extern tree string_constant (tree, tree *); diff --git a/gcc/optabs.c b/gcc/optabs.c index dcef4809d8b..e035af18c61 100644 --- a/gcc/optabs.c +++ b/gcc/optabs.c @@ -4566,8 +4566,10 @@ emit_conditional_move (rtx target, enum rtx_code code, rtx op0, rtx op1, if (!COMPARISON_P (comparison)) return NULL_RTX; - do_pending_stack_adjust (); + saved_pending_stack_adjust save; + save_pending_stack_adjust (&save); last = get_last_insn (); + do_pending_stack_adjust (); prepare_cmp_insn (XEXP (comparison, 0), XEXP (comparison, 1), GET_CODE (comparison), NULL_RTX, unsignedp, OPTAB_WIDEN, &comparison, &cmode); @@ -4587,6 +4589,7 @@ emit_conditional_move (rtx target, enum rtx_code code, rtx op0, rtx op1, } } delete_insns_since (last); + restore_pending_stack_adjust (&save); return NULL_RTX; } diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 80490ced7a0..5b7430605ff 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,7 +1,12 @@ +2013-12-03 Jakub Jelinek + + PR target/58864 + * g++.dg/opt/pr58864.C: New test. + 2013-12-02 Jeff Law PR tree-optimization/59322 - * gcc.c-torture/compile/pr59322.c: New test + * gcc.c-torture/compile/pr59322.c: New test. 2013-12-02 Sriraman Tallam diff --git a/gcc/testsuite/g++.dg/opt/pr58864.C b/gcc/testsuite/g++.dg/opt/pr58864.C new file mode 100644 index 00000000000..b8587f298a0 --- /dev/null +++ b/gcc/testsuite/g++.dg/opt/pr58864.C @@ -0,0 +1,21 @@ +// PR target/58864 +// { dg-do compile } +// { dg-options "-Os" } +// { dg-additional-options "-march=i686" { target { { i?86-*-* x86_64-*-* } && ia32 } } } + +struct A { A (); ~A (); }; +struct B { B (); }; + +float d, e; + +void +foo () +{ + A a; + float c = d; + while (1) + { + B b; + e = c ? -c : 0; + } +}