On 16-01-14 09:13, Richard Sandiford wrote:
Tom de Vries <tom_devr...@mentor.com> writes:
* The set of registers which are clobbered during a call by things like the plt
    - these are not picked up by the use-caller-save optimization. We need the
    hook to inform the compiler about these registers

Right, but...

* And finally, registers clobbered in the caller itself during a sequence of
    instructions implementing a function call. On mips, that's R6, which may be
    clobbered by the call. Normally that doesn't need mentioning in the RTL 
since
    it's a call_used_reg, but since use-caller-save might discover a set of
    registers for the called function that does not include R6, it becomes
    important to record this clobber explicitly. It could be represented in the
    RTL by a clobber on the insn, or a clobber in C_I_F_U. Or it could just be
    part of the registers returned by the hook - but that was previously deemed
    not acceptable (and it doesn't match the description of the hook).

...why do we need two different mechanisms to deal with these two?
IMO the set recorded for the callee should contain what the callee
instructions clobber and nothing else.  CALL_INSN_FUNCTION_USAGE
should contain everything clobbered by a call outside the callee,
whether that's in the calling function itself, in a PLT, in a MIPS16
stub, or whatever.


Richard,

Is this what you mean?

This patch introduces a hook that specifies which registers are implicitly clobbered by a call, not including the registers that are clobbered in the called function, and then uses that hook to add those registers to CALL_INSN_FUNCTION_USAGE.

Thanks,
- Tom

2013-04-29  Radovan Obradovic  <robrado...@mips.com>
            Tom de Vries  <t...@codesourcery.com>

        * target.def (call_clobbered_regs): New DEFHOOK.
        * doc/tm.texi.in (@node Stack and Calling): Add Miscellaneous Register
        Hooks to @menu.
        (@node Miscellaneous Register Hooks): New node.
        (@hook TARGET_CALL_CLOBBERED_REGS): New hook.
        * doc/tm.texi: Regenerate.
        * calls.c (expand_call, emit_library_call_value_1): Add regs in
        targetm.call_clobbered_regs to CALL_INSN_FUNCTION_USAGE.

diff --git a/gcc/calls.c b/gcc/calls.c
index e798c7a..edee262 100644
--- a/gcc/calls.c
+++ b/gcc/calls.c
@@ -3191,6 +3191,27 @@ expand_call (tree exp, rtx target, int ignore)
 	  add_reg_note (last, REG_CALL_DECL, datum);
 	}
 
+      if (targetm.call_clobbered_regs != NULL)
+	{
+	  struct hard_reg_set_container call_clobbered_regs;
+	  rtx last = last_call_insn ();
+
+	  CLEAR_HARD_REG_SET (call_clobbered_regs.set);
+	  if (targetm.call_clobbered_regs (fndecl, &call_clobbered_regs))
+	    {
+	      hard_reg_set_iterator hrsi;
+	      unsigned int i;
+	      EXECUTE_IF_SET_IN_HARD_REG_SET (call_clobbered_regs.set, 0, i, hrsi)
+		{
+		  rtx reg = gen_rtx_REG (word_mode, i);
+		  CALL_INSN_FUNCTION_USAGE (last)
+		    = gen_rtx_EXPR_LIST (VOIDmode,
+					 gen_rtx_CLOBBER (VOIDmode, reg),
+					 CALL_INSN_FUNCTION_USAGE (last));
+		}
+	    }
+	}
+
       /* If the call setup or the call itself overlaps with anything
 	 of the argument setup we probably clobbered our call address.
 	 In that case we can't do sibcalls.  */
@@ -4226,6 +4247,27 @@ emit_library_call_value_1 (int retval, rtx orgfun, rtx value,
       add_reg_note (last, REG_CALL_DECL, datum);
     }
 
+  if (targetm.call_clobbered_regs != NULL)
+    {
+      struct hard_reg_set_container call_clobbered_regs;
+      rtx last = last_call_insn ();
+
+      CLEAR_HARD_REG_SET (call_clobbered_regs.set);
+      if (targetm.call_clobbered_regs (fndecl, &call_clobbered_regs))
+	{
+	  hard_reg_set_iterator hrsi;
+	  unsigned int i;
+	  EXECUTE_IF_SET_IN_HARD_REG_SET (call_clobbered_regs.set, 0, i, hrsi)
+	    {
+	      rtx reg = gen_rtx_REG (word_mode, i);
+	      CALL_INSN_FUNCTION_USAGE (last)
+		= gen_rtx_EXPR_LIST (VOIDmode,
+				     gen_rtx_CLOBBER (VOIDmode, reg),
+				     CALL_INSN_FUNCTION_USAGE (last));
+	    }
+	}
+    }
+
   /* Right-shift returned value if necessary.  */
   if (!pcc_struct_value
       && TYPE_MODE (tfom) != BLKmode
diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi
index b8ca17e..cd52f73 100644
--- a/gcc/doc/tm.texi
+++ b/gcc/doc/tm.texi
@@ -3091,6 +3091,7 @@ This describes the stack layout and calling conventions.
 * Profiling::
 * Tail Calls::
 * Stack Smashing Protection::
+* Miscellaneous Register Hooks::
 @end menu
 
 @node Frame Layout
@@ -5016,6 +5017,14 @@ normally defined in @file{libgcc2.c}.
 Whether this target supports splitting the stack when the options described in @var{opts} have been passed.  This is called after options have been parsed, so the target may reject splitting the stack in some configurations.  The default version of this hook returns false.  If @var{report} is true, this function may issue a warning or error; if @var{report} is false, it must simply return a value
 @end deftypefn
 
+@node Miscellaneous Register Hooks
+@subsection Miscellaneous register hooks
+@cindex miscellaneous register hooks
+
+@deftypefn {Target Hook} bool TARGET_CALL_CLOBBERED_REGS (tree @var{fndecl}, struct hard_reg_set_container *@var{regs})
+Add any hard registers to @var{regs} that are set or clobbered by a call @var{fndecl} which are not present in the rtl representation.  This includes f.i. registers reserved for PLT, or tmp registers set or clobbered by the call, but not registers set or clobbered by the called function.  This hook returns true if it added any registers to @var{regs}.  Not defining this hook will result in conservative assumptions.
+@end deftypefn
+
 @node Varargs
 @section Implementing the Varargs Macros
 @cindex varargs implementation
diff --git a/gcc/doc/tm.texi.in b/gcc/doc/tm.texi.in
index d793d26..7022d7c 100644
--- a/gcc/doc/tm.texi.in
+++ b/gcc/doc/tm.texi.in
@@ -2720,6 +2720,7 @@ This describes the stack layout and calling conventions.
 * Profiling::
 * Tail Calls::
 * Stack Smashing Protection::
+* Miscellaneous Register Hooks::
 @end menu
 
 @node Frame Layout
@@ -3985,6 +3986,12 @@ the function prologue.  Normally, the profiling code comes after.
 
 @hook TARGET_SUPPORTS_SPLIT_STACK
 
+@node Miscellaneous Register Hooks
+@subsection Miscellaneous register hooks
+@cindex miscellaneous register hooks
+
+@hook TARGET_CALL_CLOBBERED_REGS
+
 @node Varargs
 @section Implementing the Varargs Macros
 @cindex varargs implementation
diff --git a/gcc/target.def b/gcc/target.def
index 3a64cd1..b7bb40c 100644
--- a/gcc/target.def
+++ b/gcc/target.def
@@ -5130,6 +5130,17 @@ FRAME_POINTER_REGNUM, ARG_POINTER_REGNUM, and the PIC_OFFSET_TABLE_REGNUM.",
  void, (bitmap regs),
  hook_void_bitmap)
 
+DEFHOOK
+(call_clobbered_regs,
+ "Add any hard registers to @var{regs} that are set or clobbered by a call\
+ @var{fndecl} which are not present in the rtl representation.  This includes\
+ f.i. registers reserved for PLT, or tmp registers set or clobbered by the\
+ call, but not registers set or clobbered by the called function.  This hook\
+ returns true if it added any registers to @var{regs}.  Not defining this hook\
+ will result in conservative assumptions.",
+ bool, (tree fndecl, struct hard_reg_set_container *regs),
+ NULL)
+
 /* Fill in additional registers set up by prologue into a regset.  */
 DEFHOOK
 (set_up_by_prologue,
-- 
1.8.3.2

Reply via email to