From patchwork Mon Sep 13 13:52:01 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jan Hubicka X-Patchwork-Id: 64604 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) by ozlabs.org (Postfix) with SMTP id EF8B6B6F01 for ; Mon, 13 Sep 2010 23:52:14 +1000 (EST) Received: (qmail 26828 invoked by alias); 13 Sep 2010 13:52:12 -0000 Received: (qmail 26807 invoked by uid 22791); 13 Sep 2010 13:52:10 -0000 X-SWARE-Spam-Status: No, hits=-1.7 required=5.0 tests=AWL, BAYES_00, TW_IV, T_RP_MATCHES_RCVD X-Spam-Check-By: sourceware.org Received: from nikam-dmz.ms.mff.cuni.cz (HELO nikam.ms.mff.cuni.cz) (195.113.20.16) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Mon, 13 Sep 2010 13:52:04 +0000 Received: by nikam.ms.mff.cuni.cz (Postfix, from userid 16202) id E0DC59AC823; Mon, 13 Sep 2010 15:52:01 +0200 (CEST) Date: Mon, 13 Sep 2010 15:52:01 +0200 From: Jan Hubicka To: Jan Hubicka Cc: Richard Guenther , gcc-patches@gcc.gnu.org Subject: Re: Empty static constructor folding Message-ID: <20100913135201.GA22498@kam.mff.cuni.cz> References: <20100911232546.GC28272@kam.mff.cuni.cz> <20100913122836.GA30860@kam.mff.cuni.cz> MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: <20100913122836.GA30860@kam.mff.cuni.cz> User-Agent: Mutt/1.5.18 (2008-05-17) Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org Hi, here is updated patch. It bootstrapped/regtested C only, I am doing full testing now. OK if it passes? (x86-64-linux) Honza /* { dg-do compile } */ /* { dg-options "-O -fdump-tree-ccp2" } */ struct a {int a,b;}; const static struct a a; static int b[10]; int c; test() { return a.a+b[c]; } /* { dg-final { scan-tree-dump "return 0;" "ccp2" } } */ /* { dg-final { cleanup-tree-dump "ccp2" } } */ * tree.c (build_zero_cst): New. * tree.h (build_zero_cst): Declare. * tree-ssa-ccp.c (get_constant_value): Accept general operands. (get_base_constructor): Break out from ... (fold_const_aggregate_ref): Here; handle empty constructors. * testsuite/gcc.dg/torture/pr23821.c: Drop static keyword. * testsuite/gcc.dg/tree-ssa/loop-19.c: Likewise. } } +/* See if we can find constructor defining value of BASE + possibly return offset of the definition in OFFSET. + + As a special case, return error_mark_node when constructor + is not explicitly available, but it is known to be zero + such as 'static const int a;'. */ +static tree +get_base_constructor (tree base, tree *offset) +{ + *offset = NULL; + if (TREE_CODE (base) == MEM_REF) + { + if (!integer_zerop (TREE_OPERAND (base, 1))) + *offset = TREE_OPERAND (base, 1); + + base = get_constant_value (TREE_OPERAND (base, 0)); + if (!base || TREE_CODE (base) != ADDR_EXPR) + return NULL_TREE; + base = TREE_OPERAND (base, 0); + } + + /* Get a CONSTRUCTOR. If BASE is a VAR_DECL, get its + DECL_INITIAL. If BASE is a nested reference into another + ARRAY_REF or COMPONENT_REF, make a recursive call to resolve + the inner reference. */ + switch (TREE_CODE (base)) + { + case VAR_DECL: + if (!TREE_READONLY (base) + || ((TREE_STATIC (base) || DECL_EXTERNAL (base)) + && !varpool_get_node (base)->const_value_known)) + return NULL_TREE; + + /* Fallthru. */ + case CONST_DECL: + if (!DECL_INITIAL (base) + && (TREE_STATIC (base) || DECL_EXTERNAL (base))) + return error_mark_node; + return DECL_INITIAL (base); + + break; + + case ARRAY_REF: + case COMPONENT_REF: + return fold_const_aggregate_ref (base); + break; + + case STRING_CST: + case CONSTRUCTOR: + return base; + break; + + default: + return NULL_TREE; + } +} + /* Return the tree representing the element referenced by T if T is an ARRAY_REF or COMPONENT_REF into constant aggregates. Return NULL_TREE otherwise. */ @@ -1315,7 +1378,7 @@ ccp_fold (gimple stmt) tree fold_const_aggregate_ref (tree t) { - tree base, ctor, idx, field; + tree ctor, idx, field; unsigned HOST_WIDE_INT cnt; tree cfield, cval; tree tem; @@ -1330,46 +1393,13 @@ fold_const_aggregate_ref (tree t) switch (TREE_CODE (t)) { case ARRAY_REF: - /* Get a CONSTRUCTOR. If BASE is a VAR_DECL, get its - DECL_INITIAL. If BASE is a nested reference into another - ARRAY_REF or COMPONENT_REF, make a recursive call to resolve - the inner reference. */ - base = TREE_OPERAND (t, 0); - switch (TREE_CODE (base)) - { - case MEM_REF: - /* ??? We could handle this case. */ - if (!integer_zerop (TREE_OPERAND (base, 1))) - return NULL_TREE; - base = get_base_address (base); - if (!base - || TREE_CODE (base) != VAR_DECL) - return NULL_TREE; + ctor = get_base_constructor (TREE_OPERAND (t, 0), &idx); - /* Fallthru. */ - case VAR_DECL: - if (!TREE_READONLY (base) - || TREE_CODE (TREE_TYPE (base)) != ARRAY_TYPE - || ((TREE_STATIC (base) || DECL_EXTERNAL (base)) - && !varpool_get_node (base)->const_value_known)) - return NULL_TREE; - - ctor = DECL_INITIAL (base); - break; - - case ARRAY_REF: - case COMPONENT_REF: - ctor = fold_const_aggregate_ref (base); - break; - - case STRING_CST: - case CONSTRUCTOR: - ctor = base; - break; + if (idx) + return NULL_TREE; - default: - return NULL_TREE; - } + if (ctor == error_mark_node) + return build_zero_cst (TREE_TYPE (t)); if (ctor == NULL_TREE || (TREE_CODE (ctor) != CONSTRUCTOR @@ -1436,27 +1466,13 @@ fold_const_aggregate_ref (tree t) DECL_INITIAL. If BASE is a nested reference into another ARRAY_REF or COMPONENT_REF, make a recursive call to resolve the inner reference. */ - base = TREE_OPERAND (t, 0); - switch (TREE_CODE (base)) - { - case VAR_DECL: - if (!TREE_READONLY (base) - || TREE_CODE (TREE_TYPE (base)) != RECORD_TYPE - || ((TREE_STATIC (base) || DECL_EXTERNAL (base)) - && !varpool_get_node (base)->const_value_known)) - return NULL_TREE; + ctor = get_base_constructor (TREE_OPERAND (t, 0), &idx); - ctor = DECL_INITIAL (base); - break; + if (idx) + return NULL_TREE; - case ARRAY_REF: - case COMPONENT_REF: - ctor = fold_const_aggregate_ref (base); - break; - - default: - return NULL_TREE; - } + if (ctor == error_mark_node) + return build_zero_cst (TREE_TYPE (t)); if (ctor == NULL_TREE || TREE_CODE (ctor) != CONSTRUCTOR) @@ -1482,47 +1498,24 @@ fold_const_aggregate_ref (tree t) } case MEM_REF: - /* Get the base object we are accessing. */ - base = TREE_OPERAND (t, 0); - if (TREE_CODE (base) == SSA_NAME - && (tem = get_constant_value (base))) - base = tem; - if (TREE_CODE (base) != ADDR_EXPR) - return NULL_TREE; - base = TREE_OPERAND (base, 0); - switch (TREE_CODE (base)) - { - case VAR_DECL: - if (DECL_P (base) - && !AGGREGATE_TYPE_P (TREE_TYPE (base)) - && integer_zerop (TREE_OPERAND (t, 1))) - { - tree res = get_symbol_constant_value (base); - if (res - && !useless_type_conversion_p - (TREE_TYPE (t), TREE_TYPE (res))) - res = fold_unary (VIEW_CONVERT_EXPR, TREE_TYPE (t), res); - return res; - } - - if (!TREE_READONLY (base) - || TREE_CODE (TREE_TYPE (base)) != ARRAY_TYPE - || ((TREE_STATIC (base) || DECL_EXTERNAL (base)) - && !varpool_get_node (base)->const_value_known)) - return NULL_TREE; - - ctor = DECL_INITIAL (base); - break; - - case STRING_CST: - case CONSTRUCTOR: - ctor = base; - break; - - default: - return NULL_TREE; + ctor = get_base_constructor (t, &idx); + if (!idx) + idx = integer_zero_node; + + if (ctor == error_mark_node) + return build_zero_cst (TREE_TYPE (t)); + + if (ctor && !AGGREGATE_TYPE_P (TREE_TYPE (ctor)) + && integer_zerop (TREE_OPERAND (t, 1))) + { + if (ctor + && !useless_type_conversion_p + (TREE_TYPE (t), TREE_TYPE (ctor))) + ctor = fold_unary (VIEW_CONVERT_EXPR, TREE_TYPE (t), ctor); + return ctor; } + if (ctor == NULL_TREE || (TREE_CODE (ctor) != CONSTRUCTOR && TREE_CODE (ctor) != STRING_CST)) Index: tree.c =================================================================== --- tree.c (revision 164197) +++ tree.c (working copy) @@ -1583,6 +1583,18 @@ build_one_cst (tree type) } } +/* Build 0 constant of type TYPE. This is used by constructor folding and thus + the constant should correspond zero in memory representation. */ + +tree +build_zero_cst (tree type) +{ + if (!AGGREGATE_TYPE_P (type)) + return fold_convert (type, integer_zero_node); + return build_constructor (type, NULL); +} + + /* Build a BINFO with LEN language slots. */ tree Index: tree.h =================================================================== --- tree.h (revision 164197) +++ tree.h (working copy) @@ -4038,6 +4038,7 @@ extern tree build_constructor_from_list extern tree build_real_from_int_cst (tree, const_tree); extern tree build_complex (tree, tree, tree); extern tree build_one_cst (tree); +extern tree build_zero_cst (tree); extern tree build_string (int, const char *); extern tree build_tree_list_stat (tree, tree MEM_STAT_DECL); #define build_tree_list(t,q) build_tree_list_stat(t,q MEM_STAT_INFO) Index: testsuite/gcc.dg/torture/pr23821.c =================================================================== --- testsuite/gcc.dg/torture/pr23821.c (revision 164197) +++ testsuite/gcc.dg/torture/pr23821.c (working copy) @@ -5,7 +5,7 @@ /* { dg-skip-if "" { *-*-* } { "-O1" } { "" } } */ /* { dg-options "-fdump-tree-ivcanon-details" } */ -static int a[199]; +int a[199]; extern void abort (void); Index: testsuite/gcc.dg/tree-ssa/loop-19.c =================================================================== --- testsuite/gcc.dg/tree-ssa/loop-19.c (revision 164197) +++ testsuite/gcc.dg/tree-ssa/loop-19.c (working copy) @@ -9,7 +9,7 @@ /* { dg-options "-O3 -fno-prefetch-loop-arrays -fdump-tree-optimized" } */ # define N 2000000 -static double a[N],c[N]; +double a[N],c[N]; void tuned_STREAM_Copy() { int j; Index: tree-ssa-ccp.c =================================================================== --- tree-ssa-ccp.c (revision 164198) +++ tree-ssa-ccp.c (working copy) @@ -315,7 +315,15 @@ get_value (tree var) static inline tree get_constant_value (tree var) { - prop_value_t *val = get_value (var); + prop_value_t *val; + if (TREE_CODE (var) != SSA_NAME) + { + if (is_gimple_min_invariant (var)) + return var; + return NULL_TREE; + } + val = get_value (var); if (val && val->lattice_val == CONSTANT && (TREE_CODE (val->value) != INTEGER_CST @@ -1308,6 +1315,62 @@ ccp_fold (gimple stmt)