target.h (gcc_target): Add cannot_force_const_mem.
authorRichard Henderson <rth@redhat.com>
Mon, 9 Dec 2002 23:54:01 +0000 (15:54 -0800)
committerRichard Henderson <rth@gcc.gnu.org>
Mon, 9 Dec 2002 23:54:01 +0000 (15:54 -0800)
        * target.h (gcc_target): Add cannot_force_const_mem.
        * target-def.h (TARGET_CANNOT_FORCE_CONST_MEM): New.
        (TARGET_INITIALIZER): Add it.
        * varasm.c (force_const_mem): Fail if cannot_force_const_mem.
        * expr.c (emit_move_insn): Be prepared for force_const_mem to fail.
        * reload1.c (reload): Likewise.
        * hooks.c (hook_bool_rtx_false): New.
        * hooks.h: Declare it.

        * config/i386/i386.c (ix86_cannot_force_const_mem): New.
        (TARGET_CANNOT_FORCE_CONST_MEM): New.
        (ix86_expand_move): Remove de-const-pooling hack.

* gcc.dg/tls/opt-4.c: New.

From-SVN: r59971

gcc/ChangeLog
gcc/config/i386/i386.c
gcc/expr.c
gcc/hooks.c
gcc/hooks.h
gcc/reload1.c
gcc/target-def.h
gcc/target.h
gcc/testsuite/gcc.dg/tls/opt-4.c [new file with mode: 0644]
gcc/varasm.c

index 770112f3d7f459761131c32e2682780216104acd..0b812c18a53fddec258f0dca997173dbd797482a 100644 (file)
@@ -1,3 +1,18 @@
+2002-12-09  Richard Henderson  <rth@redhat.com>
+
+       * target.h (gcc_target): Add cannot_force_const_mem.
+       * target-def.h (TARGET_CANNOT_FORCE_CONST_MEM): New.
+       (TARGET_INITIALIZER): Add it.
+       * varasm.c (force_const_mem): Fail if cannot_force_const_mem.
+       * expr.c (emit_move_insn): Be prepared for force_const_mem to fail.
+       * reload1.c (reload): Likewise.
+       * hooks.c (hook_bool_rtx_false): New.
+       * hooks.h: Declare it.
+
+       * config/i386/i386.c (ix86_cannot_force_const_mem): New.
+       (TARGET_CANNOT_FORCE_CONST_MEM): New.
+       (ix86_expand_move): Remove de-const-pooling hack.
+
 Mon Dec  9 21:33:38 CET 2002  Jan Hubicka  <jh@suse.cz>
 
        * toplev.c (dump_file): Fix order to match reality.
index 7337312ac8ec8f01e9ce3a84b44d203cd7ea2533..42f6d93d3c3089e9c6c7bc8bcfef5e0fe027f7f9 100644 (file)
@@ -763,6 +763,7 @@ struct ix86_address
 };
 
 static int ix86_decompose_address PARAMS ((rtx, struct ix86_address *));
+static bool ix86_cannot_force_const_mem PARAMS ((rtx));
 
 static void ix86_encode_section_info PARAMS ((tree, int)) ATTRIBUTE_UNUSED;
 static const char *ix86_strip_name_encoding PARAMS ((const char *))
@@ -900,6 +901,8 @@ static enum x86_64_reg_class merge_classes PARAMS ((enum x86_64_reg_class,
 #undef TARGET_HAVE_TLS
 #define TARGET_HAVE_TLS true
 #endif
+#undef TARGET_CANNOT_FORCE_CONST_MEM
+#define TARGET_CANNOT_FORCE_CONST_MEM ix86_cannot_force_const_mem
 
 #undef TARGET_ASM_OUTPUT_MI_THUNK
 #define TARGET_ASM_OUTPUT_MI_THUNK x86_output_mi_thunk
@@ -5050,6 +5053,17 @@ legitimate_constant_p (x)
   return true;
 }
 
+/* Determine if it's legal to put X into the constant pool.  This
+   is not possible for the address of thread-local symbols, which
+   is checked above.  */
+
+static bool
+ix86_cannot_force_const_mem (x)
+     rtx x;
+{
+  return !legitimate_constant_p (x);
+}
+
 /* Determine if a given RTX is a valid constant address.  */
 
 bool
@@ -7686,29 +7700,6 @@ ix86_expand_move (mode, operands)
   op0 = operands[0];
   op1 = operands[1];
 
-  /* ??? We have a slight problem.  We need to say that tls symbols are
-     not legitimate constants so that reload does not helpfully reload
-     these constants from a REG_EQUIV, which we cannot handle.  (Recall
-     that general- and local-dynamic address resolution requires a
-     function call.)
-
-     However, if we say that tls symbols are not legitimate constants,
-     then emit_move_insn helpfully drop them into the constant pool.
-
-     It is far easier to work around emit_move_insn than reload.  Recognize
-     the MEM that we would have created and extract the symbol_ref.  */
-
-  if (mode == Pmode
-      && GET_CODE (op1) == MEM
-      && RTX_UNCHANGING_P (op1))
-    {
-      tmp = maybe_get_pool_constant (op1);
-      /* Note that we only care about symbolic constants here, which
-        unlike CONST_INT will always have a proper mode.  */
-      if (tmp && GET_MODE (tmp) == Pmode)
-       op1 = tmp;
-    }
-
   if (tls_symbolic_operand (op1, Pmode))
     {
       op1 = legitimize_address (op1, op1, VOIDmode);
index 85d329f9ffce3df200465ff07633226bd08d52a7..f1b2271edd89ed75712bc92baf6c5d8919c9d768 100644 (file)
@@ -3146,6 +3146,12 @@ emit_move_insn (x, y)
        {
          y_cst = y;
          y = force_const_mem (mode, y);
+
+         /* If the target's cannot_force_const_mem prevented the spill,
+            assume that the target's move expanders will also take care
+            of the non-legitimate constant.  */
+         if (!y)
+           y = y_cst;
        }
     }
 
index 6569a38d7a0049ed486cab73ccf0bf1fb252cf29..3f212ef3e1b69f61237a21c3b10d1c4f0ca42fb9 100644 (file)
@@ -114,3 +114,10 @@ hook_bool_tree_false (a)
 {
   return false;
 }
+
+bool
+hook_bool_rtx_false (a)
+     rtx a ATTRIBUTE_UNUSED;
+{
+  return false;
+}
index 4e09da932a3c944272ebabcdf236f1bbbbf865fb..8c28194f6aca6c2f80e8189f1186f0ca97336321 100644 (file)
@@ -28,6 +28,7 @@ bool hook_bool_tree_hwi_hwi_tree_false
   PARAMS ((tree, HOST_WIDE_INT, HOST_WIDE_INT, tree));
 bool hook_bool_tree_hwi_hwi_tree_true
   PARAMS ((tree, HOST_WIDE_INT, HOST_WIDE_INT, tree));
+bool hook_bool_rtx_false PARAMS ((rtx));
 
 void hook_void_tree_int PARAMS ((tree, int));
 void hook_void_void PARAMS ((void));
index 2704dadab4d92a5b4c10dd4ba290b982b1cc4210..0f5d688c8a516ce771b389d83bfe09634b10cae4 100644 (file)
@@ -817,8 +817,12 @@ reload (first, global)
                      else if (LEGITIMATE_CONSTANT_P (x))
                        reg_equiv_constant[i] = x;
                      else
-                       reg_equiv_memory_loc[i]
-                         = force_const_mem (GET_MODE (SET_DEST (set)), x);
+                       {
+                         reg_equiv_memory_loc[i]
+                           = force_const_mem (GET_MODE (SET_DEST (set)), x);
+                         if (!reg_equiv_memory_loc[i])
+                           continue;
+                       }
                    }
                  else
                    continue;
index b866c858de78992ae3f9e098f7d71fae20355d5b..154d58d47e9a78570883760130bc659e0b1a6662 100644 (file)
@@ -241,6 +241,7 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 
 /* In hook.c.  */
 #define TARGET_CANNOT_MODIFY_JUMPS_P hook_bool_void_false
+#define TARGET_CANNOT_FORCE_CONST_MEM hook_bool_rtx_false
 #define TARGET_COMP_TYPE_ATTRIBUTES hook_int_tree_tree_1
 #define TARGET_SET_DEFAULT_TYPE_ATTRIBUTES hook_void_tree
 #define TARGET_INSERT_ATTRIBUTES hook_void_tree_treeptr
@@ -272,6 +273,7 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
   TARGET_EXPAND_BUILTIN,                       \
   TARGET_SECTION_TYPE_FLAGS,                   \
   TARGET_CANNOT_MODIFY_JUMPS_P,                        \
+  TARGET_CANNOT_FORCE_CONST_MEM,               \
   TARGET_IN_SMALL_DATA_P,                      \
   TARGET_BINDS_LOCAL_P,                                \
   TARGET_ENCODE_SECTION_INFO,                  \
index d9475625414fee46bc8e93eeea289397d73dbfc7..0ac1c5aa17b60d0f7f80177654dd8183dfc3fb92 100644 (file)
@@ -262,6 +262,9 @@ struct gcc_target
      not, at the current point in the compilation.  */
   bool (* cannot_modify_jumps_p) PARAMS ((void));
 
+  /* True if the constant X cannot be placed in the constant pool.  */
+  bool (* cannot_force_const_mem) PARAMS ((rtx));
+
   /* True if EXP should be placed in a "small data" section.  */
   bool (* in_small_data_p) PARAMS ((tree));
 
diff --git a/gcc/testsuite/gcc.dg/tls/opt-4.c b/gcc/testsuite/gcc.dg/tls/opt-4.c
new file mode 100644 (file)
index 0000000..3a95688
--- /dev/null
@@ -0,0 +1,53 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+struct A
+{
+  int a1;
+  int a2;
+};
+
+extern __thread const unsigned char *tcc1, **tcc2;
+
+extern inline const unsigned char ** __attribute__ ((const))
+foo (void)
+{
+  const unsigned char **a = &tcc1;
+  if (*a == 0)
+    *a = *tcc2 + 128;
+  return a;
+}
+
+extern inline int
+bar (const struct A *x)
+{
+  int a;
+
+  if (x->a2 & 8)
+    return 0;
+  a = x->a1;
+  return a > 0 && ((*foo ())[a] & 64);
+}
+
+int
+baz (const struct A *x, char *y)
+{
+  const struct A *a;
+
+  for (a = x; !!a->a1; a++)
+    if (! (x->a2 & 8))
+      if (bar (a))
+       {
+         *y++ = a->a1;
+         if (x->a1)
+           *y++ = ':';
+         *y = '\0';
+       }
+  return 0;
+}
+
+/* Verify tcc1 and tcc2 variables show up only in the TLS access sequences.  */
+/* { dg-final { scan-assembler "tcc1@" { target i?86-*-* x86_64-*-* } } } */
+/* { dg-final { scan-assembler "tcc2@" { target i?86-*-* x86_64-*-* } } } */
+/* { dg-final { scan-assembler-not "tcc1\[^@\]" { target i?86-*-* x86_64-*-* } } } */
+/* { dg-final { scan-assembler-not "tcc2\[^@\]" { target i?86-*-* x86_64-*-* } } } */
index 2ac3da5338c8962fd958b19bef32c8a9d0bab635..f8b33d080a62dceb8308bbb0c5820efda43c76b1 100644 (file)
@@ -3209,6 +3209,10 @@ force_const_mem (mode, x)
   struct pool_constant *pool;
   unsigned int align;
 
+  /* If we're not allowed to drop X into the constant pool, don't.  */
+  if ((*targetm.cannot_force_const_mem) (x))
+    return NULL_RTX;
+
   /* Compute hash code of X.  Search the descriptors for that hash code
      to see if any of them describes X.  If yes, we have an rtx to use.  */
   hash = const_hash_rtx (mode, x);