diff options
author | Richard Henderson <rth@cygnus.com> | 2000-09-24 16:58:24 -0700 |
---|---|---|
committer | Richard Henderson <rth@gcc.gnu.org> | 2000-09-24 16:58:24 -0700 |
commit | 2ed4af6f2d51d7296784159f679fed504795ae9a (patch) | |
tree | 0c89694b8d0f83f1d9acd7a8f89b00224260f6c3 | |
parent | fd442cef30223941cf09068241580e3d8f3fb7ae (diff) | |
download | gcc-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/ChangeLog | 21 | ||||
-rw-r--r-- | gcc/config/ia64/ia64-protos.h | 4 | ||||
-rw-r--r-- | gcc/config/ia64/ia64.c | 161 | ||||
-rw-r--r-- | gcc/config/ia64/ia64.h | 1 | ||||
-rw-r--r-- | gcc/config/ia64/ia64.md | 329 |
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") |