diff options
author | Dale Johannesen <dalej@apple.com> | 2004-03-16 22:16:41 +0000 |
---|---|---|
committer | Dale Johannesen <dalej@apple.com> | 2004-03-16 22:16:41 +0000 |
commit | 80131e0595f04c257f4c8a7bc1daefaccf70ebd9 (patch) | |
tree | 3d22377ab89b8718d053de97937d396ec617f4c3 | |
parent | 50f6616bc05060f19cd65dc3d9c5bb3bebfac310 (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-ssa | 46 | ||||
-rw-r--r-- | gcc/Makefile.in | 10 | ||||
-rw-r--r-- | gcc/c-common.c | 103 | ||||
-rw-r--r-- | gcc/c-decl.c | 4 | ||||
-rw-r--r-- | gcc/c-lang.c | 8 | ||||
-rw-r--r-- | gcc/c-tree.h | 1 | ||||
-rw-r--r-- | gcc/c-typeck.c | 10 | ||||
-rw-r--r-- | gcc/cp/cp-lang.c | 8 | ||||
-rw-r--r-- | gcc/gimplify.c | 6 | ||||
-rw-r--r-- | gcc/langhooks-def.h | 3 | ||||
-rw-r--r-- | gcc/langhooks.c | 10 | ||||
-rw-r--r-- | gcc/langhooks.h | 5 | ||||
-rw-r--r-- | gcc/stmt.c | 4 | ||||
-rw-r--r-- | gcc/toplev.c | 5 | ||||
-rw-r--r-- | gcc/tree-nrv.c | 5 | ||||
-rw-r--r-- | gcc/tree-ssa-ccp.c | 45 | ||||
-rw-r--r-- | gcc/tree-ssa-copy.c | 5 | ||||
-rw-r--r-- | gcc/tree-ssa-dom.c | 6 | ||||
-rw-r--r-- | gcc/tree-ssa-phiopt.c | 7 | ||||
-rw-r--r-- | gcc/tree-ssa.c | 5 | ||||
-rw-r--r-- | gcc/tree.h | 5 |
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; |