This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] Improve length estimate for direct calls on PA


This patch improves the length estimate for direct calls on the PA.

When C++ changed to using a local alias for methods jumped and called
from thunks, we had to use different call sequences for local calls.
These are a little shorter than the sequences we had been using before.
This patch mainly is an update to attr_length_call to allow it to
provide better length estimates for local calls.

There is also a small improvement in the length estimate for call
sequences that always fill the delay slot.

Tested on hppa-unknown-linux-gnu, hppa2.0w-hp-hpux11.11 and
hppa64-hp-hpux11.11.  Applied to the trunk.

Dave
-- 
J. David Anglin                                  dave.anglin@nrc-cnrc.gc.ca
National Research Council of Canada              (613) 990-0752 (FAX: 952-6602)

2003-08-14  John David Anglin  <dave.anglin@nrc-cnrc.gc.ca>

	* pa.c (pa_adjust_insn_length): Delete adjustment for delay slot in
	direct calls.
	(attr_length_call): Include it here.  Improve length estimate for
	local calls.
	(output_call): Use targetm.binds_local_p.

Index: config/pa/pa.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/pa/pa.c,v
retrieving revision 1.220
diff -u -3 -p -r1.220 pa.c
--- config/pa/pa.c	9 Aug 2003 16:40:33 -0000	1.220
+++ config/pa/pa.c	14 Aug 2003 17:33:58 -0000
@@ -4417,23 +4417,9 @@ pa_adjust_insn_length (insn, length)
 {
   rtx pat = PATTERN (insn);
 
-  /* Call insns which are *not* indirect and have unfilled delay slots.  */
-  if (GET_CODE (insn) == CALL_INSN)
-    {
-
-      if (GET_CODE (XVECEXP (pat, 0, 0)) == CALL
-	  && GET_CODE (XEXP (XEXP (XVECEXP (pat, 0, 0), 0), 0)) == SYMBOL_REF)
-	return 4;
-      else if (GET_CODE (XVECEXP (pat, 0, 0)) == SET
-	       && GET_CODE (XEXP (XEXP (XEXP (XVECEXP (pat, 0, 0), 1), 0), 0))
-		  == SYMBOL_REF)
-	return 4;
-      else
-	return 0;
-    }
-  /* Jumps inside switch tables which have unfilled delay slots
-     also need adjustment.  */
-  else if (GET_CODE (insn) == JUMP_INSN
+  /* Jumps inside switch tables which have unfilled delay slots need
+     adjustment.  */
+  if (GET_CODE (insn) == JUMP_INSN
 	   && simplejump_p (insn)
 	   && GET_MODE (insn) == SImode)
     return 4;
@@ -6758,77 +6744,95 @@ output_millicode_call (insn, call_dest)
 
 /* Return the attribute length of the call instruction INSN.  The SIBCALL
    flag indicates whether INSN is a regular call or a sibling call.  The
-   length returned must be longer than the code generated by output_call.
-   When the target supports jumps in the delay slot, we need an extra
-   four bytes to handle the situation where the jump can't reach its
-   destination.  */
+   length returned must be longer than the code actually generated by
+   output_call.  Since branch shortening is done before delay branch
+   sequencing, there is no way to determine whether or not the delay
+   slot will be filled during branch shortening.  Even when the delay
+   slot is filled, we may have to add a nop if the delay slot contains
+   a branch that can't reach its target.  Thus, we always have to include
+   the delay slot in the length estimate.  This used to be done in
+   pa_adjust_insn_length but we do it here now as some sequences always
+   fill the delay slot and we can save four bytes in the estimate for
+   these sequences.  */
 
 int
 attr_length_call (insn, sibcall)
      rtx insn;
      int sibcall;
 {
+  int local_call;
+  rtx call_dest;
+  tree call_decl;
+  int length = 0;
+  rtx pat = PATTERN (insn);
   unsigned long distance = -1;
-  unsigned long total = IN_NAMED_SECTION_P (cfun->decl) ? 0 : total_code_bytes;
 
   if (INSN_ADDRESSES_SET_P ())
     {
+      unsigned long total;
+
+      total = IN_NAMED_SECTION_P (cfun->decl) ? 0 : total_code_bytes;
       distance = (total + insn_current_reference_address (insn));
       if (distance < total)
 	distance = -1;
     }
 
-  if (TARGET_64BIT)
-    {
-      if (!TARGET_LONG_CALLS
-	  && ((!sibcall && distance < 7600000) || distance < 240000))
-	return 8;
-
-      return (sibcall ? 28 : 24);
-    }
+  /* Determine if this is a local call.  */
+  if (GET_CODE (XVECEXP (pat, 0, 0)) == CALL)
+    call_dest = XEXP (XEXP (XVECEXP (pat, 0, 0), 0), 0);
   else
-    {
-      if (!TARGET_LONG_CALLS
-	  && ((TARGET_PA_20 && !sibcall && distance < 7600000)
-	      || distance < 240000))
-	return 8;
+    call_dest = XEXP (XEXP (XEXP (XVECEXP (pat, 0, 0), 1), 0), 0);
 
-      if (TARGET_LONG_ABS_CALL && !flag_pic)
-	return 16;
+  call_decl = SYMBOL_REF_DECL (call_dest);
+  local_call = call_decl && (*targetm.binds_local_p) (call_decl);
 
-      if ((TARGET_SOM && TARGET_LONG_PIC_SDIFF_CALL)
-	  || (TARGET_GAS && TARGET_LONG_PIC_PCREL_CALL))
-	{
-	  if (TARGET_PA_20)
-	    return 20;
+  /* pc-relative branch.  */
+  if (!TARGET_LONG_CALLS
+      && ((TARGET_PA_20 && !sibcall && distance < 7600000)
+	  || distance < 240000))
+    length += 8;
 
-	  return 28;
-	}
-      else
-	{
-	  int length = 28;
+  /* 64-bit plabel sequence.  */
+  else if (TARGET_64BIT && !local_call)
+    length += sibcall ? 28 : 24;
 
-	  if (TARGET_SOM)
-	    length += length_fp_args (insn);
+  /* non-pic long absolute branch sequence.  */
+  else if ((TARGET_LONG_ABS_CALL || local_call) && !flag_pic)
+    length += 12;
 
-	  if (flag_pic)
-	    length += 4;
+  /* long pc-relative branch sequence.  */
+  else if ((TARGET_SOM && TARGET_LONG_PIC_SDIFF_CALL)
+	   || (TARGET_64BIT && !TARGET_GAS)
+	   || (TARGET_GAS && (TARGET_LONG_PIC_PCREL_CALL || local_call)))
+    {
+      length += 20;
 
-	  if (!sibcall)
-	    length += 4;
+      if (!TARGET_PA_20 && !TARGET_NO_SPACE_REGS)
+	length += 8;
+    }
 
-	  if (TARGET_PA_20)
-	    return length;
+  /* 32-bit plabel sequence.  */
+  else
+    {
+      length += 32;
 
-	  if (!TARGET_NO_SPACE_REGS)
-	    length += 8;
+      if (TARGET_SOM)
+	length += length_fp_args (insn);
 
+      if (flag_pic)
+	length += 4;
+
+      if (!TARGET_PA_20)
+	{
 	  if (!sibcall)
 	    length += 8;
 
-	  return length;
+	  if (!TARGET_NO_SPACE_REGS)
+	    length += 8;
 	}
     }
+
+  return length;
 }
 
 /* INSN is a function call.  It may have an unconditional jump
@@ -6846,7 +6850,7 @@ output_call (insn, call_dest, sibcall)
   int delay_slot_filled = 0;
   int seq_length = dbr_sequence_length ();
   tree call_decl = SYMBOL_REF_DECL (call_dest);
-  int local_call = call_decl && !TREE_PUBLIC (call_decl);
+  int local_call = call_decl && (*targetm.binds_local_p) (call_decl);
   rtx xoperands[2];
 
   xoperands[0] = call_dest;


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]