rs6000.c (rs6000_call_aix): Use unspec rather than mem for toc_restore.
authorAlan Modra <amodra@gmail.com>
Mon, 2 Feb 2015 07:16:11 +0000 (17:46 +1030)
committerAlan Modra <amodra@gcc.gnu.org>
Mon, 2 Feb 2015 07:16:11 +0000 (17:46 +1030)
gcc/
* config/rs6000/rs6000.c (rs6000_call_aix): Use unspec rather
than mem for toc_restore.
* config/rs6000/rs6000.md (UNSPEC_TOCSLOT): Define.
(call_indirect_aix, call_value_indirect_aix): Adjust to suit.
(call_indirect_elfv2, call_value_indirect_elfv2): Likewise.
gcc/testsuite/
* gcc.target/powerpc/cprophard.c: New.

From-SVN: r220344

gcc/ChangeLog
gcc/config/rs6000/rs6000.c
gcc/config/rs6000/rs6000.md
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.target/powerpc/cprophard.c [new file with mode: 0644]

index 3dcb6db8f37bc810df94e467aa2e97c837554f25..6453686a233ca7301d7796a7bc534c5be47ca9ba 100644 (file)
@@ -1,3 +1,11 @@
+2015-02-02  Alan Modra  <amodra@gmail.com>
+
+       * config/rs6000/rs6000.c (rs6000_call_aix): Use unspec rather
+       than mem for toc_restore.
+       * config/rs6000/rs6000.md (UNSPEC_TOCSLOT): Define.
+       (call_indirect_aix, call_value_indirect_aix): Adjust to suit.
+       (call_indirect_elfv2, call_value_indirect_elfv2): Likewise.
+
 2015-02-01  David Edelsohn  <dje.gcc@gmail.com>
 
        PR target/64047
index 661995cd08159a72ab3edd6f04a3c820c4e905c1..3c853dc046de5d4eea55332de2498e57a8ff1029 100644 (file)
@@ -32951,7 +32951,10 @@ rs6000_call_aix (rtx value, rtx func_desc, rtx flag, rtx cookie)
       rtx stack_toc_mem = gen_frame_mem (Pmode,
                                         gen_rtx_PLUS (Pmode, stack_ptr,
                                                       stack_toc_offset));
-      toc_restore = gen_rtx_SET (VOIDmode, toc_reg, stack_toc_mem);
+      rtx stack_toc_unspec = gen_rtx_UNSPEC (Pmode,
+                                            gen_rtvec (1, stack_toc_offset),
+                                            UNSPEC_TOCSLOT);
+      toc_restore = gen_rtx_SET (VOIDmode, toc_reg, stack_toc_unspec);
 
       /* Can we optimize saving the TOC in the prologue or
         do we need to do it at every call?  */
index a55719039e3a8d28bf67d968797acbc726488a9a..22787e2f70e3f2a4c927330b508b59a0c696fc40 100644 (file)
@@ -69,6 +69,7 @@
    UNSPEC_PROBE_STACK          ; probe stack memory reference
    UNSPEC_TOCPTR               ; address of a word pointing to the TOC
    UNSPEC_TOC                  ; address of the TOC (more-or-less)
+   UNSPEC_TOCSLOT              ; offset from r1 of toc pointer save slot
    UNSPEC_MOVSI_GOT
    UNSPEC_MV_CR_OV             ; move_from_CR_ov_bit
    UNSPEC_FCTIWZ
 ;; Call to indirect functions with the AIX abi using a 3 word descriptor.
 ;; Operand0 is the addresss of the function to call
 ;; Operand2 is the location in the function descriptor to load r2 from
-;; Operand3 is the stack location to hold the current TOC pointer
+;; Operand3 is the offset of the stack location holding the current TOC pointer
 
 (define_insn "*call_indirect_aix<mode>"
   [(call (mem:SI (match_operand:P 0 "register_operand" "c,*l"))
         (match_operand 1 "" "g,g"))
    (use (match_operand:P 2 "memory_operand" "<ptrm>,<ptrm>"))
-   (set (reg:P TOC_REGNUM) (match_operand:P 3 "memory_operand" "<ptrm>,<ptrm>"))
+   (set (reg:P TOC_REGNUM) (unspec [(match_operand:P 3 "const_int_operand" "n,n")] UNSPEC_TOCSLOT))
    (clobber (reg:P LR_REGNO))]
   "DEFAULT_ABI == ABI_AIX"
-  "<ptrload> 2,%2\;b%T0l\;<ptrload> 2,%3"
+  "<ptrload> 2,%2\;b%T0l\;<ptrload> 2,%3(1)"
   [(set_attr "type" "jmpreg")
    (set_attr "length" "12")])
 
        (call (mem:SI (match_operand:P 1 "register_operand" "c,*l"))
              (match_operand 2 "" "g,g")))
    (use (match_operand:P 3 "memory_operand" "<ptrm>,<ptrm>"))
-   (set (reg:P TOC_REGNUM) (match_operand:P 4 "memory_operand" "<ptrm>,<ptrm>"))
+   (set (reg:P TOC_REGNUM) (unspec [(match_operand:P 4 "const_int_operand" "n,n")] UNSPEC_TOCSLOT))
    (clobber (reg:P LR_REGNO))]
   "DEFAULT_ABI == ABI_AIX"
-  "<ptrload> 2,%3\;b%T1l\;<ptrload> 2,%4"
+  "<ptrload> 2,%3\;b%T1l\;<ptrload> 2,%4(1)"
   [(set_attr "type" "jmpreg")
    (set_attr "length" "12")])
 
 ;; Call to indirect functions with the ELFv2 ABI.
 ;; Operand0 is the addresss of the function to call
-;; Operand2 is the stack location to hold the current TOC pointer
+;; Operand2 is the offset of the stack location holding the current TOC pointer
 
 (define_insn "*call_indirect_elfv2<mode>"
   [(call (mem:SI (match_operand:P 0 "register_operand" "c,*l"))
         (match_operand 1 "" "g,g"))
-   (set (reg:P TOC_REGNUM) (match_operand:P 2 "memory_operand" "<ptrm>,<ptrm>"))
+   (set (reg:P TOC_REGNUM) (unspec [(match_operand:P 2 "const_int_operand" "n,n")] UNSPEC_TOCSLOT))
    (clobber (reg:P LR_REGNO))]
   "DEFAULT_ABI == ABI_ELFv2"
-  "b%T0l\;<ptrload> 2,%2"
+  "b%T0l\;<ptrload> 2,%2(1)"
   [(set_attr "type" "jmpreg")
    (set_attr "length" "8")])
 
   [(set (match_operand 0 "" "")
        (call (mem:SI (match_operand:P 1 "register_operand" "c,*l"))
              (match_operand 2 "" "g,g")))
-   (set (reg:P TOC_REGNUM) (match_operand:P 3 "memory_operand" "<ptrm>,<ptrm>"))
+   (set (reg:P TOC_REGNUM) (unspec [(match_operand:P 3 "const_int_operand" "n,n")] UNSPEC_TOCSLOT))
    (clobber (reg:P LR_REGNO))]
   "DEFAULT_ABI == ABI_ELFv2"
-  "b%T1l\;<ptrload> 2,%3"
+  "b%T1l\;<ptrload> 2,%3(1)"
   [(set_attr "type" "jmpreg")
    (set_attr "length" "8")])
 
index b15890b0cade2c41063c34cd65f0c0e1e41d6395..d9c83cf0716aede9fb09f11092fcc0afe9db713f 100644 (file)
@@ -1,3 +1,7 @@
+2015-02-02  Alan Modra  <amodra@gmail.com>
+
+       * gcc.target/powerpc/cprophard.c: New.
+
 2015-02-01  Andreas Tobler  <andreast@gcc.gnu.org>
 
        * gfortran.dg/enum_9.f90: Use arm_eabi instead of arm*-*-linux*.
diff --git a/gcc/testsuite/gcc.target/powerpc/cprophard.c b/gcc/testsuite/gcc.target/powerpc/cprophard.c
new file mode 100644 (file)
index 0000000..f93081f
--- /dev/null
@@ -0,0 +1,13 @@
+/* { dg-do compile { target { powerpc*-*-* && lp64 } } } */
+/* { dg-skip-if "" { powerpc*-*-darwin* } } */
+/* { dg-options "-O2" } */
+/* { dg-final { scan-assembler {ld 2,(24|40)\(1\)} } } */
+
+/* From a linux kernel mis-compile of net/core/skbuff.c.  */
+register unsigned long current_r1 asm ("r1");
+
+void f (unsigned int n, void (*fun) (unsigned long))
+{
+  while (n--)
+    (*fun) (current_r1 & -0x1000);
+}