re PR target/42564 (unrecognizable insn with -O -fPIC)
authorEric Botcazou <ebotcazou@adacore.com>
Tue, 5 Jan 2010 22:29:18 +0000 (22:29 +0000)
committerEric Botcazou <ebotcazou@gcc.gnu.org>
Tue, 5 Jan 2010 22:29:18 +0000 (22:29 +0000)
PR target/42564
* config/sparc/sparc.h (SPARC_SYMBOL_REF_TLS_P): Delete.
* config/sparc/sparc-protos.h (legitimize_pic_address): Likewise.
(legitimize_tls_address): Likewise.
(sparc_tls_referenced_p): Likewise.
* config/sparc/sparc.c (sparc_expand_move): Use legitimize_tls_address
and adjust calls to legitimize_pic_address.
(legitimate_constant_p) Use sparc_tls_referenced_p.
(legitimate_pic_operand_p): Likewise.
(sparc_legitimate_address_p): Do not use SPARC_SYMBOL_REF_TLS_P.
(sparc_tls_symbol_ref_1): Delete.
(sparc_tls_referenced_p): Make static, recognize specific patterns.
(legitimize_tls_address): Make static, handle CONST patterns.
(legitimize_pic_address): Make static, remove unused parameter and
adjust recursive calls.
(sparc_legitimize_address): Make static, use sparc_tls_referenced_p
and adjust call to legitimize_pic_address.
(sparc_output_mi_thunk): Likewise.

From-SVN: r155662

gcc/ChangeLog
gcc/config/sparc/sparc-protos.h
gcc/config/sparc/sparc.c
gcc/config/sparc/sparc.h
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/tls/opt-15.c [new file with mode: 0644]

index fc334daf61292b6fbfbd42388efc74287ce772a8..40a277b119d949cbf17d0bb78b5b656e0ec359ed 100644 (file)
@@ -1,3 +1,24 @@
+2010-01-05  Eric Botcazou  <ebotcazou@adacore.com>
+
+       PR target/42564
+       * config/sparc/sparc.h (SPARC_SYMBOL_REF_TLS_P): Delete.
+       * config/sparc/sparc-protos.h (legitimize_pic_address): Likewise.
+       (legitimize_tls_address): Likewise.
+       (sparc_tls_referenced_p): Likewise.
+       * config/sparc/sparc.c (sparc_expand_move): Use legitimize_tls_address
+       and adjust calls to legitimize_pic_address.
+       (legitimate_constant_p) Use sparc_tls_referenced_p.
+       (legitimate_pic_operand_p): Likewise.
+       (sparc_legitimate_address_p): Do not use SPARC_SYMBOL_REF_TLS_P.
+       (sparc_tls_symbol_ref_1): Delete.
+       (sparc_tls_referenced_p): Make static, recognize specific patterns.
+       (legitimize_tls_address): Make static, handle CONST patterns.
+       (legitimize_pic_address): Make static, remove unused parameter and
+       adjust recursive calls.
+       (sparc_legitimize_address): Make static, use sparc_tls_referenced_p
+       and adjust call to legitimize_pic_address.
+       (sparc_output_mi_thunk): Likewise.
+
 2010-01-05  Paolo Bonzini  <bonzinI@gnu.rg>
            H.J. Lu  <hongjiu.lu@intel.com>
 
index 097b709624be246c88d45e98b7f04a29ffab8a41..b76e45b433a3107c9c45289b7756c60c6d6c3725 100644 (file)
@@ -64,8 +64,6 @@ extern void emit_tfmode_cvt (enum rtx_code, rtx *);
 extern bool legitimate_constant_p (rtx);
 extern bool constant_address_p (rtx);
 extern bool legitimate_pic_operand_p (rtx);
-extern rtx legitimize_pic_address (rtx, enum machine_mode, rtx);
-extern rtx legitimize_tls_address (rtx);
 extern void sparc_emit_call_insn (rtx, rtx);
 extern void sparc_defer_case_vector (rtx, rtx, int);
 extern bool sparc_expand_move (enum machine_mode, rtx *);
@@ -97,7 +95,6 @@ extern int emit_move_sequence (rtx, enum machine_mode);
 extern int fp_sethi_p (rtx);
 extern int fp_mov_p (rtx);
 extern int fp_high_losum_p (rtx);
-extern bool sparc_tls_referenced_p (rtx);
 extern int mem_min_alignment (rtx, int);
 extern int pic_address_needs_scratch (rtx);
 extern int reg_unused_after (rtx, rtx);
index 82bc7d51e40fa7986bfc1e98dd3d2c83570b820e..4b904b4535236332a3bdd54bfb8c3a7360470d6e 100644 (file)
@@ -411,6 +411,9 @@ static bool sparc_strict_argument_naming (CUMULATIVE_ARGS *);
 static void sparc_va_start (tree, rtx);
 static tree sparc_gimplify_va_arg (tree, tree, gimple_seq *, gimple_seq *);
 static bool sparc_vector_mode_supported_p (enum machine_mode);
+static bool sparc_tls_referenced_p (rtx);
+static rtx legitimize_tls_address (rtx);
+static rtx legitimize_pic_address (rtx, rtx);
 static rtx sparc_legitimize_address (rtx, rtx, enum machine_mode);
 static bool sparc_pass_by_reference (CUMULATIVE_ARGS *,
                                     enum machine_mode, const_tree, bool);
@@ -992,34 +995,17 @@ sparc_expand_move (enum machine_mode mode, rtx *operands)
   /* Fixup TLS cases.  */
   if (TARGET_HAVE_TLS
       && CONSTANT_P (operands[1])
-      && GET_CODE (operands[1]) != HIGH
       && sparc_tls_referenced_p (operands [1]))
     {
-      rtx sym = operands[1];
-      rtx addend = NULL;
-
-      if (GET_CODE (sym) == CONST && GET_CODE (XEXP (sym, 0)) == PLUS)
-       {
-         addend = XEXP (XEXP (sym, 0), 1);
-         sym = XEXP (XEXP (sym, 0), 0);
-       }
-
-      gcc_assert (SPARC_SYMBOL_REF_TLS_P (sym));
-
-      sym = legitimize_tls_address (sym);
-      if (addend)
-       {
-         sym = gen_rtx_PLUS (mode, sym, addend);
-         sym = force_operand (sym, operands[0]);
-       }
-      operands[1] = sym;
+      operands[1] = legitimize_tls_address (operands[1]);
+      return false;
     }
 
   /* Fixup PIC cases.  */
   if (flag_pic && CONSTANT_P (operands[1]))
     {
       if (pic_address_needs_scratch (operands[1]))
-       operands[1] = legitimize_pic_address (operands[1], mode, 0);
+       operands[1] = legitimize_pic_address (operands[1], NULL_RTX);
 
       /* 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
@@ -1047,10 +1033,8 @@ sparc_expand_move (enum machine_mode mode, rtx *operands)
       if (symbolic_operand (operands[1], mode))
        {
          operands[1] = legitimize_pic_address (operands[1],
-                                               mode,
-                                               (reload_in_progress ?
-                                                operands[0] :
-                                                NULL_RTX));
+                                               reload_in_progress
+                                               ? operands[0] : NULL_RTX);
          return false;
        }
     }
@@ -2979,23 +2963,11 @@ pic_address_needs_scratch (rtx x)
 bool
 legitimate_constant_p (rtx x)
 {
-  rtx inner;
-
   switch (GET_CODE (x))
     {
-    case SYMBOL_REF:
-      /* TLS symbols are not constant.  */
-      if (SYMBOL_REF_TLS_MODEL (x))
-       return false;
-      break;
-
     case CONST:
-      inner = XEXP (x, 0);
-
-      /* Offsets of TLS symbols are never valid.
-        Discourage CSE from creating them.  */
-      if (GET_CODE (inner) == PLUS
-         && SPARC_SYMBOL_REF_TLS_P (XEXP (inner, 0)))
+    case SYMBOL_REF:
+      if (sparc_tls_referenced_p (x))
        return false;
       break;
 
@@ -3062,10 +3034,7 @@ legitimate_pic_operand_p (rtx x)
 {
   if (pic_address_needs_scratch (x))
     return false;
-  if (SPARC_SYMBOL_REF_TLS_P (x)
-      || (GET_CODE (x) == CONST
-         && GET_CODE (XEXP (x, 0)) == PLUS
-         && SPARC_SYMBOL_REF_TLS_P (XEXP (XEXP (x, 0), 0))))
+  if (sparc_tls_referenced_p (x))
     return false;
   return true;
 }
@@ -3103,7 +3072,7 @@ sparc_legitimate_address_p (enum machine_mode mode, rtx addr, bool strict)
           && GET_CODE (rs2) != SUBREG
           && GET_CODE (rs2) != LO_SUM
           && GET_CODE (rs2) != MEM
-          && ! SPARC_SYMBOL_REF_TLS_P (rs2)
+          && !(GET_CODE (rs2) == SYMBOL_REF && SYMBOL_REF_TLS_MODEL (rs2))
           && (! symbolic_operand (rs2, VOIDmode) || mode == Pmode)
           && (GET_CODE (rs2) != CONST_INT || SMALL_INT (rs2)))
          || ((REG_P (rs1)
@@ -3143,7 +3112,8 @@ sparc_legitimate_address_p (enum machine_mode mode, rtx addr, bool strict)
          rs2 = NULL;
          imm1 = XEXP (rs1, 1);
          rs1 = XEXP (rs1, 0);
-         if (! CONSTANT_P (imm1) || SPARC_SYMBOL_REF_TLS_P (rs1))
+         if (!CONSTANT_P (imm1)
+             || (GET_CODE (rs1) == SYMBOL_REF && SYMBOL_REF_TLS_MODEL (rs1)))
            return 0;
        }
     }
@@ -3152,7 +3122,8 @@ sparc_legitimate_address_p (enum machine_mode mode, rtx addr, bool strict)
       rs1 = XEXP (addr, 0);
       imm1 = XEXP (addr, 1);
 
-      if (! CONSTANT_P (imm1) || SPARC_SYMBOL_REF_TLS_P (rs1))
+      if (!CONSTANT_P (imm1)
+         || (GET_CODE (rs1) == SYMBOL_REF && SYMBOL_REF_TLS_MODEL (rs1)))
        return 0;
 
       /* We can't allow TFmode in 32-bit mode, because an offset greater
@@ -3228,29 +3199,28 @@ sparc_tls_got (void)
   return temp;
 }
 
-/* Return 1 if *X is a thread-local symbol.  */
-
-static int
-sparc_tls_symbol_ref_1 (rtx *x, void *data ATTRIBUTE_UNUSED)
-{
-  return SPARC_SYMBOL_REF_TLS_P (*x);
-}
-
-/* Return 1 if X contains a thread-local symbol.  */
+/* Return true if X contains a thread-local symbol.  */
 
-bool
+static bool
 sparc_tls_referenced_p (rtx x)
 {
   if (!TARGET_HAVE_TLS)
     return false;
 
-  return for_each_rtx (&x, &sparc_tls_symbol_ref_1, 0);
+  if (GET_CODE (x) == CONST && GET_CODE (XEXP (x, 0)) == PLUS)
+    x = XEXP (XEXP (x, 0), 0);
+
+  if (GET_CODE (x) == SYMBOL_REF && SYMBOL_REF_TLS_MODEL (x))
+    return true;
+
+  /* That's all we handle in legitimize_tls_address for now.  */
+  return false;
 }
 
 /* ADDR contains a thread-local SYMBOL_REF.  Generate code to compute
    this (thread-local) address.  */
 
-rtx
+static rtx
 legitimize_tls_address (rtx addr)
 {
   rtx temp1, temp2, temp3, ret, o0, got, insn;
@@ -3374,21 +3344,34 @@ legitimize_tls_address (rtx addr)
        gcc_unreachable ();
       }
 
+  else if (GET_CODE (addr) == CONST)
+    {
+      rtx base, offset;
+
+      gcc_assert (GET_CODE (XEXP (addr, 0)) == PLUS);
+
+      base = legitimize_tls_address (XEXP (XEXP (addr, 0), 0));
+      offset = XEXP (XEXP (addr, 0), 1);
+
+      base = force_operand (base, NULL_RTX);
+      if (!(GET_CODE (offset) == CONST_INT && SMALL_INT (offset)))
+       offset = force_reg (Pmode, offset);
+      ret = gen_rtx_PLUS (Pmode, base, offset);
+    }
+
   else
     gcc_unreachable ();  /* for now ... */
 
   return ret;
 }
 
-
 /* Legitimize PIC addresses.  If the address is already position-independent,
    we return ORIG.  Newly generated position-independent addresses go into a
    reg.  This is REG if nonzero, otherwise we allocate register(s) as
    necessary.  */
 
-rtx
-legitimize_pic_address (rtx orig, enum machine_mode mode ATTRIBUTE_UNUSED,
-                       rtx reg)
+static rtx
+legitimize_pic_address (rtx orig, rtx reg)
 {
   if (GET_CODE (orig) == SYMBOL_REF
       /* See the comment in sparc_expand_move.  */
@@ -3455,9 +3438,9 @@ legitimize_pic_address (rtx orig, enum machine_mode mode ATTRIBUTE_UNUSED,
        }
 
       gcc_assert (GET_CODE (XEXP (orig, 0)) == PLUS);
-      base = legitimize_pic_address (XEXP (XEXP (orig, 0), 0), Pmode, reg);
-      offset = legitimize_pic_address (XEXP (XEXP (orig, 0), 1), Pmode,
-                                      base == reg ? 0 : reg);
+      base = legitimize_pic_address (XEXP (XEXP (orig, 0), 0), reg);
+      offset = legitimize_pic_address (XEXP (XEXP (orig, 0), 1),
+                                      base == reg ? NULL_RTX : reg);
 
       if (GET_CODE (offset) == CONST_INT)
        {
@@ -3490,7 +3473,7 @@ legitimize_pic_address (rtx orig, enum machine_mode mode ATTRIBUTE_UNUSED,
 
    On SPARC, change REG+N into REG+REG, and REG+(X*Y) into REG+REG.  */
 
-rtx
+static rtx
 sparc_legitimize_address (rtx x, rtx oldx ATTRIBUTE_UNUSED,
                          enum machine_mode mode)
 {
@@ -3512,10 +3495,10 @@ sparc_legitimize_address (rtx x, rtx oldx ATTRIBUTE_UNUSED,
   if (x != orig_x && sparc_legitimate_address_p (mode, x, FALSE))
     return x;
 
-  if (SPARC_SYMBOL_REF_TLS_P (x))
+  if (sparc_tls_referenced_p (x))
     x = legitimize_tls_address (x);
   else if (flag_pic)
-    x = legitimize_pic_address (x, mode, 0);
+    x = legitimize_pic_address (x, NULL_RTX);
   else if (GET_CODE (x) == PLUS && CONSTANT_ADDRESS_P (XEXP (x, 1)))
     x = gen_rtx_PLUS (Pmode, XEXP (x, 0),
                      copy_to_mode_reg (Pmode, XEXP (x, 1)));
@@ -3524,8 +3507,9 @@ sparc_legitimize_address (rtx x, rtx oldx ATTRIBUTE_UNUSED,
                      copy_to_mode_reg (Pmode, XEXP (x, 0)));
   else if (GET_CODE (x) == SYMBOL_REF
           || GET_CODE (x) == CONST
-           || GET_CODE (x) == LABEL_REF)
+          || GET_CODE (x) == LABEL_REF)
     x = copy_to_suggested_reg (x, NULL_RTX, Pmode);
+
   return x;
 }
 
@@ -8899,7 +8883,7 @@ sparc_output_mi_thunk (FILE *file, tree thunk_fndecl ATTRIBUTE_UNUSED,
          /* Delay emitting the PIC helper function because it needs to
             change the section and we are emitting assembly code.  */
          load_pic_register (true);  /* clobbers %o7 */
-         scratch = legitimize_pic_address (funexp, Pmode, scratch);
+         scratch = legitimize_pic_address (funexp, scratch);
          seq = get_insns ();
          end_sequence ();
          emit_and_preserve (seq, spill_reg, spill_reg2);
index 58c584e6b305ace760fb5eb97f2752fbd73e2dec..344441e1bcb69316e76c10d8dc28cef491f2ab65 100644 (file)
@@ -2213,9 +2213,6 @@ extern int sparc_indent_opcode;
       }                                        \
   } while (0)
 
-#define SPARC_SYMBOL_REF_TLS_P(RTX) \
-  (GET_CODE (RTX) == SYMBOL_REF && SYMBOL_REF_TLS_MODEL (RTX) != 0)
-
 #define PRINT_OPERAND_PUNCT_VALID_P(CHAR) \
   ((CHAR) == '#' || (CHAR) == '*' || (CHAR) == '('             \
    || (CHAR) == ')' || (CHAR) == '_' || (CHAR) == '&')
index 992f31034fd43e0deec820a1a33a29868c060dc8..4f6aa65250da22bee65a5654bd6f5d289a394b5c 100644 (file)
@@ -1,3 +1,7 @@
+2010-01-05  Eric Botcazou  <ebotcazou@adacore.com>
+
+       * gcc.dg/tls/opt-15.c: New test.
+
 2010-01-05  H.J. Lu  <hongjiu.lu@intel.com>
 
        * gcc.target/i386/pr42542-1.c (res): Make it 8 elements.
diff --git a/gcc/testsuite/gcc.dg/tls/opt-15.c b/gcc/testsuite/gcc.dg/tls/opt-15.c
new file mode 100644 (file)
index 0000000..bebee8a
--- /dev/null
@@ -0,0 +1,24 @@
+/* PR target/42564 */
+/* This used to ICE on the SPARC because of an unrecognized TLS pattern.  */
+
+/* { dg-do compile } */
+/* { dg-options "-O -fPIC" } */
+/* { dg-require-effective-target tls_native } */
+/* { dg-require-effective-target fpic } */
+
+extern void *memset(void *s, int c, __SIZE_TYPE__ n);
+
+struct S1 { int i; };
+
+struct S2
+{
+  int ver;
+  struct S1 s;
+};
+
+static __thread struct S2 m;
+
+void init(void)
+{
+  memset(&m.s, 0, sizeof(m.s));
+}