With lazy PLT resolution the first load of a PLT entry may be a value
pointing at a resolver stub.  gcc's loop processing can result in the
PLT load in inline PLT calls being hoisted out of a loop in the
mistaken idea that this is an optimisation.  It isn't.  If the value
hoisted was that for a resolver stub then every call to that function
in the loop will go via the resolver, slowing things down quite
dramatically.

The PLT really is volatile, so teach gcc about that.

Bootstrapped and regression tested on powerpc64le-linux and tested
with a spec build using -mlongcalls.  OK for mainline?

        * config/rs6000/rs6000.c (rs6000_longcall_ref): Use unspec_volatile
        for PLT16_LO and PLT_PCREL.
        * config/rs6000/rs6000.md (UNSPEC_PLT16_LO, UNSPEC_PLT_PCREL): Remove.
        (UNSPECV_PLT16_LO, UNSPECV_PLT_PCREL): Define.
        (pltseq_plt16_lo_, pltseq_plt_pcrel): Use unspec_volatile.

diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c
index 46b7dec2abd..2d6790877fa 100644
--- a/gcc/config/rs6000/rs6000.c
+++ b/gcc/config/rs6000/rs6000.c
@@ -19264,8 +19264,9 @@ rs6000_longcall_ref (rtx call_ref, rtx arg)
       if (rs6000_pcrel_p (cfun))
        {
          rtx reg = gen_rtx_REG (Pmode, regno);
-         rtx u = gen_rtx_UNSPEC (Pmode, gen_rtvec (3, base, call_ref, arg),
-                                 UNSPEC_PLT_PCREL);
+         rtx u = gen_rtx_UNSPEC_VOLATILE (Pmode,
+                                          gen_rtvec (3, base, call_ref, arg),
+                                          UNSPECV_PLT_PCREL);
          emit_insn (gen_rtx_SET (reg, u));
          return reg;
        }
@@ -19284,8 +19285,9 @@ rs6000_longcall_ref (rtx call_ref, rtx arg)
       rtx reg = gen_rtx_REG (Pmode, regno);
       rtx hi = gen_rtx_UNSPEC (Pmode, gen_rtvec (3, base, call_ref, arg),
                               UNSPEC_PLT16_HA);
-      rtx lo = gen_rtx_UNSPEC (Pmode, gen_rtvec (3, reg, call_ref, arg),
-                              UNSPEC_PLT16_LO);
+      rtx lo = gen_rtx_UNSPEC_VOLATILE (Pmode,
+                                       gen_rtvec (3, reg, call_ref, arg),
+                                       UNSPECV_PLT16_LO);
       emit_insn (gen_rtx_SET (reg, hi));
       emit_insn (gen_rtx_SET (reg, lo));
       return reg;
diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md
index ad88b6783af..5a8e9de670b 100644
--- a/gcc/config/rs6000/rs6000.md
+++ b/gcc/config/rs6000/rs6000.md
@@ -148,8 +148,6 @@
    UNSPEC_SI_FROM_SF
    UNSPEC_PLTSEQ
    UNSPEC_PLT16_HA
-   UNSPEC_PLT16_LO
-   UNSPEC_PLT_PCREL
   ])
 
 ;;
@@ -178,6 +176,8 @@
    UNSPECV_MTFSB1              ; Set FPSCR Field bit to 1
    UNSPECV_SPLIT_STACK_RETURN   ; A camouflaged return
    UNSPECV_SPEC_BARRIER         ; Speculation barrier
+   UNSPECV_PLT16_LO
+   UNSPECV_PLT_PCREL
   ])
 
 ; The three different kinds of epilogue.
@@ -10359,10 +10359,10 @@
 
 (define_insn "*pltseq_plt16_lo_<mode>"
   [(set (match_operand:P 0 "gpc_reg_operand" "=r")
-       (unspec:P [(match_operand:P 1 "gpc_reg_operand" "b")
-                  (match_operand:P 2 "symbol_ref_operand" "s")
-                  (match_operand:P 3 "" "")]
-                 UNSPEC_PLT16_LO))]
+       (unspec_volatile:P [(match_operand:P 1 "gpc_reg_operand" "b")
+                           (match_operand:P 2 "symbol_ref_operand" "s")
+                           (match_operand:P 3 "" "")]
+                          UNSPECV_PLT16_LO))]
   "TARGET_PLTSEQ"
 {
   return rs6000_pltseq_template (operands, RS6000_PLTSEQ_PLT16_LO);
@@ -10382,10 +10382,10 @@
 
 (define_insn "*pltseq_plt_pcrel<mode>"
   [(set (match_operand:P 0 "gpc_reg_operand" "=r")
-       (unspec:P [(match_operand:P 1 "" "")
-                  (match_operand:P 2 "symbol_ref_operand" "s")
-                  (match_operand:P 3 "" "")]
-                 UNSPEC_PLT_PCREL))]
+       (unspec_volatile:P [(match_operand:P 1 "" "")
+                           (match_operand:P 2 "symbol_ref_operand" "s")
+                           (match_operand:P 3 "" "")]
+                          UNSPECV_PLT_PCREL))]
   "HAVE_AS_PLTSEQ && TARGET_ELF
    && rs6000_pcrel_p (cfun)"
 {

-- 
Alan Modra
Australia Development Lab, IBM

Reply via email to