On Sat, Sep 01, 2018 at 06:38:35AM -0500, Segher Boessenkool wrote:
> > 
> > With -fno-omit-frame-pointer, arg pointer is eliminated with hard frame
> > pointer.  But
> > 
> > commit cd557ff63f388ad27c376d0a225e74d3594a6f9d
> > Author: hjl <hjl@138bc75d-0d04-0410-961f-82ee72b054a4>
> > Date:   Thu Aug 10 15:29:05 2017 +0000
> > 
> >     i386: Don't use frame pointer without stack access
> > 
> >     When there is no stack access, there is no need to use frame pointer
> >     even if -fno-omit-frame-pointer is used and caller's frame pointer is
> >     unchanged.
> > 
> > changed it in the last minute.  It is too late to go back.  When it is done,
> > hard frame pointer must be replaced by stack pointer - UNITS_PER_WORD
> > if it is ever used.
> 
> So after that patch something uses the hard frame pointer, while it also
> claims nothing uses the hard frame pointer?  Sounds to me you should fix
> the uses, and all will be fine.
> 
> 

Here is the patch to replace hard frame pointer with stack pointer
- UNITS_PER_WORD in x86 backend.

OK for trunk?

H.J.
---
With

commit cd557ff63f388ad27c376d0a225e74d3594a6f9d
Author: hjl <hjl@138bc75d-0d04-0410-961f-82ee72b054a4>
Date:   Thu Aug 10 15:29:05 2017 +0000

    i386: Don't use frame pointer without stack access

    When there is no stack access, there is no need to use frame pointer
    even if -fno-omit-frame-pointer is used and caller's frame pointer is
    unchanged.

frame pointer may not be available even if -fno-omit-frame-pointer is
used.  When this happened, arg pointer in debug info may be eliminated
by hard frame pointer.  In this case, hard frame pointer should be
replaced by stack pointer - UNITS_PER_WORD.

This patch adds replace_fp_with_sp_in_debug_info to x86 machine_function,
replaces arg pointer in debug info with stack pointer - UNITS_PER_WORD
if it is eliminated by hard frame pointer and disallows hard frame pointer
in debug info when frame pointer isn't available.

gcc/

        PR debug/86593
        * dwarf2out.c (based_loc_descr): Disallow hard frame pointer when
        frame pointer isn't available.
        (compute_frame_pointer_to_fb_displacement): Likewise.
        * config/i386/i386.c (ix86_finalize_stack_frame_flags): Set
        replace_fp_with_sp_in_debug_info to true if frame pointer isn't
        used.
        (ix86_replace_fp_with_sp_1): New function.
        (ix86_replace_fp_with_sp): Likewise.
        (ix86_reorg): Call ix86_replace_fp_with_sp if needed.
        * config/i386/i386.h (machine_function): Add
        replace_fp_with_sp_in_debug_info.

gcc/testsuite/

        PR debug/86593
        * g++.dg/pr86593-1.C: New test.
        * g++.dg/pr86593-2.C: Likewise.
---
 gcc/config/i386/i386.c           | 103 +++++++++++++++++++++++++++++++
 gcc/config/i386/i386.h           |   4 ++
 gcc/dwarf2out.c                  |   6 +-
 gcc/testsuite/g++.dg/pr86593-1.C |  11 ++++
 gcc/testsuite/g++.dg/pr86593-2.C |  11 ++++
 5 files changed, 131 insertions(+), 4 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/pr86593-1.C
 create mode 100644 gcc/testsuite/g++.dg/pr86593-2.C

diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
index 8672a666024..8166ea06d42 100644
--- a/gcc/config/i386/i386.c
+++ b/gcc/config/i386/i386.c
@@ -13161,6 +13161,11 @@ ix86_finalize_stack_frame_flags (void)
          df_compute_regs_ever_live (true);
          df_analyze ();
 
+         /* Replace hard frame pointer with stack pointer in debug
+            info.  */
+         cfun->machine->replace_fp_with_sp_in_debug_info
+           = debug_info_level > DINFO_LEVEL_NONE;
+
          if (flag_var_tracking)
            {
              /* Since frame pointer is no longer available, replace it with
@@ -41944,6 +41949,99 @@ ix86_seh_fixup_eh_fallthru (void)
     }
 }
 
+/* Help function for ix86_replace_fp_with_sp.  */
+
+static rtx
+ix86_replace_fp_with_sp_1 (rtx x)
+{
+  if (!x)
+    return x;
+
+  if (x == hard_frame_pointer_rtx)
+    return plus_constant (Pmode, stack_pointer_rtx, -UNITS_PER_WORD);
+
+  const char *fmt = GET_RTX_FORMAT (GET_CODE (x));
+  int i, j;
+  for (i = GET_RTX_LENGTH (GET_CODE (x)) - 1; i >= 0; i--)
+    {
+      if (fmt[i] == 'e')
+       XEXP (x, i) = ix86_replace_fp_with_sp_1 (XEXP (x, i));
+      else if (fmt[i] == 'E')
+       for (j = XVECLEN (x, i) - 1; j >= 0; j--)
+         XVECEXP (x, i, j) = ix86_replace_fp_with_sp_1 (XVECEXP (x, i, j));
+    }
+
+  return x;
+}
+
+/* Replace hard frame pointer in debug info with stack pointer
+   - UNITS_PER_WORD.  */
+
+static void
+ix86_replace_fp_with_sp (void)
+{
+  if (flag_var_tracking)
+    {
+      rtx_insn *insn, *next;
+      rtx replace, note;
+      for (insn = get_insns (); insn; insn = next)
+       {
+         next = NEXT_INSN (insn);
+         if (NOTE_P (insn))
+           {
+             if (NOTE_KIND (insn) == NOTE_INSN_VAR_LOCATION)
+               {
+                 replace = PATTERN (insn);
+                 if (reg_mentioned_p (arg_pointer_rtx, replace))
+                   {
+                     replace = eliminate_regs (replace, VOIDmode,
+                                               NULL_RTX);
+                     if (reg_mentioned_p (hard_frame_pointer_rtx,
+                                          replace))
+                       {
+                         ix86_replace_fp_with_sp_1 (replace);
+                         PATTERN (insn) = replace;
+                       }
+                   }
+               }
+           }
+         else if (CALL_P (insn))
+           {
+             note = find_reg_note (insn, REG_CALL_ARG_LOCATION,
+                                   NULL_RTX);
+             if (note && reg_mentioned_p (arg_pointer_rtx, note))
+               {
+                 replace = eliminate_regs (XEXP (note, 0), VOIDmode,
+                                           NULL_RTX);
+                 if (reg_mentioned_p (hard_frame_pointer_rtx, replace))
+                   {
+                     ix86_replace_fp_with_sp_1 (replace);
+                     remove_note (insn, note);
+                     add_reg_note (insn, REG_CALL_ARG_LOCATION,
+                                   replace);
+                   }
+               }
+           }
+       }
+    }
+
+  for (tree arg = DECL_ARGUMENTS (current_function_decl);
+       arg;
+       arg = TREE_CHAIN (arg))
+    {
+      rtx incoming = DECL_INCOMING_RTL (arg);
+      if (reg_mentioned_p (arg_pointer_rtx, incoming))
+       {
+         incoming = eliminate_regs (incoming, VOIDmode, NULL_RTX);
+         if (reg_mentioned_p (hard_frame_pointer_rtx, incoming))
+           {
+             ix86_replace_fp_with_sp_1 (incoming);
+             DECL_INCOMING_RTL (arg) = incoming;
+           }
+       }
+    }
+}
+
 /* Implement machine specific optimizations.  We implement padding of returns
    for K8 CPUs and pass to avoid 4 jumps in the single 16 byte window.  */
 static void
@@ -41956,6 +42054,11 @@ ix86_reorg (void)
   if (TARGET_SEH && current_function_has_exception_handlers ())
     ix86_seh_fixup_eh_fallthru ();
 
+  /* Replace hard frame pointer in debug info with stack pointer
+     - UNITS_PER_WORD after the variable tracking pass.  */
+  if (cfun->machine->replace_fp_with_sp_in_debug_info)
+    ix86_replace_fp_with_sp ();
+
   if (optimize && optimize_function_for_speed_p (cfun))
     {
       if (TARGET_PAD_SHORT_FUNCTION)
diff --git a/gcc/config/i386/i386.h b/gcc/config/i386/i386.h
index 2a46fccdec1..23cef7a9c61 100644
--- a/gcc/config/i386/i386.h
+++ b/gcc/config/i386/i386.h
@@ -2610,6 +2610,10 @@ struct GTY(()) machine_function {
   /* Nonzero if the function places outgoing arguments on stack.  */
   BOOL_BITFIELD outgoing_args_on_stack : 1;
 
+  /* If true, replace hard frame pointer with stack pointer in debug
+     info.  */
+  BOOL_BITFIELD replace_fp_with_sp_in_debug_info : 1;
+
   /* The largest alignment, in bytes, of stack slot actually used.  */
   unsigned int max_used_stack_alignment;
 
diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c
index 77317ed2575..a879ac1f18c 100644
--- a/gcc/dwarf2out.c
+++ b/gcc/dwarf2out.c
@@ -14327,8 +14327,7 @@ based_loc_descr (rtx reg, poly_int64 offset,
        {
          elim = strip_offset_and_add (elim, &offset);
          gcc_assert ((SUPPORTS_STACK_ALIGNMENT
-                      && (elim == hard_frame_pointer_rtx
-                          || elim == stack_pointer_rtx))
+                      && elim == stack_pointer_rtx)
                      || elim == (frame_pointer_needed
                                  ? hard_frame_pointer_rtx
                                  : stack_pointer_rtx));
@@ -20515,8 +20514,7 @@ compute_frame_pointer_to_fb_displacement (poly_int64 
offset)
      frame_pointer_fb_offset, we won't need one either.  */
   frame_pointer_fb_offset_valid
     = ((SUPPORTS_STACK_ALIGNMENT
-       && (elim == hard_frame_pointer_rtx
-           || elim == stack_pointer_rtx))
+       && elim == stack_pointer_rtx)
        || elim == (frame_pointer_needed
                   ? hard_frame_pointer_rtx
                   : stack_pointer_rtx));
diff --git a/gcc/testsuite/g++.dg/pr86593-1.C b/gcc/testsuite/g++.dg/pr86593-1.C
new file mode 100644
index 00000000000..31dc4153cb9
--- /dev/null
+++ b/gcc/testsuite/g++.dg/pr86593-1.C
@@ -0,0 +1,11 @@
+// { dg-options "-O -g -fno-omit-frame-pointer -fvar-tracking" }
+
+struct Foo
+{
+  int bar(int a, int b, int c, int i1, int i2, int i3, int d);
+};
+
+int Foo::bar(int a, int b, int c, int i1, int i2, int i3, int d)
+{
+  return 0;
+}
diff --git a/gcc/testsuite/g++.dg/pr86593-2.C b/gcc/testsuite/g++.dg/pr86593-2.C
new file mode 100644
index 00000000000..65aeac98099
--- /dev/null
+++ b/gcc/testsuite/g++.dg/pr86593-2.C
@@ -0,0 +1,11 @@
+// { dg-options "-O -g -fno-omit-frame-pointer -fno-var-tracking" }
+
+struct Foo
+{
+  int bar(int a, int b, int c, int i1, int i2, int i3, int d);
+};
+
+int Foo::bar(int a, int b, int c, int i1, int i2, int i3, int d)
+{
+  return 0;
+}
-- 
2.17.1

Reply via email to