]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
re PR target/42601 (Simplify code to address function static variables with option...
authorWei Guozhi <carrot@google.com>
Sat, 10 Apr 2010 13:13:47 +0000 (13:13 +0000)
committerWei Guozhi <carrot@gcc.gnu.org>
Sat, 10 Apr 2010 13:13:47 +0000 (13:13 +0000)
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.

From-SVN: r158189

gcc/ChangeLog
gcc/config/arm/arm.c
gcc/config/arm/arm.md

index ed09c30850a36f0ccc49869376262d4609f64e09..68bc18a878ea2344a7d158966f1c1d7d3afb38b9 100644 (file)
@@ -1,3 +1,12 @@
+2010-04-10  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.
+
 2010-04-10  Bernd Schmidt  <bernd.schmidt@codesourcery.com>
 
        * ira-costs.c (record_reg_classes): Ignore alternatives that are
index 242ead5f02786046384c4281c46be3e546962bf3..1a555b8706b10a7f2eb30fb031f9c1a565b56334 100644 (file)
@@ -224,6 +224,7 @@ static bool arm_can_eliminate (const int, 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);
 
 \f
 /* Table of machine attributes.  */
@@ -4905,29 +4906,16 @@ legitimize_pic_address (rtx orig, enum machine_mode mode, rtx reg)
     {
       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
@@ -4939,16 +4927,23 @@ legitimize_pic_address (rtx orig, enum machine_mode mode, rtx reg)
               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);
@@ -5155,6 +5150,43 @@ arm_load_pic_register (unsigned long saved_regs ATTRIBUTE_UNUSED)
   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
@@ -21325,6 +21357,16 @@ arm_output_addr_const_extra (FILE *fp, rtx x)
       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 738c3a73d13821cfc235f7bedb7e37cb35c7a4ed..c5e2a16e694c27d79b763af03661063ec41caae4 100644 (file)
                          ; 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.
   ]
 )