diff options
-rw-r--r-- | gcc/ChangeLog | 20 | ||||
-rw-r--r-- | gcc/cgraph.h | 2 | ||||
-rw-r--r-- | gcc/cgraphunit.c | 3 | ||||
-rw-r--r-- | gcc/expr.c | 132 | ||||
-rw-r--r-- | gcc/gimple-fold.c | 27 | ||||
-rw-r--r-- | gcc/ipa-inline-analysis.c | 3 | ||||
-rw-r--r-- | gcc/ipa.c | 9 | ||||
-rw-r--r-- | gcc/lto-cgraph.c | 7 | ||||
-rw-r--r-- | gcc/lto/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/lto/lto-partition.c | 2 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 4 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/tree-ssa/attr-alias-2.c | 30 | ||||
-rw-r--r-- | gcc/tree-ssa-loop-ivcanon.c | 2 | ||||
-rw-r--r-- | gcc/varpool.c | 90 |
14 files changed, 224 insertions, 112 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 8b6bc6f..b2c2ee7 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,23 @@ +2013-06-19 Jan Hubicka <jh@suse.cz> + + * cgraph.h (const_value_known_p): Replace by ... + (ctor_for_folding): .. this one. + * cgraphunit.c (process_function_and_variable_attributes): Use it. + * lto-cgraph.c (compute_ltrans_boundary): Use ctor_for_folding. + * expr.c (expand_expr_real_1): Likewise. + (string_constant): Likewise. + * tree-ssa-loop-ivcanon.c (constant_after_peeling): Likewise. + * ipa.c (process_references): Likewise. + (symtab_remove_unreachable_nodes): Likewise. + * ipa-inline-analysis.c (param_change_prob): Likewise. + * gimple-fold.c (canonicalize_constructor_val): Likewise. + (get_base_constructor): Likwise. + * varpool.c (varpool_remove_node): Likewise. + (varpool_remove_initializer): LIkewise. + (dump_varpool_node): LIkwise. + (const_value_known_p): Rewrite to ... + (ctor_for_folding): ... this one. + 2013-06-19 Jakub Jelinek <jakub@redhat.com> PR driver/57651 diff --git a/gcc/cgraph.h b/gcc/cgraph.h index 6259189..ef2a2a0 100644 --- a/gcc/cgraph.h +++ b/gcc/cgraph.h @@ -797,7 +797,7 @@ void varpool_analyze_node (struct varpool_node *); struct varpool_node * varpool_extra_name_alias (tree, tree); struct varpool_node * varpool_create_variable_alias (tree, tree); void varpool_reset_queue (void); -bool const_value_known_p (tree); +tree ctor_for_folding (tree); bool varpool_for_node_and_aliases (struct varpool_node *, bool (*) (struct varpool_node *, void *), void *, bool); diff --git a/gcc/cgraphunit.c b/gcc/cgraphunit.c index 51365eb..731a0e9 100644 --- a/gcc/cgraphunit.c +++ b/gcc/cgraphunit.c @@ -762,8 +762,7 @@ process_function_and_variable_attributes (struct cgraph_node *first, { tree decl = vnode->symbol.decl; if (DECL_EXTERNAL (decl) - && DECL_INITIAL (decl) - && const_value_known_p (decl)) + && DECL_INITIAL (decl)) varpool_finalize_decl (decl); if (DECL_PRESERVE_P (decl)) vnode->symbol.force_output = true; @@ -9698,6 +9698,7 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode, { tree array = treeop0; tree index = treeop1; + tree init; /* Fold an expression like: "foo"[2]. This is not done in fold so it won't happen inside &. @@ -9744,76 +9745,72 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode, && modifier != EXPAND_INITIALIZER && modifier != EXPAND_MEMORY && TREE_READONLY (array) && ! TREE_SIDE_EFFECTS (array) - && TREE_CODE (array) == VAR_DECL && DECL_INITIAL (array) - && TREE_CODE (DECL_INITIAL (array)) != ERROR_MARK - && const_value_known_p (array)) + && TREE_CODE (index) == INTEGER_CST + && (TREE_CODE (array) == VAR_DECL + || TREE_CODE (array) == CONST_DECL) + && (init = ctor_for_folding (array)) != error_mark_node) { - if (TREE_CODE (index) == INTEGER_CST) + if (TREE_CODE (init) == CONSTRUCTOR) { - tree init = DECL_INITIAL (array); + unsigned HOST_WIDE_INT ix; + tree field, value; - if (TREE_CODE (init) == CONSTRUCTOR) - { - unsigned HOST_WIDE_INT ix; - tree field, value; + FOR_EACH_CONSTRUCTOR_ELT (CONSTRUCTOR_ELTS (init), ix, + field, value) + if (tree_int_cst_equal (field, index)) + { + if (TREE_SIDE_EFFECTS (value)) + break; - FOR_EACH_CONSTRUCTOR_ELT (CONSTRUCTOR_ELTS (init), ix, - field, value) - if (tree_int_cst_equal (field, index)) + if (TREE_CODE (value) == CONSTRUCTOR) { - if (TREE_SIDE_EFFECTS (value)) + /* If VALUE is a CONSTRUCTOR, this + optimization is only useful if + this doesn't store the CONSTRUCTOR + into memory. If it does, it is more + efficient to just load the data from + the array directly. */ + rtx ret = expand_constructor (value, target, + modifier, true); + if (ret == NULL_RTX) break; - - if (TREE_CODE (value) == CONSTRUCTOR) - { - /* If VALUE is a CONSTRUCTOR, this - optimization is only useful if - this doesn't store the CONSTRUCTOR - into memory. If it does, it is more - efficient to just load the data from - the array directly. */ - rtx ret = expand_constructor (value, target, - modifier, true); - if (ret == NULL_RTX) - break; - } - - return expand_expr (fold (value), target, tmode, - modifier); } - } - else if(TREE_CODE (init) == STRING_CST) + + return expand_expr (fold (value), target, tmode, + modifier); + } + } + else if(TREE_CODE (init) == STRING_CST) + { + tree index1 = index; + tree low_bound = array_ref_low_bound (exp); + index1 = fold_convert_loc (loc, sizetype, + treeop1); + + /* Optimize the special-case of a zero lower bound. + + We convert the low_bound to sizetype to avoid some problems + with constant folding. (E.g. suppose the lower bound is 1, + and its mode is QI. Without the conversion,l (ARRAY + +(INDEX-(unsigned char)1)) becomes ((ARRAY+(-(unsigned char)1)) + +INDEX), which becomes (ARRAY+255+INDEX). Opps!) */ + + if (! integer_zerop (low_bound)) + index1 = size_diffop_loc (loc, index1, + fold_convert_loc (loc, sizetype, + low_bound)); + + if (0 > compare_tree_int (index1, + TREE_STRING_LENGTH (init))) { - tree index1 = index; - tree low_bound = array_ref_low_bound (exp); - index1 = fold_convert_loc (loc, sizetype, - treeop1); - - /* Optimize the special-case of a zero lower bound. - - We convert the low_bound to sizetype to avoid some problems - with constant folding. (E.g. suppose the lower bound is 1, - and its mode is QI. Without the conversion,l (ARRAY - +(INDEX-(unsigned char)1)) becomes ((ARRAY+(-(unsigned char)1)) - +INDEX), which becomes (ARRAY+255+INDEX). Opps!) */ - - if (! integer_zerop (low_bound)) - index1 = size_diffop_loc (loc, index1, - fold_convert_loc (loc, sizetype, - low_bound)); - - if (0 > compare_tree_int (index1, - TREE_STRING_LENGTH (init))) - { - tree type = TREE_TYPE (TREE_TYPE (init)); - enum machine_mode mode = TYPE_MODE (type); - - if (GET_MODE_CLASS (mode) == MODE_INT - && GET_MODE_SIZE (mode) == 1) - return gen_int_mode (TREE_STRING_POINTER (init) - [TREE_INT_CST_LOW (index1)], - mode); - } + tree type = TREE_TYPE (TREE_TYPE (init)); + enum machine_mode mode = TYPE_MODE (type); + + if (GET_MODE_CLASS (mode) == MODE_INT + && GET_MODE_SIZE (mode) == 1) + return gen_int_mode (TREE_STRING_POINTER (init) + [TREE_INT_CST_LOW (index1)], + mode); } } } @@ -10676,17 +10673,18 @@ string_constant (tree arg, tree *ptr_offset) || TREE_CODE (array) == CONST_DECL) { int length; + tree init = ctor_for_folding (array); /* Variables initialized to string literals can be handled too. */ - if (!const_value_known_p (array) - || !DECL_INITIAL (array) - || TREE_CODE (DECL_INITIAL (array)) != STRING_CST) + if (init == error_mark_node + || !init + || TREE_CODE (init) != STRING_CST) return 0; /* Avoid const char foo[4] = "abcde"; */ if (DECL_SIZE_UNIT (array) == NULL_TREE || TREE_CODE (DECL_SIZE_UNIT (array)) != INTEGER_CST - || (length = TREE_STRING_LENGTH (DECL_INITIAL (array))) <= 0 + || (length = TREE_STRING_LENGTH (init)) <= 0 || compare_tree_int (DECL_SIZE_UNIT (array), length) < 0) return 0; @@ -10699,7 +10697,7 @@ string_constant (tree arg, tree *ptr_offset) return 0; *ptr_offset = offset; - return DECL_INITIAL (array); + return init; } return 0; diff --git a/gcc/gimple-fold.c b/gcc/gimple-fold.c index 60fca6b..b6d22b3 100644 --- a/gcc/gimple-fold.c +++ b/gcc/gimple-fold.c @@ -192,9 +192,9 @@ canonicalize_constructor_val (tree cval, tree from_decl) tree get_symbol_constant_value (tree sym) { - if (const_value_known_p (sym)) + tree val = ctor_for_folding (sym); + if (val != error_mark_node) { - tree val = DECL_INITIAL (sym); if (val) { val = canonicalize_constructor_val (unshare_expr (val), sym); @@ -2695,19 +2695,18 @@ get_base_constructor (tree base, HOST_WIDE_INT *bit_offset, switch (TREE_CODE (base)) { case VAR_DECL: - if (!const_value_known_p (base)) - return NULL_TREE; - - /* Fallthru. */ case CONST_DECL: - if (!DECL_INITIAL (base) - && (TREE_STATIC (base) || DECL_EXTERNAL (base))) - return error_mark_node; - /* Do not return an error_mark_node DECL_INITIAL. LTO uses this - as special marker (_not_ zero ...) for its own purposes. */ - if (DECL_INITIAL (base) == error_mark_node) - return NULL_TREE; - return DECL_INITIAL (base); + { + tree init = ctor_for_folding (base); + + /* Our semantic is exact oposite of ctor_for_folding; + NULL means unknown, while error_mark_node is 0. */ + if (init == error_mark_node) + return NULL_TREE; + if (!init) + return error_mark_node; + return init; + } case ARRAY_REF: case COMPONENT_REF: diff --git a/gcc/ipa-inline-analysis.c b/gcc/ipa-inline-analysis.c index a25f517..9a36292 100644 --- a/gcc/ipa-inline-analysis.c +++ b/gcc/ipa-inline-analysis.c @@ -2106,8 +2106,9 @@ param_change_prob (gimple stmt, int i) struct record_modified_bb_info info; bitmap_iterator bi; unsigned index; + tree init = ctor_for_folding (base); - if (const_value_known_p (base)) + if (init != error_mark_node) return 0; if (!bb->frequency) return REG_BR_PROB_BASE; @@ -145,7 +145,9 @@ process_references (struct ipa_ref_list *list, constant folding. Keep references alive so partitioning knows about potential references. */ || (TREE_CODE (node->symbol.decl) == VAR_DECL - && flag_wpa && const_value_known_p (node->symbol.decl))))) + && flag_wpa + && ctor_for_folding (node->symbol.decl) + != error_mark_node)))) pointer_set_insert (reachable, node); enqueue_node ((symtab_node) node, first, reachable); } @@ -400,6 +402,7 @@ symtab_remove_unreachable_nodes (bool before_inlining_p, FILE *file) } else if (!pointer_set_contains (reachable, vnode)) { + tree init; if (vnode->symbol.definition) { if (file) @@ -411,8 +414,10 @@ symtab_remove_unreachable_nodes (bool before_inlining_p, FILE *file) vnode->symbol.aux = NULL; /* Keep body if it may be useful for constant folding. */ - if (!const_value_known_p (vnode->symbol.decl)) + if ((init = ctor_for_folding (vnode->symbol.decl)) == error_mark_node) varpool_remove_initializer (vnode); + else + DECL_INITIAL (vnode->symbol.decl) = init; ipa_remove_all_references (&vnode->symbol.ref_list); } else diff --git a/gcc/lto-cgraph.c b/gcc/lto-cgraph.c index e3f8880..2122f70 100644 --- a/gcc/lto-cgraph.c +++ b/gcc/lto-cgraph.c @@ -766,10 +766,9 @@ compute_ltrans_boundary (lto_symtab_encoder_t in_encoder) symtab_node node = lto_symtab_encoder_deref (encoder, i); if (varpool_node *vnode = dyn_cast <varpool_node> (node)) { - if (DECL_INITIAL (vnode->symbol.decl) - && !lto_symtab_encoder_encode_initializer_p (encoder, - vnode) - && const_value_known_p (vnode->symbol.decl)) + if (!lto_symtab_encoder_encode_initializer_p (encoder, + vnode) + && ctor_for_folding (vnode->symbol.decl) != error_mark_node) { lto_set_symtab_encoder_encode_initializer (encoder, vnode); add_references (encoder, &vnode->symbol.ref_list); diff --git a/gcc/lto/ChangeLog b/gcc/lto/ChangeLog index aeda657..2723678 100644 --- a/gcc/lto/ChangeLog +++ b/gcc/lto/ChangeLog @@ -1,3 +1,8 @@ +2013-06-19 Jan Hubicka <jh@suse.cz> + + * lto-partition.c (add_references_to_partition): Use + ctor_for_folding. + 2013-06-18 Richard Biener <rguenther@suse.de> * lto.c (lto_register_var_decl_in_symtab): Pass in cache index diff --git a/gcc/lto/lto-partition.c b/gcc/lto/lto-partition.c index 6f45380..ffc8da3 100644 --- a/gcc/lto/lto-partition.c +++ b/gcc/lto/lto-partition.c @@ -146,7 +146,7 @@ add_references_to_partition (ltrans_partition part, symtab_node node) Recursively look into the initializers of the constant variable and add references, too. */ else if (is_a <varpool_node> (ref->referred) - && const_value_known_p (ref->referred->symbol.decl) + && ctor_for_folding (ref->referred->symbol.decl) != error_mark_node && !lto_symtab_encoder_in_partition_p (part->encoder, ref->referred)) { if (!part->initializers_visited) diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index f731837..baae9b9 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2013-06-19 Jan Hubicka <jh@suse.cz> + + * gcc.dg/tree-ssa/attr-alias-2.c: New testcase. + 2013-06-19 Balaji V. Iyer <balaji.v.iyer@intel.com> * c-c++-common/cilk-plus/AN/builtin_fn_custom.c: Replaced all the diff --git a/gcc/testsuite/gcc.dg/tree-ssa/attr-alias-2.c b/gcc/testsuite/gcc.dg/tree-ssa/attr-alias-2.c new file mode 100644 index 0000000..50623a4 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/attr-alias-2.c @@ -0,0 +1,30 @@ +/* { dg-do compile } */ +/* { dg-require-alias "" } */ +/* { dg-options "-O2 -fdump-tree-optimized" } */ +static int a=4; +static int b __attribute__ ((alias("a"))); +main() +{ + return b+a; +} +/* { dg-final { scan-tree-dump "return 8" "optimized" } } */ +/* { dg-do compile } */ +/* { dg-require-alias "" } */ +/* { dg-options "-O2 -fdump-tree-optimized" } */ +static int a=4; +static int b __attribute__ ((alias("a"))); +main() +{ + return b+a; +} +/* { dg-final { scan-tree-dump "return 8" "optimized" } } */ +/* { dg-do compile } */ +/* { dg-require-alias "" } */ +/* { dg-options "-O2 -fdump-tree-optimized" } */ +static int a=4; +static int b __attribute__ ((alias("a"))); +main() +{ + return b+a; +} +/* { dg-final { scan-tree-dump "return 8" "optimized" } } */ diff --git a/gcc/tree-ssa-loop-ivcanon.c b/gcc/tree-ssa-loop-ivcanon.c index 45774e6..91cf8c1 100644 --- a/gcc/tree-ssa-loop-ivcanon.c +++ b/gcc/tree-ssa-loop-ivcanon.c @@ -174,7 +174,7 @@ constant_after_peeling (tree op, gimple stmt, struct loop *loop) while (handled_component_p (base)) base = TREE_OPERAND (base, 0); if ((DECL_P (base) - && const_value_known_p (base)) + && ctor_for_folding (base) != error_mark_node) || CONSTANT_CLASS_P (base)) { /* If so, see if we understand all the indices. */ diff --git a/gcc/varpool.c b/gcc/varpool.c index 80e98b3..b426757 100644 --- a/gcc/varpool.c +++ b/gcc/varpool.c @@ -66,12 +66,15 @@ void varpool_remove_node (struct varpool_node *node) { symtab_unregister_node ((symtab_node)node); + tree init; /* Because we remove references from external functions before final compilation, we may end up removing useful constructors. FIXME: We probably want to trace boundaries better. */ - if (!const_value_known_p (node->symbol.decl)) + if ((init = ctor_for_folding (node->symbol.decl)) == error_mark_node) varpool_remove_initializer (node); + else + DECL_INITIAL (node->symbol.decl) = init; ggc_free (node); } @@ -109,7 +112,7 @@ dump_varpool_node (FILE *f, struct varpool_node *node) fprintf (f, " output"); if (TREE_READONLY (node->symbol.decl)) fprintf (f, " read-only"); - if (const_value_known_p (node->symbol.decl)) + if (ctor_for_folding (node->symbol.decl) != error_mark_node) fprintf (f, " const-value-known"); fprintf (f, "\n"); } @@ -144,44 +147,93 @@ varpool_node_for_asm (tree asmname) } /* Return if DECL is constant and its initial value is known (so we can do - constant folding using DECL_INITIAL (decl)). */ + constant folding using DECL_INITIAL (decl)). + Return ERROR_MARK_NODE when value is unknown. */ -bool -const_value_known_p (tree decl) +tree +ctor_for_folding (tree decl) { + struct varpool_node *node, *real_node; + tree real_decl; + if (TREE_CODE (decl) != VAR_DECL - &&TREE_CODE (decl) != CONST_DECL) - return false; + && TREE_CODE (decl) != CONST_DECL) + return error_mark_node; if (TREE_CODE (decl) == CONST_DECL || DECL_IN_CONSTANT_POOL (decl)) - return true; + return DECL_INITIAL (decl); + + if (TREE_THIS_VOLATILE (decl)) + return error_mark_node; + + /* Do not care about automatic variables. Those are never initialized + anyway, because gimplifier exapnds the code*/ + if (!TREE_STATIC (decl) && !DECL_EXTERNAL (decl)) + { + gcc_assert (!TREE_PUBLIC (decl)); + return error_mark_node; + } gcc_assert (TREE_CODE (decl) == VAR_DECL); - if (!TREE_READONLY (decl) || TREE_THIS_VOLATILE (decl)) - return false; + node = varpool_get_node (decl); + if (node) + { + real_node = varpool_variable_node (node); + real_decl = real_node->symbol.decl; + } + else + real_decl = decl; + + /* See if we are dealing with alias. + In most cases alias is just alternative symbol pointing to a given + constructor. This allows us to use interposition rules of DECL + constructor of REAL_NODE. However weakrefs are special by being just + alternative name of their target (if defined). */ + if (decl != real_decl) + { + gcc_assert (!DECL_INITIAL (decl) + || DECL_INITIAL (decl) == error_mark_node); + if (lookup_attribute ("weakref", DECL_ATTRIBUTES (decl))) + { + node = varpool_alias_target (node); + decl = node->symbol.decl; + } + } - /* Gimplifier takes away constructors of local vars */ - if (!TREE_STATIC (decl) && !DECL_EXTERNAL (decl)) - return DECL_INITIAL (decl) != NULL; + /* Vtables are defined by their types and must match no matter of interposition + rules. */ + if (DECL_VIRTUAL_P (real_decl)) + { + gcc_checking_assert (TREE_READONLY (real_decl)); + return DECL_INITIAL (real_decl); + } + + /* If thre is no constructor, we have nothing to do. */ + if (DECL_INITIAL (real_decl) == error_mark_node) + return error_mark_node; - gcc_assert (TREE_STATIC (decl) || DECL_EXTERNAL (decl)); + /* Non-readonly alias of readonly variable is also de-facto readonly, + because the variable itself is in readonly section. + We also honnor READONLY flag on alias assuming that user knows + what he is doing. */ + if (!TREE_READONLY (decl) && !TREE_READONLY (real_decl)) + return error_mark_node; /* Variables declared 'const' without an initializer have zero as the initializer if they may not be overridden at link or run time. */ - if (!DECL_INITIAL (decl) - && (DECL_EXTERNAL (decl) - || decl_replaceable_p (decl))) - return false; + if (!DECL_INITIAL (real_decl) + && (DECL_EXTERNAL (decl) || decl_replaceable_p (decl))) + return error_mark_node; /* Variables declared `const' with an initializer are considered to not be overwritable with different initializer by default. ??? Previously we behaved so for scalar variables but not for array accesses. */ - return true; + return DECL_INITIAL (real_decl); } /* Add the variable DECL to the varpool. |