diff mbox series

[2/3,amdgcn] Use frame pointer for CFA expressions.

Message ID 20210622171443.1287801-3-abidh@codesourcery.com
State New
Headers show
Series Improve debug support. | expand

Commit Message

Abid Qadeer June 22, 2021, 5:14 p.m. UTC
As size of address is bigger than registers in amdgcn, we are forced to use
DW_CFA_def_cfa_expression to make an expression that concatenates multiple
registers for the value of the CFA.  This then prohibits us from using many
of the dwarf ops which expect CFA rule to be a single regsiter plus an offset.
Using frame pointer in the CFA rule is only real possibility as it is saved
in every frame and it is easy to unwind its value.

So unless user gives fomit-frame-pointer, we use frame pointer for the
cfi information.  This options also has a different default now.

gcc/

	* common/config/gcn/gcn-common.c
	(gcn_option_optimization_table): Change OPT_fomit_frame_pointer to -O3.
	(gcn_expand_prologue): Prefer the frame pointer when emitting CFI.
	(gcn_frame_pointer_rqd): New function.
	(TARGET_FRAME_POINTER_REQUIRED): New hook.
---
 gcc/common/config/gcn/gcn-common.c |  2 +-
 gcc/config/gcn/gcn.c               | 60 +++++++++++++++++++++++-------
 2 files changed, 47 insertions(+), 15 deletions(-)

Comments

Andrew Stubbs June 23, 2021, 9:32 a.m. UTC | #1
On 22/06/2021 18:14, Hafiz Abid Qadeer wrote:
> As size of address is bigger than registers in amdgcn, we are forced to use
> DW_CFA_def_cfa_expression to make an expression that concatenates multiple
> registers for the value of the CFA.  This then prohibits us from using many
> of the dwarf ops which expect CFA rule to be a single regsiter plus an offset.
> Using frame pointer in the CFA rule is only real possibility as it is saved
> in every frame and it is easy to unwind its value.
> 
> So unless user gives fomit-frame-pointer, we use frame pointer for the
> cfi information.  This options also has a different default now.
> 
> gcc/
> 
> 	* common/config/gcn/gcn-common.c
> 	(gcn_option_optimization_table): Change OPT_fomit_frame_pointer to -O3.
> 	(gcn_expand_prologue): Prefer the frame pointer when emitting CFI.
> 	(gcn_frame_pointer_rqd): New function.
> 	(TARGET_FRAME_POINTER_REQUIRED): New hook.
> ---
>   gcc/common/config/gcn/gcn-common.c |  2 +-
>   gcc/config/gcn/gcn.c               | 60 +++++++++++++++++++++++-------
>   2 files changed, 47 insertions(+), 15 deletions(-)
> 
> diff --git a/gcc/common/config/gcn/gcn-common.c b/gcc/common/config/gcn/gcn-common.c
> index 305c310f940..695eb467e34 100644
> --- a/gcc/common/config/gcn/gcn-common.c
> +++ b/gcc/common/config/gcn/gcn-common.c
> @@ -27,7 +27,7 @@
>   /* Set default optimization options.  */
>   static const struct default_options gcn_option_optimization_table[] =
>     {
> -    { OPT_LEVELS_1_PLUS, OPT_fomit_frame_pointer, NULL, 1 },
> +    { OPT_LEVELS_3_PLUS, OPT_fomit_frame_pointer, NULL, 1 },
>       { OPT_LEVELS_NONE, 0, NULL, 0 }
>     };
>   
> diff --git a/gcc/config/gcn/gcn.c b/gcc/config/gcn/gcn.c
> index 3ab16548aad..0eac3aa3844 100644
> --- a/gcc/config/gcn/gcn.c
> +++ b/gcc/config/gcn/gcn.c
> @@ -2900,10 +2900,14 @@ gcn_expand_prologue ()
>   	  rtx adjustment = gen_int_mode (sp_adjust, SImode);
>   	  rtx insn = emit_insn (gen_addsi3_scalar_carry (sp_lo, sp_lo,
>   							 adjustment, scc));
> -	  RTX_FRAME_RELATED_P (insn) = 1;
> -	  add_reg_note (insn, REG_FRAME_RELATED_EXPR,
> -			gen_rtx_SET (sp,
> -				     gen_rtx_PLUS (DImode, sp, adjustment)));
> +	  if (!offsets->need_frame_pointer)
> +	    {
> +	      RTX_FRAME_RELATED_P (insn) = 1;
> +	      add_reg_note (insn, REG_FRAME_RELATED_EXPR,
> +			    gen_rtx_SET (sp,
> +					 gen_rtx_PLUS (DImode, sp,
> +						       adjustment)));
> +	    }
>   	  emit_insn (gen_addcsi3_scalar_zero (sp_hi, sp_hi, scc));
>   	}
>   
> @@ -2917,25 +2921,24 @@ gcn_expand_prologue ()
>   	  rtx adjustment = gen_int_mode (fp_adjust, SImode);
>   	  rtx insn = emit_insn (gen_addsi3_scalar_carry(fp_lo, sp_lo,
>   							adjustment, scc));
> -	  RTX_FRAME_RELATED_P (insn) = 1;
> -	  add_reg_note (insn, REG_FRAME_RELATED_EXPR,
> -			gen_rtx_SET (fp,
> -				     gen_rtx_PLUS (DImode, sp, adjustment)));
>   	  emit_insn (gen_addcsi3_scalar (fp_hi, sp_hi,
>   					 (fp_adjust < 0 ? GEN_INT (-1)
>   					  : const0_rtx),
>   					 scc, scc));
> +
> +	  /* Set the CFA to the entry stack address, as an offset from the
> +	     frame pointer.  This is preferred because the frame pointer is
> +	     saved in each frame, whereas the stack pointer is not.  */
> +	  RTX_FRAME_RELATED_P (insn) = 1;
> +	  add_reg_note (insn, REG_CFA_DEF_CFA,
> +			gen_rtx_PLUS (DImode, fp,
> +				      GEN_INT (-(offsets->pretend_size
> +						 + offsets->callee_saves))));
>   	}
>   
>         rtx_insn *seq = get_insns ();
>         end_sequence ();
>   
> -      /* FIXME: Prologue insns should have this flag set for debug output, etc.
> -	 but it causes issues for now.
> -      for (insn = seq; insn; insn = NEXT_INSN (insn))
> -        if (INSN_P (insn))
> -	  RTX_FRAME_RELATED_P (insn) = 1;*/
> -
>         emit_insn (seq);
>       }
>     else
> @@ -3011,6 +3014,16 @@ gcn_expand_prologue ()
>   		    gen_rtx_SET (sp, gen_rtx_PLUS (DImode, sp,
>   						   dbg_adjustment)));
>   
> +      if (offsets->need_frame_pointer)
> +	{
> +	  /* Set the CFA to the entry stack address, as an offset from the
> +	     frame pointer.  This is necessary when alloca is used, and
> +	     harmless otherwise.  */
> +	  rtx neg_adjust = gen_int_mode (-offsets->callee_saves, DImode);
> +	  add_reg_note (insn, REG_CFA_DEF_CFA,
> +			gen_rtx_PLUS (DImode, fp, neg_adjust));
> +	}
> +
>         /* Make sure the flat scratch reg doesn't get optimised away.  */
>         emit_insn (gen_prologue_use (gen_rtx_REG (DImode, FLAT_SCRATCH_REG)));
>       }
> @@ -3114,6 +3127,23 @@ gcn_expand_epilogue (void)
>     emit_jump_insn (gen_gcn_return ());
>   }
>   
> +/* Implement TARGET_FRAME_POINTER_REQUIRED.
> +
> +   Return true if the frame pointer should not be eliminated.  */
> +
> +bool
> +gcn_frame_pointer_rqd (void)
> +{
> +  /* GDB needs the frame pointer in order to unwind properly,
> +     but that's not important for the entry point, unless alloca is used.
> +     It's not important for code execution, so we should repect the
> +     -fomit-frame-pointer flag.  */
> +  return (!flag_omit_frame_pointer
> +	  && cfun
> +	  && (cfun->calls_alloca
> +	      || (cfun->machine && cfun->machine->normal_function)));
> +}
> +
>   /* Implement TARGET_CAN_ELIMINATE.
>    
>      Return true if the compiler is allowed to try to replace register number
> @@ -6373,6 +6403,8 @@ gcn_dwarf_register_span (rtx rtl)
>   #define TARGET_EMUTLS_VAR_INIT gcn_emutls_var_init
>   #undef  TARGET_EXPAND_BUILTIN
>   #define TARGET_EXPAND_BUILTIN gcn_expand_builtin
> +#undef  TARGET_FRAME_POINTER_REQUIRED
> +#define TARGET_FRAME_POINTER_REQUIRED gcn_frame_pointer_rqd
>   #undef  TARGET_FUNCTION_ARG
>   #undef  TARGET_FUNCTION_ARG_ADVANCE
>   #define TARGET_FUNCTION_ARG_ADVANCE gcn_function_arg_advance
> 

OK.

Andrew
diff mbox series

Patch

diff --git a/gcc/common/config/gcn/gcn-common.c b/gcc/common/config/gcn/gcn-common.c
index 305c310f940..695eb467e34 100644
--- a/gcc/common/config/gcn/gcn-common.c
+++ b/gcc/common/config/gcn/gcn-common.c
@@ -27,7 +27,7 @@ 
 /* Set default optimization options.  */
 static const struct default_options gcn_option_optimization_table[] =
   {
-    { OPT_LEVELS_1_PLUS, OPT_fomit_frame_pointer, NULL, 1 },
+    { OPT_LEVELS_3_PLUS, OPT_fomit_frame_pointer, NULL, 1 },
     { OPT_LEVELS_NONE, 0, NULL, 0 }
   };
 
diff --git a/gcc/config/gcn/gcn.c b/gcc/config/gcn/gcn.c
index 3ab16548aad..0eac3aa3844 100644
--- a/gcc/config/gcn/gcn.c
+++ b/gcc/config/gcn/gcn.c
@@ -2900,10 +2900,14 @@  gcn_expand_prologue ()
 	  rtx adjustment = gen_int_mode (sp_adjust, SImode);
 	  rtx insn = emit_insn (gen_addsi3_scalar_carry (sp_lo, sp_lo,
 							 adjustment, scc));
-	  RTX_FRAME_RELATED_P (insn) = 1;
-	  add_reg_note (insn, REG_FRAME_RELATED_EXPR,
-			gen_rtx_SET (sp,
-				     gen_rtx_PLUS (DImode, sp, adjustment)));
+	  if (!offsets->need_frame_pointer)
+	    {
+	      RTX_FRAME_RELATED_P (insn) = 1;
+	      add_reg_note (insn, REG_FRAME_RELATED_EXPR,
+			    gen_rtx_SET (sp,
+					 gen_rtx_PLUS (DImode, sp,
+						       adjustment)));
+	    }
 	  emit_insn (gen_addcsi3_scalar_zero (sp_hi, sp_hi, scc));
 	}
 
@@ -2917,25 +2921,24 @@  gcn_expand_prologue ()
 	  rtx adjustment = gen_int_mode (fp_adjust, SImode);
 	  rtx insn = emit_insn (gen_addsi3_scalar_carry(fp_lo, sp_lo,
 							adjustment, scc));
-	  RTX_FRAME_RELATED_P (insn) = 1;
-	  add_reg_note (insn, REG_FRAME_RELATED_EXPR,
-			gen_rtx_SET (fp,
-				     gen_rtx_PLUS (DImode, sp, adjustment)));
 	  emit_insn (gen_addcsi3_scalar (fp_hi, sp_hi,
 					 (fp_adjust < 0 ? GEN_INT (-1)
 					  : const0_rtx),
 					 scc, scc));
+
+	  /* Set the CFA to the entry stack address, as an offset from the
+	     frame pointer.  This is preferred because the frame pointer is
+	     saved in each frame, whereas the stack pointer is not.  */
+	  RTX_FRAME_RELATED_P (insn) = 1;
+	  add_reg_note (insn, REG_CFA_DEF_CFA,
+			gen_rtx_PLUS (DImode, fp,
+				      GEN_INT (-(offsets->pretend_size
+						 + offsets->callee_saves))));
 	}
 
       rtx_insn *seq = get_insns ();
       end_sequence ();
 
-      /* FIXME: Prologue insns should have this flag set for debug output, etc.
-	 but it causes issues for now.
-      for (insn = seq; insn; insn = NEXT_INSN (insn))
-        if (INSN_P (insn))
-	  RTX_FRAME_RELATED_P (insn) = 1;*/
-
       emit_insn (seq);
     }
   else
@@ -3011,6 +3014,16 @@  gcn_expand_prologue ()
 		    gen_rtx_SET (sp, gen_rtx_PLUS (DImode, sp,
 						   dbg_adjustment)));
 
+      if (offsets->need_frame_pointer)
+	{
+	  /* Set the CFA to the entry stack address, as an offset from the
+	     frame pointer.  This is necessary when alloca is used, and
+	     harmless otherwise.  */
+	  rtx neg_adjust = gen_int_mode (-offsets->callee_saves, DImode);
+	  add_reg_note (insn, REG_CFA_DEF_CFA,
+			gen_rtx_PLUS (DImode, fp, neg_adjust));
+	}
+
       /* Make sure the flat scratch reg doesn't get optimised away.  */
       emit_insn (gen_prologue_use (gen_rtx_REG (DImode, FLAT_SCRATCH_REG)));
     }
@@ -3114,6 +3127,23 @@  gcn_expand_epilogue (void)
   emit_jump_insn (gen_gcn_return ());
 }
 
+/* Implement TARGET_FRAME_POINTER_REQUIRED.
+
+   Return true if the frame pointer should not be eliminated.  */
+
+bool
+gcn_frame_pointer_rqd (void)
+{
+  /* GDB needs the frame pointer in order to unwind properly,
+     but that's not important for the entry point, unless alloca is used.
+     It's not important for code execution, so we should repect the
+     -fomit-frame-pointer flag.  */
+  return (!flag_omit_frame_pointer
+	  && cfun
+	  && (cfun->calls_alloca
+	      || (cfun->machine && cfun->machine->normal_function)));
+}
+
 /* Implement TARGET_CAN_ELIMINATE.
  
    Return true if the compiler is allowed to try to replace register number
@@ -6373,6 +6403,8 @@  gcn_dwarf_register_span (rtx rtl)
 #define TARGET_EMUTLS_VAR_INIT gcn_emutls_var_init
 #undef  TARGET_EXPAND_BUILTIN
 #define TARGET_EXPAND_BUILTIN gcn_expand_builtin
+#undef  TARGET_FRAME_POINTER_REQUIRED
+#define TARGET_FRAME_POINTER_REQUIRED gcn_frame_pointer_rqd
 #undef  TARGET_FUNCTION_ARG
 #undef  TARGET_FUNCTION_ARG_ADVANCE
 #define TARGET_FUNCTION_ARG_ADVANCE gcn_function_arg_advance