[ARC] Use GOTOFFPC relocation for pc-relative accesses.
authorClaudiu Zissulescu <claziss@synopsys.com>
Thu, 16 Jun 2016 12:29:29 +0000 (14:29 +0200)
committerClaudiu Zissulescu <claziss@gcc.gnu.org>
Thu, 16 Jun 2016 12:29:29 +0000 (14:29 +0200)
gcc/
2016-06-16  Claudiu Zissulescu  <claziss@synopsys.com>
    Joern Rennecke  <joern.rennecke@embecosm.com>

* config/arc/arc.c (arc_print_operand_address): Handle pc-relative
addresses.
(arc_needs_pcl_p): Add GOTOFFPC.
(arc_legitimate_pic_addr_p): Likewise.
(arc_output_pic_addr_const): Likewise.
(arc_legitimize_pic_address): Generate a pc-relative address using
GOTOFFPC.
(arc_output_libcall): Use @pcl syntax.
(arc_delegitimize_address_0): Delegitimize ARC_UNSPEC_GOTOFFPC.
* config/arc/arc.md ("unspec"): Add ARC_UNSPEC_GOTOFFPC.
(*movsi_insn): Use @pcl syntax.
(doloop_begin_i): Likewise.

Co-Authored-By: Joern Rennecke <joern.rennecke@embecosm.com>
From-SVN: r237525

gcc/ChangeLog
gcc/config/arc/arc.c
gcc/config/arc/arc.md

index 0e95c7028f67af4af968399082bed1cdab258cd0..8847e672972219e3d400ac31d0985a940e98b597 100644 (file)
@@ -1,3 +1,19 @@
+2016-06-16  Claudiu Zissulescu  <claziss@synopsys.com>
+           Joern Rennecke  <joern.rennecke@embecosm.com>
+
+       * config/arc/arc.c (arc_print_operand_address): Handle pc-relative
+       addresses.
+       (arc_needs_pcl_p): Add GOTOFFPC.
+       (arc_legitimate_pic_addr_p): Likewise.
+       (arc_output_pic_addr_const): Likewise.
+       (arc_legitimize_pic_address): Generate a pc-relative address using
+       GOTOFFPC.
+       (arc_output_libcall): Use @pcl syntax.
+       (arc_delegitimize_address_0): Delegitimize ARC_UNSPEC_GOTOFFPC.
+       * config/arc/arc.md ("unspec"): Add ARC_UNSPEC_GOTOFFPC.
+       (*movsi_insn): Use @pcl syntax.
+       (doloop_begin_i): Likewise.
+
 2016-06-16  Martin Liska  <mliska@suse.cz>
 
        * predict.def: Define a new predictor.
index 49edc0a7f65759c2b00142ec1e0638305203625f..c0aa075cddb9da0e1f676db8d53d827e1b822181 100644 (file)
@@ -3528,7 +3528,8 @@ arc_print_operand_address (FILE *file , rtx addr)
                 || XINT (c, 1) == UNSPEC_TLS_IE))
            || (GET_CODE (c) == PLUS
                && GET_CODE (XEXP (c, 0)) == UNSPEC
-               && (XINT (XEXP (c, 0), 1) == UNSPEC_TLS_OFF)))
+               && (XINT (XEXP (c, 0), 1) == UNSPEC_TLS_OFF
+                   || XINT (XEXP (c, 0), 1) == ARC_UNSPEC_GOTOFFPC)))
          {
            arc_output_pic_addr_const (file, c, 0);
            break;
@@ -4636,6 +4637,7 @@ arc_needs_pcl_p (rtx x)
     switch (XINT (x, 1))
       {
       case ARC_UNSPEC_GOT:
+      case ARC_UNSPEC_GOTOFFPC:
       case UNSPEC_TLS_GD:
       case UNSPEC_TLS_IE:
        return true;
@@ -4698,9 +4700,10 @@ arc_legitimate_pic_addr_p (rtx addr)
       || XVECLEN (addr, 0) != 1)
     return false;
 
-  /* Must be one of @GOT, @GOTOFF, @tlsgd, tlsie.  */
+  /* Must be one of @GOT, @GOTOFF, @GOTOFFPC, @tlsgd, tlsie.  */
   if (XINT (addr, 1) != ARC_UNSPEC_GOT
       && XINT (addr, 1) != ARC_UNSPEC_GOTOFF
+      && XINT (addr, 1) != ARC_UNSPEC_GOTOFFPC
       && XINT (addr, 1) != UNSPEC_TLS_GD
       && XINT (addr, 1) != UNSPEC_TLS_IE)
     return false;
@@ -4917,26 +4920,15 @@ arc_legitimize_pic_address (rtx orig, rtx oldx)
       else if (!flag_pic)
        return orig;
       else if (CONSTANT_POOL_ADDRESS_P (addr) || SYMBOL_REF_LOCAL_P (addr))
-       {
-         /* This symbol may be referenced via a displacement from the
-            PIC base address (@GOTOFF).  */
+       return gen_rtx_CONST (Pmode,
+                             gen_rtx_UNSPEC (Pmode, gen_rtvec (1, addr),
+                             ARC_UNSPEC_GOTOFFPC));
 
-         /* FIXME: if we had a way to emit pc-relative adds that
-            don't create a GOT entry, we could do without the use of
-            the gp register.  */
-         crtl->uses_pic_offset_table = 1;
-         pat = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, addr), ARC_UNSPEC_GOTOFF);
-         pat = gen_rtx_CONST (Pmode, pat);
-         pat = gen_rtx_PLUS (Pmode, pic_offset_table_rtx, pat);
-       }
-      else
-       {
-         /* This symbol must be referenced via a load from the
-            Global Offset Table (@GOTPC).  */
-         pat = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, addr), ARC_UNSPEC_GOT);
-         pat = gen_rtx_CONST (Pmode, pat);
-         pat = gen_const_mem (Pmode, pat);
-       }
+      /* This symbol must be referenced via a load from the Global
+        Offset Table (@GOTPC).  */
+      pat = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, addr), ARC_UNSPEC_GOT);
+      pat = gen_rtx_CONST (Pmode, pat);
+      pat = gen_const_mem (Pmode, pat);
 
       if (oldx == NULL)
        oldx = gen_reg_rtx (Pmode);
@@ -4952,6 +4944,7 @@ arc_legitimize_pic_address (rtx orig, rtx oldx)
          if (GET_CODE (addr) == UNSPEC)
            {
              /* Check that the unspec is one of the ones we generate?  */
+             return orig;
            }
          else
            gcc_assert (GET_CODE (addr) == PLUS);
@@ -5105,6 +5098,9 @@ arc_output_pic_addr_const (FILE * file, rtx x, int code)
        case ARC_UNSPEC_GOTOFF:
          suffix = "@gotoff";
          break;
+       case ARC_UNSPEC_GOTOFFPC:
+         suffix = "@pcl",   pcrel = true;
+         break;
        case ARC_UNSPEC_PLT:
          suffix = "@plt";
          break;
@@ -5389,6 +5385,7 @@ arc_legitimate_constant_p (machine_mode mode, rtx x)
          {
          case ARC_UNSPEC_PLT:
          case ARC_UNSPEC_GOTOFF:
+         case ARC_UNSPEC_GOTOFFPC:
          case ARC_UNSPEC_GOT:
          case UNSPEC_TLS_GD:
          case UNSPEC_TLS_IE:
@@ -7648,7 +7645,7 @@ arc_output_libcall (const char *fname)
      || (TARGET_MEDIUM_CALLS && arc_ccfsm_cond_exec_p ()))
     {
       if (flag_pic)
-       sprintf (buf, "add r12,pcl,@%s-(.&-4)\n\tjl%%!%%* [r12]", fname);
+       sprintf (buf, "add r12,pcl,@%s@pcl\n\tjl%%!%%* [r12]", fname);
       else
        sprintf (buf, "jl%%! @%s", fname);
     }
@@ -8578,13 +8575,21 @@ arc_legitimize_address (rtx orig_x, rtx oldx, machine_mode mode)
 static rtx
 arc_delegitimize_address_0 (rtx x)
 {
-  rtx u, gp;
+  rtx u, gp, p;
 
   if (GET_CODE (x) == CONST && GET_CODE (u = XEXP (x, 0)) == UNSPEC)
     {
-      if (XINT (u, 1) == ARC_UNSPEC_GOT)
+      if (XINT (u, 1) == ARC_UNSPEC_GOT
+         || XINT (u, 1) == ARC_UNSPEC_GOTOFFPC)
        return XVECEXP (u, 0, 0);
     }
+  else if (GET_CODE (x) == CONST && GET_CODE (p = XEXP (x, 0)) == PLUS
+          && GET_CODE (u = XEXP (p, 0)) == UNSPEC
+          && (XINT (u, 1) == ARC_UNSPEC_GOT
+              || XINT (u, 1) == ARC_UNSPEC_GOTOFFPC))
+    return gen_rtx_CONST
+           (GET_MODE (x),
+            gen_rtx_PLUS (GET_MODE (p), XVECEXP (u, 0, 0), XEXP (p, 1)));
   else if (GET_CODE (x) == PLUS
           && ((REG_P (gp = XEXP (x, 0))
                && REGNO (gp) == PIC_OFFSET_TABLE_REGNUM)
index a4ee08450a8c8109000451a8537c347de80465cb..1102c53da2606e5c6f95ffc8f73cd9c8767f2e9e 100644 (file)
 ;;  UNSPEC_GOT       4        symbol to be rerenced through the GOT
 ;;  UNSPEC_GOTOFF    5        Local symbol.To be referenced relative to the
 ;;                            GOTBASE.(Referenced as @GOTOFF)
+;;  UNSPEC_GOTOFFPC  6        Local symbol.  To be referenced pc-relative.
 ;;  ----------------------------------------------------------------------------
 
 (define_c_enum "unspec" [
   ARC_UNSPEC_PLT
   ARC_UNSPEC_GOT
   ARC_UNSPEC_GOTOFF
+  ARC_UNSPEC_GOTOFFPC
   UNSPEC_TLS_GD
   UNSPEC_TLS_LD
   UNSPEC_TLS_IE
    * return INTVAL (operands[1]) & 0xffffff ? \"movbi.cl %0,%1 >> %p1,%p1,8;8\" : \"movbi.cl %0,%L1 >> 24,24,8;9\";
    mov%? %0,%1         ;10
    add %0,%S1          ;11
-   * return arc_get_unalign () ? \"add %0,pcl,%1-.+2\" : \"add %0,pcl,%1-.\";
+   add %0,pcl,%1@pcl    ;12
    mov%? %0,%S1%&      ;13
    mov%? %0,%S1                ;14
    ld%? %0,%1%&                ;15
          /* ??? Can do better for when a scratch register
             is known.  But that would require extra testing.  */
          arc_clear_unalign ();
-         return ".p2align 2\;push_s r0\;add r0,pcl,24\;sr r0,[2]; LP_START\;add r0,pcl,.L__GCC__LP%1-.+2\;sr r0,[3]; LP_END\;pop_s r0";
+         return ".p2align 2\;push_s r0\;add r0,pcl,24\;sr r0,[2]; LP_START\;add r0,pcl,.L__GCC__LP%1@pcl\;sr r0,[3]; LP_END\;pop_s r0";
        }
       output_asm_insn ((size < 2048
                        ? "lp .L__GCC__LP%1" : "sr .L__GCC__LP%1,[3]; LP_END"),