X-Git-Url: http://git.sourceforge.jp/view?p=pf3gnuchains%2Fgcc-fork.git;a=blobdiff_plain;f=gcc%2Fgimple.c;h=e5dc184d460834de44c00d6129045f7e4b87c21a;hp=105fb1b60613792c08fdf88e32df690854e83713;hb=d417cc8b1bc927d7c4cc124aad5f3e9451f2ec20;hpb=65162f7e02aaf62896f005048c16da509503c314 diff --git a/gcc/gimple.c b/gcc/gimple.c index 105fb1b6061..e5dc184d460 100644 --- a/gcc/gimple.c +++ b/gcc/gimple.c @@ -1,6 +1,6 @@ /* Gimple IR support functions. - Copyright 2007, 2008, 2009 Free Software Foundation, Inc. + Copyright 2007, 2008, 2009, 2010 Free Software Foundation, Inc. Contributed by Aldy Hernandez This file is part of GCC. @@ -171,7 +171,7 @@ gimple_set_subcode (gimple g, unsigned subcode) /* Build a tuple with operands. CODE is the statement to build (which must be one of the GIMPLE_WITH_OPS tuples). SUBCODE is the sub-code - for the new tuple. NUM_OPS is the number of operands to allocate. */ + for the new tuple. NUM_OPS is the number of operands to allocate. */ #define gimple_build_with_ops(c, s, n) \ gimple_build_with_ops_stat (c, s, n MEM_STAT_INFO) @@ -198,6 +198,21 @@ gimple_build_return (tree retval) return s; } +/* Reset alias information on call S. */ + +void +gimple_call_reset_alias_info (gimple s) +{ + if (gimple_call_flags (s) & ECF_CONST) + memset (gimple_call_use_set (s), 0, sizeof (struct pt_solution)); + else + pt_solution_reset (gimple_call_use_set (s)); + if (gimple_call_flags (s) & (ECF_CONST|ECF_PURE|ECF_NOVOPS)) + memset (gimple_call_clobber_set (s), 0, sizeof (struct pt_solution)); + else + pt_solution_reset (gimple_call_clobber_set (s)); +} + /* Helper for gimple_build_call, gimple_build_call_vec and gimple_build_call_from_tree. Build the basic components of a GIMPLE_CALL statement to function FN with NARGS arguments. */ @@ -209,6 +224,7 @@ gimple_build_call_1 (tree fn, unsigned nargs) if (TREE_CODE (fn) == FUNCTION_DECL) fn = build_fold_addr_expr (fn); gimple_set_op (s, 1, fn); + gimple_call_reset_alias_info (s); return s; } @@ -281,6 +297,7 @@ gimple_build_call_from_tree (tree t) gimple_call_set_return_slot_opt (call, CALL_EXPR_RETURN_SLOT_OPT (t)); gimple_call_set_from_thunk (call, CALL_FROM_THUNK_P (t)); gimple_call_set_va_arg_pack (call, CALL_EXPR_VA_ARG_PACK (t)); + gimple_call_set_nothrow (call, TREE_NOTHROW (t)); gimple_set_no_warning (call, TREE_NO_WARNING (t)); return call; @@ -350,7 +367,7 @@ gimple_build_assign_with_ops_stat (enum tree_code subcode, tree lhs, tree op1, /* Need 1 operand for LHS and 1 or 2 for the RHS (depending on the code). */ num_ops = get_gimple_rhs_num_ops (subcode) + 1; - + p = gimple_build_with_ops_stat (GIMPLE_ASSIGN, (unsigned)subcode, num_ops PASS_MEM_STAT); gimple_assign_set_lhs (p, lhs); @@ -375,7 +392,7 @@ gimple_build_assign_with_ops_stat (enum tree_code subcode, tree lhs, tree op1, gimple gimplify_assign (tree dst, tree src, gimple_seq *seq_p) -{ +{ tree t = build2 (MODIFY_EXPR, TREE_TYPE (dst), dst, src); gimplify_and_add (t, seq_p); ggc_free (t); @@ -485,7 +502,7 @@ gimple_build_goto (tree dest) /* Build a GIMPLE_NOP statement. */ -gimple +gimple gimple_build_nop (void) { return gimple_alloc (GIMPLE_NOP, 0); @@ -517,7 +534,7 @@ gimple_build_bind (tree vars, gimple_seq body, tree block) */ static inline gimple -gimple_build_asm_1 (const char *string, unsigned ninputs, unsigned noutputs, +gimple_build_asm_1 (const char *string, unsigned ninputs, unsigned noutputs, unsigned nclobbers, unsigned nlabels) { gimple p; @@ -539,7 +556,7 @@ gimple_build_asm_1 (const char *string, unsigned ninputs, unsigned noutputs, #ifdef GATHER_STATISTICS gimple_alloc_sizes[(int) gimple_alloc_kind (GIMPLE_ASM)] += size; #endif - + return p; } @@ -555,7 +572,7 @@ gimple_build_asm_1 (const char *string, unsigned ninputs, unsigned noutputs, LABELS is a vector of destination labels. */ gimple -gimple_build_asm_vec (const char *string, VEC(tree,gc)* inputs, +gimple_build_asm_vec (const char *string, VEC(tree,gc)* inputs, VEC(tree,gc)* outputs, VEC(tree,gc)* clobbers, VEC(tree,gc)* labels) { @@ -564,10 +581,10 @@ gimple_build_asm_vec (const char *string, VEC(tree,gc)* inputs, p = gimple_build_asm_1 (string, VEC_length (tree, inputs), - VEC_length (tree, outputs), + VEC_length (tree, outputs), VEC_length (tree, clobbers), VEC_length (tree, labels)); - + for (i = 0; i < VEC_length (tree, inputs); i++) gimple_asm_set_input_op (p, i, VEC_index (tree, inputs, i)); @@ -576,10 +593,10 @@ gimple_build_asm_vec (const char *string, VEC(tree,gc)* inputs, for (i = 0; i < VEC_length (tree, clobbers); i++) gimple_asm_set_clobber_op (p, i, VEC_index (tree, clobbers, i)); - + for (i = 0; i < VEC_length (tree, labels); i++) gimple_asm_set_label_op (p, i, VEC_index (tree, labels, i)); - + return p; } @@ -620,7 +637,7 @@ gimple_build_eh_filter (tree types, gimple_seq failure) gimple gimple_build_eh_must_not_throw (tree decl) { - gimple p = gimple_alloc (GIMPLE_EH_MUST_NOT_THROW, 1); + gimple p = gimple_alloc (GIMPLE_EH_MUST_NOT_THROW, 0); gcc_assert (TREE_CODE (decl) == FUNCTION_DECL); gcc_assert (flags_from_decl_or_type (decl) & ECF_NORETURN); @@ -684,7 +701,7 @@ gimple_build_resx (int region) NLABELS is the number of labels in the switch excluding the default. DEFAULT_LABEL is the default label for the switch statement. */ -gimple +gimple gimple_build_switch_nlabels (unsigned nlabels, tree index, tree default_label) { /* nlabels + 1 default label + 1 index. */ @@ -700,10 +717,10 @@ gimple_build_switch_nlabels (unsigned nlabels, tree index, tree default_label) /* Build a GIMPLE_SWITCH statement. INDEX is the switch's index. - NLABELS is the number of labels in the switch excluding the DEFAULT_LABEL. + NLABELS is the number of labels in the switch excluding the DEFAULT_LABEL. ... are the labels excluding the default. */ -gimple +gimple gimple_build_switch (unsigned nlabels, tree index, tree default_label, ...) { va_list al; @@ -779,7 +796,7 @@ gimple_build_debug_bind_stat (tree var, tree value, gimple stmt MEM_STAT_DECL) BODY is the sequence of statements for which only one thread can execute. NAME is optional identifier for this critical block. */ -gimple +gimple gimple_build_omp_critical (gimple_seq body, tree name) { gimple p = gimple_alloc (GIMPLE_OMP_CRITICAL, 0); @@ -793,7 +810,7 @@ gimple_build_omp_critical (gimple_seq body, tree name) /* Build a GIMPLE_OMP_FOR statement. BODY is sequence of statements inside the for loop. - CLAUSES, are any of the OMP loop construct's clauses: private, firstprivate, + CLAUSES, are any of the OMP loop construct's clauses: private, firstprivate, lastprivate, reductions, ordered, schedule, and nowait. COLLAPSE is the collapse count. PRE_BODY is the sequence of statements that are loop invariant. */ @@ -822,8 +839,8 @@ gimple_build_omp_for (gimple_seq body, tree clauses, size_t collapse, CHILD_FN is the function created for the parallel threads to execute. DATA_ARG are the shared data argument(s). */ -gimple -gimple_build_omp_parallel (gimple_seq body, tree clauses, tree child_fn, +gimple +gimple_build_omp_parallel (gimple_seq body, tree clauses, tree child_fn, tree data_arg) { gimple p = gimple_alloc (GIMPLE_OMP_PARALLEL, 0); @@ -846,7 +863,7 @@ gimple_build_omp_parallel (gimple_seq body, tree clauses, tree child_fn, COPY_FN is the optional function for firstprivate initialization. ARG_SIZE and ARG_ALIGN are size and alignment of the data block. */ -gimple +gimple gimple_build_omp_task (gimple_seq body, tree clauses, tree child_fn, tree data_arg, tree copy_fn, tree arg_size, tree arg_align) @@ -884,7 +901,7 @@ gimple_build_omp_section (gimple_seq body) BODY is the sequence of statements to be executed by just the master. */ -gimple +gimple gimple_build_omp_master (gimple_seq body) { gimple p = gimple_alloc (GIMPLE_OMP_MASTER, 0); @@ -900,7 +917,7 @@ gimple_build_omp_master (gimple_seq body) CONTROL_DEF is the definition of the control variable. CONTROL_USE is the use of the control variable. */ -gimple +gimple gimple_build_omp_continue (tree control_def, tree control_use) { gimple p = gimple_alloc (GIMPLE_OMP_CONTINUE, 0); @@ -914,7 +931,7 @@ gimple_build_omp_continue (tree control_def, tree control_use) BODY is the sequence of statements inside a loop that will executed in sequence. */ -gimple +gimple gimple_build_omp_ordered (gimple_seq body) { gimple p = gimple_alloc (GIMPLE_OMP_ORDERED, 0); @@ -928,7 +945,7 @@ gimple_build_omp_ordered (gimple_seq body) /* Build a GIMPLE_OMP_RETURN statement. WAIT_P is true if this is a non-waiting return. */ -gimple +gimple gimple_build_omp_return (bool wait_p) { gimple p = gimple_alloc (GIMPLE_OMP_RETURN, 0); @@ -945,7 +962,7 @@ gimple_build_omp_return (bool wait_p) CLAUSES are any of the OMP sections contsruct's clauses: private, firstprivate, lastprivate, reduction, and nowait. */ -gimple +gimple gimple_build_omp_sections (gimple_seq body, tree clauses) { gimple p = gimple_alloc (GIMPLE_OMP_SECTIONS, 0); @@ -972,7 +989,7 @@ gimple_build_omp_sections_switch (void) CLAUSES are any of the OMP single construct's clauses: private, firstprivate, copyprivate, nowait. */ -gimple +gimple gimple_build_omp_single (gimple_seq body, tree clauses) { gimple p = gimple_alloc (GIMPLE_OMP_SINGLE, 0); @@ -1081,7 +1098,7 @@ gimple_seq_free (gimple_seq seq) /* If this triggers, it's a sign that the same list is being freed twice. */ gcc_assert (seq != gimple_seq_cache || gimple_seq_cache == NULL); - + /* Add SEQ to the pool of free sequences. */ seq->next_free = gimple_seq_cache; gimple_seq_cache = seq; @@ -1179,7 +1196,7 @@ gimple_seq_copy (gimple_seq src) /* Walk all the statements in the sequence SEQ calling walk_gimple_stmt on each one. WI is as in walk_gimple_stmt. - + If walk_gimple_stmt returns non-NULL, the walk is stopped, the value is stored in WI->CALLBACK_RESULT and the statement that produced the value is returned. @@ -1297,7 +1314,7 @@ walk_gimple_asm (gimple stmt, walk_tree_fn callback_op, The return value is that returned by the last call to walk_tree, or NULL_TREE if no CALLBACK_OP is specified. */ -inline tree +tree walk_gimple_op (gimple stmt, walk_tree_fn callback_op, struct walk_stmt_info *wi) { @@ -1308,11 +1325,15 @@ walk_gimple_op (gimple stmt, walk_tree_fn callback_op, switch (gimple_code (stmt)) { case GIMPLE_ASSIGN: - /* Walk the RHS operands. A formal temporary LHS may use a - COMPONENT_REF RHS. */ + /* Walk the RHS operands. If the LHS is of a non-renamable type or + is a register variable, we may use a COMPONENT_REF on the RHS. */ if (wi) - wi->val_only = !is_gimple_reg (gimple_assign_lhs (stmt)) - || !gimple_assign_single_p (stmt); + { + tree lhs = gimple_assign_lhs (stmt); + wi->val_only + = (is_gimple_reg_type (TREE_TYPE (lhs)) && !is_gimple_reg (lhs)) + || !gimple_assign_single_p (stmt); + } for (i = 1; i < gimple_num_ops (stmt); i++) { @@ -1733,9 +1754,86 @@ gimple_call_flags (const_gimple stmt) flags = 0; } + if (stmt->gsbase.subcode & GF_CALL_NOTHROW) + flags |= ECF_NOTHROW; + return flags; } +/* Detects argument flags for argument number ARG on call STMT. */ + +int +gimple_call_arg_flags (const_gimple stmt, unsigned arg) +{ + tree type = TREE_TYPE (TREE_TYPE (gimple_call_fn (stmt))); + tree attr = lookup_attribute ("fn spec", TYPE_ATTRIBUTES (type)); + if (!attr) + return 0; + + attr = TREE_VALUE (TREE_VALUE (attr)); + if (1 + arg >= (unsigned) TREE_STRING_LENGTH (attr)) + return 0; + + switch (TREE_STRING_POINTER (attr)[1 + arg]) + { + case 'x': + case 'X': + return EAF_UNUSED; + + case 'R': + return EAF_DIRECT | EAF_NOCLOBBER | EAF_NOESCAPE; + + case 'r': + return EAF_NOCLOBBER | EAF_NOESCAPE; + + case 'W': + return EAF_DIRECT | EAF_NOESCAPE; + + case 'w': + return EAF_NOESCAPE; + + case '.': + default: + return 0; + } +} + +/* Detects return flags for the call STMT. */ + +int +gimple_call_return_flags (const_gimple stmt) +{ + tree type; + tree attr = NULL_TREE; + + if (gimple_call_flags (stmt) & ECF_MALLOC) + return ERF_NOALIAS; + + type = TREE_TYPE (TREE_TYPE (gimple_call_fn (stmt))); + attr = lookup_attribute ("fn spec", TYPE_ATTRIBUTES (type)); + if (!attr) + return 0; + + attr = TREE_VALUE (TREE_VALUE (attr)); + if (TREE_STRING_LENGTH (attr) < 1) + return 0; + + switch (TREE_STRING_POINTER (attr)[0]) + { + case '1': + case '2': + case '3': + case '4': + return ERF_RETURNS_ARG | (TREE_STRING_POINTER (attr)[0] - '1'); + + case 'm': + return ERF_NOALIAS; + + case '.': + default: + return 0; + } +} /* Return true if GS is a copy assignment. */ @@ -1789,7 +1887,7 @@ gimple_assign_single_p (gimple gs) assignment. I suspect there may be cases where gimple_assign_copy_p, gimple_assign_single_p, or equivalent logic is used where a similar treatment of unary NOPs is appropriate. */ - + bool gimple_assign_unary_nop_p (gimple gs) { @@ -1835,54 +1933,6 @@ gimple_set_bb (gimple stmt, basic_block bb) } -/* Fold the expression computed by STMT. If the expression can be - folded, return the folded result, otherwise return NULL. STMT is - not modified. */ - -tree -gimple_fold (const_gimple stmt) -{ - location_t loc = gimple_location (stmt); - switch (gimple_code (stmt)) - { - case GIMPLE_COND: - return fold_binary_loc (loc, gimple_cond_code (stmt), - boolean_type_node, - gimple_cond_lhs (stmt), - gimple_cond_rhs (stmt)); - - case GIMPLE_ASSIGN: - switch (get_gimple_rhs_class (gimple_assign_rhs_code (stmt))) - { - case GIMPLE_UNARY_RHS: - return fold_unary_loc (loc, gimple_assign_rhs_code (stmt), - TREE_TYPE (gimple_assign_lhs (stmt)), - gimple_assign_rhs1 (stmt)); - case GIMPLE_BINARY_RHS: - return fold_binary_loc (loc, gimple_assign_rhs_code (stmt), - TREE_TYPE (gimple_assign_lhs (stmt)), - gimple_assign_rhs1 (stmt), - gimple_assign_rhs2 (stmt)); - case GIMPLE_SINGLE_RHS: - return fold (gimple_assign_rhs1 (stmt)); - default:; - } - break; - - case GIMPLE_SWITCH: - return gimple_switch_index (stmt); - - case GIMPLE_CALL: - return NULL_TREE; - - default: - break; - } - - gcc_unreachable (); -} - - /* Modify the RHS of the assignment pointed-to by GSI using the operands in the expression tree EXPR. @@ -1981,6 +2031,39 @@ gimple_set_lhs (gimple stmt, tree lhs) gcc_unreachable(); } +/* Replace the LHS of STMT, an assignment, either a GIMPLE_ASSIGN or a + GIMPLE_CALL, with NLHS, in preparation for modifying the RHS to an + expression with a different value. + + This will update any annotations (say debug bind stmts) referring + to the original LHS, so that they use the RHS instead. This is + done even if NLHS and LHS are the same, for it is understood that + the RHS will be modified afterwards, and NLHS will not be assigned + an equivalent value. + + Adjusting any non-annotation uses of the LHS, if needed, is a + responsibility of the caller. + + The effect of this call should be pretty much the same as that of + inserting a copy of STMT before STMT, and then removing the + original stmt, at which time gsi_remove() would have update + annotations, but using this function saves all the inserting, + copying and removing. */ + +void +gimple_replace_lhs (gimple stmt, tree nlhs) +{ + if (MAY_HAVE_DEBUG_STMTS) + { + tree lhs = gimple_get_lhs (stmt); + + gcc_assert (SSA_NAME_DEF_STMT (lhs) == stmt); + + insert_debug_temp_for_var_def (NULL, lhs); + } + + gimple_set_lhs (stmt, nlhs); +} /* Return a deep copy of statement STMT. All the operands from STMT are reallocated and copied using unshare_expr. The DEF, USE, VDEF @@ -2869,7 +2952,7 @@ get_base_address (tree t) { while (handled_component_p (t)) t = TREE_OPERAND (t, 0); - + if (SSA_VAR_P (t) || TREE_CODE (t) == STRING_CST || TREE_CODE (t) == CONSTRUCTOR @@ -2937,9 +3020,14 @@ recalculate_side_effects (tree t) tree canonicalize_cond_expr_cond (tree t) { + /* Strip conversions around boolean operations. */ + if (CONVERT_EXPR_P (t) + && truth_value_p (TREE_CODE (TREE_OPERAND (t, 0)))) + t = TREE_OPERAND (t, 0); + /* For (bool)x use x != 0. */ - if (TREE_CODE (t) == NOP_EXPR - && TREE_TYPE (t) == boolean_type_node) + if (CONVERT_EXPR_P (t) + && TREE_CODE (TREE_TYPE (t)) == BOOLEAN_TYPE) { tree top0 = TREE_OPERAND (t, 0); t = build2 (NE_EXPR, TREE_TYPE (t), @@ -3090,35 +3178,6 @@ lookup_type_pair (tree t1, tree t2, htab_t *visited_p, struct obstack *ob_p) } -/* Force merging the type T2 into the type T1. */ - -void -gimple_force_type_merge (tree t1, tree t2) -{ - void **slot; - type_pair_t p; - - /* There's no other way than copying t2 to t1 in this case. - Yuck. We'll just call this "completing" t1. */ - memcpy (t1, t2, tree_size (t1)); - - /* Adjust the hash value of T1 if it was computed already. Otherwise - we would be forced to not hash fields of structs to match the - hash value of an incomplete struct. */ - if (type_hash_cache - && (slot = pointer_map_contains (type_hash_cache, t1)) != NULL) - { - gimple_type_hash (t2); - *slot = *pointer_map_contains (type_hash_cache, t2); - } - - /* Adjust cached comparison results for T1 and T2 to make sure - they now compare compatible. */ - p = lookup_type_pair (t1, t2, >c_visited, >c_ob); - p->same_p = 1; -} - - /* Return true if T1 and T2 have the same name. If FOR_COMPLETION_P is true then if any type has no name return false, otherwise return true if both types have no names. */ @@ -3160,16 +3219,35 @@ compare_type_names_p (tree t1, tree t2, bool for_completion_p) return false; } -/* Return true if the field decls F1 and F2 are at the same offset. */ +/* Return true if the field decls F1 and F2 are at the same offset. -static bool -compare_field_offset (tree f1, tree f2) + This is intended to be used on GIMPLE types only. In order to + compare GENERIC types, use fields_compatible_p instead. */ + +bool +gimple_compare_field_offset (tree f1, tree f2) { if (DECL_OFFSET_ALIGN (f1) == DECL_OFFSET_ALIGN (f2)) - return (operand_equal_p (DECL_FIELD_OFFSET (f1), - DECL_FIELD_OFFSET (f2), 0) - && tree_int_cst_equal (DECL_FIELD_BIT_OFFSET (f1), - DECL_FIELD_BIT_OFFSET (f2))); + { + tree offset1 = DECL_FIELD_OFFSET (f1); + tree offset2 = DECL_FIELD_OFFSET (f2); + return ((offset1 == offset2 + /* Once gimplification is done, self-referential offsets are + instantiated as operand #2 of the COMPONENT_REF built for + each access and reset. Therefore, they are not relevant + anymore and fields are interchangeable provided that they + represent the same access. */ + || (TREE_CODE (offset1) == PLACEHOLDER_EXPR + && TREE_CODE (offset2) == PLACEHOLDER_EXPR + && (DECL_SIZE (f1) == DECL_SIZE (f2) + || (TREE_CODE (DECL_SIZE (f1)) == PLACEHOLDER_EXPR + && TREE_CODE (DECL_SIZE (f2)) == PLACEHOLDER_EXPR) + || operand_equal_p (DECL_SIZE (f1), DECL_SIZE (f2), 0)) + && DECL_ALIGN (f1) == DECL_ALIGN (f2)) + || operand_equal_p (offset1, offset2, 0)) + && tree_int_cst_equal (DECL_FIELD_BIT_OFFSET (f1), + DECL_FIELD_BIT_OFFSET (f2))); + } /* Fortran and C do not always agree on what DECL_OFFSET_ALIGN should be, so handle differing ones specially by decomposing @@ -3196,30 +3274,65 @@ compare_field_offset (tree f1, tree f2) /* Return 1 iff T1 and T2 are structurally identical. Otherwise, return 0. */ -int +static int gimple_types_compatible_p (tree t1, tree t2) { type_pair_t p = NULL; /* Check first for the obvious case of pointer identity. */ if (t1 == t2) - goto same_types; + return 1; /* Check that we have two types to compare. */ if (t1 == NULL_TREE || t2 == NULL_TREE) - goto different_types; + return 0; /* Can't be the same type if the types don't have the same code. */ if (TREE_CODE (t1) != TREE_CODE (t2)) - goto different_types; + return 0; + + /* Can't be the same type if they have different CV qualifiers. */ + if (TYPE_QUALS (t1) != TYPE_QUALS (t2)) + return 0; /* Void types are always the same. */ if (TREE_CODE (t1) == VOID_TYPE) - goto same_types; + return 1; - /* Can't be the same type if they have different CV qualifiers. */ - if (TYPE_QUALS (t1) != TYPE_QUALS (t2)) - goto different_types; + /* For numerical types do some simple checks before doing three + hashtable queries. */ + if (INTEGRAL_TYPE_P (t1) + || SCALAR_FLOAT_TYPE_P (t1) + || FIXED_POINT_TYPE_P (t1) + || TREE_CODE (t1) == VECTOR_TYPE + || TREE_CODE (t1) == COMPLEX_TYPE + || TREE_CODE (t1) == OFFSET_TYPE) + { + /* Can't be the same type if they have different alignment, + sign, precision or mode. */ + if (TYPE_ALIGN (t1) != TYPE_ALIGN (t2) + || TYPE_PRECISION (t1) != TYPE_PRECISION (t2) + || TYPE_MODE (t1) != TYPE_MODE (t2) + || TYPE_UNSIGNED (t1) != TYPE_UNSIGNED (t2)) + return 0; + + if (TREE_CODE (t1) == INTEGER_TYPE + && (TYPE_IS_SIZETYPE (t1) != TYPE_IS_SIZETYPE (t2) + || TYPE_STRING_FLAG (t1) != TYPE_STRING_FLAG (t2))) + return 0; + + /* That's all we need to check for float and fixed-point types. */ + if (SCALAR_FLOAT_TYPE_P (t1) + || FIXED_POINT_TYPE_P (t1)) + return 1; + + /* Perform cheap tail-recursion for vector and complex types. */ + if (TREE_CODE (t1) == VECTOR_TYPE + || TREE_CODE (t1) == COMPLEX_TYPE) + return gimple_types_compatible_p (TREE_TYPE (t1), TREE_TYPE (t2)); + + /* For integral types fall thru to more complex checks. */ + } /* If the hash values of t1 and t2 are different the types can't possibly be the same. This helps keeping the type-pair hashtable @@ -3252,71 +3365,6 @@ gimple_types_compatible_p (tree t1, tree t2) if (!attribute_list_equal (TYPE_ATTRIBUTES (t1), TYPE_ATTRIBUTES (t2))) goto different_types; - /* For numerical types, the bounds must coincide. */ - if (INTEGRAL_TYPE_P (t1) - || SCALAR_FLOAT_TYPE_P (t1) - || FIXED_POINT_TYPE_P (t1)) - { - /* Can't be the same type if they have different size, alignment, - sign, precision or mode. Note that from now on, comparisons - between *_CST nodes must be done using tree_int_cst_equal because - we cannot assume that constants from T1 and T2 will be shared - since T1 and T2 are distinct pointers. */ - if (!tree_int_cst_equal (TYPE_SIZE (t1), TYPE_SIZE (t2)) - || !tree_int_cst_equal (TYPE_SIZE_UNIT (t1), TYPE_SIZE_UNIT (t2)) - || TYPE_ALIGN (t1) != TYPE_ALIGN (t2) - || TYPE_PRECISION (t1) != TYPE_PRECISION (t2) - || TYPE_MODE (t1) != TYPE_MODE (t2) - || TYPE_UNSIGNED (t1) != TYPE_UNSIGNED (t2)) - goto different_types; - - /* For non-enumeral types, check type bounds. FIXME lto, we - cannot check bounds on enumeral types because different front - ends will produce different values. In C, enumeral types are - integers, while in C++ each element will have its own - symbolic value. We should decide how enums are to be - represented in GIMPLE and have each front end lower to that. */ - if (TREE_CODE (t1) != ENUMERAL_TYPE) - { - tree min1 = TYPE_MIN_VALUE (t1); - tree max1 = TYPE_MAX_VALUE (t1); - tree min2 = TYPE_MIN_VALUE (t2); - tree max2 = TYPE_MAX_VALUE (t2); - bool min_equal_p = false; - bool max_equal_p = false; - - /* If either type has a minimum value, the other type must - have the same. */ - if (min1 == NULL_TREE && min2 == NULL_TREE) - min_equal_p = true; - else if (min1 && min2 && operand_equal_p (min1, min2, 0)) - min_equal_p = true; - - /* Likewise, if either type has a maximum value, the other - type must have the same. */ - if (max1 == NULL_TREE && max2 == NULL_TREE) - max_equal_p = true; - else if (max1 && max2 && operand_equal_p (max1, max2, 0)) - max_equal_p = true; - - if (!min_equal_p || !max_equal_p) - goto different_types; - } - - if (TREE_CODE (t1) == INTEGER_TYPE) - { - if (TYPE_IS_SIZETYPE (t1) == TYPE_IS_SIZETYPE (t2) - && TYPE_STRING_FLAG (t1) == TYPE_STRING_FLAG (t2)) - goto same_types; - else - goto different_types; - } - else if (TREE_CODE (t1) == BOOLEAN_TYPE) - goto same_types; - else if (TREE_CODE (t1) == REAL_TYPE) - goto same_types; - } - /* Do type-specific comparisons. */ switch (TREE_CODE (t1)) { @@ -3324,7 +3372,8 @@ gimple_types_compatible_p (tree t1, tree t2) /* Array types are the same if the element types are the same and the number of elements are the same. */ if (!gimple_types_compatible_p (TREE_TYPE (t1), TREE_TYPE (t2)) - || TYPE_STRING_FLAG (t1) != TYPE_STRING_FLAG (t2)) + || TYPE_STRING_FLAG (t1) != TYPE_STRING_FLAG (t2) + || TYPE_NONALIASED_COMPONENT (t1) != TYPE_NONALIASED_COMPONENT (t2)) goto different_types; else { @@ -3353,9 +3402,15 @@ gimple_types_compatible_p (tree t1, tree t2) /* The minimum/maximum values have to be the same. */ if ((min1 == min2 - || (min1 && min2 && operand_equal_p (min1, min2, 0))) + || (min1 && min2 + && ((TREE_CODE (min1) == PLACEHOLDER_EXPR + && TREE_CODE (min2) == PLACEHOLDER_EXPR) + || operand_equal_p (min1, min2, 0)))) && (max1 == max2 - || (max1 && max2 && operand_equal_p (max1, max2, 0)))) + || (max1 && max2 + && ((TREE_CODE (max1) == PLACEHOLDER_EXPR + && TREE_CODE (max2) == PLACEHOLDER_EXPR) + || operand_equal_p (max1, max2, 0))))) goto same_types; else goto different_types; @@ -3402,134 +3457,179 @@ gimple_types_compatible_p (tree t1, tree t2) } } + case OFFSET_TYPE: + { + if (!gimple_types_compatible_p (TREE_TYPE (t1), TREE_TYPE (t2)) + || !gimple_types_compatible_p (TYPE_OFFSET_BASETYPE (t1), + TYPE_OFFSET_BASETYPE (t2))) + goto different_types; + + goto same_types; + } + case POINTER_TYPE: case REFERENCE_TYPE: - { - /* If the two pointers have different ref-all attributes, - they can't be the same type. */ - if (TYPE_REF_CAN_ALIAS_ALL (t1) != TYPE_REF_CAN_ALIAS_ALL (t2)) - goto different_types; - - /* If one pointer points to an incomplete type variant of - the other pointed-to type they are the same. */ - if (TREE_CODE (TREE_TYPE (t1)) == TREE_CODE (TREE_TYPE (t2)) - && RECORD_OR_UNION_TYPE_P (TREE_TYPE (t1)) - && (!COMPLETE_TYPE_P (TREE_TYPE (t1)) - || !COMPLETE_TYPE_P (TREE_TYPE (t2))) - && compare_type_names_p (TREE_TYPE (t1), TREE_TYPE (t2), true)) - { - /* Replace the pointed-to incomplete type with the - complete one. */ - if (COMPLETE_TYPE_P (TREE_TYPE (t2))) - TREE_TYPE (t1) = TREE_TYPE (t2); - else - TREE_TYPE (t2) = TREE_TYPE (t1); - goto same_types; - } + { + /* If the two pointers have different ref-all attributes, + they can't be the same type. */ + if (TYPE_REF_CAN_ALIAS_ALL (t1) != TYPE_REF_CAN_ALIAS_ALL (t2)) + goto different_types; - /* Otherwise, pointer and reference types are the same if the - pointed-to types are the same. */ - if (gimple_types_compatible_p (TREE_TYPE (t1), TREE_TYPE (t2))) + /* If one pointer points to an incomplete type variant of + the other pointed-to type they are the same. */ + if (TREE_CODE (TREE_TYPE (t1)) == TREE_CODE (TREE_TYPE (t2)) + && RECORD_OR_UNION_TYPE_P (TREE_TYPE (t1)) + && (!COMPLETE_TYPE_P (TREE_TYPE (t1)) + || !COMPLETE_TYPE_P (TREE_TYPE (t2))) + && TYPE_QUALS (TREE_TYPE (t1)) == TYPE_QUALS (TREE_TYPE (t2)) + && compare_type_names_p (TYPE_MAIN_VARIANT (TREE_TYPE (t1)), + TYPE_MAIN_VARIANT (TREE_TYPE (t2)), true)) + { + /* Replace the pointed-to incomplete type with the + complete one. + ??? This simple name-based merging causes at least some + of the ICEs in canonicalizing FIELD_DECLs during stmt + read. For example in GCC we have two different struct deps + and we mismatch the use in struct cpp_reader in sched-int.h + vs. mkdeps.c. Of course the whole exercise is for TBAA + with structs which contain pointers to incomplete types + in one unit and to complete ones in another. So we + probably should merge these types only with more context. */ + if (COMPLETE_TYPE_P (TREE_TYPE (t2))) + TREE_TYPE (t1) = TREE_TYPE (t2); + else + TREE_TYPE (t2) = TREE_TYPE (t1); goto same_types; - + } + + /* Otherwise, pointer and reference types are the same if the + pointed-to types are the same. */ + if (gimple_types_compatible_p (TREE_TYPE (t1), TREE_TYPE (t2))) + goto same_types; + + goto different_types; + } + + case INTEGER_TYPE: + case BOOLEAN_TYPE: + { + tree min1 = TYPE_MIN_VALUE (t1); + tree max1 = TYPE_MAX_VALUE (t1); + tree min2 = TYPE_MIN_VALUE (t2); + tree max2 = TYPE_MAX_VALUE (t2); + bool min_equal_p = false; + bool max_equal_p = false; + + /* If either type has a minimum value, the other type must + have the same. */ + if (min1 == NULL_TREE && min2 == NULL_TREE) + min_equal_p = true; + else if (min1 && min2 && operand_equal_p (min1, min2, 0)) + min_equal_p = true; + + /* Likewise, if either type has a maximum value, the other + type must have the same. */ + if (max1 == NULL_TREE && max2 == NULL_TREE) + max_equal_p = true; + else if (max1 && max2 && operand_equal_p (max1, max2, 0)) + max_equal_p = true; + + if (!min_equal_p || !max_equal_p) goto different_types; - } - case ENUMERAL_TYPE: - { - /* For enumeral types, all the values must be the same. */ - tree v1, v2; + goto same_types; + } - if (TYPE_VALUES (t1) == TYPE_VALUES (t2)) - goto same_types; + case ENUMERAL_TYPE: + { + /* FIXME lto, we cannot check bounds on enumeral types because + different front ends will produce different values. + In C, enumeral types are integers, while in C++ each element + will have its own symbolic value. We should decide how enums + are to be represented in GIMPLE and have each front end lower + to that. */ + tree v1, v2; + + /* For enumeral types, all the values must be the same. */ + if (TYPE_VALUES (t1) == TYPE_VALUES (t2)) + goto same_types; - for (v1 = TYPE_VALUES (t1), v2 = TYPE_VALUES (t2); - v1 && v2; - v1 = TREE_CHAIN (v1), v2 = TREE_CHAIN (v2)) - { - tree c1 = TREE_VALUE (v1); - tree c2 = TREE_VALUE (v2); + for (v1 = TYPE_VALUES (t1), v2 = TYPE_VALUES (t2); + v1 && v2; + v1 = TREE_CHAIN (v1), v2 = TREE_CHAIN (v2)) + { + tree c1 = TREE_VALUE (v1); + tree c2 = TREE_VALUE (v2); - if (TREE_CODE (c1) == CONST_DECL) - c1 = DECL_INITIAL (c1); + if (TREE_CODE (c1) == CONST_DECL) + c1 = DECL_INITIAL (c1); - if (TREE_CODE (c2) == CONST_DECL) - c2 = DECL_INITIAL (c2); + if (TREE_CODE (c2) == CONST_DECL) + c2 = DECL_INITIAL (c2); - if (tree_int_cst_equal (c1, c2) != 1) - goto different_types; - } + if (tree_int_cst_equal (c1, c2) != 1) + goto different_types; + } - /* If one enumeration has more values than the other, they - are not the same. */ - if (v1 || v2) - goto different_types; + /* If one enumeration has more values than the other, they + are not the same. */ + if (v1 || v2) + goto different_types; - goto same_types; - } + goto same_types; + } case RECORD_TYPE: case UNION_TYPE: case QUAL_UNION_TYPE: - { - tree f1, f2; - - /* If one type requires structural equality checks and the - other doesn't, do not merge the types. */ - if (TYPE_STRUCTURAL_EQUALITY_P (t1) - != TYPE_STRUCTURAL_EQUALITY_P (t2)) - goto different_types; - - /* The struct tags shall compare equal. */ - if (!compare_type_names_p (TYPE_MAIN_VARIANT (t1), - TYPE_MAIN_VARIANT (t2), false)) - goto different_types; + { + tree f1, f2; - /* For aggregate types, all the fields must be the same. */ - for (f1 = TYPE_FIELDS (t1), f2 = TYPE_FIELDS (t2); - f1 && f2; - f1 = TREE_CHAIN (f1), f2 = TREE_CHAIN (f2)) - { - /* The fields must have the same name, offset and type. */ - if (DECL_NAME (f1) != DECL_NAME (f2) - || !compare_field_offset (f1, f2) - || !gimple_types_compatible_p (TREE_TYPE (f1), - TREE_TYPE (f2))) - goto different_types; - } + /* If one type requires structural equality checks and the + other doesn't, do not merge the types. */ + if (TYPE_STRUCTURAL_EQUALITY_P (t1) + != TYPE_STRUCTURAL_EQUALITY_P (t2)) + goto different_types; - /* If one aggregate has more fields than the other, they - are not the same. */ - if (f1 || f2) - goto different_types; + /* The struct tags shall compare equal. */ + if (!compare_type_names_p (TYPE_MAIN_VARIANT (t1), + TYPE_MAIN_VARIANT (t2), false)) + goto different_types; - goto same_types; - } + /* For aggregate types, all the fields must be the same. */ + for (f1 = TYPE_FIELDS (t1), f2 = TYPE_FIELDS (t2); + f1 && f2; + f1 = TREE_CHAIN (f1), f2 = TREE_CHAIN (f2)) + { + /* The fields must have the same name, offset and type. */ + if (DECL_NAME (f1) != DECL_NAME (f2) + || DECL_NONADDRESSABLE_P (f1) != DECL_NONADDRESSABLE_P (f2) + || !gimple_compare_field_offset (f1, f2) + || !gimple_types_compatible_p (TREE_TYPE (f1), + TREE_TYPE (f2))) + goto different_types; + } - case VECTOR_TYPE: - if (TYPE_VECTOR_SUBPARTS (t1) != TYPE_VECTOR_SUBPARTS (t2)) - goto different_types; + /* If one aggregate has more fields than the other, they + are not the same. */ + if (f1 || f2) + goto different_types; - /* Fallthru */ - case COMPLEX_TYPE: - if (!gimple_types_compatible_p (TREE_TYPE (t1), TREE_TYPE (t2))) - goto different_types; - goto same_types; + goto same_types; + } default: - goto different_types; + gcc_unreachable (); } /* Common exit path for types that are not compatible. */ different_types: - if (p) - p->same_p = 0; + p->same_p = 0; return 0; /* Common exit path for types that are compatible. */ same_types: - if (p) - p->same_p = 1; + p->same_p = 1; return 1; } @@ -3688,7 +3788,28 @@ iterative_hash_gimple_type (tree type, hashval_t val, sccstack, sccstate, sccstate_obstack); } - /* Recurse for aggregates with a single element. */ + /* For integer types hash the types min/max values and the string flag. */ + if (TREE_CODE (type) == INTEGER_TYPE) + { + /* OMP lowering can introduce error_mark_node in place of + random local decls in types. */ + if (TYPE_MIN_VALUE (type) != error_mark_node) + v = iterative_hash_expr (TYPE_MIN_VALUE (type), v); + if (TYPE_MAX_VALUE (type) != error_mark_node) + v = iterative_hash_expr (TYPE_MAX_VALUE (type), v); + v = iterative_hash_hashval_t (TYPE_STRING_FLAG (type), v); + } + + /* For array types hash their domain and the string flag. */ + if (TREE_CODE (type) == ARRAY_TYPE + && TYPE_DOMAIN (type)) + { + v = iterative_hash_hashval_t (TYPE_STRING_FLAG (type), v); + v = visit (TYPE_DOMAIN (type), state, v, + sccstack, sccstate, sccstate_obstack); + } + + /* Recurse for aggregates with a single element type. */ if (TREE_CODE (type) == ARRAY_TYPE || TREE_CODE (type) == COMPLEX_TYPE || TREE_CODE (type) == VECTOR_TYPE) @@ -3826,6 +3947,12 @@ gimple_register_type (tree t) gcc_assert (TYPE_P (t)); + /* Always register the main variant first. This is important so we + pick up the non-typedef variants as canonical, otherwise we'll end + up taking typedef ids for structure tags during comparison. */ + if (TYPE_MAIN_VARIANT (t) != t) + gimple_register_type (TYPE_MAIN_VARIANT (t)); + if (gimple_types == NULL) gimple_types = htab_create (16381, gimple_type_hash, gimple_type_eq, 0); @@ -4131,7 +4258,6 @@ gimple_signed_type (tree type) alias_set_type gimple_get_alias_set (tree t) { - static bool recursing_p; tree u; /* Permit type-punning when accessing a union, provided the access @@ -4171,15 +4297,9 @@ gimple_get_alias_set (tree t) } else if (POINTER_TYPE_P (t)) { - tree t1; + /* From the common C and C++ langhook implementation: - /* ??? We can end up creating cycles with TYPE_MAIN_VARIANT - and TYPE_CANONICAL. Avoid recursing endlessly between - this langhook and get_alias_set. */ - if (recursing_p) - return -1; - - /* Unfortunately, there is no canonical form of a pointer type. + Unfortunately, there is no canonical form of a pointer type. In particular, if we have `typedef int I', then `int *', and `I *' are different types. So, we have to pick a canonical representative. We do this below. @@ -4201,15 +4321,36 @@ gimple_get_alias_set (tree t) can dereference IPP and CIPP. So, we ignore cv-qualifiers on the pointed-to types. This issue has been reported to the C++ committee. */ - t1 = build_type_no_quals (t); - if (t1 != t) - { - alias_set_type set; - recursing_p = true; - set = get_alias_set (t1); - recursing_p = false; - return set; - } + + /* In addition to the above canonicalization issue with LTO + we should also canonicalize `T (*)[]' to `T *' avoiding + alias issues with pointer-to element types and pointer-to + array types. + + Likewise we need to deal with the situation of incomplete + pointed-to types and make `*(struct X **)&a' and + `*(struct X {} **)&a' alias. Otherwise we will have to + guarantee that all pointer-to incomplete type variants + will be replaced by pointer-to complete type variants if + they are available. + + With LTO the convenient situation of using `void *' to + access and store any pointer type will also become + more apparent (and `void *' is just another pointer-to + incomplete type). Assigning alias-set zero to `void *' + and all pointer-to incomplete types is a not appealing + solution. Assigning an effective alias-set zero only + affecting pointers might be - by recording proper subset + relationships of all pointer alias-sets. + + Pointer-to function types are another grey area which + needs caution. Globbing them all into one alias-set + or the above effective zero set would work. */ + + /* For now just assign the same alias-set to all pointers. + That's simple and avoids all the above problems. */ + if (t != ptr_type_node) + return get_alias_set (ptr_type_node); } return -1; @@ -4523,9 +4664,9 @@ gimple_ior_addresses_taken_1 (gimple stmt ATTRIBUTE_UNUSED, tree addr, void *data) { bitmap addresses_taken = (bitmap)data; - while (handled_component_p (addr)) - addr = TREE_OPERAND (addr, 0); - if (DECL_P (addr)) + addr = get_base_address (addr); + if (addr + && DECL_P (addr)) { bitmap_set_bit (addresses_taken, DECL_UID (addr)); return true; @@ -4550,7 +4691,8 @@ gimple_ior_addresses_taken (bitmap addresses_taken, gimple stmt) const char * gimple_decl_printable_name (tree decl, int verbosity) { - gcc_assert (decl && DECL_NAME (decl)); + if (!DECL_NAME (decl)) + return NULL; if (DECL_ASSEMBLER_NAME_SET_P (decl)) { @@ -4575,43 +4717,4 @@ gimple_decl_printable_name (tree decl, int verbosity) return IDENTIFIER_POINTER (DECL_NAME (decl)); } - -/* Fold a OBJ_TYPE_REF expression to the address of a function. - KNOWN_TYPE carries the true type of OBJ_TYPE_REF_OBJECT(REF). Adapted - from cp_fold_obj_type_ref, but it tolerates types with no binfo - data. */ - -tree -gimple_fold_obj_type_ref (tree ref, tree known_type) -{ - HOST_WIDE_INT index; - HOST_WIDE_INT i; - tree v; - tree fndecl; - - if (TYPE_BINFO (known_type) == NULL_TREE) - return NULL_TREE; - - v = BINFO_VIRTUALS (TYPE_BINFO (known_type)); - index = tree_low_cst (OBJ_TYPE_REF_TOKEN (ref), 1); - i = 0; - while (i != index) - { - i += (TARGET_VTABLE_USES_DESCRIPTORS - ? TARGET_VTABLE_USES_DESCRIPTORS : 1); - v = TREE_CHAIN (v); - } - - fndecl = TREE_VALUE (v); - -#ifdef ENABLE_CHECKING - gcc_assert (tree_int_cst_equal (OBJ_TYPE_REF_TOKEN (ref), - DECL_VINDEX (fndecl))); -#endif - - cgraph_node (fndecl)->local.vtable_method = true; - - return build_fold_addr_expr (fndecl); -} - #include "gt-gimple.h"