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]

ia64 sibcall support


        * 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.

Index: ia64-protos.h
===================================================================
RCS file: /cvs/gcc/egcs/gcc/config/ia64/ia64-protos.h,v
retrieving revision 1.22
diff -c -p -d -r1.22 ia64-protos.h
*** ia64-protos.h	2000/09/18 19:03:37	1.22
--- ia64-protos.h	2000/09/24 23:50:45
*************** extern int fr_reg_or_fp01_operand PARAMS
*** 57,63 ****
  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));
--- 57,62 ----
*************** extern rtx ia64_gp_save_reg PARAMS((int)
*** 73,82 ****
  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 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_function_prologue PARAMS((FILE *, int));
  extern void ia64_function_epilogue PARAMS((FILE *, int));
  
--- 72,82 ----
  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((int));
  extern void ia64_function_prologue PARAMS((FILE *, int));
  extern void ia64_function_epilogue PARAMS((FILE *, int));
  
Index: ia64.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/config/ia64/ia64.c,v
retrieving revision 1.50
diff -c -p -d -r1.50 ia64.c
*** ia64.c	2000/09/18 19:03:37	1.50
--- ia64.c	2000/09/24 23:50:45
*************** signed_inequality_operator (op, mode)
*** 676,716 ****
  	      || 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
--- 676,681 ----
*************** ia64_expand_compare (code, mode)
*** 1044,1049 ****
--- 1009,1106 ----
  
    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.  */
  
*************** ia64_expand_prologue ()
*** 1819,1825 ****
  
    /* 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)
      {
        /* If there is no alloc, but there are input registers used, then we
  	 need a .regstk directive.  */
--- 1876,1883 ----
  
    /* 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_input_regs <= current_function_args_info.words)
      {
        /* If there is no alloc, but there are input registers used, then we
  	 need a .regstk directive.  */
*************** ia64_expand_prologue ()
*** 2090,2096 ****
     insn to prevent such scheduling.  */
  
  void
! ia64_expand_epilogue ()
  {
    rtx insn, reg, alt_reg, ar_unat_save_reg;
    int regno, alt_regno, cfa_off;
--- 2148,2155 ----
     insn to prevent such scheduling.  */
  
  void
! ia64_expand_epilogue (sibcall_p)
!      int sibcall_p;
  {
    rtx insn, reg, alt_reg, ar_unat_save_reg;
    int regno, alt_regno, cfa_off;
*************** ia64_expand_epilogue ()
*** 2303,2309 ****
    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))));
  }
  
  /* Return 1 if br.ret can do all the work required to return from a
--- 2362,2369 ----
    if (cfun->machine->ia64_eh_epilogue_bsp)
      emit_insn (gen_set_bsp (cfun->machine->ia64_eh_epilogue_bsp));
   
!   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
*************** struct reg_flags
*** 3642,3647 ****
--- 3702,3708 ----
    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,
*************** rtx_needs_barrier (x, flags, pred)
*** 3935,3943 ****
  
        /* 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)
  	{
  	  new_flags.is_write = 1;
  	  need_barrier |= rws_access_regno (REG_RP, new_flags, pred);
--- 3996,4002 ----
  
        /* Avoid multiple register writes, in case this is a pattern with
  	 multiple CALL rtx.  This avoids an abort in rws_access_reg.  */
!       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);
*************** rtx_needs_barrier (x, flags, pred)
*** 3968,3979 ****
        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;
  
--- 4027,4033 ----
*************** rtx_needs_barrier (x, flags, pred)
*** 4096,4101 ****
--- 4150,4156 ----
  	  break;
  
  	case 7: /* pred_rel_mutex */
+ 	case 9: /* pic call */
          case 12: /* mf */
          case 19: /* fetchadd_acq */
  	case 20: /* mov = ar.bsp */
*************** rtx_needs_barrier (x, flags, pred)
*** 4185,4190 ****
--- 4240,4246 ----
  	  default:
  	    abort ();
  	  }
+       break;
      }
    return need_barrier;
  }
*************** emit_insn_group_barriers (insns)
*** 4229,4234 ****
--- 4285,4291 ----
  
  	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);
  
*************** emit_insn_group_barriers (insns)
*** 4298,4315 ****
  		     The second element of the vector is representative.  */
  		case CODE_FOR_doloop_end_internal:
  		  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.  */
--- 4355,4360 ----
Index: ia64.h
===================================================================
RCS file: /cvs/gcc/egcs/gcc/config/ia64/ia64.h,v
retrieving revision 1.45
diff -c -p -d -r1.45 ia64.h
*** ia64.h	2000/09/18 19:03:37	1.45
--- ia64.h	2000/09/24 23:50:45
*************** do {									\
*** 2697,2703 ****
  { "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}},						\
--- 2697,2702 ----
Index: ia64.md
===================================================================
RCS file: /cvs/gcc/egcs/gcc/config/ia64/ia64.md,v
retrieving revision 1.48
diff -c -p -d -r1.48 ia64.md
*** ia64.md	2000/09/18 19:03:37	1.48
--- ia64.md	2000/09/24 23:50:45
***************
*** 62,67 ****
--- 62,68 ----
  ;;	5	recip_approx
  ;;	7	pred_rel_mutex
  ;;	8	popcnt
+ ;;	9	pic call
  ;;	12	mf
  ;;	13	cmpxchg_acq
  ;;	19	fetchadd_acq
***************
*** 4708,4789 ****
    ""
    "
  {
!   /* ??? 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]));
! 
    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))]
    ""
    "
  {
!   /* ??? 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
  ;; increased by one).
! 
  ;; Subroutines that return `BLKmode' objects use the `call' insn.
  
  (define_expand "call_value"
--- 4709,4735 ----
    ""
    "
  {
!   ia64_expand_call (NULL_RTX, operands[0], operands[2], 0);
    DONE;
  }")
  
! (define_expand "sibcall"
!   [(use (match_operand:DI 0 "" ""))
!    (use (match_operand 1 "" ""))
!    (use (match_operand 2 "" ""))
!    (use (match_operand 3 "" ""))]
    ""
    "
  {
!   ia64_expand_call (NULL_RTX, operands[0], operands[2], 1);
!   DONE;
  }")
  
  ;; 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
  ;; increased by one).
! ;;
  ;; Subroutines that return `BLKmode' objects use the `call' insn.
  
  (define_expand "call_value"
***************
*** 4795,4981 ****
    ""
    "
  {
!   /* ??? 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]));
! 
    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))]
    ""
    "
  {
!   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"
--- 4741,4763 ----
    ""
    "
  {
!   ia64_expand_call (operands[0], operands[1], operands[3], 0);
    DONE;
  }")
  
! (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 "" ""))]
    ""
    "
  {
!   ia64_expand_call (operands[0], operands[1], operands[3], 1);
!   DONE;
  }")
  
  ;; Call subroutine returning any type.
  
  (define_expand "untyped_call"
***************
*** 5005,5010 ****
--- 4787,4845 ----
    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,5103 ****
  }")
  
  (define_expand "epilogue"
!   [(const_int 2)]
    ""
    "
  {
!   ia64_expand_epilogue ();
    DONE;
  }")
  
--- 4928,4947 ----
  }")
  
  (define_expand "epilogue"
!   [(return)]
    ""
    "
  {
!   ia64_expand_epilogue (0);
!   DONE;
! }")
! 
! (define_expand "sibcall_epilogue"
!   [(return)]
!   ""
!   "
! {
!   ia64_expand_epilogue (1);
    DONE;
  }")
  
***************
*** 5200,5207 ****
    [(set_attr "type" "I")])
  
  (define_insn "set_bsp"
!   [(unspec_volatile [(const_int 0)] 5)
!    (use (match_operand:DI 0 "register_operand" "r"))]
    ""
    "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")
--- 5044,5050 ----
    [(set_attr "type" "I")])
  
  (define_insn "set_bsp"
!   [(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")

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