aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Henderson <rth@cygnus.com>2000-09-24 16:58:24 -0700
committerRichard Henderson <rth@gcc.gnu.org>2000-09-24 16:58:24 -0700
commit2ed4af6f2d51d7296784159f679fed504795ae9a (patch)
tree0c89694b8d0f83f1d9acd7a8f89b00224260f6c3
parentfd442cef30223941cf09068241580e3d8f3fb7ae (diff)
downloadgcc-2ed4af6f2d51d7296784159f679fed504795ae9a.zip
gcc-2ed4af6f2d51d7296784159f679fed504795ae9a.tar.gz
gcc-2ed4af6f2d51d7296784159f679fed504795ae9a.tar.bz2
ia64-protos.h: Update.
* config/ia64/ia64-protos.h: Update. * config/ia64/ia64.c (call_multiple_values_operation): Remove. (ia64_expand_call): New. (ia64_expand_prologue): Emit an alloc if we need extra input registers. (ia64_expand_epilogue): New arg sibcall_p; don't emit the return instruction if true. (struct reg_flags): Add is_sibcall. (rtx_needs_barrier): A sibcall does not use CFM et al. Ignore USEs. (emit_insn_group_barriers): Set flags.is_sibcall. Remove hacks for CODE_FOR_gr_spill_internal/CODE_FOR_gr_restore_internal. * config/ia64/ia64.h (PREDICATE_CODES): Update. * config/ia64/ia64.md (call): Use ia64_expand_call. (call_value): Likewise. (sibcall, sibcall_value): New. (call patterns): Remove extra expanders; tidy. (sibcall_epilogue): New. (set_bsp): Remove the extra USE. Put the operand inside the UNSPEC. From-SVN: r36597
-rw-r--r--gcc/ChangeLog21
-rw-r--r--gcc/config/ia64/ia64-protos.h4
-rw-r--r--gcc/config/ia64/ia64.c161
-rw-r--r--gcc/config/ia64/ia64.h1
-rw-r--r--gcc/config/ia64/ia64.md329
5 files changed, 212 insertions, 304 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 0e48841..aa4a660 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,5 +1,26 @@
2000-09-24 Richard Henderson <rth@cygnus.com>
+ * config/ia64/ia64-protos.h: Update.
+ * config/ia64/ia64.c (call_multiple_values_operation): Remove.
+ (ia64_expand_call): New.
+ (ia64_expand_prologue): Emit an alloc if we need extra input
+ registers.
+ (ia64_expand_epilogue): New arg sibcall_p; don't emit the return
+ instruction if true.
+ (struct reg_flags): Add is_sibcall.
+ (rtx_needs_barrier): A sibcall does not use CFM et al. Ignore USEs.
+ (emit_insn_group_barriers): Set flags.is_sibcall. Remove hacks
+ for CODE_FOR_gr_spill_internal/CODE_FOR_gr_restore_internal.
+ * config/ia64/ia64.h (PREDICATE_CODES): Update.
+ * config/ia64/ia64.md (call): Use ia64_expand_call.
+ (call_value): Likewise.
+ (sibcall, sibcall_value): New.
+ (call patterns): Remove extra expanders; tidy.
+ (sibcall_epilogue): New.
+ (set_bsp): Remove the extra USE. Put the operand inside the UNSPEC.
+
+2000-09-24 Richard Henderson <rth@cygnus.com>
+
* emit-rtl.c (gen_lowpart_common): Use trunc_int_for_mode.
* sibcall.c (skip_pic_restore): New.
diff --git a/gcc/config/ia64/ia64-protos.h b/gcc/config/ia64/ia64-protos.h
index 7cde4ea..839648c 100644
--- a/gcc/config/ia64/ia64-protos.h
+++ b/gcc/config/ia64/ia64-protos.h
@@ -57,7 +57,6 @@ extern int fr_reg_or_fp01_operand PARAMS((rtx, enum machine_mode));
extern int normal_comparison_operator PARAMS((rtx, enum machine_mode));
extern int adjusted_comparison_operator PARAMS((rtx, enum machine_mode));
extern int signed_inequality_operator PARAMS((rtx, enum machine_mode));
-extern int call_multiple_values_operation PARAMS((rtx, enum machine_mode));
extern int destination_operand PARAMS((rtx, enum machine_mode));
extern int not_postinc_memory_operand PARAMS((rtx, enum machine_mode));
extern int predicate_operator PARAMS((rtx, enum machine_mode));
@@ -73,10 +72,11 @@ extern rtx ia64_gp_save_reg PARAMS((int));
extern rtx ia64_split_timode PARAMS((rtx[], rtx, rtx));
extern rtx spill_tfmode_operand PARAMS((rtx, int));
extern rtx ia64_expand_compare PARAMS((enum rtx_code, enum machine_mode));
+extern void ia64_expand_call PARAMS((rtx, rtx, rtx, int));
extern HOST_WIDE_INT ia64_initial_elimination_offset PARAMS((int, int));
extern void ia64_expand_prologue PARAMS((void));
-extern void ia64_expand_epilogue PARAMS((void));
+extern void ia64_expand_epilogue PARAMS((int));
extern void ia64_function_prologue PARAMS((FILE *, int));
extern void ia64_function_epilogue PARAMS((FILE *, int));
diff --git a/gcc/config/ia64/ia64.c b/gcc/config/ia64/ia64.c
index 31c54bc..a6de784 100644
--- a/gcc/config/ia64/ia64.c
+++ b/gcc/config/ia64/ia64.c
@@ -676,41 +676,6 @@ signed_inequality_operator (op, mode)
|| code == LE || code == LT));
}
-/* Return 1 if OP is a call returning an HFA. It is known to be a PARALLEL
- and the first section has already been tested. */
-
-int
-call_multiple_values_operation (op, mode)
- rtx op;
- enum machine_mode mode ATTRIBUTE_UNUSED;
-{
- int count = XVECLEN (op, 0) - 2;
- int i;
- unsigned int dest_regno;
-
- /* Perform a quick check so we don't block up below. */
- if (count <= 1
- || GET_CODE (XVECEXP (op, 0, 0)) != SET
- || GET_CODE (SET_DEST (XVECEXP (op, 0, 0))) != REG
- || GET_CODE (SET_SRC (XVECEXP (op, 0, 0))) != CALL)
- return 0;
-
- dest_regno = REGNO (SET_DEST (XVECEXP (op, 0, 0)));
-
- for (i = 1; i < count; i++)
- {
- rtx elt = XVECEXP (op, 0, i + 2);
-
- if (GET_CODE (elt) != SET
- || GET_CODE (SET_SRC (elt)) != CALL
- || GET_CODE (SET_DEST (elt)) != REG
- || REGNO (SET_DEST (elt)) != dest_regno + i)
- return 0;
- }
-
- return 1;
-}
-
/* Return 1 if this operator is valid for predication. */
int
@@ -1044,6 +1009,98 @@ ia64_expand_compare (code, mode)
return gen_rtx_fmt_ee (code, mode, cmp, const0_rtx);
}
+
+/* Emit the appropriate sequence for a call. */
+
+void
+ia64_expand_call (retval, addr, nextarg, sibcall_p)
+ rtx retval;
+ rtx addr;
+ rtx nextarg;
+ int sibcall_p;
+{
+ rtx insn, b0, gp_save, narg_rtx;
+ int narg;
+
+ addr = XEXP (addr, 0);
+ b0 = gen_rtx_REG (DImode, R_BR (0));
+
+ if (! nextarg)
+ narg = 0;
+ else if (IN_REGNO_P (REGNO (nextarg)))
+ narg = REGNO (nextarg) - IN_REG (0);
+ else
+ narg = REGNO (nextarg) - OUT_REG (0);
+ narg_rtx = GEN_INT (narg);
+
+ if (TARGET_NO_PIC || TARGET_AUTO_PIC)
+ {
+ if (sibcall_p)
+ insn = gen_sibcall_nopic (addr, narg_rtx, b0);
+ else if (! retval)
+ insn = gen_call_nopic (addr, narg_rtx, b0);
+ else
+ insn = gen_call_value_nopic (retval, addr, narg_rtx, b0);
+ emit_call_insn (insn);
+ return;
+ }
+
+ if (sibcall_p)
+ gp_save = NULL_RTX;
+ else
+ gp_save = ia64_gp_save_reg (setjmp_operand (addr, VOIDmode));
+
+ /* If this is an indirect call, then we have the address of a descriptor. */
+ if (! symbolic_operand (addr, VOIDmode))
+ {
+ rtx dest;
+
+ if (! sibcall_p)
+ emit_move_insn (gp_save, pic_offset_table_rtx);
+
+ dest = force_reg (DImode, gen_rtx_MEM (DImode, addr));
+ emit_move_insn (pic_offset_table_rtx,
+ gen_rtx_MEM (DImode, plus_constant (addr, 8)));
+
+ if (sibcall_p)
+ insn = gen_sibcall_pic (dest, narg_rtx, b0);
+ else if (! retval)
+ insn = gen_call_pic (dest, narg_rtx, b0);
+ else
+ insn = gen_call_value_pic (retval, dest, narg_rtx, b0);
+ emit_call_insn (insn);
+
+ if (! sibcall_p)
+ emit_move_insn (pic_offset_table_rtx, gp_save);
+ }
+ else if (TARGET_CONST_GP)
+ {
+ if (sibcall_p)
+ insn = gen_sibcall_nopic (addr, narg_rtx, b0);
+ else if (! retval)
+ insn = gen_call_nopic (addr, narg_rtx, b0);
+ else
+ insn = gen_call_value_nopic (retval, addr, narg_rtx, b0);
+ emit_call_insn (insn);
+ }
+ else
+ {
+ if (sibcall_p)
+ emit_call_insn (gen_sibcall_pic (addr, narg_rtx, b0));
+ else
+ {
+ emit_move_insn (gp_save, pic_offset_table_rtx);
+
+ if (! retval)
+ insn = gen_call_pic (addr, narg_rtx, b0);
+ else
+ insn = gen_call_value_pic (retval, addr, narg_rtx, b0);
+ emit_call_insn (insn);
+
+ emit_move_insn (pic_offset_table_rtx, gp_save);
+ }
+ }
+}
/* Begin the assembly file. */
@@ -1819,7 +1876,8 @@ ia64_expand_prologue ()
/* We don't need an alloc instruction if we've used no outputs or locals. */
if (current_frame_info.n_local_regs == 0
- && current_frame_info.n_output_regs == 0)
+ && current_frame_info.n_output_regs == 0
+ && current_frame_info.n_input_regs <= current_function_args_info.words)
{
/* If there is no alloc, but there are input registers used, then we
need a .regstk directive. */
@@ -2090,7 +2148,8 @@ ia64_expand_prologue ()
insn to prevent such scheduling. */
void
-ia64_expand_epilogue ()
+ia64_expand_epilogue (sibcall_p)
+ int sibcall_p;
{
rtx insn, reg, alt_reg, ar_unat_save_reg;
int regno, alt_regno, cfa_off;
@@ -2303,7 +2362,8 @@ ia64_expand_epilogue ()
if (cfun->machine->ia64_eh_epilogue_bsp)
emit_insn (gen_set_bsp (cfun->machine->ia64_eh_epilogue_bsp));
- emit_jump_insn (gen_return_internal (gen_rtx_REG (DImode, BR_REG (0))));
+ if (! sibcall_p)
+ emit_jump_insn (gen_return_internal (gen_rtx_REG (DImode, BR_REG (0))));
}
/* Return 1 if br.ret can do all the work required to return from a
@@ -3642,6 +3702,7 @@ struct reg_flags
unsigned int is_branch : 1; /* Is register used as part of a branch? */
unsigned int is_and : 1; /* Is register used as part of and.orcm? */
unsigned int is_or : 1; /* Is register used as part of or.andcm? */
+ unsigned int is_sibcall : 1; /* Is this a sibling or normal call? */
};
static void rws_update PARAMS ((struct reg_write_state *, int,
@@ -3935,9 +3996,7 @@ rtx_needs_barrier (x, flags, pred)
/* Avoid multiple register writes, in case this is a pattern with
multiple CALL rtx. This avoids an abort in rws_access_reg. */
- /* ??? This assumes that no rtx other than CALL/RETURN sets REG_AR_CFM,
- and that we don't have predicated calls/returns. */
- if (! rws_insn[REG_AR_CFM].write_count)
+ if (! flags.is_sibcall && ! rws_insn[REG_AR_CFM].write_count)
{
new_flags.is_write = 1;
need_barrier |= rws_access_regno (REG_RP, new_flags, pred);
@@ -3968,12 +4027,7 @@ rtx_needs_barrier (x, flags, pred)
return need_barrier;
case CLOBBER:
-#if 0
case USE:
- /* We must handle USE here in case it occurs within a PARALLEL.
- For instance, the mov ar.pfs= instruction has a USE which requires
- a barrier between it and an immediately preceeding alloc. */
-#endif
/* Clobber & use are for earlier compiler-phases only. */
break;
@@ -4096,6 +4150,7 @@ rtx_needs_barrier (x, flags, pred)
break;
case 7: /* pred_rel_mutex */
+ case 9: /* pic call */
case 12: /* mf */
case 19: /* fetchadd_acq */
case 20: /* mov = ar.bsp */
@@ -4185,6 +4240,7 @@ rtx_needs_barrier (x, flags, pred)
default:
abort ();
}
+ break;
}
return need_barrier;
}
@@ -4229,6 +4285,7 @@ emit_insn_group_barriers (insns)
case CALL_INSN:
flags.is_branch = 1;
+ flags.is_sibcall = SIBLING_CALL_P (insn);
memset (rws_insn, 0, sizeof (rws_insn));
need_barrier = rtx_needs_barrier (PATTERN (insn), flags, 0);
@@ -4300,18 +4357,6 @@ emit_insn_group_barriers (insns)
pat = XVECEXP (pat, 0, 1);
break;
- /* We include ar.unat in the rtl pattern so that sched2
- does not move the ar.unat save/restore after/before
- a gr spill/fill. However, we special case these
- insns based on their unspec number so as to model
- their precise ar.unat bit operations. If we pass on
- the use/clobber of the whole ar.unat register we'll
- waste this effort. */
- case CODE_FOR_gr_spill_internal:
- case CODE_FOR_gr_restore_internal:
- pat = XVECEXP (pat, 0, 0);
- break;
-
/* Doesn't generate code. */
case CODE_FOR_pred_rel_mutex:
continue;
diff --git a/gcc/config/ia64/ia64.h b/gcc/config/ia64/ia64.h
index f2402a3..6126fa6 100644
--- a/gcc/config/ia64/ia64.h
+++ b/gcc/config/ia64/ia64.h
@@ -2697,7 +2697,6 @@ do { \
{ "normal_comparison_operator", {EQ, NE, GT, LE, GTU, LEU}}, \
{ "adjusted_comparison_operator", {LT, GE, LTU, GEU}}, \
{ "signed_inequality_operator", {GE, GT, LE, LT}}, \
-{ "call_multiple_values_operation", {PARALLEL}}, \
{ "predicate_operator", {NE, EQ}}, \
{ "ar_lc_reg_operand", {REG}}, \
{ "ar_ccv_reg_operand", {REG}}, \
diff --git a/gcc/config/ia64/ia64.md b/gcc/config/ia64/ia64.md
index 45479a2..11b14c0 100644
--- a/gcc/config/ia64/ia64.md
+++ b/gcc/config/ia64/ia64.md
@@ -62,6 +62,7 @@
;; 5 recip_approx
;; 7 pred_rel_mutex
;; 8 popcnt
+;; 9 pic call
;; 12 mf
;; 13 cmpxchg_acq
;; 19 fetchadd_acq
@@ -4708,82 +4709,27 @@
""
"
{
- /* ??? Stripping off the MEM isn't correct. Will lose alias info. */
- rtx addr = XEXP (operands[0], 0);
- enum machine_mode mode = GET_MODE (addr);
-
- if (TARGET_NO_PIC || TARGET_AUTO_PIC)
- emit_call_insn (gen_call_internal (addr, operands[1],
- gen_rtx_REG (DImode, R_BR (0))));
-
- /* If this is an indirect call, then we have the address of a descriptor. */
- else if (! symbolic_operand (addr, mode))
- emit_insn (gen_indirect_call_pic (addr, operands[1]));
- else if (TARGET_CONST_GP)
- emit_call_insn (gen_call_internal (addr, operands[1],
- gen_rtx_REG (DImode, R_BR (0))));
- else
- emit_insn (gen_call_pic (addr, operands[1]));
-
+ ia64_expand_call (NULL_RTX, operands[0], operands[2], 0);
DONE;
}")
-(define_expand "indirect_call_pic"
- [(set (match_dup 2) (reg:DI 1))
- (set (match_dup 3) (mem:DI (match_operand 0 "" "")))
- (set (match_dup 4) (plus:DI (match_dup 0) (const_int 8)))
- (set (reg:DI 1) (mem:DI (match_dup 4)))
- (parallel [(call (mem:DI (match_dup 3)) (match_operand 1 "" ""))
- (use (reg:DI 1))
- (clobber (reg:DI 320))])
- (set (reg:DI 1) (match_dup 2))]
- ""
- "
-{
- operands[2] = ia64_gp_save_reg (0);
- operands[3] = gen_reg_rtx (DImode);
- operands[4] = gen_reg_rtx (DImode);
-}")
-
-;; ??? Saving/restoring the GP register is not needed if we are calling
-;; a function in the same module.
-
-(define_expand "call_pic"
- [(set (match_dup 2) (reg:DI 1))
- (parallel [(call (mem:DI (match_operand 0 "" "")) (match_operand 1 "" ""))
- (use (reg:DI 1))
- (clobber (reg:DI 320))])
- (set (reg:DI 1) (match_dup 2))]
+(define_expand "sibcall"
+ [(use (match_operand:DI 0 "" ""))
+ (use (match_operand 1 "" ""))
+ (use (match_operand 2 "" ""))
+ (use (match_operand 3 "" ""))]
""
"
{
- /* ??? Using setjmp_operand is an unsatisfying solution. Should rethink. */
- operands[2] = ia64_gp_save_reg (setjmp_operand (XEXP (operands[0], 0),
- VOIDmode));
+ ia64_expand_call (NULL_RTX, operands[0], operands[2], 1);
+ DONE;
}")
-(define_insn "call_internal"
- [(call (mem:DI (match_operand:DI 0 "call_operand" "bi"))
- (match_operand 1 "" ""))
- (clobber (match_operand:DI 2 "register_operand" "=b"))]
- ""
- "br.call%+.many %2 = %0"
- [(set_attr "type" "B")])
-
-(define_insn "*call_internal1"
- [(call (mem:DI (match_operand:DI 0 "call_operand" "bi"))
- (match_operand 1 "" ""))
- (use (reg:DI 1))
- (clobber (match_operand:DI 2 "register_operand" "=b"))]
- ""
- "br.call%+.many %2 = %0"
- [(set_attr "type" "B")])
-
;; Subroutine call instruction returning a value. Operand 0 is the hard
-;; register in which the value is returned. There are three more operands, the
-;; same as the three operands of the `call' instruction (but with numbers
+;; register in which the value is returned. There are three more operands,
+;; the same as the three operands of the `call' instruction (but with numbers
;; increased by one).
-
+;;
;; Subroutines that return `BLKmode' objects use the `call' insn.
(define_expand "call_value"
@@ -4795,187 +4741,23 @@
""
"
{
- /* ??? Stripping off the MEM isn't correct. Will lose alias info. */
- rtx addr = XEXP (operands[1], 0);
- enum machine_mode mode = GET_MODE (addr);
-
- if (TARGET_NO_PIC || TARGET_AUTO_PIC)
- emit_call_insn (gen_call_value_internal (operands[0], addr, operands[2],
- gen_rtx_REG (DImode, R_BR (0))));
-
- /* If this is an indirect call, then we have the address of a descriptor. */
- else if (! symbolic_operand (addr, mode))
- {
- /* This is for HFA returns. */
- if (GET_CODE (operands[0]) == PARALLEL)
- emit_insn (gen_indirect_call_multiple_values_pic (operands[0], addr,
- operands[2]));
- else
- emit_insn (gen_indirect_call_value_pic (operands[0], addr,
- operands[2]));
- }
- else if (TARGET_CONST_GP)
- emit_call_insn (gen_call_value_internal (operands[0], addr, operands[2],
- gen_rtx_REG (DImode, R_BR (0))));
- /* This is for HFA returns. */
- else if (GET_CODE (operands[0]) == PARALLEL)
- emit_insn (gen_call_multiple_values_pic (operands[0], addr, operands[2]));
- else
- emit_insn (gen_call_value_pic (operands[0], addr, operands[2]));
-
+ ia64_expand_call (operands[0], operands[1], operands[3], 0);
DONE;
}")
-(define_expand "indirect_call_value_pic"
- [(set (match_dup 3) (reg:DI 1))
- (set (match_dup 4) (mem:DI (match_operand 1 "" "")))
- (set (match_dup 5) (plus:DI (match_dup 1) (const_int 8)))
- (set (reg:DI 1) (mem:DI (match_dup 5)))
- (parallel [(set (match_operand 0 "" "")
- (call (mem:DI (match_dup 4)) (match_operand 2 "" "")))
- (use (reg:DI 1))
- (clobber (reg:DI 320))])
- (set (reg:DI 1) (match_dup 3))]
- ""
- "
-{
- operands[3] = ia64_gp_save_reg (0);
- operands[4] = gen_reg_rtx (DImode);
- operands[5] = gen_reg_rtx (DImode);
-}")
-
-(define_expand "indirect_call_multiple_values_pic"
- [(set (match_dup 3) (reg:DI 1))
- (set (match_dup 4) (mem:DI (match_operand 1 "" "")))
- (set (match_dup 5) (plus:DI (match_dup 1) (const_int 8)))
- (set (reg:DI 1) (mem:DI (match_dup 5)))
- (match_par_dup 6 [(set (match_operand 0 "" "")
- (call (mem:DI (match_dup 4))
- (match_operand 2 "" "")))
- (use (reg:DI 1))
- (clobber (reg:DI 320))])
- (set (reg:DI 1) (match_dup 3))]
- ""
- "
-{
- int count;
- int i;
- rtx call;
-
- operands[3] = ia64_gp_save_reg (0);
- operands[4] = gen_reg_rtx (DImode);
- operands[5] = gen_reg_rtx (DImode);
-
- /* This code is the same as the code in call_multiple_values_pic, except
- that op3 was replaced with op6 and op1 was replaced with op4. */
- call = gen_rtx_CALL (VOIDmode, gen_rtx_MEM (DImode, operands[4]),
- operands[2]);
-
- count = XVECLEN (operands[0], 0);
- operands[6] = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (count + 2));
-
- XVECEXP (operands[6], 0, 0)
- = gen_rtx_SET (VOIDmode, XEXP (XVECEXP (operands[0], 0, 0), 0), call);
-
- XVECEXP (operands[6], 0, 1)
- = gen_rtx_USE (DImode, gen_rtx_REG (DImode, GR_REG (1)));
- XVECEXP (operands[6], 0, 2)
- = gen_rtx_CLOBBER (DImode, gen_rtx_REG (DImode, BR_REG (0)));
-
- for (i = 1; i < count; i++)
- XVECEXP (operands[6], 0, i + 2)
- = gen_rtx_SET (VOIDmode, XEXP (XVECEXP (operands[0], 0, i), 0), call);
-
-}")
-
-;; ??? Saving/restoring the GP register is not needed if we are calling
-;; a function in the same module.
-
-(define_expand "call_value_pic"
- [(set (match_dup 3) (reg:DI 1))
- (parallel [(set (match_operand 0 "" "")
- (call (mem:DI (match_operand 1 "" ""))
- (match_operand 2 "" "")))
- (use (reg:DI 1))
- (clobber (reg:DI 320))])
- (set (reg:DI 1) (match_dup 3))]
- ""
- "
-{
- /* ??? Using setjmp_operand is an unsatisfying solution. Should rethink. */
- operands[3] = ia64_gp_save_reg (setjmp_operand (XEXP (operands[1], 0),
- VOIDmode));
-}")
-
-;; ??? Saving/restoring the GP register is not needed if we are calling
-;; a function in the same module.
-
-(define_expand "call_multiple_values_pic"
- [(set (match_dup 4) (reg:DI 1))
- (match_par_dup 3 [(set (match_operand 0 "" "")
- (call (mem:DI (match_operand 1 "" ""))
- (match_operand 2 "" "")))
- (use (reg:DI 1))
- (clobber (reg:DI 320))])
- (set (reg:DI 1) (match_dup 4))]
+(define_expand "sibcall_value"
+ [(use (match_operand 0 "" ""))
+ (use (match_operand:DI 1 "" ""))
+ (use (match_operand 2 "" ""))
+ (use (match_operand 3 "" ""))
+ (use (match_operand 4 "" ""))]
""
"
{
- int count;
- int i;
- rtx call;
-
- operands[4] = ia64_gp_save_reg (0);
-
- call = gen_rtx_CALL (VOIDmode, gen_rtx_MEM (DImode, operands[1]),
- operands[2]);
-
- count = XVECLEN (operands[0], 0);
- operands[3] = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (count + 2));
-
- XVECEXP (operands[3], 0, 0)
- = gen_rtx_SET (VOIDmode, XEXP (XVECEXP (operands[0], 0, 0), 0), call);
-
- XVECEXP (operands[3], 0, 1)
- = gen_rtx_USE (DImode, gen_rtx_REG (DImode, GR_REG (1)));
- XVECEXP (operands[3], 0, 2)
- = gen_rtx_CLOBBER (DImode, gen_rtx_REG (DImode, BR_REG (0)));
-
- for (i = 1; i < count; i++)
- XVECEXP (operands[3], 0, i + 2)
- = gen_rtx_SET (VOIDmode, XEXP (XVECEXP (operands[0], 0, i), 0), call);
+ ia64_expand_call (operands[0], operands[1], operands[3], 1);
+ DONE;
}")
-(define_insn "call_value_internal"
- [(set (match_operand 0 "register_operand" "=rf")
- (call (mem:DI (match_operand:DI 1 "call_operand" "bi"))
- (match_operand 2 "" "")))
- (clobber (match_operand:DI 3 "register_operand" "=b"))]
- ""
- "br.call%+.many %3 = %1"
- [(set_attr "type" "B")])
-
-(define_insn "*call_value_internal1"
- [(set (match_operand 0 "register_operand" "=rf")
- (call (mem:DI (match_operand:DI 1 "call_operand" "bi"))
- (match_operand 2 "" "")))
- (use (reg:DI 1))
- (clobber (match_operand:DI 3 "register_operand" "=b"))]
- ""
- "br.call%+.many %3 = %1"
- [(set_attr "type" "B")])
-
-(define_insn "*call_multiple_values_internal1"
- [(match_parallel 0 "call_multiple_values_operation"
- [(set (match_operand 1 "register_operand" "=rf")
- (call (mem:DI (match_operand:DI 2 "call_operand" "bi"))
- (match_operand 3 "" "")))
- (use (reg:DI 1))
- (clobber (match_operand:DI 4 "register_operand" "=b"))])]
- ""
- "br.call%+.many %4 = %2"
- [(set_attr "type" "B")])
-
;; Call subroutine returning any type.
(define_expand "untyped_call"
@@ -5005,6 +4787,59 @@
DONE;
}")
+(define_insn "call_nopic"
+ [(call (mem:DI (match_operand:DI 0 "call_operand" "bi"))
+ (match_operand 1 "" ""))
+ (clobber (match_operand:DI 2 "register_operand" "=b"))]
+ ""
+ "br.call%+.many %2 = %0"
+ [(set_attr "type" "B")])
+
+(define_insn "call_value_nopic"
+ [(set (match_operand 0 "" "")
+ (call (mem:DI (match_operand:DI 1 "call_operand" "bi"))
+ (match_operand 2 "" "")))
+ (clobber (match_operand:DI 3 "register_operand" "=b"))]
+ ""
+ "br.call%+.many %3 = %1"
+ [(set_attr "type" "B")])
+
+(define_insn "sibcall_nopic"
+ [(call (mem:DI (match_operand:DI 0 "call_operand" "bi"))
+ (match_operand 1 "" ""))
+ (use (match_operand:DI 2 "register_operand" "=b"))]
+ ""
+ "br%+.many %0"
+ [(set_attr "type" "B")])
+
+(define_insn "call_pic"
+ [(call (mem:DI (match_operand:DI 0 "call_operand" "bi"))
+ (match_operand 1 "" ""))
+ (use (unspec [(reg:DI 1)] 9))
+ (clobber (match_operand:DI 2 "register_operand" "=b"))]
+ ""
+ "br.call%+.many %2 = %0"
+ [(set_attr "type" "B")])
+
+(define_insn "call_value_pic"
+ [(set (match_operand 0 "" "")
+ (call (mem:DI (match_operand:DI 1 "call_operand" "bi"))
+ (match_operand 2 "" "")))
+ (use (unspec [(reg:DI 1)] 9))
+ (clobber (match_operand:DI 3 "register_operand" "=b"))]
+ ""
+ "br.call%+.many %3 = %1"
+ [(set_attr "type" "B")])
+
+(define_insn "sibcall_pic"
+ [(call (mem:DI (match_operand:DI 0 "call_operand" "bi"))
+ (match_operand 1 "" ""))
+ (use (unspec [(reg:DI 1)] 9))
+ (use (match_operand:DI 2 "register_operand" "=b"))]
+ ""
+ "br%+.many %0"
+ [(set_attr "type" "B")])
+
(define_insn "return_internal"
[(return)
(use (match_operand:DI 0 "register_operand" "b"))]
@@ -5093,11 +4928,20 @@
}")
(define_expand "epilogue"
- [(const_int 2)]
+ [(return)]
+ ""
+ "
+{
+ ia64_expand_epilogue (0);
+ DONE;
+}")
+
+(define_expand "sibcall_epilogue"
+ [(return)]
""
"
{
- ia64_expand_epilogue ();
+ ia64_expand_epilogue (1);
DONE;
}")
@@ -5200,8 +5044,7 @@
[(set_attr "type" "I")])
(define_insn "set_bsp"
- [(unspec_volatile [(const_int 0)] 5)
- (use (match_operand:DI 0 "register_operand" "r"))]
+ [(unspec_volatile [(match_operand:DI 0 "register_operand" "r")] 5)]
""
"flushrs\;mov r19=ar.rsc\;;;\;and r19=0x1c,r19\;;;\;mov ar.rsc=r19\;;;\;mov ar.bspstore=%0\;;;\;or r19=0x3,r19\;;;\;loadrs\;invala\;;;\;mov ar.rsc=r19"
[(set_attr "type" "unknown")