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]

[PATCH: PR target/42601] Simplify code sequence to address static var with option -fpic


Hi

Current code sequence to address static variables with option -fpic is:

        ldr     r3, .L2
        ldr     r2, .L2+4
.LPIC0:
        add     r3, pc
        add     r3, r3, r2
        ...
.L2:
        .word   _GLOBAL_OFFSET_TABLE_-(.LPIC0+4)
        .word   .LANCHOR0(GOTOFF)

With this patch it can be simplified as:

        ldr     r3, .L2
.LPIC0:
        add     r3, pc
        ...
.L2:
        .word   .LANCHOR0-(.LPIC0+4)

This patch modifies function legitimize_pic_address to call arm_pic_static_addr
when it detects a static symbol. Function arm_pic_static_addr generates two
instructions to compute the address. The first one loads the offset of the
symbol to the label of next instruction. The next instruction adds the offset
and the pc value together to get the address.

The offset pattern is similar to that used in arm_load_pic_register:

(unspec:UNSPEC_SYMBOL_OFFSET
        (static symbol)
        (plus (const (unspec:UNSPEC_PIC_LABEL (labelno)))
              (const TARGET_ARM ? 8 : 4)))

Test:
This patch was applied to trunk GCC and tested on qemu with glibc.
No new failure.

ChangeLog:
2010-02-04  Wei Guozhi  <carrot@google.com>

        PR target/42601
        * config/arm/arm.c (arm_pic_static_addr): New function.
        (legitimize_pic_address): Call arm_pic_static_addr when it detects
        a static symbol.
		(arm_output_addr_const_extra): Output expression for new pattern.
        * config/arm/arm.md (UNSPEC_SYMBOL_OFFSET): New unspec symbol.


thanks
Guozhi


Index: arm.c
===================================================================
--- arm.c       (revision 156452)
+++ arm.c       (working copy)
@@ -224,6 +224,7 @@ static bool arm_can_eliminate (const int
 static void arm_asm_trampoline_template (FILE *);
 static void arm_trampoline_init (rtx, tree, rtx);
 static rtx arm_trampoline_adjust_address (rtx);
+static rtx arm_pic_static_addr (rtx orig, rtx reg);

 /* Table of machine attributes.  */
@@ -4908,29 +4909,16 @@ legitimize_pic_address (rtx orig, enum m
     {
       rtx pic_ref, address;
       rtx insn;
-      int subregs = 0;
-
-      /* If this function doesn't have a pic register, create one now.  */
-      require_pic_register ();

       if (reg == 0)
        {
          gcc_assert (can_create_pseudo_p ());
          reg = gen_reg_rtx (Pmode);
-
-         subregs = 1;
+         address = gen_reg_rtx (Pmode);
        }
-
-      if (subregs)
-       address = gen_reg_rtx (Pmode);
       else
        address = reg;

-      if (TARGET_32BIT)
-       emit_insn (gen_pic_load_addr_32bit (address, orig));
-      else /* TARGET_THUMB1 */
-       emit_insn (gen_pic_load_addr_thumb1 (address, orig));
-
       /* VxWorks does not impose a fixed gap between segments; the run-time
         gap can be different from the object-file gap.  We therefore can't
         use GOTOFF unless we are absolutely sure that the symbol is in the
@@ -4942,16 +4930,23 @@ legitimize_pic_address (rtx orig, enum m
               SYMBOL_REF_LOCAL_P (orig)))
          && NEED_GOT_RELOC
          && !TARGET_VXWORKS_RTP)
-       pic_ref = gen_rtx_PLUS (Pmode, cfun->machine->pic_reg, address);
+       insn = arm_pic_static_addr (orig, reg);
       else
        {
+         /* If this function doesn't have a pic register, create one now.  */
+         require_pic_register ();
+
+         if (TARGET_32BIT)
+           emit_insn (gen_pic_load_addr_32bit (address, orig));
+         else /* TARGET_THUMB1 */
+           emit_insn (gen_pic_load_addr_thumb1 (address, orig));
+
          pic_ref = gen_const_mem (Pmode,
                                   gen_rtx_PLUS (Pmode, cfun->machine->pic_reg,
                                                 address));
+         insn = emit_move_insn (reg, pic_ref);
        }

-      insn = emit_move_insn (reg, pic_ref);
-
       /* Put a REG_EQUAL note on this insn, so that it can be optimized
         by loop.  */
       set_unique_reg_note (insn, REG_EQUAL, orig);
@@ -5158,6 +5153,43 @@ arm_load_pic_register (unsigned long sav
   emit_use (pic_reg);
 }

+/* Generate code to load the address of a static var when flag_pic is set.  */
+static rtx
+arm_pic_static_addr (rtx orig, rtx reg)
+{
+  rtx l1, labelno, offset_rtx, insn;
+
+  gcc_assert (flag_pic);
+
+  /* We use an UNSPEC rather than a LABEL_REF because this label
+     never appears in the code stream.  */
+  labelno = GEN_INT (pic_labelno++);
+  l1 = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, labelno), UNSPEC_PIC_LABEL);
+  l1 = gen_rtx_CONST (VOIDmode, l1);
+
+  /* On the ARM the PC register contains 'dot + 8' at the time of the
+     addition, on the Thumb it is 'dot + 4'.  */
+  offset_rtx = plus_constant (l1, TARGET_ARM ? 8 : 4);
+  offset_rtx = gen_rtx_UNSPEC (Pmode, gen_rtvec (2, orig, offset_rtx),
+                               UNSPEC_SYMBOL_OFFSET);
+  offset_rtx = gen_rtx_CONST (Pmode, offset_rtx);
+
+  if (TARGET_32BIT)
+    {
+      emit_insn (gen_pic_load_addr_32bit (reg, offset_rtx));
+      if (TARGET_ARM)
+       insn = emit_insn (gen_pic_add_dot_plus_eight (reg, reg, labelno));
+      else
+       insn = emit_insn (gen_pic_add_dot_plus_four (reg, reg, labelno));
+    }
+  else /* TARGET_THUMB1 */
+    {
+      emit_insn (gen_pic_load_addr_thumb1 (reg, offset_rtx));
+      insn = emit_insn (gen_pic_add_dot_plus_four (reg, reg, labelno));
+    }
+
+  return insn;
+}

 /* Return nonzero if X is valid as an ARM state addressing register.  */
 static int
@@ -21174,6 +21206,16 @@ arm_output_addr_const_extra (FILE *fp, r
       fputc (')', fp);
       return TRUE;
     }
+  else if (GET_CODE (x) == UNSPEC && XINT (x, 1) == UNSPEC_SYMBOL_OFFSET)
+    {
+      output_addr_const (fp, XVECEXP (x, 0, 0));
+      if (GOT_PCREL)
+       fputs ("+.", fp);
+      fputs ("-(", fp);
+      output_addr_const (fp, XVECEXP (x, 0, 1));
+      fputc (')', fp);
+      return TRUE;
+    }
   else if (GET_CODE (x) == CONST_VECTOR)
     return arm_emit_vector_const (fp, x);

Index: arm.md
===================================================================
--- arm.md      (revision 156452)
+++ arm.md      (working copy)
@@ -101,6 +101,8 @@
                          ; a given symbolic address.
    (UNSPEC_THUMB1_CASESI 25) ; A Thumb1 compressed dispatch-table call.
    (UNSPEC_RBIT 26)       ; rbit operation.
+   (UNSPEC_SYMBOL_OFFSET 27) ; The offset of the start of the symbol from
+                             ; another symbolic address.
   ]
 )


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