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]
Other format: [Raw text]

optimize x86 pic register loads


The unfortunate thing about current_function_uses_pic_offset_table
is that it is set, but never reset after dead code is removed.

It is possible to use regs_ever_live instead, but one has to be
careful -- reload can create new address constants when none 
existed before, which can create the first use of the pic register.
This problem can be solved by having the backend set regs_ever_live
instead of current_function_uses_pic_offset_table.

It is still possible to wind up with the pic register being saved
and restored when unused, but it's harder to trigger.  Libgcj has
one routine in which post-reload cross-jumping proves that two
arms of an IF are identical.  It then removes the compare and branch.
The compare was the only user of the pic register.  In this case
we remove the pic register calculation, but cannot remove the save
and restore.  Oh well.

This is worth -1k to the size of glibc, and about the same to the
size of stage2/cc1 when built with -fpic.

Installed mainline only.


r~


        * config/i386/i386.c (ix86_save_reg): Examine regs_ever_live,
        not current_function_uses_pic_offset_table and
        current_function_uses_const_pool; examine current_function_profile.
        (ix86_expand_prologue): Likewise.  Add pic_offset_table_rtx as
        input to blockage if needed.
        (ix86_expand_call): Do not set current_function_uses_pic_offset_table.
        (legitimize_pic_address): Likewise.  Set regs_ever_live for
        pic_offset_table_rtx when invoked during reload.
        * config/i386/i386.h (FINALIZE_PIC): Remove.
        * config/i386/i386.md (tablejump): Reformat.  Do not set
        current_function_uses_pic_offset_table.
        (tls_global_dynamic, tls_local_dynamic_base): Likewise.
        (blockage): Accept anything as operand 0.

Index: i386.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/i386/i386.c,v
retrieving revision 1.410
diff -c -p -d -u -r1.410 i386.c
--- i386.c	28 May 2002 20:27:45 -0000	1.410
+++ i386.c	28 May 2002 20:35:44 -0000
@@ -4012,8 +4012,8 @@ ix86_save_reg (regno, maybe_eh_return)
      int maybe_eh_return;
 {
   if (regno == PIC_OFFSET_TABLE_REGNUM
-      && (current_function_uses_pic_offset_table
-	  || current_function_uses_const_pool
+      && (regs_ever_live[regno]
+	  || current_function_profile
 	  || current_function_calls_eh_return))
     return 1;
 
@@ -4235,9 +4235,9 @@ void
 ix86_expand_prologue ()
 {
   rtx insn;
-  int pic_reg_used = (flag_pic && (current_function_uses_pic_offset_table
-				  || current_function_uses_const_pool)
-		      && !TARGET_64BIT);
+  int pic_reg_used = (PIC_OFFSET_TABLE_REGNUM != INVALID_REGNUM
+		      && (regs_ever_live[PIC_OFFSET_TABLE_REGNUM]
+			  || current_function_profile));
   struct ix86_frame frame;
   int use_mov = 0;
   HOST_WIDE_INT allocate;
@@ -4320,18 +4320,19 @@ ix86_expand_prologue ()
     {
       insn = emit_insn (gen_set_got (pic_offset_table_rtx));
 
-      /* ??? The current_function_uses_pic_offset_table flag is woefully
-	 inaccurate, as it isn't updated as code gets deleted.  Allow the
-	 thing to be removed.  A better solution would be to actually get
-	 proper liveness for ebx, as then we won't save/restore it too.  */
+      /* Even with accurate pre-reload life analysis, we can wind up
+	 deleting all references to the pic register after reload.
+	 Consider if cross-jumping unifies two sides of a branch
+	 controled by a comparison vs the only read from a global.
+	 In which case, allow the set_got to be deleted, though we're
+	 too late to do anything about the ebx save in the prologue.  */
       REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_MAYBE_DEAD, const0_rtx, NULL);
     }
 
-  /* 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 (current_function_profile && ! pic_reg_used)
-    emit_insn (gen_blockage ());
+  /* Prevent function calls from be scheduled before the call to mcount.
+     In the pic_reg_used case, make sure that the got load isn't deleted.  */
+  if (current_function_profile)
+    emit_insn (gen_blockage (pic_reg_used ? pic_offset_table_rtx : const0_rtx));
 }
 
 /* Emit code to restore saved registers using MOV insns.  First register
@@ -5245,7 +5246,8 @@ legitimize_pic_address (orig, reg)
 	  /* This symbol may be referenced via a displacement from the PIC
 	     base address (@GOTOFF).  */
 
-	  current_function_uses_pic_offset_table = 1;
+	  if (reload_in_progress)
+	    regs_ever_live[PIC_OFFSET_TABLE_REGNUM] = 1;
 	  new = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, addr), UNSPEC_GOTOFF);
 	  new = gen_rtx_CONST (Pmode, new);
 	  new = gen_rtx_PLUS (Pmode, pic_offset_table_rtx, new);
@@ -5261,7 +5263,6 @@ legitimize_pic_address (orig, reg)
     {
       if (TARGET_64BIT)
 	{
-	  current_function_uses_pic_offset_table = 1;
 	  new = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, addr), UNSPEC_GOTPCREL);
 	  new = gen_rtx_CONST (Pmode, new);
 	  new = gen_rtx_MEM (Pmode, new);
@@ -5281,7 +5282,8 @@ legitimize_pic_address (orig, reg)
 	  /* This symbol must be referenced via a load from the
 	     Global Offset Table (@GOT).  */
 
-	  current_function_uses_pic_offset_table = 1;
+	  if (reload_in_progress)
+	    regs_ever_live[PIC_OFFSET_TABLE_REGNUM] = 1;
 	  new = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, addr), UNSPEC_GOT);
 	  new = gen_rtx_CONST (Pmode, new);
 	  new = gen_rtx_PLUS (Pmode, pic_offset_table_rtx, new);
@@ -5322,7 +5324,8 @@ legitimize_pic_address (orig, reg)
 	    {
 	      if (!TARGET_64BIT)
 		{
-		  current_function_uses_pic_offset_table = 1;
+		  if (reload_in_progress)
+		    regs_ever_live[PIC_OFFSET_TABLE_REGNUM] = 1;
 		  new = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, op0),
 					UNSPEC_GOTOFF);
 		  new = gen_rtx_PLUS (Pmode, new, op1);
@@ -5518,7 +5521,8 @@ legitimize_address (x, oldx, mode)
         case TLS_MODEL_INITIAL_EXEC:
 	  if (flag_pic)
 	    {
-	      current_function_uses_pic_offset_table = 1;
+	      if (reload_in_progress)
+		regs_ever_live[PIC_OFFSET_TABLE_REGNUM] = 1;
 	      pic = pic_offset_table_rtx;
 	    }
 	  else
@@ -10464,10 +10468,7 @@ ix86_expand_call (retval, fnaddr, callar
   if (! TARGET_64BIT && flag_pic
       && GET_CODE (XEXP (fnaddr, 0)) == SYMBOL_REF
       && ! SYMBOL_REF_FLAG (XEXP (fnaddr, 0)))
-    {
-      current_function_uses_pic_offset_table = 1;
-      use_reg (&use, pic_offset_table_rtx);
-    }
+    use_reg (&use, pic_offset_table_rtx);
 
   if (TARGET_64BIT && INTVAL (callarg2) >= 0)
     {
Index: i386.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/i386/i386.h,v
retrieving revision 1.263
diff -c -p -d -u -r1.263 i386.h
--- i386.h	23 May 2002 21:55:29 -0000	1.263
+++ i386.h	28 May 2002 20:35:44 -0000
@@ -2406,17 +2406,6 @@ enum ix86_builtins
       fputs (user_label_prefix, FILE);		\
     fputs (xname, FILE);			\
   } while (0)
-
-/* The `FINALIZE_PIC' macro serves as a hook to emit these special
-   codes once the function is being compiled into assembly code, but
-   not before.  (It is not done before, because in the case of
-   compiling an inline function, it would lead to multiple PIC
-   prologues being included in functions which used inline functions
-   and were compiled to assembly language.)  */
-
-#define FINALIZE_PIC \
-  (current_function_uses_pic_offset_table |= current_function_profile)
-
 
 /* Max number of args passed in registers.  If this is more than 3, we will
    have problems with ebx (register #4), since it is a caller save register and
Index: i386.md
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/i386/i386.md,v
retrieving revision 1.367
diff -c -p -d -u -r1.367 i386.md
--- i386.md	23 May 2002 21:55:30 -0000	1.367
+++ i386.md	28 May 2002 20:35:45 -0000
@@ -12699,29 +12699,34 @@
 	      (use (label_ref (match_operand 1 "" "")))])]
   ""
 {
-  /* In PIC mode, the table entries are stored GOT-relative.  Convert
-     the relative address to an absolute address.  */
+  /* In PIC mode, the table entries are stored GOT (32-bit) or PC (64-bit)
+     relative.  Convert the relative address to an absolute address.  */
   if (flag_pic)
     {
+      rtx op0, op1;
+      enum rtx_code code;
+
       if (TARGET_64BIT)
-	operands[0] = expand_simple_binop (Pmode, PLUS, operands[0],
-					   gen_rtx_LABEL_REF (Pmode, operands[1]),
-					   NULL_RTX, 0,
-					   OPTAB_DIRECT);
+	{
+	  code = PLUS;
+	  op0 = operands[0];
+	  op1 = gen_rtx_LABEL_REF (Pmode, operands[1]);
+	}
       else if (HAVE_AS_GOTOFF_IN_DATA)
 	{
-	  operands[0] = expand_simple_binop (Pmode, PLUS, operands[0],
-					     pic_offset_table_rtx, NULL_RTX,
-					     1, OPTAB_DIRECT);
-	  current_function_uses_pic_offset_table = 1;
+	  code = PLUS;
+	  op0 = operands[0];
+	  op1 = pic_offset_table_rtx;
 	}
       else
 	{
-	  operands[0] = expand_simple_binop (Pmode, MINUS, pic_offset_table_rtx,
-					     operands[0], NULL_RTX, 1,
-					     OPTAB_DIRECT);
-	  current_function_uses_pic_offset_table = 1;
+	  code = MINUS;
+	  op0 = pic_offset_table_rtx;
+	  op1 = operands[0];
 	}
+
+      operands[0] = expand_simple_binop (Pmode, code, op0, op1, NULL_RTX, 1,
+					 OPTAB_DIRECT);
     }
 })
 
@@ -13061,7 +13066,7 @@
      registers we stored in the result block.  We avoid problems by
      claiming that all hard registers are used and clobbered at this
      point.  */
-  emit_insn (gen_blockage ());
+  emit_insn (gen_blockage (const0_rtx));
 
   DONE;
 })
@@ -13072,7 +13077,7 @@
 ;; all of memory.  This blocks insns from being moved across this point.
 
 (define_insn "blockage"
-  [(unspec_volatile [(const_int 0)] UNSPECV_BLOCKAGE)]
+  [(unspec_volatile [(match_operand 0 "" "")] UNSPECV_BLOCKAGE)]
   ""
   ""
   [(set_attr "length" "0")])
@@ -13391,7 +13396,6 @@
 {
   if (!flag_pic)
     abort ();
-  current_function_uses_pic_offset_table = 1;
   operands[2] = pic_offset_table_rtx;
   operands[3] = ix86_tls_get_addr ();
 })
@@ -13434,7 +13438,6 @@
 {
   if (!flag_pic)
     abort ();
-  current_function_uses_pic_offset_table = 1;
   operands[1] = pic_offset_table_rtx;
   operands[2] = ix86_tls_get_addr ();
 })


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