aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDale Johannesen <dalej@apple.com>2004-03-16 22:16:41 +0000
committerDale Johannesen <dalej@apple.com>2004-03-16 22:16:41 +0000
commit80131e0595f04c257f4c8a7bc1daefaccf70ebd9 (patch)
tree3d22377ab89b8718d053de97937d396ec617f4c3
parent50f6616bc05060f19cd65dc3d9c5bb3bebfac310 (diff)
2004-03-16 Dale Johannesen <dalej@apple.com>
* Makefile.in (tree-ssa-phiopt.o): add langhooks.h dependency. (tree-nrv.o): Ditto. (tree-ssa-copy.o): Ditto. (tree-ssa-dom.o): Ditto. (tree-ssa-ccp.o): Ditto. * c-common.c: Add #include hashtab.h. (c_type_hash): New. (c_common_get_alias_set): Handle multiple type nodes referring to "the same" type, currently for C90 only. * c-decl.c (current_file_decl): Move to toplev.c. * c-lang.c (LANG_HOOKS_TYPES_COMPATIBLE_P): Define to c_types_compatible_p. (c_types_compatible_p): New. * c-tree.h (c_types_compatible_p): New declaration. * c-typeck.c (tagged_types_tu_compatible_p): Allow for compiler-generated TYPE_DECLs without a DECL_ORIGINAL_TYPE. * gimplify.c (canonicalize_addr_expr): Use types_compatible_p langhook. (cpt_same_type): Ditto. * langhooks-def.h (lhd_types_compatible_p): New declaration. LANG_HOOKS_TYPES_COMPATIBLE_P: New. * langhooks.c (lhd_types_compatible_p): New. * langhooks.h (struct lang_hooks): Add types_compatible_p. * stmt.c (tail_recursion_args): Use types_compatible_p langhook. * toplev.c (current_file_decl): New, moved from c-decl.c. * tree-nrv.c: Include langhooks.h. (tree_nrv): Use types_compatible_p langhook. * tree-ssa-ccp.c: Include langhooks.h. (maybe_fold_offset_to_array_ref): Use types_compatible_p langhook. (maybe_fold_offset_to_component_ref): Ditto (2 places). (fold_stmt_r): Make sure rhs of COMPONENT_REF is in lhs type. * tree-ssa-copy.c: Include langhooks.h. (cprop_into_stmt): Use types_compatible_p langhook. * tree-ssa-dom.c: Include langhooks.h. (avail_expr_p): Use types_compatible_p langhook. * tree-ssa-phiopt.c: Include langhooks.h. (conditional_replacement): Use types_compatible_p langhook. * tree-ssa.c (tree_ssa_useless_type_conversion_1): Use types_compatible_p langhook. * tree.h (current_file_decl): New declaration. * cp/cp-lang.c (cxx_types_compatible_p): New. LANG_HOOKS_TYPES_COMPATIBLE_P: New. git-svn-id: https://gcc.gnu.org/svn/gcc/branches/tree-ssa-20020619-branch@79551 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r--gcc/ChangeLog.tree-ssa46
-rw-r--r--gcc/Makefile.in10
-rw-r--r--gcc/c-common.c103
-rw-r--r--gcc/c-decl.c4
-rw-r--r--gcc/c-lang.c8
-rw-r--r--gcc/c-tree.h1
-rw-r--r--gcc/c-typeck.c10
-rw-r--r--gcc/cp/cp-lang.c8
-rw-r--r--gcc/gimplify.c6
-rw-r--r--gcc/langhooks-def.h3
-rw-r--r--gcc/langhooks.c10
-rw-r--r--gcc/langhooks.h5
-rw-r--r--gcc/stmt.c4
-rw-r--r--gcc/toplev.c5
-rw-r--r--gcc/tree-nrv.c5
-rw-r--r--gcc/tree-ssa-ccp.c45
-rw-r--r--gcc/tree-ssa-copy.c5
-rw-r--r--gcc/tree-ssa-dom.c6
-rw-r--r--gcc/tree-ssa-phiopt.c7
-rw-r--r--gcc/tree-ssa.c5
-rw-r--r--gcc/tree.h5
21 files changed, 266 insertions, 35 deletions
diff --git a/gcc/ChangeLog.tree-ssa b/gcc/ChangeLog.tree-ssa
index 72c3511f6bb..848cb33ed84 100644
--- a/gcc/ChangeLog.tree-ssa
+++ b/gcc/ChangeLog.tree-ssa
@@ -1,4 +1,48 @@
-2004-03-16 Dale Johannesen <dale@apple.com>
+2004-03-16 Dale Johannesen <dalej@apple.com>
+
+ * Makefile.in (tree-ssa-phiopt.o): add langhooks.h dependency.
+ (tree-nrv.o): Ditto.
+ (tree-ssa-copy.o): Ditto.
+ (tree-ssa-dom.o): Ditto.
+ (tree-ssa-ccp.o): Ditto.
+ * c-common.c: Add #include hashtab.h.
+ (c_type_hash): New.
+ (c_common_get_alias_set): Handle multiple type nodes referring
+ to "the same" type, currently for C90 only.
+ * c-decl.c (current_file_decl): Move to toplev.c.
+ * c-lang.c (LANG_HOOKS_TYPES_COMPATIBLE_P): Define to
+ c_types_compatible_p.
+ (c_types_compatible_p): New.
+ * c-tree.h (c_types_compatible_p): New declaration.
+ * c-typeck.c (tagged_types_tu_compatible_p): Allow for
+ compiler-generated TYPE_DECLs without a DECL_ORIGINAL_TYPE.
+ * gimplify.c (canonicalize_addr_expr): Use types_compatible_p langhook.
+ (cpt_same_type): Ditto.
+ * langhooks-def.h (lhd_types_compatible_p): New declaration.
+ LANG_HOOKS_TYPES_COMPATIBLE_P: New.
+ * langhooks.c (lhd_types_compatible_p): New.
+ * langhooks.h (struct lang_hooks): Add types_compatible_p.
+ * stmt.c (tail_recursion_args): Use types_compatible_p langhook.
+ * toplev.c (current_file_decl): New, moved from c-decl.c.
+ * tree-nrv.c: Include langhooks.h.
+ (tree_nrv): Use types_compatible_p langhook.
+ * tree-ssa-ccp.c: Include langhooks.h.
+ (maybe_fold_offset_to_array_ref): Use types_compatible_p langhook.
+ (maybe_fold_offset_to_component_ref): Ditto (2 places).
+ (fold_stmt_r): Make sure rhs of COMPONENT_REF is in lhs type.
+ * tree-ssa-copy.c: Include langhooks.h.
+ (cprop_into_stmt): Use types_compatible_p langhook.
+ * tree-ssa-dom.c: Include langhooks.h.
+ (avail_expr_p): Use types_compatible_p langhook.
+ * tree-ssa-phiopt.c: Include langhooks.h.
+ (conditional_replacement): Use types_compatible_p langhook.
+ * tree-ssa.c (tree_ssa_useless_type_conversion_1): Use
+ types_compatible_p langhook.
+ * tree.h (current_file_decl): New declaration.
+ * cp/cp-lang.c (cxx_types_compatible_p): New.
+ LANG_HOOKS_TYPES_COMPATIBLE_P: New.
+
+2004-03-16 Dale Johannesen <dalej@apple.com>
PR optimization/14498
* gimplify.c (copy_if_shared_r): Mark VA_ARGS_EXPRs as volatile.
diff --git a/gcc/Makefile.in b/gcc/Makefile.in
index 18b0785fb48..d0f0b228e3f 100644
--- a/gcc/Makefile.in
+++ b/gcc/Makefile.in
@@ -1566,18 +1566,18 @@ tree-ssa-forwprop.o : tree-ssa-forwprop.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
$(TREE_FLOW_H) tree-pass.h $(TREE_DUMP_H)
tree-ssa-phiopt.o : tree-ssa-phiopt.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
$(TM_H) errors.h $(GGC_H) $(TREE_H) $(RTL_H) $(TM_P_H) $(BASIC_BLOCK_H) \
- $(TREE_FLOW_H) tree-pass.h $(TREE_DUMP_H)
+ $(TREE_FLOW_H) tree-pass.h $(TREE_DUMP_H) langhooks.h
tree-nrv.o : tree-nrv.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
$(TM_H) $(TREE_H) $(RTL_H) function.h $(BASIC_BLOCK_H) $(EXPR_H) \
- diagnostic.h $(TREE_FLOW_H) $(TIMEVAR_H) $(TREE_DUMP_H) tree-pass.h
+ diagnostic.h $(TREE_FLOW_H) $(TIMEVAR_H) $(TREE_DUMP_H) tree-pass.h langhooks.h
tree-ssa-copy.o : tree-ssa-copy.c $(TREE_FLOW_H) $(CONFIG_H) $(SYSTEM_H) \
$(RTL_H) $(TREE_H) $(TM_P_H) $(EXPR_H) $(GGC_H) output.h diagnostic.h \
errors.h function.h $(TIMEVAR_H) $(TM_H) coretypes.h $(TREE_DUMP_H) \
- $(BASIC_BLOCK_H) tree-pass.h
+ $(BASIC_BLOCK_H) tree-pass.h langhooks.h
tree-ssa-dom.o : tree-ssa-dom.c $(TREE_FLOW_H) $(CONFIG_H) $(SYSTEM_H) \
$(RTL_H) $(TREE_H) $(TM_P_H) $(EXPR_H) $(GGC_H) output.h diagnostic.h \
errors.h function.h $(TIMEVAR_H) $(TM_H) coretypes.h $(TREE_DUMP_H) \
- $(BASIC_BLOCK_H) domwalk.h real.h tree-pass.h flags.h
+ $(BASIC_BLOCK_H) domwalk.h real.h tree-pass.h flags.h langhooks.h
tree-ssanames.o : tree-ssanames.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
$(TM_H) $(TREE_H) varray.h $(GGC_H) gt-tree-ssanames.h
tree-phinodes.o : tree-phinodes.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
@@ -1837,7 +1837,7 @@ tree-ssa-dce.o : tree-ssa-dce.c $(CONFIG_H) system.h errors.h $(TREE_H) \
tree-ssa-ccp.o : tree-ssa-ccp.c $(CONFIG_H) system.h errors.h $(TREE_H) \
$(RTL_H) $(TM_P_H) $(TREE_FLOW_H) diagnostic.h tree-inline.h \
$(TIMEVAR_H) $(TM_H) coretypes.h $(TREE_DUMP_H) $(TREE_SIMPLE_H) \
- $(EXPR_H) tree-pass.h flags.h
+ $(EXPR_H) tree-pass.h flags.h langhooks.h
tree-sra.o : tree-sra.c $(CONFIG_H) system.h errors.h $(TREE_H) $(RTL_H) \
$(TM_P_H) $(TREE_FLOW_H) diagnostic.h tree-inline.h \
$(TIMEVAR_H) $(TM_H) coretypes.h $(TREE_DUMP_H) $(TREE_SIMPLE_H) \
diff --git a/gcc/c-common.c b/gcc/c-common.c
index edbf311d0ea..d23a5bc5d0e 100644
--- a/gcc/c-common.c
+++ b/gcc/c-common.c
@@ -43,6 +43,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#include "c-tree.h"
#include "toplev.h"
#include "tree-iterator.h"
+#include "hashtab.h"
cpp_reader *parse_in; /* Declared in c-pragma.h. */
@@ -2816,6 +2817,49 @@ c_apply_type_quals_to_decl (int type_quals, tree decl)
}
}
+/* Hash function for the problem of multiple type definitions in
+ different files. This must hash all types that will compare
+ equal via comptypes to the same value. In practice it hashes
+ on some of the simple stuff and leaves the details to comptypes. */
+
+static hashval_t
+c_type_hash (const void *p)
+{
+ int i = 0;
+ int shift, size;
+ tree t = (tree)p;
+ tree t2;
+ switch (TREE_CODE (t))
+ {
+ /* For pointers, hash on pointee type plus some swizzling. */
+ case POINTER_TYPE:
+ return c_type_hash (TREE_TYPE (t)) ^ 0x3003003;
+ /* Hash on number of elements and total size. */
+ case ENUMERAL_TYPE:
+ shift = 3;
+ t2 = TYPE_VALUES (t);
+ break;
+ case RECORD_TYPE:
+ shift = 0;
+ t2 = TYPE_FIELDS (t);
+ break;
+ case QUAL_UNION_TYPE:
+ shift = 1;
+ t2 = TYPE_FIELDS (t);
+ break;
+ case UNION_TYPE:
+ shift = 2;
+ t2 = TYPE_FIELDS (t);
+ break;
+ default:
+ abort ();
+ }
+ for (; t2; t2 = TREE_CHAIN (t2))
+ i++;
+ size = TREE_INT_CST_LOW (TYPE_SIZE (t));
+ return ((size << 24) | (i << shift));
+}
+
/* Return the typed-based alias set for T, which may be an expression
or a type. Return -1 if we don't do anything special. */
@@ -2823,6 +2867,8 @@ HOST_WIDE_INT
c_common_get_alias_set (tree t)
{
tree u;
+ PTR *slot;
+ static htab_t type_hash_table;
/* Permit type-punning when accessing a union, provided the access
is directly through the union. For example, this code does not
@@ -2895,6 +2941,63 @@ c_common_get_alias_set (tree t)
return get_alias_set (t1);
}
+ /* Handle the case of multiple type nodes referring to "the same" type,
+ which occurs with IMA. These share an alias set. FIXME: Currently only
+ C90 is handled. (In C99 type compatibility is not transitive, which
+ complicates things mightily. The alias set splay trees can theoretically
+ represent this, but insertion is tricky when you consider all the
+ different orders things might arrive in.) */
+
+ if (c_language != clk_c || flag_isoc99)
+ return -1;
+
+ /* Save time if there's only one input file. */
+ if (!current_file_decl || TREE_CHAIN (current_file_decl) == NULL_TREE)
+ return -1;
+
+ /* Pointers need special handling if they point to any type that
+ needs special handling (below). */
+ if (TREE_CODE (t) == POINTER_TYPE)
+ {
+ tree t2;
+ /* Find bottom type under any nested POINTERs. */
+ for (t2 = TREE_TYPE (t);
+ TREE_CODE (t2) == POINTER_TYPE;
+ t2 = TREE_TYPE (t2))
+ ;
+ if (TREE_CODE (t2) != RECORD_TYPE
+ && TREE_CODE (t2) != ENUMERAL_TYPE
+ && TREE_CODE (t2) != QUAL_UNION_TYPE
+ && TREE_CODE (t2) != UNION_TYPE)
+ return -1;
+ if (TYPE_SIZE (t2) == 0)
+ return -1;
+ }
+ /* These are the only cases that need special handling. */
+ if (TREE_CODE (t) != RECORD_TYPE
+ && TREE_CODE (t) != ENUMERAL_TYPE
+ && TREE_CODE (t) != QUAL_UNION_TYPE
+ && TREE_CODE (t) != UNION_TYPE
+ && TREE_CODE (t) != POINTER_TYPE)
+ return -1;
+ /* Undefined? */
+ if (TYPE_SIZE (t) == 0)
+ return -1;
+
+ /* Look up t in hash table. Only one of the compatible types within each
+ alias set is recorded in the table. */
+ if (!type_hash_table)
+ type_hash_table = htab_create (1021, c_type_hash,
+ (htab_eq) lang_hooks.types_compatible_p,
+ NULL);
+ slot = htab_find_slot (type_hash_table, t, INSERT);
+ if (*slot != NULL)
+ return TYPE_ALIAS_SET ((tree)*slot);
+ else
+ /* Our caller will assign and record (in t) a new alias set; all we need
+ to do is remember t in the hash table. */
+ *slot = t;
+
return -1;
}
diff --git a/gcc/c-decl.c b/gcc/c-decl.c
index 8518c435df4..85fa68fca2a 100644
--- a/gcc/c-decl.c
+++ b/gcc/c-decl.c
@@ -143,10 +143,6 @@ static GTY(()) tree truly_local_externals;
static GTY(()) tree first_builtin_decl;
static GTY(()) tree last_builtin_decl;
-/* A DECL for the current file-scope context. */
-
-static GTY(()) tree current_file_decl;
-
/* Set to 0 at beginning of a function definition, set to 1 if
a return statement that specifies a return value is seen. */
diff --git a/gcc/c-lang.c b/gcc/c-lang.c
index 42e013c6b79..ec3bde3f1fb 100644
--- a/gcc/c-lang.c
+++ b/gcc/c-lang.c
@@ -150,6 +150,9 @@ enum c_language_kind c_language = clk_c;
#undef LANG_HOOKS_GIMPLIFY_EXPR
#define LANG_HOOKS_GIMPLIFY_EXPR c_gimplify_expr
+#undef LANG_HOOKS_TYPES_COMPATIBLE_P
+#define LANG_HOOKS_TYPES_COMPATIBLE_P c_types_compatible_p
+
/* ### When changing hooks, consider if ObjC needs changing too!! ### */
/* Each front end provides its own. */
@@ -196,6 +199,11 @@ finish_file (void)
c_objc_common_finish_file ();
}
+int
+c_types_compatible_p (tree x, tree y)
+{
+ return comptypes (TYPE_MAIN_VARIANT (x), TYPE_MAIN_VARIANT (y), 0);
+}
static void
c_initialize_diagnostics (diagnostic_context *context)
{
diff --git a/gcc/c-tree.h b/gcc/c-tree.h
index 770ed5bc3bd..5eda48e7513 100644
--- a/gcc/c-tree.h
+++ b/gcc/c-tree.h
@@ -303,6 +303,7 @@ extern void c_finish_case (void);
extern tree build_asm_expr (tree, tree, tree, tree, bool);
extern tree build_asm_stmt (tree, tree);
extern tree c_convert_parm_for_inlining (tree, tree, tree, int);
+extern int c_types_compatible_p (tree, tree);
/* Set to 0 at beginning of a function definition, set to 1 if
a return statement that specifies a return value is seen. */
diff --git a/gcc/c-typeck.c b/gcc/c-typeck.c
index 87a4068eef0..7dd495b7e59 100644
--- a/gcc/c-typeck.c
+++ b/gcc/c-typeck.c
@@ -672,11 +672,15 @@ tagged_types_tu_compatible_p (tree t1, tree t2, int flags)
/* We have to verify that the tags of the types are the same. This
is harder than it looks because this may be a typedef, so we have
to go look at the original type. It may even be a typedef of a
- typedef... */
- while (TYPE_NAME (t1) && TREE_CODE (TYPE_NAME (t1)) == TYPE_DECL)
+ typedef...
+ In the case of compiler-created builtin structs the TYPE_DECL
+ may be a dummy, with no DECL_ORIGINAL_TYPE. Don't fault. */
+ while (TYPE_NAME (t1) && TREE_CODE (TYPE_NAME (t1)) == TYPE_DECL
+ && DECL_ORIGINAL_TYPE (TYPE_NAME (t1)))
t1 = DECL_ORIGINAL_TYPE (TYPE_NAME (t1));
- while (TYPE_NAME (t2) && TREE_CODE (TYPE_NAME (t2)) == TYPE_DECL)
+ while (TYPE_NAME (t2) && TREE_CODE (TYPE_NAME (t2)) == TYPE_DECL
+ && DECL_ORIGINAL_TYPE (TYPE_NAME (t2)))
t2 = DECL_ORIGINAL_TYPE (TYPE_NAME (t2));
/* C90 didn't have the requirement that the two tags be the same. */
diff --git a/gcc/cp/cp-lang.c b/gcc/cp/cp-lang.c
index 43e7a859ad5..e80b0cd1b4a 100644
--- a/gcc/cp/cp-lang.c
+++ b/gcc/cp/cp-lang.c
@@ -39,6 +39,7 @@ static bool cxx_warn_unused_global_decl (tree);
static tree cp_expr_size (tree);
static size_t cp_tree_size (enum tree_code);
static bool cp_var_mod_type_p (tree);
+static int cxx_types_compatible_p (tree, tree);
static int cp_expand_decl (tree);
static void cxx_initialize_diagnostics (diagnostic_context *);
@@ -181,6 +182,8 @@ static void cxx_initialize_diagnostics (diagnostic_context *);
#define LANG_HOOKS_INCOMPLETE_TYPE_ERROR cxx_incomplete_type_error
#undef LANG_HOOKS_TYPE_PROMOTES_TO
#define LANG_HOOKS_TYPE_PROMOTES_TO cxx_type_promotes_to
+#undef LANG_HOOKS_TYPES_COMPATIBLE_P
+#define LANG_HOOKS_TYPES_COMPATIBLE_P cxx_types_compatible_p
#undef LANG_HOOKS_REGISTER_BUILTIN_TYPE
#define LANG_HOOKS_REGISTER_BUILTIN_TYPE c_register_builtin_type
#undef LANG_HOOKS_GIMPLIFY_EXPR
@@ -357,6 +360,11 @@ cp_var_mod_type_p (tree type)
return false;
}
+static int cxx_types_compatible_p (tree x, tree y)
+{
+ return comptypes (TYPE_MAIN_VARIANT (x), TYPE_MAIN_VARIANT (y), 0);
+}
+
/* Stub routine to tell people that this doesn't work yet. */
void
c_reset_state (void)
diff --git a/gcc/gimplify.c b/gcc/gimplify.c
index f432c8856e4..f08ff05dd1b 100644
--- a/gcc/gimplify.c
+++ b/gcc/gimplify.c
@@ -1487,13 +1487,13 @@ canonicalize_addr_expr (tree* expr_p)
/* Both cast and addr_expr types should address the same object type. */
dctype = TREE_TYPE (ctype);
ddatype = TREE_TYPE (datype);
- if (TYPE_MAIN_VARIANT (ddatype) != TYPE_MAIN_VARIANT (dctype))
+ if (!lang_hooks.types_compatible_p (ddatype, dctype))
return;
/* The addr_expr and the object type should match. */
obj_expr = TREE_OPERAND (addr_expr, 0);
otype = TREE_TYPE (obj_expr);
- if (TYPE_MAIN_VARIANT (otype) != TYPE_MAIN_VARIANT (datype))
+ if (!lang_hooks.types_compatible_p (otype, datype))
return;
/* All checks succeeded. Build a new node to merge the cast. */
@@ -3519,7 +3519,7 @@ gimplify_expr (tree *expr_p, tree *pre_p, tree *post_p,
static bool
cpt_same_type (tree a, tree b)
{
- if (TYPE_MAIN_VARIANT (a) == TYPE_MAIN_VARIANT (b))
+ if (lang_hooks.types_compatible_p (a, b))
return true;
/* ??? The C++ FE decomposes METHOD_TYPES to FUNCTION_TYPES and doesn't
diff --git a/gcc/langhooks-def.h b/gcc/langhooks-def.h
index 33f8b9ccbb2..746143c4d0b 100644
--- a/gcc/langhooks-def.h
+++ b/gcc/langhooks-def.h
@@ -55,6 +55,7 @@ extern int lhd_unsafe_for_reeval (tree);
extern void lhd_clear_binding_stack (void);
extern void lhd_print_tree_nothing (FILE *, tree, int);
extern const char *lhd_decl_printable_name (tree, int);
+extern int lhd_types_compatible_p (tree, tree);
extern rtx lhd_expand_expr (tree, rtx, enum machine_mode, int, rtx *);
extern int lhd_expand_decl (tree);
extern void lhd_print_error_function (struct diagnostic_context *,
@@ -128,6 +129,7 @@ extern int lhd_gimplify_expr (tree *, tree *, tree *);
#define LANG_HOOKS_GET_CALLEE_FNDECL lhd_return_null_tree
#define LANG_HOOKS_EXPR_SIZE lhd_expr_size
#define LANG_HOOKS_TREE_SIZE lhd_tree_size
+#define LANG_HOOKS_TYPES_COMPATIBLE_P lhd_types_compatible_p
#define LANG_HOOKS_FUNCTION_INIT lhd_do_nothing_f
#define LANG_HOOKS_FUNCTION_FINAL lhd_do_nothing_f
@@ -309,6 +311,7 @@ extern tree lhd_make_node (enum tree_code);
LANG_HOOKS_PRINT_TYPE, \
LANG_HOOKS_PRINT_IDENTIFIER, \
LANG_HOOKS_DECL_PRINTABLE_NAME, \
+ LANG_HOOKS_TYPES_COMPATIBLE_P, \
LANG_HOOKS_GET_CALLEE_FNDECL, \
LANG_HOOKS_PRINT_ERROR_FUNCTION, \
LANG_HOOKS_EXPR_SIZE, \
diff --git a/gcc/langhooks.c b/gcc/langhooks.c
index d0aae80c9b2..d48a0c9033f 100644
--- a/gcc/langhooks.c
+++ b/gcc/langhooks.c
@@ -294,6 +294,16 @@ lhd_decl_printable_name (tree decl, int verbosity ATTRIBUTE_UNUSED)
return IDENTIFIER_POINTER (DECL_NAME (decl));
}
+/* This compares two types for equivalence ("compatible" in C-based languages).
+ This routine should only return 1 if it is sure. It should not be used
+ in contexts where erroneously returning 0 causes problems. */
+
+int
+lhd_types_compatible_p (tree x, tree y)
+{
+ return TYPE_MAIN_VARIANT (x) == TYPE_MAIN_VARIANT (y);
+}
+
/* lang_hooks.tree_inlining.walk_subtrees is called by walk_tree()
after handling common cases, but before walking code-specific
sub-trees. If this hook is overridden for a language, it should
diff --git a/gcc/langhooks.h b/gcc/langhooks.h
index a5884f7c243..e46bbf54613 100644
--- a/gcc/langhooks.h
+++ b/gcc/langhooks.h
@@ -382,6 +382,11 @@ struct lang_hooks
types in C++. */
const char *(*decl_printable_name) (tree decl, int verbosity);
+ /* This compares two types for equivalence ("compatible" in C-based languages).
+ This routine should only return 1 if it is sure. It should not be used
+ in contexts where erroneously returning 0 causes problems. */
+ int (*types_compatible_p) (tree x, tree y);
+
/* Given a CALL_EXPR, return a function decl that is its target. */
tree (*lang_get_callee_fndecl) (tree);
diff --git a/gcc/stmt.c b/gcc/stmt.c
index 3568df9160b..68feb95e905 100644
--- a/gcc/stmt.c
+++ b/gcc/stmt.c
@@ -3291,8 +3291,8 @@ tail_recursion_args (tree actuals, tree formals)
for (a = actuals, f = formals, i = 0; a && f; a = TREE_CHAIN (a), f = TREE_CHAIN (f), i++)
{
- if (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_VALUE (a)))
- != TYPE_MAIN_VARIANT (TREE_TYPE (f)))
+ if (!lang_hooks.types_compatible_p (TREE_TYPE (TREE_VALUE (a)),
+ TREE_TYPE (f)))
return 0;
if (GET_CODE (DECL_RTL (f)) != REG || DECL_MODE (f) == BLKmode)
return 0;
diff --git a/gcc/toplev.c b/gcc/toplev.c
index b744805575f..2a3b5ec73ec 100644
--- a/gcc/toplev.c
+++ b/gcc/toplev.c
@@ -212,6 +212,11 @@ tree current_function_decl;
if none. */
tree current_function_func_begin_label;
+/* A DECL for the current file-scope context. When using IMA, this heads a
+ chain of FILE_DECLs; currently only C uses it. */
+
+tree current_file_decl;
+
/* Nonzero if doing dwarf2 duplicate elimination. */
int flag_eliminate_dwarf2_dups = 0;
diff --git a/gcc/tree-nrv.c b/gcc/tree-nrv.c
index 194b2baef71..ff4626faabd 100644
--- a/gcc/tree-nrv.c
+++ b/gcc/tree-nrv.c
@@ -32,6 +32,7 @@ Boston, MA 02111-1307, USA. */
#include "timevar.h"
#include "tree-dump.h"
#include "tree-pass.h"
+#include "langhooks.h"
/* This file implements return value optimizations for functions which
return aggregate types.
@@ -156,8 +157,8 @@ tree_nrv (void)
|| TREE_STATIC (found)
|| TREE_ADDRESSABLE (found)
|| DECL_ALIGN (found) > DECL_ALIGN (result)
- || (TYPE_MAIN_VARIANT (TREE_TYPE (found))
- != TYPE_MAIN_VARIANT (result_type)))
+ || !lang_hooks.types_compatible_p (TREE_TYPE (found),
+ result_type))
return;
}
}
diff --git a/gcc/tree-ssa-ccp.c b/gcc/tree-ssa-ccp.c
index e9a5a24780c..839245d5169 100644
--- a/gcc/tree-ssa-ccp.c
+++ b/gcc/tree-ssa-ccp.c
@@ -40,6 +40,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#include "errors.h"
#include "ggc.h"
#include "tree.h"
+#include "langhooks.h"
/* These RTL headers are needed for basic-block.h. */
#include "rtl.h"
@@ -1434,7 +1435,7 @@ maybe_fold_offset_to_array_ref (tree base, tree offset, tree orig_type)
if (TREE_CODE (array_type) != ARRAY_TYPE)
return NULL_TREE;
elt_type = TREE_TYPE (array_type);
- if (TYPE_MAIN_VARIANT (orig_type) != TYPE_MAIN_VARIANT (elt_type))
+ if (!lang_hooks.types_compatible_p (orig_type, elt_type))
return NULL_TREE;
/* Whee. Ignore indexing of variable sized types. */
@@ -1487,7 +1488,7 @@ maybe_fold_offset_to_component_ref (tree record_type, tree base, tree offset,
return NULL_TREE;
/* Short-circuit silly cases. */
- if (TYPE_MAIN_VARIANT (record_type) == TYPE_MAIN_VARIANT (orig_type))
+ if (lang_hooks.types_compatible_p (record_type, orig_type))
return NULL_TREE;
tail_array_field = NULL_TREE;
@@ -1544,7 +1545,7 @@ maybe_fold_offset_to_component_ref (tree record_type, tree base, tree offset,
/* Here we exactly match the offset being checked. If the types match,
then we can return that field. */
- else if (TYPE_MAIN_VARIANT (orig_type) == TYPE_MAIN_VARIANT (field_type))
+ else if (lang_hooks.types_compatible_p (orig_type, field_type))
{
if (base_is_ptr)
base = build1 (INDIRECT_REF, record_type, base);
@@ -1808,6 +1809,44 @@ fold_stmt_r (tree *expr_p, int *walk_subtrees, void *data)
t = maybe_fold_stmt_plus (expr);
break;
+ case COMPONENT_REF:
+ t = walk_tree (&TREE_OPERAND (expr, 0), fold_stmt_r, data, NULL);
+ if (t)
+ return t;
+ *walk_subtrees = 0;
+
+ /* Make sure the FIELD_DECL is actually a field in the type on
+ the lhs. In cases with IMA it is possible that it came
+ from another, equivalent type at this point. We have
+ already checked the equivalence in this case.
+ Match on type plus offset, to allow for unnamed fields.
+ We won't necessarily get the corresponding field for
+ unions; this is believed to be harmless. */
+
+ if ((current_file_decl && TREE_CHAIN (current_file_decl))
+ && (DECL_FIELD_CONTEXT (TREE_OPERAND (expr, 1)) !=
+ TREE_TYPE (TREE_OPERAND (expr, 0))))
+ {
+ tree f;
+ tree orig_field = TREE_OPERAND (expr, 1);
+ tree orig_type = TREE_TYPE (orig_field);
+ for (f = TYPE_FIELDS (TREE_TYPE (TREE_OPERAND (expr, 0)));
+ f; f = TREE_CHAIN (f))
+ {
+ if (lang_hooks.types_compatible_p (TREE_TYPE (f), orig_type)
+ && tree_int_cst_compare (DECL_FIELD_BIT_OFFSET (f),
+ DECL_FIELD_BIT_OFFSET (orig_field)) == 0
+ && tree_int_cst_compare (DECL_FIELD_OFFSET (f),
+ DECL_FIELD_OFFSET (orig_field)) == 0)
+{
+ TREE_OPERAND (expr, 1) = f;
+ break;
+}
+ }
+ /* Fall through is an error; it will be detected in tree-sra. */
+ }
+ break;
+
default:
return NULL_TREE;
}
diff --git a/gcc/tree-ssa-copy.c b/gcc/tree-ssa-copy.c
index d737c1d89ba..65a52b74287 100644
--- a/gcc/tree-ssa-copy.c
+++ b/gcc/tree-ssa-copy.c
@@ -37,6 +37,7 @@ Boston, MA 02111-1307, USA. */
#include "tree-dump.h"
#include "tree-flow.h"
#include "tree-pass.h"
+#include "langhooks.h"
/* This file provides a handful of interfaces for performing const/copy
propagation and simple expression replacement which keep variable
@@ -219,8 +220,8 @@ cprop_into_stmt (tree stmt, varray_type const_and_copies)
constant by converting the constant to the proper type. Note
that convert may return a non-gimple expression, in which case
we ignore this propagation opportunity. */
- if (TYPE_MAIN_VARIANT (op_type) != TYPE_MAIN_VARIANT (val_type)
- && TREE_CODE (val) != SSA_NAME)
+ if (!lang_hooks.types_compatible_p (op_type, val_type)
+ && TREE_CODE (val) != SSA_NAME)
{
val = convert (TREE_TYPE (*op_p), val);
if (!is_gimple_min_invariant (val)
diff --git a/gcc/tree-ssa-dom.c b/gcc/tree-ssa-dom.c
index ed3c98ec292..b922b01610b 100644
--- a/gcc/tree-ssa-dom.c
+++ b/gcc/tree-ssa-dom.c
@@ -41,7 +41,7 @@ Boston, MA 02111-1307, USA. */
#include "real.h"
#include "tree-pass.h"
#include "flags.h"
-
+#include "langhooks.h"
/* This file implements optimizations on the dominator tree. */
@@ -3090,8 +3090,8 @@ avail_expr_eq (const void *p1, const void *p2)
same VUSE operands. */
if (TREE_CODE (rhs1) == TREE_CODE (rhs2)
&& (TREE_TYPE (rhs1) == TREE_TYPE (rhs2)
- || (TYPE_MAIN_VARIANT (TREE_TYPE (rhs1))
- == TYPE_MAIN_VARIANT (TREE_TYPE (rhs2))))
+ || lang_hooks.types_compatible_p (TREE_TYPE (rhs1),
+ TREE_TYPE (rhs2)))
&& operand_equal_p (rhs1, rhs2, 0))
{
vuse_optype ops1 = STMT_VUSE_OPS (s1);
diff --git a/gcc/tree-ssa-phiopt.c b/gcc/tree-ssa-phiopt.c
index db704c8790b..9bcb7144a50 100644
--- a/gcc/tree-ssa-phiopt.c
+++ b/gcc/tree-ssa-phiopt.c
@@ -33,6 +33,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#include "tree-flow.h"
#include "tree-pass.h"
#include "tree-dump.h"
+#include "langhooks.h"
static void tree_ssa_phiopt (void);
static bool conditional_replacement (basic_block bb, tree phi, tree arg0,
@@ -177,15 +178,13 @@ conditional_replacement (basic_block bb, tree phi, tree arg0, tree arg1)
cond = COND_EXPR_COND (last_stmt (cond_block));
result = PHI_RESULT (phi);
if (TREE_CODE (cond) != SSA_NAME
- && (TYPE_MAIN_VARIANT (TREE_TYPE (cond))
- != TYPE_MAIN_VARIANT (TREE_TYPE (result))))
+ && !lang_hooks.types_compatible_p (TREE_TYPE (cond), TREE_TYPE (result)))
return false;
/* If the condition was a naked SSA_NAME and the type is not the
same as the type of the result, then convert the type of the
condition. */
- if (TYPE_MAIN_VARIANT (TREE_TYPE (cond))
- != TYPE_MAIN_VARIANT (TREE_TYPE (result)))
+ if (!lang_hooks.types_compatible_p (TREE_TYPE (cond), TREE_TYPE (result)))
cond = convert (TREE_TYPE (result), cond);
/* We need to know which is the true edge and which is the false
diff --git a/gcc/tree-ssa.c b/gcc/tree-ssa.c
index 19514e01f7f..11dd4b983d0 100644
--- a/gcc/tree-ssa.c
+++ b/gcc/tree-ssa.c
@@ -3660,7 +3660,7 @@ tree_ssa_useless_type_conversion_1 (tree outer_type, tree inner_type)
strip the type conversion and enter the equivalence into
the table. */
if (inner_type == outer_type
- || TYPE_MAIN_VARIANT (inner_type) == TYPE_MAIN_VARIANT (outer_type))
+ || (lang_hooks.types_compatible_p (inner_type, outer_type)))
return true;
/* If both types are pointers and the outer type is a (void *), then
@@ -3678,8 +3678,7 @@ tree_ssa_useless_type_conversion_1 (tree outer_type, tree inner_type)
so strip conversions that just switch between them. */
else if (POINTER_TYPE_P (inner_type)
&& POINTER_TYPE_P (outer_type)
- && (TYPE_MAIN_VARIANT (TREE_TYPE (inner_type))
- == TYPE_MAIN_VARIANT (TREE_TYPE (outer_type))))
+ && lang_hooks.types_compatible_p (inner_type, outer_type))
return true;
/* If both the inner and outer types are integral types, then the
diff --git a/gcc/tree.h b/gcc/tree.h
index 5c3c4de2ddf..64d6d8eaeb9 100644
--- a/gcc/tree.h
+++ b/gcc/tree.h
@@ -3233,6 +3233,11 @@ extern GTY(()) tree current_function_decl;
/* Nonzero means a FUNC_BEGIN label was emitted. */
extern GTY(()) tree current_function_func_begin_label;
+/* A DECL for the current file-scope context. When using IMA, this heads a
+ chain of FILE_DECLs; currently only C uses it. */
+
+extern GTY(()) tree current_file_decl;
+
/* Nonzero means all ..._TYPE nodes should be allocated permanently. */
extern int all_types_permanent;