On Thu, Aug 30, 2018 at 10:21 AM, Jason Merrill <ja...@redhat.com> wrote:
>
>> r138335 allowed arg_pointer_rtx to be eliminated by either FP or SP,
>> but only when dynamic stack alignment is supported.  In this case,
>> arg_pointer_rtx is eliminated by FP even when frame_pointer_needed
>> is false and there is no dynamic stack alignment at all.
>>
>>> gcc_assert (elim == stack_pointer_rtx || (frame_pointer_needed && elim
>>> == hard_frame_pointer_rtx));
>>>
>>> so as not to allow eliminating to an uninitialized FP.
>>
>> FP isn't uninitialized.  It is initialized the same way as in the case of
>> SUPPORTS_STACK_ALIGNMENT is true.
>
> How is that?  Why would it be initialized when frame_pointer_needed is
> false?  What does it mean for frame_pointer_needed to be false, if
> not, as in the documentation of -fomit-frame-pointer,
>
> "This avoids the instructions to save, set up and restore the frame
> pointer; on many targets it also makes an extra register available."
>
> ?
>

A backend may not set up frame pointer even with -fno-omit-frame-pointer.
In the case of x86,  hard frame pointer can be represented by stack pointer
- UNITS_PER_WORD.

This patch adds hard_frame_pointer_from_stack_pointer_plus_offset and
hard_frame_pointer_offset to rtl_data to allow a backend to represent
hard frame pointer as stack pointer + offset.

OK for trunk?


-- 
H.J.
From 6fc2b6ca9ca77afa2057d2d48ec8f8131036100e Mon Sep 17 00:00:00 2001
From: "H.J. Lu" <hjl.to...@gmail.com>
Date: Wed, 8 Aug 2018 06:20:27 -0700
Subject: [PATCH] DWARF: Represent hard frame pointer as stack pointer + offset

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 and frame pointer may be eliminated
by hard frame pointer.  In this case, hard frame pointer may be represented
by stack pointer + offset.

This patch adds hard_frame_pointer_from_stack_pointer_plus_offset and
hard_frame_pointer_offset to rtl_data to allow a backend to represent
hard frame pointer as stack pointer + offset.

gcc/

	PR debug/86593
	* dwarf2out.c (based_loc_descr): When frame pointer isn't
	used, if arg pointer or frame pointer are eliminated by hard
	frame pointer, use stack pointer + offset to access stack
	variables if possible.  Update gcc_assert.
	* emit-rtl.h (rtl_data): Add hard_frame_pointer_offset and
	hard_frame_pointer_from_stack_pointer_plus_offset.
	* config/i386/i386.c (ix86_finalize_stack_frame_flags): Set
	hard_frame_pointer_from_stack_pointer_plus_offset and
	hard_frame_pointer_offset to represent hard frame pointer as
	stack pointer - UNITS_PER_WORD if frame pointer isn't used.

gcc/testsuite/

	PR debug/86593
	* g++.dg/pr86593.C: New test.
---
 gcc/config/i386/i386.c         |  6 ++++--
 gcc/dwarf2out.c                | 13 +++++++++++--
 gcc/emit-rtl.h                 |  8 ++++++++
 gcc/testsuite/g++.dg/pr86593.C | 11 +++++++++++
 4 files changed, 34 insertions(+), 4 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/pr86593.C

diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
index 8672a666024..775b96473b1 100644
--- a/gcc/config/i386/i386.c
+++ b/gcc/config/i386/i386.c
@@ -13161,10 +13161,12 @@ ix86_finalize_stack_frame_flags (void)
 	  df_compute_regs_ever_live (true);
 	  df_analyze ();
 
+	  /* Since frame pointer is no longer available, replace it with
+	     stack pointer - UNITS_PER_WORD in debug insns.  */
+	  crtl->hard_frame_pointer_from_stack_pointer_plus_offset = true;
+	  crtl->hard_frame_pointer_offset = -UNITS_PER_WORD;
 	  if (flag_var_tracking)
 	    {
-	      /* Since frame pointer is no longer available, replace it with
-		 stack pointer - UNITS_PER_WORD in debug insns.  */
 	      df_ref ref, next;
 	      for (ref = DF_REG_USE_CHAIN (HARD_FRAME_POINTER_REGNUM);
 		   ref; ref = next)
diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c
index 77317ed2575..09f3c192129 100644
--- a/gcc/dwarf2out.c
+++ b/gcc/dwarf2out.c
@@ -14326,9 +14326,18 @@ based_loc_descr (rtx reg, poly_int64 offset,
       if (elim != reg)
 	{
 	  elim = strip_offset_and_add (elim, &offset);
+
+	  if (!frame_pointer_needed
+	      && elim == hard_frame_pointer_rtx
+	      && crtl->hard_frame_pointer_from_stack_pointer_plus_offset)
+	    {
+	      int fp_offset = crtl->hard_frame_pointer_offset;
+	      int base_reg = DWARF_FRAME_REGNUM (STACK_POINTER_REGNUM);
+	      return new_reg_loc_descr (base_reg, offset + fp_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));
diff --git a/gcc/emit-rtl.h b/gcc/emit-rtl.h
index f089355aef7..c69730e2900 100644
--- a/gcc/emit-rtl.h
+++ b/gcc/emit-rtl.h
@@ -282,6 +282,14 @@ struct GTY(()) rtl_data {
      pass.  */
   bool bb_reorder_complete;
 
+  /* True if hard frame pointer can be represented as stack pointer
+     + offset in the current function.  */
+  bool hard_frame_pointer_from_stack_pointer_plus_offset;
+
+  /* Offset from stack pointer if hard frame pointer can be represented
+     as stack pointer + offset in the current function.   */
+  int hard_frame_pointer_offset;
+
   /* Like regs_ever_live, but 1 if a reg is set or clobbered from an
      asm.  Unlike regs_ever_live, elements of this array corresponding
      to eliminable regs (like the frame pointer) are set if an asm
diff --git a/gcc/testsuite/g++.dg/pr86593.C b/gcc/testsuite/g++.dg/pr86593.C
new file mode 100644
index 00000000000..f4de0c1166a
--- /dev/null
+++ b/gcc/testsuite/g++.dg/pr86593.C
@@ -0,0 +1,11 @@
+// { dg-options "-O -g -fno-omit-frame-pointer" }
+
+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