Mercurial > hg > CbC > CbC_gcc
diff gcc/gimple.c @ 63:b7f97abdc517 gcc-4.6-20100522
update gcc from gcc-4.5.0 to gcc-4.6
author | ryoma <e075725@ie.u-ryukyu.ac.jp> |
---|---|
date | Mon, 24 May 2010 12:47:05 +0900 |
parents | 77e2b8dfacca |
children | f6334be47118 |
line wrap: on
line diff
--- a/gcc/gimple.c Fri Feb 12 23:41:23 2010 +0900 +++ b/gcc/gimple.c Mon May 24 12:47:05 2010 +0900 @@ -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 <aldyh@redhat.com> This file is part of GCC. @@ -198,6 +198,21 @@ 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 @@ 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_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; @@ -620,7 +637,7 @@ 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); @@ -1297,7 +1314,7 @@ 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 @@ 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 @@ 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. */ @@ -1835,54 +1933,6 @@ } -/* 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. @@ -3169,16 +3219,35 @@ 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. + + This is intended to be used on GIMPLE types only. In order to + compare GENERIC types, use fields_compatible_p instead. */ bool -compare_field_offset (tree f1, tree f2) +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 @@ -3333,9 +3402,15 @@ /* 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; @@ -3406,11 +3481,20 @@ && 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. */ + 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 @@ -3520,7 +3604,7 @@ /* 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) - || !compare_field_offset (f1, f2) + || !gimple_compare_field_offset (f1, f2) || !gimple_types_compatible_p (TREE_TYPE (f1), TREE_TYPE (f2))) goto different_types; @@ -3707,8 +3791,12 @@ /* For integer types hash the types min/max values and the string flag. */ if (TREE_CODE (type) == INTEGER_TYPE) { - v = iterative_hash_expr (TYPE_MIN_VALUE (type), v); - v = iterative_hash_expr (TYPE_MAX_VALUE (type), v); + /* 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); } @@ -4576,9 +4664,9 @@ 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; @@ -4603,7 +4691,8 @@ 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)) { @@ -4628,43 +4717,4 @@ 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"