Jakub Jelinek <ja...@redhat.com> wrote:
>Hi!
>
>The following testcase ICEs because expand_cond_expr_using_cmove
>calls emit_conditional_move (which calls do_pending_stack_adjust
>under some circumstances), but when that fails, just removes all the
>insns generated by emit_conditional_move (and perhaps some earlier ones
>too), thus it removes also the stack adjustment.
>
>Apparently 2 similar places were fixing it by just calling
>do_pending_stack_adjust () first just in case, some other places
>had (most likely) the same bug as this function.
>
>Rather than adding do_pending_stack_adjust () in all the places,
>especially
>when it isn't clear whether emit_conditional_move will be called at all
>and
>whether it will actually do do_pending_stack_adjust (), I chose to add
>two new functions to save/restore the pending stack adjustment state,
>so that when instruction sequence is thrown away (either by doing
>start_sequence/end_sequence around it and not emitting it, or
>delete_insns_since) the state can be restored, and have changed all the
>places that IMHO need it for emit_conditional_move.
>
>Bootstrapped/regtested on x86_64-linux and i686-linux, ok for
>trunk/4.8?

The idea is good but I'd like to see a struct rather than an array for the 
storage.

Thanks,
Richard.


>2013-11-29  Jakub Jelinek  <ja...@redhat.com>
>
>       PR target/58864
>       * dojump.c (save_pending_stack_adjust, restore_pending_stack_adjust):
>       New functions.
>       * expr.h (save_pending_stack_adjust, restore_pending_stack_adjust):
>       New prototypes.
>       * expr.c (expand_cond_expr_using_cmove): Use it.
>       (expand_expr_real_2): Use it instead of unconditional
>       do_pending_stack_adjust.
>       * optabs.c (expand_doubleword_shift): Use it.
>       * expmed.c (expand_sdiv_pow2): Use it instead of unconditional
>       do_pending_stack_adjust.
>       (emit_store_flag): Use it.
>
>       * g++.dg/opt/pr58864.C: New test.
>
>--- gcc/expr.c.jj      2013-11-27 18:02:46.000000000 +0100
>+++ gcc/expr.c 2013-11-29 14:35:12.234808484 +0100
>@@ -7951,6 +7951,9 @@ expand_cond_expr_using_cmove (tree treeo
>   else
>     temp = assign_temp (type, 0, 1);
> 
>+  int save[2];
>+  save_pending_stack_adjust (save);
>+
>   start_sequence ();
>   expand_operands (treeop1, treeop2,
>                  temp, &op1, &op2, EXPAND_NORMAL);
>@@ -8009,6 +8012,7 @@ expand_cond_expr_using_cmove (tree treeo
>   /* Otherwise discard the sequence and fall back to code with
>      branches.  */
>   end_sequence ();
>+  restore_pending_stack_adjust (save);
> #endif
>   return NULL_RTX;
> }
>@@ -8789,12 +8793,9 @@ expand_expr_real_2 (sepops ops, rtx targ
>       if (can_conditionally_move_p (mode))
>         {
>           rtx insn;
>+          int save[2];
> 
>-          /* ??? 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 ();
>+          save_pending_stack_adjust (save);
> 
>           start_sequence ();
> 
>@@ -8817,6 +8818,7 @@ expand_expr_real_2 (sepops ops, rtx targ
>           /* Otherwise discard the sequence and fall back to code with
>              branches.  */
>           end_sequence ();
>+          restore_pending_stack_adjust (save);
>         }
> #endif
>       if (target != op0)
>--- gcc/optabs.c.jj    2013-11-19 21:56:22.000000000 +0100
>+++ gcc/optabs.c       2013-11-29 14:39:15.963513835 +0100
>@@ -1079,17 +1079,20 @@ expand_doubleword_shift (enum machine_mo
> 
> #ifdef HAVE_conditional_move
>   /* Try using conditional moves to generate straight-line code.  */
>-  {
>-    rtx start = get_last_insn ();
>-    if (expand_doubleword_shift_condmove (op1_mode, binoptab,
>-                                        cmp_code, cmp1, cmp2,
>-                                        outof_input, into_input,
>-                                        op1, superword_op1,
>-                                        outof_target, into_target,
>-                                        unsignedp, methods, shift_mask))
>-      return true;
>-    delete_insns_since (start);
>-  }
>+  int save[2];
>+
>+  save_pending_stack_adjust (save);
>+
>+  rtx start = get_last_insn ();
>+  if (expand_doubleword_shift_condmove (op1_mode, binoptab,
>+                                      cmp_code, cmp1, cmp2,
>+                                      outof_input, into_input,
>+                                      op1, superword_op1,
>+                                      outof_target, into_target,
>+                                      unsignedp, methods, shift_mask))
>+    return true;
>+  delete_insns_since (start);
>+  restore_pending_stack_adjust (save);
> #endif
> 
>/* As a last resort, use branches to select the correct alternative. 
>*/
>--- gcc/dojump.c.jj    2013-11-19 21:56:27.000000000 +0100
>+++ gcc/dojump.c       2013-11-29 14:35:35.088685749 +0100
>@@ -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 (int save[2])
>+{
>+  save[0] = pending_stack_adjust;
>+  save[1] = stack_pointer_delta;
>+}
>+
>+/* Restore the saved pending_stack_adjust/stack_pointer_delta.  */
>+
>+void
>+restore_pending_stack_adjust (int save[2])
>+{
>+  if (inhibit_defer_pop == 0)
>+    {
>+      pending_stack_adjust = save[0];
>+      stack_pointer_delta = save[1];
>+    }
>+}
> >
> /* Expand conditional expressions.  */
> 
>--- gcc/expr.h.jj      2013-11-19 21:56:27.000000000 +0100
>+++ gcc/expr.h 2013-11-29 14:35:23.438747999 +0100
>@@ -473,6 +473,16 @@ extern void clear_pending_stack_adjust (
>/* Pop any previously-pushed arguments that have not been popped yet. 
>*/
> extern void do_pending_stack_adjust (void);
> 
>+/* 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 (int [2]);
>+
>+/* Restore the saved pending_stack_adjust/stack_pointer_delta.  */
>+
>+extern void restore_pending_stack_adjust (int [2]);
>+
> /* Return the tree node and offset if a given argument corresponds to
>    a string constant.  */
> extern tree string_constant (tree, tree *);
>--- gcc/expmed.c.jj    2013-11-19 21:56:36.000000000 +0100
>+++ gcc/expmed.c       2013-11-29 14:41:16.887872205 +0100
>@@ -3735,11 +3735,9 @@ expand_sdiv_pow2 (enum machine_mode mode
>       >= 2)
>     {
>       rtx temp2;
>+      int save[2];
> 
>-      /* ??? 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 ();
>+      save_pending_stack_adjust (save);
> 
>       start_sequence ();
>       temp2 = copy_to_mode_reg (mode, op0);
>@@ -3758,6 +3756,7 @@ expand_sdiv_pow2 (enum machine_mode mode
>         return expand_shift (RSHIFT_EXPR, mode, temp2, logd, NULL_RTX, 0);
>       }
>       end_sequence ();
>+      restore_pending_stack_adjust (save);
>     }
> #endif
> 
>@@ -5508,6 +5507,9 @@ emit_store_flag (rtx target, enum rtx_co
>       if (tem == 0)
>       return 0;
> 
>+      int save[2];
>+      save_pending_stack_adjust (save);
>+
>       if (and_them)
>         tem = emit_conditional_move (target, code, op0, op1, mode,
>                                    tem, const0_rtx, GET_MODE (tem), 0);
>@@ -5516,7 +5518,10 @@ emit_store_flag (rtx target, enum rtx_co
>                                    trueval, tem, GET_MODE (tem), 0);
> 
>       if (tem == 0)
>-        delete_insns_since (last);
>+      {
>+        delete_insns_since (last);
>+        restore_pending_stack_adjust (save);
>+      }
>       return tem;
> #else
>       return 0;
>--- gcc/testsuite/g++.dg/opt/pr58864.C.jj      2013-11-29 13:49:24.450415660
>+0100
>+++ gcc/testsuite/g++.dg/opt/pr58864.C 2013-11-29 13:47:47.000000000
>+0100
>@@ -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;
>+    }
>+}
>
>       Jakub


Reply via email to