rs6000.c (create_TOC_reference): Wrap high part of toc-relative address in CONST.
authorAlan Modra <amodra@gmail.com>
Mon, 20 Jun 2011 05:12:10 +0000 (14:42 +0930)
committerAlan Modra <amodra@gcc.gnu.org>
Mon, 20 Jun 2011 05:12:10 +0000 (14:42 +0930)
* config/rs6000/rs6000.c (create_TOC_reference): Wrap high part
of toc-relative address in CONST.
(rs6000_delegitimize_address): Recognize changed address.
(rs6000_legitimize_reload_address): Likewise.
(rs6000_emit_move): Don't force these constants to memory.
* config/rs6000/rs6000.md (tls_gd, tls_gd_high): Wrap high part of
toc-relative address in CONST.
(tls_ld, tls_ld_high, tls_got_dtprel, tls_got_dtprel_high): Likewise.
(tls_got_tprel, tls_got_tprel_high, largetoc_high): Likewise.

From-SVN: r175200

gcc/ChangeLog
gcc/config/rs6000/rs6000.c
gcc/config/rs6000/rs6000.md

index 31f23a23c12bc6b53bcc18962deeef0914a342ce..c971faf5c76ce22e6847ec9acffae040a3512a64 100644 (file)
@@ -1,3 +1,15 @@
+2011-06-20  Alan Modra  <amodra@gmail.com>
+
+       * config/rs6000/rs6000.c (create_TOC_reference): Wrap high part
+       of toc-relative address in CONST.
+       (rs6000_delegitimize_address): Recognize changed address.
+       (rs6000_legitimize_reload_address): Likewise.
+       (rs6000_emit_move): Don't force these constants to memory.
+       * config/rs6000/rs6000.md (tls_gd, tls_gd_high): Wrap high part of
+       toc-relative address in CONST.
+       (tls_ld, tls_ld_high, tls_got_dtprel, tls_got_dtprel_high): Likewise.
+       (tls_got_tprel, tls_got_tprel_high, largetoc_high): Likewise.
+
 2011-06-18  H.J. Lu  <hongjiu.lu@intel.com>
 
        * longlong.h (count_leading_zeros): Use long long builtin for
index c15c04e1e6a2a71c0af0a391b1e7e3896f11600e..df6e7d93a5d3d5eddb35288173992b3219cce040 100644 (file)
@@ -5803,12 +5803,13 @@ rs6000_delegitimize_address (rtx orig_x)
                   || TARGET_MINIMAL_TOC
                   || TARGET_CMODEL != CMODEL_SMALL))
              || (TARGET_CMODEL != CMODEL_SMALL
-                 && GET_CODE (XEXP (x, 0)) == PLUS
-                 && GET_CODE (XEXP (XEXP (x, 0), 0)) == REG
-                 && REGNO (XEXP (XEXP (x, 0), 0)) == TOC_REGISTER
-                 && GET_CODE (XEXP (XEXP (x, 0), 1)) == HIGH
+                 && GET_CODE (XEXP (x, 0)) == CONST
+                 && GET_CODE (XEXP (XEXP (x, 0), 0)) == PLUS
+                 && GET_CODE (XEXP (XEXP (XEXP (x, 0), 0), 0)) == REG
+                 && REGNO (XEXP (XEXP (XEXP (x, 0), 0), 0)) == TOC_REGISTER
+                 && GET_CODE (XEXP (XEXP (XEXP (x, 0), 0), 1)) == HIGH
                  && rtx_equal_p (XEXP (x, 1),
-                                 XEXP (XEXP (XEXP (x, 0), 1), 0)))))
+                                 XEXP (XEXP (XEXP (XEXP (x, 0), 0), 1), 0)))))
        {
          y = XVECEXP (y, 0, 0);
          if (offset != NULL_RTX)
@@ -6147,11 +6148,12 @@ rs6000_legitimize_reload_address (rtx x, enum machine_mode mode,
       && GET_CODE (XEXP (x, 0)) == PLUS
       && GET_CODE (XEXP (XEXP (x, 0), 0)) == REG
       && REGNO (XEXP (XEXP (x, 0), 0)) == TOC_REGISTER
-      && GET_CODE (XEXP (XEXP (x, 0), 1)) == HIGH
+      && GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST
+      && GET_CODE (XEXP (XEXP (XEXP (x, 0), 1), 0)) == HIGH
       && GET_CODE (XEXP (x, 1)) == CONST
       && GET_CODE (XEXP (XEXP (x, 1), 0)) == UNSPEC
       && XINT (XEXP (XEXP (x, 1), 0), 1) == UNSPEC_TOCREL
-      && rtx_equal_p (XEXP (XEXP (XEXP (x, 0), 1), 0), XEXP (x, 1)))
+      && rtx_equal_p (XEXP (XEXP (XEXP (XEXP (x, 0), 1), 0), 0), XEXP (x, 1)))
     {
       push_reload (XEXP (x, 0), NULL_RTX, &XEXP (x, 0), NULL,
                   BASE_REG_CLASS, Pmode, VOIDmode, 0, 0,
@@ -7197,6 +7199,11 @@ rs6000_emit_move (rtx dest, rtx source, enum machine_mode mode)
        }
       else if (mode == Pmode
               && CONSTANT_P (operands[1])
+              && GET_CODE (operands[1]) != HIGH
+              && !(TARGET_CMODEL != CMODEL_SMALL
+                   && GET_CODE (operands[1]) == CONST
+                   && GET_CODE (XEXP (operands[1], 0)) == PLUS
+                   && GET_CODE (XEXP (XEXP (operands[1], 0), 1)) == HIGH)
               && ((GET_CODE (operands[1]) != CONST_INT
                    && ! easy_fp_constant (operands[1], mode))
                   || (GET_CODE (operands[1]) == CONST_INT
@@ -7204,7 +7211,6 @@ rs6000_emit_move (rtx dest, rtx source, enum machine_mode mode)
                           > (TARGET_CMODEL != CMODEL_SMALL ? 3 : 2)))
                   || (GET_CODE (operands[0]) == REG
                       && FP_REGNO_P (REGNO (operands[0]))))
-              && GET_CODE (operands[1]) != HIGH
               && ! legitimate_constant_pool_address_p (operands[1], mode,
                                                        false)
               && ! toc_relative_expr_p (operands[1])
@@ -19063,7 +19069,9 @@ create_TOC_reference (rtx symbol, rtx largetoc_reg)
   tocreg = gen_rtx_REG (Pmode, TOC_REGISTER);
   if (TARGET_CMODEL != CMODEL_SMALL)
     {
-      rtx hi = gen_rtx_PLUS (Pmode, tocreg, gen_rtx_HIGH (Pmode, tocrel));
+      rtx hi = gen_rtx_CONST (Pmode,
+                             gen_rtx_PLUS (Pmode, tocreg, 
+                                           gen_rtx_HIGH (Pmode, tocrel)));
       if (largetoc_reg != NULL)
        {
          emit_move_insn (largetoc_reg, hi);
index 61a70eeff338baf1de303481ceaeb994af13fe2e..e70598d9f3e7707aac518dd7203c6ae9949db237 100644 (file)
   "addi %0,%1,%2@got@tlsgd"
   "&& TARGET_CMODEL != CMODEL_SMALL"
   [(set (match_dup 3)
-       (plus:TLSmode (match_dup 1)
-         (high:TLSmode
-           (unspec:TLSmode [(match_dup 2)] UNSPEC_TLSGD))))
+       (const:TLSmode
+         (plus:TLSmode (match_dup 1)
+           (high:TLSmode
+             (unspec:TLSmode [(match_dup 2)] UNSPEC_TLSGD)))))
    (set (match_dup 0)
        (lo_sum:TLSmode (match_dup 3)
            (unspec:TLSmode [(match_dup 2)] UNSPEC_TLSGD)))]
 
 (define_insn "*tls_gd_high<TLSmode:tls_abi_suffix>"
   [(set (match_operand:TLSmode 0 "gpc_reg_operand" "=b")
-     (plus:TLSmode (match_operand:TLSmode 1 "gpc_reg_operand" "b")
-       (high:TLSmode
-         (unspec:TLSmode [(match_operand:TLSmode 2 "rs6000_tls_symbol_ref" "")]
-                         UNSPEC_TLSGD))))]
+     (const:TLSmode
+       (plus:TLSmode (match_operand:TLSmode 1 "gpc_reg_operand" "b")
+        (high:TLSmode
+          (unspec:TLSmode [(match_operand:TLSmode 2 "rs6000_tls_symbol_ref" "")]
+                          UNSPEC_TLSGD)))))]
   "HAVE_AS_TLS && TARGET_TLS_MARKERS && TARGET_CMODEL != CMODEL_SMALL"
   "addis %0,%1,%2@got@tlsgd@ha"
   [(set_attr "length" "4")])
   "addi %0,%1,%&@got@tlsld"
   "&& TARGET_CMODEL != CMODEL_SMALL"
   [(set (match_dup 2)
-       (plus:TLSmode (match_dup 1)
-         (high:TLSmode
-           (unspec:TLSmode [(const_int 0)] UNSPEC_TLSLD))))
+       (const:TLSmode
+         (plus:TLSmode (match_dup 1)
+           (high:TLSmode
+             (unspec:TLSmode [(const_int 0)] UNSPEC_TLSLD)))))
    (set (match_dup 0)
        (lo_sum:TLSmode (match_dup 2)
            (unspec:TLSmode [(const_int 0)] UNSPEC_TLSLD)))]
 
 (define_insn "*tls_ld_high<TLSmode:tls_abi_suffix>"
   [(set (match_operand:TLSmode 0 "gpc_reg_operand" "=b")
-     (plus:TLSmode (match_operand:TLSmode 1 "gpc_reg_operand" "b")
-       (high:TLSmode
-         (unspec:TLSmode [(const_int 0)] UNSPEC_TLSLD))))]
+     (const:TLSmode
+       (plus:TLSmode (match_operand:TLSmode 1 "gpc_reg_operand" "b")
+        (high:TLSmode
+          (unspec:TLSmode [(const_int 0)] UNSPEC_TLSLD)))))]
   "HAVE_AS_TLS && TARGET_TLS_MARKERS && TARGET_CMODEL != CMODEL_SMALL"
   "addis %0,%1,%&@got@tlsld@ha"
   [(set_attr "length" "4")])
   "l<TLSmode:tls_insn_suffix> %0,%2@got@dtprel(%1)"
   "&& TARGET_CMODEL != CMODEL_SMALL"
   [(set (match_dup 3)
-       (plus:TLSmode (match_dup 1)
-         (high:TLSmode
-           (unspec:TLSmode [(match_dup 2)] UNSPEC_TLSGOTDTPREL))))
+       (const:TLSmode
+         (plus:TLSmode (match_dup 1)
+           (high:TLSmode
+             (unspec:TLSmode [(match_dup 2)] UNSPEC_TLSGOTDTPREL)))))
    (set (match_dup 0)
        (lo_sum:TLSmode (match_dup 3)
            (unspec:TLSmode [(match_dup 2)] UNSPEC_TLSGOTDTPREL)))]
 
 (define_insn "*tls_got_dtprel_high<TLSmode:tls_abi_suffix>"
   [(set (match_operand:TLSmode 0 "gpc_reg_operand" "=b")
-     (plus:TLSmode (match_operand:TLSmode 1 "gpc_reg_operand" "b")
-       (high:TLSmode
-        (unspec:TLSmode [(match_operand:TLSmode 2 "rs6000_tls_symbol_ref" "")]
-                        UNSPEC_TLSGOTDTPREL))))]
+     (const:TLSmode
+       (plus:TLSmode (match_operand:TLSmode 1 "gpc_reg_operand" "b")
+        (high:TLSmode
+          (unspec:TLSmode [(match_operand:TLSmode 2 "rs6000_tls_symbol_ref" "")]
+                          UNSPEC_TLSGOTDTPREL)))))]
   "HAVE_AS_TLS && TARGET_CMODEL != CMODEL_SMALL"
   "addis %0,%1,%2@got@dtprel@ha"
   [(set_attr "length" "4")])
   "l<TLSmode:tls_insn_suffix> %0,%2@got@tprel(%1)"
   "&& TARGET_CMODEL != CMODEL_SMALL"
   [(set (match_dup 3)
-       (plus:TLSmode (match_dup 1)
-         (high:TLSmode
-           (unspec:TLSmode [(match_dup 2)] UNSPEC_TLSGOTTPREL))))
+       (const:TLSmode
+         (plus:TLSmode (match_dup 1)
+           (high:TLSmode
+             (unspec:TLSmode [(match_dup 2)] UNSPEC_TLSGOTTPREL)))))
    (set (match_dup 0)
        (lo_sum:TLSmode (match_dup 3)
            (unspec:TLSmode [(match_dup 2)] UNSPEC_TLSGOTTPREL)))]
 
 (define_insn "*tls_got_tprel_high<TLSmode:tls_abi_suffix>"
   [(set (match_operand:TLSmode 0 "gpc_reg_operand" "=b")
-     (plus:TLSmode (match_operand:TLSmode 1 "gpc_reg_operand" "b")
-       (high:TLSmode
-        (unspec:TLSmode [(match_operand:TLSmode 2 "rs6000_tls_symbol_ref" "")]
-                        UNSPEC_TLSGOTTPREL))))]
+     (const:TLSmode
+       (plus:TLSmode (match_operand:TLSmode 1 "gpc_reg_operand" "b")
+        (high:TLSmode
+          (unspec:TLSmode [(match_operand:TLSmode 2 "rs6000_tls_symbol_ref" "")]
+                          UNSPEC_TLSGOTTPREL)))))]
   "HAVE_AS_TLS && TARGET_CMODEL != CMODEL_SMALL"
   "addis %0,%1,%2@got@tprel@ha"
   [(set_attr "length" "4")])
 ;; Largetoc support
 (define_insn "largetoc_high"
   [(set (match_operand:DI 0 "gpc_reg_operand" "=b")
-        (plus:DI (match_operand:DI 1 "gpc_reg_operand" "b")
-                (high:DI (match_operand:DI 2 "" ""))))]
+       (const:DI
+         (plus:DI (match_operand:DI 1 "gpc_reg_operand" "b")
+                  (high:DI (match_operand:DI 2 "" "")))))]
    "TARGET_ELF && TARGET_CMODEL != CMODEL_SMALL"
    "{cau|addis} %0,%1,%2@ha")