aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorJohn David Anglin <dave.anglin@nrc-cnrc.gc.ca>2003-08-14 18:06:12 +0000
committerJohn David Anglin <danglin@gcc.gnu.org>2003-08-14 18:06:12 +0000
commit3256230283e35950672c596e3a9bbe68967941d1 (patch)
treecdd7610dcd50fe973582972d66a316d8c780186c /gcc
parentdaa027cc473c361231dd4aa9f362674fe2c9a0fb (diff)
downloadgcc-3256230283e35950672c596e3a9bbe68967941d1.zip
gcc-3256230283e35950672c596e3a9bbe68967941d1.tar.gz
gcc-3256230283e35950672c596e3a9bbe68967941d1.tar.bz2
pa.c (pa_adjust_insn_length): Delete adjustment for delay slot in direct calls.
* 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. From-SVN: r70441
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog8
-rw-r--r--gcc/config/pa/pa.c122
2 files changed, 71 insertions, 59 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index cf86c0a..565fc99 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,11 @@
+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.
+
2003-08-14 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
* builtins.c (CASE_MATHFN): New helper macro.
diff --git a/gcc/config/pa/pa.c b/gcc/config/pa/pa.c
index eb875f8..88c3d08 100644
--- a/gcc/config/pa/pa.c
+++ b/gcc/config/pa/pa.c
@@ -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;