i386.c (legitimize_tls_address): Generate tls_initial_exec_64_sun only when !TARGET_X32.
[gcc.git] / gcc / tree-ssa-structalias.c
index 51f2aa1bf7cab34cf62249476d8bb7a46109e2a6..e2fdff34e7bbad4a493754cd26c3f5d46877c208 100644 (file)
@@ -303,6 +303,7 @@ static varinfo_t first_vi_for_offset (varinfo_t, unsigned HOST_WIDE_INT);
 static varinfo_t first_or_preceding_vi_for_offset (varinfo_t,
                                                   unsigned HOST_WIDE_INT);
 static varinfo_t lookup_vi_for_tree (tree);
+static inline bool type_can_have_subvars (const_tree);
 
 /* Pool of variable info structures.  */
 static alloc_pool variable_info_pool;
@@ -2758,7 +2759,7 @@ get_constraint_for_ssa_var (tree t, VEC(ce_s, heap) **results, bool address_p)
       if (node && node->alias)
        {
          node = varpool_variable_node (node, NULL);
-         t = node->decl;
+         t = node->symbol.decl;
        }
     }
 
@@ -3275,7 +3276,8 @@ get_constraint_for_1 (tree t, VEC (ce_s, heap) **results, bool address_p,
                return;
 
              cs = *VEC_last (ce_s, *results);
-             if (cs.type == DEREF)
+             if (cs.type == DEREF
+                 && type_can_have_subvars (TREE_TYPE (t)))
                {
                  /* For dereferences this means we have to defer it
                     to solving time.  */
@@ -4022,8 +4024,11 @@ find_func_aliases_for_builtin_call (gimple t)
       case BUILT_IN_MEMMOVE_CHK:
       case BUILT_IN_MEMPCPY_CHK:
       case BUILT_IN_STPCPY_CHK:
+      case BUILT_IN_STPNCPY_CHK:
       case BUILT_IN_STRCAT_CHK:
       case BUILT_IN_STRNCAT_CHK:
+      case BUILT_IN_TM_MEMCPY:
+      case BUILT_IN_TM_MEMMOVE:
        {
          tree res = gimple_call_lhs (t);
          tree dest = gimple_call_arg (t, (DECL_FUNCTION_CODE (fndecl)
@@ -4037,7 +4042,8 @@ find_func_aliases_for_builtin_call (gimple t)
                  || DECL_FUNCTION_CODE (fndecl) == BUILT_IN_STPCPY
                  || DECL_FUNCTION_CODE (fndecl) == BUILT_IN_STPNCPY
                  || DECL_FUNCTION_CODE (fndecl) == BUILT_IN_MEMPCPY_CHK
-                 || DECL_FUNCTION_CODE (fndecl) == BUILT_IN_STPCPY_CHK)
+                 || DECL_FUNCTION_CODE (fndecl) == BUILT_IN_STPCPY_CHK
+                 || DECL_FUNCTION_CODE (fndecl) == BUILT_IN_STPNCPY_CHK)
                get_constraint_for_ptr_offset (dest, NULL_TREE, &rhsc);
              else
                get_constraint_for (dest, &rhsc);
@@ -4056,6 +4062,7 @@ find_func_aliases_for_builtin_call (gimple t)
        }
       case BUILT_IN_MEMSET:
       case BUILT_IN_MEMSET_CHK:
+      case BUILT_IN_TM_MEMSET:
        {
          tree res = gimple_call_lhs (t);
          tree dest = gimple_call_arg (t, 0);
@@ -4197,6 +4204,50 @@ find_func_aliases_for_builtin_call (gimple t)
            }
          return true;
        }
+      CASE_BUILT_IN_TM_STORE (1):
+      CASE_BUILT_IN_TM_STORE (2):
+      CASE_BUILT_IN_TM_STORE (4):
+      CASE_BUILT_IN_TM_STORE (8):
+      CASE_BUILT_IN_TM_STORE (FLOAT):
+      CASE_BUILT_IN_TM_STORE (DOUBLE):
+      CASE_BUILT_IN_TM_STORE (LDOUBLE):
+      CASE_BUILT_IN_TM_STORE (M64):
+      CASE_BUILT_IN_TM_STORE (M128):
+      CASE_BUILT_IN_TM_STORE (M256):
+       {
+         tree addr = gimple_call_arg (t, 0);
+         tree src = gimple_call_arg (t, 1);
+
+         get_constraint_for (addr, &lhsc);
+         do_deref (&lhsc);
+         get_constraint_for (src, &rhsc);
+         process_all_all_constraints (lhsc, rhsc);
+         VEC_free (ce_s, heap, lhsc);
+         VEC_free (ce_s, heap, rhsc);
+         return true;
+       }
+      CASE_BUILT_IN_TM_LOAD (1):
+      CASE_BUILT_IN_TM_LOAD (2):
+      CASE_BUILT_IN_TM_LOAD (4):
+      CASE_BUILT_IN_TM_LOAD (8):
+      CASE_BUILT_IN_TM_LOAD (FLOAT):
+      CASE_BUILT_IN_TM_LOAD (DOUBLE):
+      CASE_BUILT_IN_TM_LOAD (LDOUBLE):
+      CASE_BUILT_IN_TM_LOAD (M64):
+      CASE_BUILT_IN_TM_LOAD (M128):
+      CASE_BUILT_IN_TM_LOAD (M256):
+       {
+         tree dest = gimple_call_lhs (t);
+         tree addr = gimple_call_arg (t, 0);
+
+         get_constraint_for (dest, &lhsc);
+         get_constraint_for (addr, &rhsc);
+         do_deref (&rhsc);
+         process_all_all_constraints (lhsc, rhsc);
+         VEC_free (ce_s, heap, lhsc);
+         VEC_free (ce_s, heap, rhsc);
+         return true;
+       }
       /* Variadic argument handling needs to be handled in IPA
         mode as well.  */
       case BUILT_IN_VA_START:
@@ -4437,7 +4488,11 @@ find_func_aliases (gimple origt)
       tree lhsop = gimple_assign_lhs (t);
       tree rhsop = (gimple_num_ops (t) == 2) ? gimple_assign_rhs1 (t) : NULL;
 
-      if (rhsop && AGGREGATE_TYPE_P (TREE_TYPE (lhsop)))
+      if (rhsop && TREE_CLOBBER_P (rhsop))
+       /* Ignore clobbers, they don't actually store anything into
+          the LHS.  */
+       ;
+      else if (rhsop && AGGREGATE_TYPE_P (TREE_TYPE (lhsop)))
        do_structure_copy (lhsop, rhsop);
       else
        {
@@ -4706,6 +4761,7 @@ find_func_clobbers (gimple origt)
          case BUILT_IN_MEMMOVE_CHK:
          case BUILT_IN_MEMPCPY_CHK:
          case BUILT_IN_STPCPY_CHK:
+         case BUILT_IN_STPNCPY_CHK:
          case BUILT_IN_STRCAT_CHK:
          case BUILT_IN_STRNCAT_CHK:
            {
@@ -4989,6 +5045,15 @@ sort_fieldstack (VEC(fieldoff_s,heap) *fieldstack)
   VEC_qsort (fieldoff_s, fieldstack, fieldoff_compare);
 }
 
+/* Return true if T is a type that can have subvars.  */
+
+static inline bool
+type_can_have_subvars (const_tree t)
+{
+  /* Aggregates without overlapping fields can have subvars.  */
+  return TREE_CODE (t) == RECORD_TYPE;
+}
+
 /* Return true if V is a tree that we can have subvars for.
    Normally, this is any aggregate type.  Also complex
    types which are not gimple registers can have subvars.  */
@@ -5004,11 +5069,7 @@ var_can_have_subvars (const_tree v)
   if (!DECL_P (v))
     return false;
 
-  /* Aggregates without overlapping fields can have subvars.  */
-  if (TREE_CODE (TREE_TYPE (v)) == RECORD_TYPE)
-    return true;
-
-  return false;
+  return type_can_have_subvars (TREE_TYPE (v));
 }
 
 /* Return true if T is a type that does contain pointers.  */
@@ -5522,7 +5583,8 @@ create_variable_info_for (tree decl, const char *name)
 
          /* If this is a global variable with an initializer and we are in
             IPA mode generate constraints for it.  */
-         if (DECL_INITIAL (decl))
+         if (DECL_INITIAL (decl)
+             && vnode->analyzed)
            {
              VEC (ce_s, heap) *rhsc = NULL;
              struct constraint_expr lhs, *rhsp;
@@ -5603,7 +5665,8 @@ intra_create_variable_infos (void)
         Treat restrict qualified references the same.  */
       if (TYPE_RESTRICT (TREE_TYPE (t))
          && ((DECL_BY_REFERENCE (t) && POINTER_TYPE_P (TREE_TYPE (t)))
-             || TREE_CODE (TREE_TYPE (t)) == REFERENCE_TYPE))
+             || TREE_CODE (TREE_TYPE (t)) == REFERENCE_TYPE)
+         && !type_contains_placeholder_p (TREE_TYPE (TREE_TYPE (t))))
        {
          struct constraint_expr lhsc, rhsc;
          varinfo_t vi;
@@ -6777,7 +6840,7 @@ static bool
 associate_varinfo_to_alias (struct cgraph_node *node, void *data)
 {
   if (node->alias || node->thunk.thunk_p)
-    insert_vi_for_tree (node->decl, (varinfo_t)data);
+    insert_vi_for_tree (node->symbol.decl, (varinfo_t)data);
   return false;
 }
 
@@ -6795,12 +6858,12 @@ ipa_pta_execute (void)
 
   if (dump_file && (dump_flags & TDF_DETAILS))
     {
-      dump_cgraph (dump_file);
+      dump_symtab (dump_file);
       fprintf (dump_file, "\n");
     }
 
   /* Build the constraints.  */
-  for (node = cgraph_nodes; node; node = node->next)
+  FOR_EACH_DEFINED_FUNCTION (node)
     {
       varinfo_t vi;
       /* Nodes without a body are not interesting.  Especially do not
@@ -6811,18 +6874,18 @@ ipa_pta_execute (void)
 
       gcc_assert (!node->clone_of);
 
-      vi = create_function_info_for (node->decl,
-                                    alias_get_name (node->decl));
+      vi = create_function_info_for (node->symbol.decl,
+                                    alias_get_name (node->symbol.decl));
       cgraph_for_node_and_aliases (node, associate_varinfo_to_alias, vi, true);
     }
 
   /* Create constraints for global variables and their initializers.  */
-  for (var = varpool_nodes; var; var = var->next)
+  FOR_EACH_VARIABLE (var)
     {
       if (var->alias)
        continue;
 
-      get_vi_for_tree (var->decl);
+      get_vi_for_tree (var->symbol.decl);
     }
 
   if (dump_file)
@@ -6834,7 +6897,7 @@ ipa_pta_execute (void)
     }
   from = VEC_length (constraint_t, constraints);
 
-  for (node = cgraph_nodes; node; node = node->next)
+  FOR_EACH_DEFINED_FUNCTION (node)
     {
       struct function *func;
       basic_block bb;
@@ -6848,33 +6911,34 @@ ipa_pta_execute (void)
        {
          fprintf (dump_file,
                   "Generating constraints for %s", cgraph_node_name (node));
-         if (DECL_ASSEMBLER_NAME_SET_P (node->decl))
+         if (DECL_ASSEMBLER_NAME_SET_P (node->symbol.decl))
            fprintf (dump_file, " (%s)",
-                    IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (node->decl)));
+                    IDENTIFIER_POINTER
+                      (DECL_ASSEMBLER_NAME (node->symbol.decl)));
          fprintf (dump_file, "\n");
        }
 
-      func = DECL_STRUCT_FUNCTION (node->decl);
+      func = DECL_STRUCT_FUNCTION (node->symbol.decl);
       old_func_decl = current_function_decl;
       push_cfun (func);
-      current_function_decl = node->decl;
+      current_function_decl = node->symbol.decl;
 
       /* For externally visible or attribute used annotated functions use
         local constraints for their arguments.
         For local functions we see all callers and thus do not need initial
         constraints for parameters.  */
-      if (node->reachable_from_other_partition
-         || node->local.externally_visible
-         || node->needed)
+      if (node->symbol.used_from_other_partition
+         || node->symbol.externally_visible
+         || node->symbol.force_output)
        {
          intra_create_variable_infos ();
 
          /* We also need to make function return values escape.  Nothing
             escapes by returning from main though.  */
-         if (!MAIN_NAME_P (DECL_NAME (node->decl)))
+         if (!MAIN_NAME_P (DECL_NAME (node->symbol.decl)))
            {
              varinfo_t fi, rvi;
-             fi = lookup_vi_for_tree (node->decl);
+             fi = lookup_vi_for_tree (node->symbol.decl);
              rvi = first_vi_for_offset (fi, fi_result);
              if (rvi && rvi->offset == fi_result)
                {
@@ -6941,7 +7005,7 @@ ipa_pta_execute (void)
   ipa_escaped_pt.ipa_escaped = 0;
 
   /* Assign the points-to sets to the SSA names in the unit.  */
-  for (node = cgraph_nodes; node; node = node->next)
+  FOR_EACH_DEFINED_FUNCTION (node)
     {
       tree ptr;
       struct function *fn;
@@ -6955,7 +7019,7 @@ ipa_pta_execute (void)
       if (!cgraph_function_with_gimple_body_p (node))
        continue;
 
-      fn = DECL_STRUCT_FUNCTION (node->decl);
+      fn = DECL_STRUCT_FUNCTION (node->symbol.decl);
 
       /* Compute the points-to sets for pointer SSA_NAMEs.  */
       FOR_EACH_VEC_ELT (tree, fn->gimple_df->ssa_names, i, ptr)
@@ -6966,7 +7030,7 @@ ipa_pta_execute (void)
        }
 
       /* Compute the call-use and call-clobber sets for all direct calls.  */
-      fi = lookup_vi_for_tree (node->decl);
+      fi = lookup_vi_for_tree (node->symbol.decl);
       gcc_assert (fi->is_fn_info);
       find_what_var_points_to (first_vi_for_offset (fi, fi_clobbers),
                               &clobbers);