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]

i386 PIC prologues/epilogues changes (and replacement for CONST fix)


Hi
This patch redesign the PIC code somewhat - it changes the call expanders to
explicitly mention the ebx, so all uses of PIC pointers are visible in the insn
chain.  Then it modifies the prologue_set_got and prologue_get_pc to not use
volatiles and set what happends.

The patterns are now schedulable and the pop can be simplified by
combine_stack_adjustments pass.

And lastly I don't keep track of current_function_uses_pic_offset_table over
compilation, but set it in the reload according to EBX liveness information.
This is still not perfect, since we should teach reload to use EBX for other
purposes when GOT pointer is not necesary, but still better than previously.
It also protect gcc from reporting ICEs about removing prologue insns.

Bootstraped with -fpic.
Honza

Thu Aug  3 11:51:17 CEST 2000  Jan Hubicka  <jh@suse.cz>
	* i386.c (label_ref_operand): New.
	(constant_call_address_operand): Accept only the SYMBOL_REF references
	(asm_output_function_prefix): Use current_function_uses_pic_offset_table.
	(ix86_expand_prologue): Likewise.
	(load_pic_register): Create new-stype insn chain.
	(ix86_compute_frame_size): Compute value of
	current_function_uses_pic_offset_table.
	(legitimize_pic_address): Use Pmode CONSTs and UNSPECs,
	do not set current_function_uses_pic_offset_table.
	(print_operand_address): Use Pmode CONST.
	* i386.h (PREDICATE_CODES) Add const248_operand and label_ref_operand.
	* i386-protos.h (label_ref_operand): Declare.
	* i386.md (call expanders): Generate *_ebx patterns when function
	is non-local, do not set current_function_uses_pic_offset_table.
	(call_pop_0_ebx, call_0_ebx, call_value_pop_0_ebx, call_value_0_ebx)
	New patterns.
	(prologue_set_got): Avoid unspecs in the pattern.
	(prologue_get_pc): Likewise.
	(prologue_get_pc_deep): New pattern.

*** i386.c.old	Mon Jul 10 15:51:23 2000
--- i386.c	Thu Aug  3 11:11:23 2000
*************** symbolic_operand (op, mode)
*** 1051,1056 ****
--- 1121,1134 ----
      }
  }
  
+ int
+ label_ref_operand (op, mode)
+      register rtx op;
+      enum machine_mode mode ATTRIBUTE_UNUSED;
+ {
+   return GET_CODE (op) == LABEL_REF;
+ }
+ 
  /* Return true if the operand contains a @GOT or @GOTOFF reference.  */
  
  int
*************** constant_call_address_operand (op, mode)
*** 1119,1126 ****
       enum machine_mode mode ATTRIBUTE_UNUSED;
  {
    return (GET_CODE (op) == MEM
! 	  && CONSTANT_ADDRESS_P (XEXP (op, 0))
! 	  && GET_CODE (XEXP (op, 0)) !=  CONST_INT);
  }
  
  /* Match exactly zero and one.  */
--- 1197,1203 ----
       enum machine_mode mode ATTRIBUTE_UNUSED;
  {
    return (GET_CODE (op) == MEM
! 	  && GET_CODE (XEXP (op, 0)) == SYMBOL_REF);
  }
  
  /* Match exactly zero and one.  */
*************** asm_output_function_prefix (file, name)
*** 1669,1681 ****
       const char *name ATTRIBUTE_UNUSED;
  {
    rtx xops[2];
-   int pic_reg_used = flag_pic && (current_function_uses_pic_offset_table
- 				  || current_function_uses_const_pool);
    xops[0] = pic_offset_table_rtx;
    xops[1] = stack_pointer_rtx;
  
    /* Deep branch prediction favors having a return for every call. */
!   if (pic_reg_used && TARGET_DEEP_BRANCH_PREDICTION)
      {
        if (!pic_label_output)
  	{
--- 1751,1761 ----
       const char *name ATTRIBUTE_UNUSED;
  {
    rtx xops[2];
    xops[0] = pic_offset_table_rtx;
    xops[1] = stack_pointer_rtx;
  
    /* Deep branch prediction favors having a return for every call. */
!   if (current_function_uses_pic_offset_table && TARGET_DEEP_BRANCH_PREDICTION)
      {
        if (!pic_label_output)
  	{
*************** asm_output_function_prefix (file, name)
*** 1700,1706 ****
  void
  load_pic_register ()
  {
!   rtx gotsym, pclab;
  
    if (global_offset_table_name == NULL)
      {
--- 1780,1786 ----
  void
  load_pic_register ()
  {
!   rtx gotsym, pclab, calldest;
  
    if (global_offset_table_name == NULL)
      {
*************** load_pic_register ()
*** 1710,1715 ****
--- 1790,1796 ----
      }
    gotsym = gen_rtx_SYMBOL_REF (Pmode, global_offset_table_name);
  
+   pclab = gen_rtx_LABEL_REF (VOIDmode, gen_label_rtx ());
    if (TARGET_DEEP_BRANCH_PREDICTION)
      {
        if (pic_label_name == NULL) 
*************** load_pic_register ()
*** 1718,1735 ****
  	  ggc_add_string_root (&pic_label_name, 1);
  	  ASM_GENERATE_INTERNAL_LABEL (pic_label_name, "LPR", 0);
  	}
!       pclab = gen_rtx_MEM (QImode, gen_rtx_SYMBOL_REF (Pmode, pic_label_name));
      }
    else
      {
!       pclab = gen_rtx_LABEL_REF (VOIDmode, gen_label_rtx ());
      }
  
-   emit_insn (gen_prologue_get_pc (pic_offset_table_rtx, pclab));
- 
-   if (! TARGET_DEEP_BRANCH_PREDICTION)
-     emit_insn (gen_popsi1 (pic_offset_table_rtx));
- 
    emit_insn (gen_prologue_set_got (pic_offset_table_rtx, gotsym, pclab));
  }
  
--- 1799,1813 ----
  	  ggc_add_string_root (&pic_label_name, 1);
  	  ASM_GENERATE_INTERNAL_LABEL (pic_label_name, "LPR", 0);
  	}
!       calldest = gen_rtx_MEM (QImode, gen_rtx_SYMBOL_REF (Pmode, pic_label_name));
!       emit_insn (gen_prologue_get_pc_deep (pic_offset_table_rtx, pclab, calldest));
      }
    else
      {
!       emit_insn (gen_prologue_get_pc (pclab));
!       emit_insn (gen_popsi1 (pic_offset_table_rtx));
      }
  
    emit_insn (gen_prologue_set_got (pic_offset_table_rtx, gotsym, pclab));
  }
  
*************** static int
*** 1752,1766 ****
  ix86_nsaved_regs ()
  {
    int nregs = 0;
-   int pic_reg_used = flag_pic && (current_function_uses_pic_offset_table
- 				  || current_function_uses_const_pool);
    int limit = (frame_pointer_needed
  	       ? HARD_FRAME_POINTER_REGNUM : STACK_POINTER_REGNUM);
    int regno;
  
    for (regno = limit - 1; regno >= 0; regno--)
      if ((regs_ever_live[regno] && ! call_used_regs[regno])
! 	|| (regno == PIC_OFFSET_TABLE_REGNUM && pic_reg_used))
        {
  	nregs ++;
        }
--- 1830,1843 ----
  ix86_nsaved_regs ()
  {
    int nregs = 0;
    int limit = (frame_pointer_needed
  	       ? HARD_FRAME_POINTER_REGNUM : STACK_POINTER_REGNUM);
    int regno;
  
    for (regno = limit - 1; regno >= 0; regno--)
      if ((regs_ever_live[regno] && ! call_used_regs[regno])
! 	|| (regno == PIC_OFFSET_TABLE_REGNUM
! 	    && current_function_uses_pic_offset_table))
        {
  	nregs ++;
        }
*************** ix86_compute_frame_size (size, nregs_on_
*** 1848,1853 ****
--- 1925,1943 ----
    int offset;
    int preferred_alignment = cfun->preferred_stack_boundary / BITS_PER_UNIT;
  
+   /* This is kind of hack - originally we kept track of the
+      current_function_uses_pic_offset_table during rtx generation to decide
+      whether the pic is used.  This makes unnecesary loads of pic register
+      when the code is eliminated later.  Now all code requiring pic register
+      mentiones it explicitly, so we can use liveness information to decide
+      whether pic is needed or not.  Ideally we should teach reload to use
+      pic register as general purpose register when not necesary, but this is
+      tricky, so for now go with this hack to disable
+      current_function_uses_pic_offset_table when it is not really needed.  */
+   current_function_uses_pic_offset_table
+     = flag_pic && (current_function_uses_const_pool
+ 		   || regs_ever_live [PIC_OFFSET_TABLE_REGNUM]);
+ 
    nregs = ix86_nsaved_regs ();
    total_size = size;
  
*************** ix86_emit_save_regs ()
*** 1907,1920 ****
    register int regno;
    int limit;
    rtx insn;
-   int pic_reg_used = flag_pic && (current_function_uses_pic_offset_table
- 				  || current_function_uses_const_pool);
    limit = (frame_pointer_needed
  	   ? HARD_FRAME_POINTER_REGNUM : STACK_POINTER_REGNUM);
  
    for (regno = limit - 1; regno >= 0; regno--)
      if ((regs_ever_live[regno] && !call_used_regs[regno])
! 	|| (regno == PIC_OFFSET_TABLE_REGNUM && pic_reg_used))
        {
  	insn = emit_insn (gen_push (gen_rtx_REG (SImode, regno)));
  	RTX_FRAME_RELATED_P (insn) = 1;
--- 1997,2009 ----
    register int regno;
    int limit;
    rtx insn;
    limit = (frame_pointer_needed
  	   ? HARD_FRAME_POINTER_REGNUM : STACK_POINTER_REGNUM);
  
    for (regno = limit - 1; regno >= 0; regno--)
      if ((regs_ever_live[regno] && !call_used_regs[regno])
! 	|| (regno == PIC_OFFSET_TABLE_REGNUM
! 	    && current_function_uses_pic_offset_table))
        {
  	insn = emit_insn (gen_push (gen_rtx_REG (SImode, regno)));
  	RTX_FRAME_RELATED_P (insn) = 1;
*************** ix86_expand_prologue ()
*** 1929,1936 ****
    HOST_WIDE_INT tsize = ix86_compute_frame_size (get_frame_size (), (int *)0, (int *)0,
  						 (int *)0);
    rtx insn;
-   int pic_reg_used = flag_pic && (current_function_uses_pic_offset_table
- 				  || current_function_uses_const_pool);
  
    /* Note: AT&T enter does NOT have reversed args.  Enter is probably
       slower on all targets.  Also sdb doesn't like it.  */
--- 2018,2023 ----
*************** ix86_expand_prologue ()
*** 1981,1993 ****
    SUBTARGET_PROLOGUE;
  #endif  
  
!   if (pic_reg_used)
      load_pic_register ();
  
    /* If we are profiling, make sure no instructions are scheduled before
       the call to mcount.  However, if -fpic, the above call will have
       done that.  */
!   if ((profile_flag || profile_block_flag) && ! pic_reg_used)
      emit_insn (gen_blockage ());
  }
  
--- 2068,2081 ----
    SUBTARGET_PROLOGUE;
  #endif  
  
!   if (current_function_uses_pic_offset_table)
      load_pic_register ();
  
    /* If we are profiling, make sure no instructions are scheduled before
       the call to mcount.  However, if -fpic, the above call will have
       done that.  */
!   if ((profile_flag || profile_block_flag)
!       && ! current_function_uses_pic_offset_table)
      emit_insn (gen_blockage ());
  }
  
*************** ix86_emit_restore_regs_using_mov (pointe
*** 2018,2031 ****
  	int offset;
  {
    int regno;
-   int pic_reg_used = flag_pic && (current_function_uses_pic_offset_table
- 				  || current_function_uses_const_pool);
    int limit = (frame_pointer_needed
  	       ? HARD_FRAME_POINTER_REGNUM : STACK_POINTER_REGNUM);
  
    for (regno = 0; regno < limit; regno++)
      if ((regs_ever_live[regno] && !call_used_regs[regno])
! 	|| (regno == PIC_OFFSET_TABLE_REGNUM && pic_reg_used))
        {
  	emit_move_insn (gen_rtx_REG (SImode, regno),
  			adj_offsettable_operand (gen_rtx_MEM (SImode,
--- 2106,2118 ----
  	int offset;
  {
    int regno;
    int limit = (frame_pointer_needed
  	       ? HARD_FRAME_POINTER_REGNUM : STACK_POINTER_REGNUM);
  
    for (regno = 0; regno < limit; regno++)
      if ((regs_ever_live[regno] && !call_used_regs[regno])
! 	|| (regno == PIC_OFFSET_TABLE_REGNUM
! 	    && current_function_uses_pic_offset_table))
        {
  	emit_move_insn (gen_rtx_REG (SImode, regno),
  			adj_offsettable_operand (gen_rtx_MEM (SImode,
*************** ix86_expand_epilogue (emit_return)
*** 2044,2051 ****
    int nregs;
    int regno;
  
-   int pic_reg_used = flag_pic && (current_function_uses_pic_offset_table
- 				  || current_function_uses_const_pool);
    int sp_valid = !frame_pointer_needed || current_function_sp_is_unchanging;
    HOST_WIDE_INT offset;
    HOST_WIDE_INT tsize = ix86_compute_frame_size (get_frame_size (), &nregs,
--- 2131,2136 ----
*************** ix86_expand_epilogue (emit_return)
*** 2120,2126 ****
  
        for (regno = 0; regno < STACK_POINTER_REGNUM; regno++)
  	if ((regs_ever_live[regno] && !call_used_regs[regno])
! 	    || (regno == PIC_OFFSET_TABLE_REGNUM && pic_reg_used))
  	  emit_insn (gen_popsi1 (gen_rtx_REG (SImode, regno)));
      }
  
--- 2205,2212 ----
  
        for (regno = 0; regno < STACK_POINTER_REGNUM; regno++)
  	if ((regs_ever_live[regno] && !call_used_regs[regno])
! 	    || (regno == PIC_OFFSET_TABLE_REGNUM
! 		&& current_function_uses_pic_offset_table))
  	  emit_insn (gen_popsi1 (gen_rtx_REG (SImode, regno)));
      }
  
*************** legitimize_pic_address (orig, reg)
*** 2579,2587 ****
        /* This symbol may be referenced via a displacement from the PIC
  	 base address (@GOTOFF).  */
  
!       current_function_uses_pic_offset_table = 1;
!       new = gen_rtx_UNSPEC (VOIDmode, gen_rtvec (1, addr), 7);
!       new = gen_rtx_CONST (VOIDmode, new);
        new = gen_rtx_PLUS (Pmode, pic_offset_table_rtx, new);
  
        if (reg != 0)
--- 2682,2689 ----
        /* This symbol may be referenced via a displacement from the PIC
  	 base address (@GOTOFF).  */
  
!       new = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, addr), 7);
!       new = gen_rtx_CONST (Pmode, new);
        new = gen_rtx_PLUS (Pmode, pic_offset_table_rtx, new);
  
        if (reg != 0)
*************** legitimize_pic_address (orig, reg)
*** 2595,2603 ****
        /* This symbol must be referenced via a load from the
  	 Global Offset Table (@GOT). */
  
!       current_function_uses_pic_offset_table = 1;
!       new = gen_rtx_UNSPEC (VOIDmode, gen_rtvec (1, addr), 6);
!       new = gen_rtx_CONST (VOIDmode, new);
        new = gen_rtx_PLUS (Pmode, pic_offset_table_rtx, new);
        new = gen_rtx_MEM (Pmode, new);
        RTX_UNCHANGING_P (new) = 1;
--- 2697,2704 ----
        /* This symbol must be referenced via a load from the
  	 Global Offset Table (@GOT). */
  
!       new = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, addr), 6);
!       new = gen_rtx_CONST (Pmode, new);
        new = gen_rtx_PLUS (Pmode, pic_offset_table_rtx, new);
        new = gen_rtx_MEM (Pmode, new);
        RTX_UNCHANGING_P (new) = 1;
*************** legitimize_pic_address (orig, reg)
*** 2631,2640 ****
  		       || SYMBOL_REF_FLAG (op0))))
  	      && GET_CODE (op1) == CONST_INT)
  	    {
! 	      current_function_uses_pic_offset_table = 1;
! 	      new = gen_rtx_UNSPEC (VOIDmode, gen_rtvec (1, op0), 7);
! 	      new = gen_rtx_PLUS (VOIDmode, new, op1);
! 	      new = gen_rtx_CONST (VOIDmode, new);
  	      new = gen_rtx_PLUS (Pmode, pic_offset_table_rtx, new);
  
  	      if (reg != 0)
--- 2732,2740 ----
  		       || SYMBOL_REF_FLAG (op0))))
  	      && GET_CODE (op1) == CONST_INT)
  	    {
! 	      new = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, op0), 7);
! 	      new = gen_rtx_PLUS (Pmode, new, op1);
! 	      new = gen_rtx_CONST (Pmode, new);
  	      new = gen_rtx_PLUS (Pmode, pic_offset_table_rtx, new);
  
  	      if (reg != 0)
*************** print_operand_address (file, addr)
*** 3465,3471 ****
  		  && GET_CODE (XEXP (XEXP (disp, 0), 1)) == CONST_INT)
  		{
  		  offset = XEXP (XEXP (disp, 0), 1);
! 		  disp = gen_rtx_CONST (VOIDmode,
  					XEXP (XEXP (disp, 0), 0));
  		}
  
--- 3569,3575 ----
  		  && GET_CODE (XEXP (XEXP (disp, 0), 1)) == CONST_INT)
  		{
  		  offset = XEXP (XEXP (disp, 0), 1);
! 		  disp = gen_rtx_CONST (Pmode,
  					XEXP (XEXP (disp, 0), 0));
  		}
  
*** i386.h.old	Mon Jul 10 15:51:23 2000
--- i386.h	Wed Aug  2 21:00:17 2000
*************** do { long l;						\
*** 2563,2569 ****
--- 2579,2587 ----
  
  #define PREDICATE_CODES							\
    {"const_int_1_operand", {CONST_INT}},					\
+   {"const248_operand", {CONST_INT}},					\
    {"symbolic_operand", {SYMBOL_REF, LABEL_REF, CONST}},			\
+   {"label_ref_operand", {LABEL_REF}},					\
    {"aligned_operand", {CONST_INT, CONST_DOUBLE, CONST, SYMBOL_REF,	\
  		       LABEL_REF, SUBREG, REG, MEM}},			\
    {"pic_symbolic_operand", {CONST}},					\
*** i386-protos.h.old	Mon Jul 10 15:51:23 2000
--- i386-protos.h	Wed Aug  2 21:00:01 2000
*************** extern int symbolic_reference_mentioned_
*** 43,48 ****
--- 43,49 ----
  
  extern int const_int_1_operand PARAMS ((rtx, enum machine_mode));
  extern int symbolic_operand PARAMS ((rtx, enum machine_mode));
+ extern int label_ref_operand PARAMS ((rtx, enum machine_mode));
  extern int pic_symbolic_operand PARAMS ((rtx, enum machine_mode));
  extern int call_insn_operand PARAMS ((rtx, enum machine_mode));
  extern int constant_call_address_operand PARAMS ((rtx, enum machine_mode));
*** i386.md.old	Mon Jul 10 15:51:23 2000
--- i386.md	Thu Aug  3 01:32:53 2000
***************
*** 8200,8212 ****
        emit_insn (gen_call (operands[0], operands[1]));
        DONE;
      }
- 
-   /* ??? Not true for calls to static functions.  */
-   if (flag_pic)
-     current_function_uses_pic_offset_table = 1;
- 
    if (! call_insn_operand (operands[0], QImode))
      XEXP (operands[0], 0) = copy_to_mode_reg (Pmode, XEXP (operands[0], 0));
  }")
  
  (define_insn "*call_pop_0"
--- 8515,8531 ----
        emit_insn (gen_call (operands[0], operands[1]));
        DONE;
      }
    if (! call_insn_operand (operands[0], QImode))
      XEXP (operands[0], 0) = copy_to_mode_reg (Pmode, XEXP (operands[0], 0));
+   /* Static functions and indirect calls don't need pic pointer.  */
+   if (flag_pic
+       && constant_call_address_operand (operands[0], SImode)
+       && !SYMBOL_REF_FLAG (XEXP (operands[0], 0)))
+     {
+       emit_insn (gen_call_pop_0_ebx (operands[0], operands[1],
+ 				     operands[2], operands[3]));
+       DONE;
+     }
  }")
  
  (define_insn "*call_pop_0"
***************
*** 8214,8219 ****
--- 8533,8554 ----
  	 (match_operand:SI 1 "" ""))
     (set (reg:SI 7) (plus:SI (reg:SI 7)
  			    (match_operand:SI 3 "immediate_operand" "")))]
+   "!flag_pic || SYMBOL_REF_FLAG (XEXP (operands[0], 0))"
+   "*
+ {
+   if (SIBLING_CALL_P (insn))
+     return \"jmp\\t%P0\";
+   else
+     return \"call\\t%P0\";
+ }"
+   [(set_attr "type" "call")])
+ 
+ (define_insn "call_pop_0_ebx"
+   [(call (match_operand:QI 0 "constant_call_address_operand" "")
+ 	 (match_operand:SI 1 "" ""))
+    (set (reg:SI 7) (plus:SI (reg:SI 7)
+ 			    (match_operand:SI 3 "immediate_operand" "")))
+    (use (reg:SI 3))]
    ""
    "*
  {
***************
*** 8254,8270 ****
    ""
    "
  {
-   /* ??? Not true for calls to static functions.  */
-   if (flag_pic)
-     current_function_uses_pic_offset_table = 1;
- 
    if (! call_insn_operand (operands[0], QImode))
      XEXP (operands[0], 0) = copy_to_mode_reg (Pmode, XEXP (operands[0], 0));
  }")
  
  (define_insn "*call_0"
    [(call (match_operand:QI 0 "constant_call_address_operand" "")
  	 (match_operand:SI 1 "" ""))]
    ""
    "*
  {
--- 8589,8623 ----
    ""
    "
  {
    if (! call_insn_operand (operands[0], QImode))
      XEXP (operands[0], 0) = copy_to_mode_reg (Pmode, XEXP (operands[0], 0));
+   /* Static functions and indirect calls don't need pic pointer.  */
+   if (flag_pic
+       && constant_call_address_operand (operands[0], SImode)
+       && !SYMBOL_REF_FLAG (XEXP (operands[0], 0)))
+     {
+       emit_insn (gen_call_0_ebx (operands[0], operands[1]));
+       DONE;
+     }
  }")
  
  (define_insn "*call_0"
    [(call (match_operand:QI 0 "constant_call_address_operand" "")
  	 (match_operand:SI 1 "" ""))]
+   "!flag_pic || SYMBOL_REF_FLAG (XEXP (operands[0], 0))"
+   "*
+ {
+   if (SIBLING_CALL_P (insn))
+     return \"jmp\\t%P0\";
+   else
+     return \"call\\t%P0\";
+ }"
+   [(set_attr "type" "call")])
+ 
+ (define_insn "call_0_ebx"
+   [(call (match_operand:QI 0 "constant_call_address_operand" "")
+ 	 (match_operand:SI 1 "" ""))
+    (use (reg:SI 3))]
    ""
    "*
  {
***************
*** 8314,8326 ****
        emit_insn (gen_call_value (operands[0], operands[1], operands[2]));
        DONE;
      }
- 
-   /* ??? Not true for calls to static functions.  */
-   if (flag_pic)
-     current_function_uses_pic_offset_table = 1;
- 
    if (! call_insn_operand (operands[1], QImode))
      XEXP (operands[1], 0) = copy_to_mode_reg (Pmode, XEXP (operands[1], 0));
  }")
  
  (define_expand "call_value"
--- 8667,8684 ----
        emit_insn (gen_call_value (operands[0], operands[1], operands[2]));
        DONE;
      }
    if (! call_insn_operand (operands[1], QImode))
      XEXP (operands[1], 0) = copy_to_mode_reg (Pmode, XEXP (operands[1], 0));
+   /* Static functions and indirect calls don't need pic pointer.  */
+   if (flag_pic
+       && constant_call_address_operand (operands[1], SImode)
+       && !SYMBOL_REF_FLAG (XEXP (operands[1], 0)))
+     {
+       emit_insn (gen_call_value_pop_0_ebx (operands[0], operands[1],
+ 					   operands[2], operands[3],
+ 					   operands[4]));
+       DONE;
+     }
  }")
  
  (define_expand "call_value"
***************
*** 8331,8342 ****
    ""
    "
  {
-   /* ??? Not true for calls to static functions.  */
-   if (flag_pic)
-     current_function_uses_pic_offset_table = 1;
- 
    if (! call_insn_operand (operands[1], QImode))
      XEXP (operands[1], 0) = copy_to_mode_reg (Pmode, XEXP (operands[1], 0));
  }")
  
  ;; Call subroutine returning any type.
--- 8689,8705 ----
    ""
    "
  {
    if (! call_insn_operand (operands[1], QImode))
      XEXP (operands[1], 0) = copy_to_mode_reg (Pmode, XEXP (operands[1], 0));
+   /* Static functions and indirect calls don't need pic pointer.  */
+   if (flag_pic
+       && constant_call_address_operand (operands[1], SImode)
+       && !SYMBOL_REF_FLAG (XEXP (operands[1], 0)))
+     {
+       emit_insn (gen_call_value_0_ebx (operands[0], operands[1],
+ 				       operands[2]));
+       DONE;
+     }
  }")
  
  ;; Call subroutine returning any type.
***************
*** 8437,8456 ****
  
  (define_insn "prologue_set_got"
    [(set (match_operand:SI 0 "register_operand" "=r")
! 	(unspec_volatile:SI
! 	 [(plus:SI (match_dup 0)
! 		   (plus:SI (match_operand:SI 1 "symbolic_operand" "")
! 			    (minus:SI (pc) (match_operand 2 "" ""))))] 1))
     (clobber (reg:CC 17))]
!   ""
    "*
  {
    if (GET_CODE (operands[2]) == LABEL_REF)
       operands[2] = XEXP (operands[2], 0);
!   if (TARGET_DEEP_BRANCH_PREDICTION) 
!     return \"add{l}\\t{%1, %0|%0, %1}\";
!   else  
!     return \"add{l}\\t{%1+[.-%X2], %0|%0, %a1+(.-%X2)}\";
  }"
    [(set_attr "type" "alu")
     ; Since this insn may have two constant operands, we must set the
--- 8800,8816 ----
  
  (define_insn "prologue_set_got"
    [(set (match_operand:SI 0 "register_operand" "=r")
! 	(plus:SI (match_dup 0)
! 		 (const:SI
! 		    (minus:SI (match_operand:SI 1 "symbolic_operand" "")
! 			      (match_operand 2 "label_ref_operand" "")))))
     (clobber (reg:CC 17))]
!   "flag_pic"
    "*
  {
    if (GET_CODE (operands[2]) == LABEL_REF)
       operands[2] = XEXP (operands[2], 0);
!   return \"add{l}\\t{%1+[.-%X2], %0|%0, %a1+(.-%X2)}\";
  }"
    [(set_attr "type" "alu")
     ; Since this insn may have two constant operands, we must set the
***************
*** 8459,8480 ****
     (set_attr "mode" "SI")])
  
  (define_insn "prologue_get_pc"
    [(set (match_operand:SI 0 "register_operand" "=r")
!     (unspec_volatile:SI [(plus:SI (pc) (match_operand 1 "" ""))] 2))]
!   ""
    "*
  {
!   if (GET_CODE (operands[1]) == LABEL_REF)
!     operands[1] = XEXP (operands[1], 0);
!   output_asm_insn (\"call\\t%X1\", operands);
!   if (! TARGET_DEEP_BRANCH_PREDICTION)
!     {
!       ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\",
! 				 CODE_LABEL_NUMBER (operands[1]));
!     }
    RET;
  }"
!   [(set_attr "type" "multi")])
  
  (define_expand "epilogue"
    [(const_int 1)]
--- 8819,8857 ----
     (set_attr "mode" "SI")])
  
  (define_insn "prologue_get_pc"
+   [(set (mem:SI (pre_dec:SI (reg:SI 7)))
+ 	(match_operand 0 "label_ref_operand" ""))]
+   "flag_pic && !TARGET_DEEP_BRANCH_PREDICTION"
+   "*
+ {
+   operands[0] = XEXP (operands[0], 0);
+   output_asm_insn (\"call\\t%X0\", operands);
+   ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\",
+ 			     CODE_LABEL_NUMBER (operands[0]));
+   RET;
+ }"
+   [(set_attr "type" "call")
+    (set_attr "modrm" "0")
+    (set_attr "length_address" "0")
+    (set_attr "length_immediate" "4")])
+ 
+ (define_insn "prologue_get_pc_deep"
    [(set (match_operand:SI 0 "register_operand" "=r")
! 	(match_operand 1 "label_ref_operand" ""))
!    (use (match_operand:SI 2 "" ""))]
!   "flag_pic && TARGET_DEEP_BRANCH_PREDICTION"
    "*
  {
!   operands[1] = XEXP (operands[1], 0);
!   output_asm_insn (\"call\\t%X2\", operands);
!   ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\",
! 			     CODE_LABEL_NUMBER (operands[1]));
    RET;
  }"
!   [(set_attr "type" "call")
!    (set_attr "modrm" "0")
!    (set_attr "length_address" "0")
!    (set_attr "length_immediate" "4")])
  
  (define_expand "epilogue"
    [(const_int 1)]
***************
*** 10792,10797 ****
--- 11169,11191 ----
  	      (match_operand:SI 2 "" "")))
     (set (reg:SI 7) (plus:SI (reg:SI 7)
  			    (match_operand:SI 4 "immediate_operand" "")))]
+   "!flag_pic || SYMBOL_REF_FLAG (XEXP (operands[1], 0))"
+   "*
+ {
+   if (SIBLING_CALL_P (insn))
+     return \"jmp\\t%P1\";
+   else
+     return \"call\\t%P1\";
+ }"
+   [(set_attr "type" "callv")])
+ 
+ (define_insn "call_value_pop_0_ebx"
+   [(set (match_operand 0 "" "")
+ 	(call (match_operand:QI 1 "constant_call_address_operand" "")
+ 	      (match_operand:SI 2 "" "")))
+    (set (reg:SI 7) (plus:SI (reg:SI 7)
+ 			    (match_operand:SI 4 "immediate_operand" "")))
+    (use (reg:SI 3))]
    ""
    "*
  {
***************
*** 10830,10835 ****
--- 11224,11244 ----
    [(set (match_operand 0 "" "")
  	(call (match_operand:QI 1 "constant_call_address_operand" "")
  	      (match_operand:SI 2 "" "")))]
+   "!flag_pic || SYMBOL_REF_FLAG (XEXP (operands[1], 0))"
+   "*
+ {
+   if (SIBLING_CALL_P (insn))
+     return \"jmp\\t%P1\";
+   else
+     return \"call\\t%P1\";
+ }"
+   [(set_attr "type" "callv")])
+ 
+ (define_insn "call_value_0_ebx"
+   [(set (match_operand 0 "" "")
+ 	(call (match_operand:QI 1 "constant_call_address_operand" "")
+ 	      (match_operand:SI 2 "" "")))
+    (use (reg:SI 3))]
    ""
    "*
  {

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