mirror of
git://gcc.gnu.org/git/gcc.git
synced 2024-12-16 20:19:48 +08:00
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
This commit is contained in:
parent
fd442cef30
commit
2ed4af6f2d
@ -1,3 +1,24 @@
|
||||
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.
|
||||
|
@ -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));
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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}}, \
|
||||
|
@ -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))]
|
||||
(define_expand "sibcall"
|
||||
[(use (match_operand:DI 0 "" ""))
|
||||
(use (match_operand 1 "" ""))
|
||||
(use (match_operand 2 "" ""))
|
||||
(use (match_operand 3 "" ""))]
|
||||
""
|
||||
"
|
||||
{
|
||||
operands[2] = ia64_gp_save_reg (0);
|
||||
operands[3] = gen_reg_rtx (DImode);
|
||||
operands[4] = gen_reg_rtx (DImode);
|
||||
ia64_expand_call (NULL_RTX, operands[0], operands[2], 1);
|
||||
DONE;
|
||||
}")
|
||||
|
||||
;; ??? 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))]
|
||||
""
|
||||
"
|
||||
{
|
||||
/* ??? Using setjmp_operand is an unsatisfying solution. Should rethink. */
|
||||
operands[2] = ia64_gp_save_reg (setjmp_operand (XEXP (operands[0], 0),
|
||||
VOIDmode));
|
||||
}")
|
||||
|
||||
(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))]
|
||||
(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 "" ""))]
|
||||
""
|
||||
"
|
||||
{
|
||||
operands[3] = ia64_gp_save_reg (0);
|
||||
operands[4] = gen_reg_rtx (DImode);
|
||||
operands[5] = gen_reg_rtx (DImode);
|
||||
ia64_expand_call (operands[0], operands[1], operands[3], 1);
|
||||
DONE;
|
||||
}")
|
||||
|
||||
(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))]
|
||||
""
|
||||
"
|
||||
{
|
||||
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);
|
||||
}")
|
||||
|
||||
(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 ();
|
||||
ia64_expand_epilogue (0);
|
||||
DONE;
|
||||
}")
|
||||
|
||||
(define_expand "sibcall_epilogue"
|
||||
[(return)]
|
||||
""
|
||||
"
|
||||
{
|
||||
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")
|
||||
|
Loading…
Reference in New Issue
Block a user