Bug 14841 - [tree-ssa] const_array[CST] is not folded
Summary: [tree-ssa] const_array[CST] is not folded
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: tree-optimization (show other bugs)
Version: tree-ssa
: P2 enhancement
Target Milestone: 4.1.0
Assignee: Kazu Hirata
URL: http://gcc.gnu.org/ml/gcc-patches/200...
Keywords: missed-optimization, patch, TREE
Depends on: 17046
Blocks: 8826 14840 15838 22303
  Show dependency treegraph
 
Reported: 2004-04-03 23:49 UTC by Kazu Hirata
Modified: 2006-05-08 15:07 UTC (History)
7 users (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed: 2005-03-04 03:57:51


Attachments
fold array refs to constant arrays with a constant index (1.07 KB, patch)
2004-08-30 22:23 UTC, Steven Bosscher
Details | Diff
patch (2.22 KB, text/plain)
2005-05-07 14:30 UTC, Kazu Hirata
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Kazu Hirata 2004-04-03 23:49:30 UTC
static const int banana[] = { 0, 1, 2, 3 };

int
foo (void)
{
  return banana[2];
}

const int grape[] = { 0, 1, 2, 3 };

int
bar (void)
{
  return grape[2];
}

I get:

;; Function foo (foo)

foo ()
{
<bb 0>:
  return banana[2];

}



;; Function bar (bar)

bar ()
{
<bb 0>:
  return grape[2];

}
Comment 1 Andrew Pinski 2004-04-04 03:00:27 UTC
Confirmed.
Comment 2 Steven Bosscher 2004-08-13 00:04:25 UTC
Given your test case, 
 
(gdb) set args -O2 t.c 
(gdb) b fold if (current_function_decl != (tree*)0) 
Breakpoint 5 at 0x658717: file ../../mainline/gcc/fold-const.c, line 6018. 
(gdb) run 
Starting program: /space/stevenb/build/gcc/cc1 -O2 t.c 
Breakpoint 3 at 0x2a9569d9c0 
Breakpoint 4 at 0x2a9569c750 
 foo 
 
Breakpoint 5, fold (expr=0x2a95905f80) at ../../mainline/gcc/fold-const.c:6018 
6018      const tree t = expr; 
(gdb) p debug_generic_expr (expr) 
banana<D1464>[2] 
$2 = void 
(gdb) p debug_tree(expr) 
 <array_ref 0x2a95905f80 
    type <integer_type 0x2a955978c0 int SI 
        size <integer_cst 0x2a95595780 constant invariant 32> 
        unit size <integer_cst 0x2a955958d0 constant invariant 4> 
        align 32 symtab 0 alias set -1 precision 32 min <integer_cst 
0x2a95595870 -2147483648> max <integer_cst 0x2a955958a0 2147483647> 
        pointer_to_this <pointer_type 0x2a955a8540>> 
    readonly 
    arg 0 <var_decl 0x2a95901ee0 banana 
        type <array_type 0x2a95901e00 type <integer_type 0x2a9562ec40 int> 
            BLK 
            size <integer_cst 0x2a95595de0 constant invariant 128> 
            unit size <integer_cst 0x2a9559f4b0 constant invariant 16> 
            align 32 symtab 0 alias set -1 domain <integer_type 0x2a95629a80>> 
        readonly used static BLK file t.c line 1 size <integer_cst 
0x2a95595de0 128> unit size <integer_cst 0x2a9559f4b0 16> 
        align 32 initial <constructor 0x2a9562c080>> 
    arg 1 <integer_cst 0x2a95913f30 type <integer_type 0x2a955978c0 int> 
constant invariant 2>> 
$3 = void 
(gdb) p debug_tree ((tree *)0x2a9562c080) 
 <constructor 0x2a9562c080 
    type <array_type 0x2a95901e00 
        type <integer_type 0x2a9562ec40 int readonly SI 
            size <integer_cst 0x2a95595780 constant invariant 32> 
            unit size <integer_cst 0x2a955958d0 constant invariant 4> 
            align 32 symtab 0 alias set -1 precision 32 min <integer_cst 
0x2a95595870 -2147483648> max <integer_cst 0x2a955958a0 2147483647> 
            pointer_to_this <pointer_type 0x2a9562ed20>> 
        BLK 
        size <integer_cst 0x2a95595de0 constant invariant 128> 
        unit size <integer_cst 0x2a9559f4b0 constant invariant 16> 
        align 32 symtab 0 alias set -1 
        domain <integer_type 0x2a95629a80 type <integer_type 0x2a955a6700 long 
unsigned int> 
            DI 
            size <integer_cst 0x2a95595900 constant invariant 64> 
            unit size <integer_cst 0x2a95595a50 constant invariant 8> 
            align 64 symtab 0 alias set -1 precision 64 min <integer_cst 
0x2a9559f5d0 0> max <integer_cst 0x2a95628000 3>>> 
    constant invariant static 
    arg 0 <tree_list 0x2a959139f0 
        purpose <integer_cst 0x2a959139c0 constant invariant 0> 
        value <integer_cst 0x2a95913990 constant invariant 0> 
        chain <tree_list 0x2a95913a80 
            purpose <integer_cst 0x2a95913a50 constant invariant 1> 
            value <integer_cst 0x2a95913a20 constant invariant 1> 
            chain <tree_list 0x2a95913b10 
                purpose <integer_cst 0x2a95913ae0 constant invariant 2> 
                value <integer_cst 0x2a95913ab0 constant invariant 2> 
                chain <tree_list 0x2a95913bd0 
                    purpose <integer_cst 0x2a95913ba0 constant invariant 3> 
                    value <integer_cst 0x2a95913b70 constant invariant 3>>>>>> 
$4 = void 
(gdb) 
 
So somebody should just teach fold-const to fold ARRAY_REFs to 
readonly memory. 
 
Comment 3 Kazu Hirata 2004-08-13 08:13:00 UTC
There is a piece of code in expr.c around line 6700 that folds references to
constant arrays with constant indecies.

The only problem is that we have to be careful not to fold
things like &array[2].

I am not sure if there is a way to see the containing expression
in fold().
Comment 4 Steven Bosscher 2004-08-30 22:23:32 UTC
Created attachment 7007 [details]
fold array refs to constant arrays with a constant index

Find attached the almost completely untested patch ;-)

I'm going away for a week and a bit, if nobody else has tested it by then I'll
give it a spin.  At least it bootstraps (C only) on AMD64.
Comment 5 Steven Bosscher 2004-08-30 22:24:09 UTC
Diego said he want to lose track of this one. 
Comment 6 Steven Bosscher 2004-08-30 22:26:30 UTC
hmm for the really ambitious, of course that list_length call isn't strictly 
necessary... 
Comment 7 Andrew Pinski 2004-08-30 22:26:52 UTC
And the related bug is for structs, see PR 15838 for that one.
Comment 8 Steven Bosscher 2004-08-31 00:10:41 UTC
Or I would lose track of it myself 
Comment 9 Diego Novillo 2004-08-31 00:18:22 UTC
> fold array refs to constant arrays with a constant index
> 
> Find attached the almost completely untested patch ;-)
> 
Looks OK.  I would split the test done at the start of const_array_const_idx_elt
into a predicate that we can call from evaluate_stmt beforehand.

OK with that change (testing, etc).


Diego.
Comment 10 Giovanni Bajo 2004-08-31 02:03:31 UTC
Quick question, isn't it better to do this in fold?
Comment 11 Andrew Pinski 2004-08-31 02:06:22 UTC
Because you cannot do it in fold because we get the expression a[2] which is part of the bigger 
expression &a[2] which means that we cannot fold the first expression.
Comment 12 Steven Bosscher 2004-08-31 09:38:56 UTC
Subject: Re:  [tree-ssa] const_array[CST] is not folded

On Tuesday 31 August 2004 04:06, pinskia at gcc dot gnu dot org wrote:
> ------- Additional Comments From pinskia at gcc dot gnu dot org  2004-08-31
> 02:06 ------- Because you cannot do it in fold because we get the
> expression a[2] which is part of the bigger expression &a[2] which means
> that we cannot fold the first expression.

Exactly. CCP is the right place for this.

The expr.c hack can probably be removed when the patch is in, if
somebody is interested.

Gr.
Steven


Comment 13 Steven Bosscher 2004-08-31 18:13:12 UTC
mine 
Comment 14 Steven Bosscher 2004-08-31 21:00:44 UTC
simple patch not good enough, and no clue how to 
handle "x = a.b.c.d.e[2].f[4].g" 
Comment 15 Diego Novillo 2004-08-31 21:03:03 UTC
OK.  I'll put it in my queue.
Comment 16 Steven Bosscher 2004-09-03 21:48:51 UTC
What makes the general case with more fields a bit hard is that you apparently need to 
traverse the component/array ref list to the innermost reference to find the referenced variable.  
Otherwise there is to way to see if the component/array ref references a constant initializer.  
Like so: 
 
(gdb) p debug_tree (*stmt_p) 
 <modify_expr 0x2a95595870 
    type <integer_type 0x2a955968c0 int public SI 
        size <integer_cst 0x2a955949c0 constant invariant 32> 
        unit size <integer_cst 0x2a95594420 constant invariant 4> 
        align 32 symtab 0 alias set 4 precision 32 min <integer_cst 0x2a95594960 -2147483648> 
max <integer_cst 0x2a95594990 2147483647> 
        pointer_to_this <pointer_type 0x2a955b0540>> 
    side-effects 
    arg 0 <var_decl 0x2a959238c0 T.0 type <integer_type 0x2a955968c0 int> 
        used ignored SI file t.c line 12 size <integer_cst 0x2a955949c0 32> unit size 
<integer_cst 0x2a95594420 4> 
        align 32 context <function_decl 0x2a95923540 main>> 
    arg 1 <component_ref 0x2a95595820 type <integer_type 0x2a955968c0 int> 
 
        arg 0 <component_ref 0x2a955957d0 type <record_type 0x2a9590fe00 b> 
            arg 0 <var_decl 0x2a959232a0 t> arg 1 <field_decl 0x2a959230e0 b>> 
        arg 1 <field_decl 0x2a95923000 i type <integer_type 0x2a955968c0 int> 
            SI file t.c line 3 size <integer_cst 0x2a955949c0 32> unit size <integer_cst 
0x2a95594420 4> 
            align 32 offset_align 128 
            offset <integer_cst 0x2a95594450 constant invariant 0> 
            bit offset <integer_cst 0x2a955aa810 constant invariant 0> context <record_type 
0x2a9590fe00 b> arguments <integer_cst 0x2a95594450 0>>> 
    t.c:12> 
$11 = void 
(gdb) p debug_tree (rhs) 
 <component_ref 0x2a95595820 
    type <integer_type 0x2a955968c0 int public SI 
        size <integer_cst 0x2a955949c0 constant invariant 32> 
        unit size <integer_cst 0x2a95594420 constant invariant 4> 
        align 32 symtab 0 alias set 4 precision 32 min <integer_cst 0x2a95594960 -2147483648> 
max <integer_cst 0x2a95594990 2147483647> 
        pointer_to_this <pointer_type 0x2a955b0540>> 
 
    arg 0 <component_ref 0x2a955957d0 
        type <record_type 0x2a9590fe00 b type_0 SI size <integer_cst 0x2a955949c0 32> unit 
size <integer_cst 0x2a95594420 4> 
            align 32 symtab 0 alias set 3 fields <field_decl 0x2a95923000 i> context 
<translation_unit_decl 0x2a959239a0> 
            chain <type_decl 0x2a9590fee0>> 
 
        arg 0 <var_decl 0x2a959232a0 t type <record_type 0x2a9590fc40 a> 
            asm_written used public static SI file t.c line 7 size <integer_cst 0x2a955949c0 32> 
unit size <integer_cst 0x2a95594420 4> 
            align 32 initial <constructor 0x2a95634340> 
            (mem/s:SI (symbol_ref:DI ("t") [flags 0x2] <var_decl 0x2a959232a0 t>) [2 t+0 S4 A32]) 
chain <function_decl 0x2a95923540 main>> 
        arg 1 <field_decl 0x2a959230e0 b type <record_type 0x2a9590fe00 b> 
            SI file t.c line 4 size <integer_cst 0x2a955949c0 32> unit size <integer_cst 
0x2a95594420 4> 
            align 32 offset_align 128 
            offset <integer_cst 0x2a95594450 constant invariant 0> 
            bit offset <integer_cst 0x2a955aa810 constant invariant 0> context <record_type 
0x2a9590fc40 a> arguments <integer_cst 0x2a95594450 0>>> 
    arg 1 <field_decl 0x2a95923000 i type <integer_type 0x2a955968c0 int> 
        SI file t.c line 3 size <integer_cst 0x2a955949c0 32> unit size <integer_cst 
0x2a95594420 4> 
        align 32 offset_align 128 offset <integer_cst 0x2a95594450 0> bit offset <integer_cst 
0x2a955aa810 0> context <record_type 0x2a9590fe00 b> arguments <integer_cst 
0x2a95594450 0>>> 
$12 = void 
(gdb) p rhs->common.constant_flag 
$13 = 0 
(gdb) p debug_tree (rhs->exp.operands[0]->exp.operands[0]) 
 <var_decl 0x2a959232a0 t 
    type <record_type 0x2a9590fc40 a type_0 SI 
        size <integer_cst 0x2a955949c0 constant invariant 32> 
        unit size <integer_cst 0x2a95594420 constant invariant 4> 
        align 32 symtab 0 alias set 2 
        fields <field_decl 0x2a959230e0 b type <record_type 0x2a9590fe00 b> 
            SI file t.c line 4 size <integer_cst 0x2a955949c0 32> unit size <integer_cst 
0x2a95594420 4> 
            align 32 offset_align 128 
            offset <integer_cst 0x2a95594450 constant invariant 0> 
            bit offset <integer_cst 0x2a955aa810 constant invariant 0> context <record_type 
0x2a9590fc40 a> arguments <integer_cst 0x2a95594450 0>> context <translation_unit_decl 
0x2a959239a0> 
        chain <type_decl 0x2a9590fd20>> 
    asm_written used public static SI file t.c line 7 size <integer_cst 0x2a955949c0 32> unit 
size <integer_cst 0x2a95594420 4> 
    align 32 initial <constructor 0x2a95634340> 
    (mem/s:SI (symbol_ref:DI ("t") [flags 0x2] <var_decl 0x2a959232a0 t>) [2 t+0 S4 A32]) 
chain <function_decl 0x2a95923540 main>> 
$14 = void 
 
Either we should somehow mark the component ref itself as constant, or we have to traverse 
the (in this case) COMPONENT_REF to the innermost reference to see the variable that is 
referenced.  That might actually get pretty expensive, I'd think...??? 
Comment 17 Kazu Hirata 2005-05-07 03:08:12 UTC
I've extended Steven's patch to handle nested aggregates
(i.e. any combination of ARRAY_REF and COMPONENT_REF).

Comment 18 Paul Schlie 2005-05-07 05:12:21 UTC
(In reply to comment #17)
> I've extended Steven's patch to handle nested aggregates
> (i.e. any combination of ARRAY_REF and COMPONENT_REF).

Does it also work with terminating static const char "strings" which
for some odd reason aren't char ARRAYs referenced via an ARRAY_REF's ?
Comment 19 Kazu Hirata 2005-05-07 14:30:07 UTC
Created attachment 8836 [details]
patch
Comment 20 GCC Commits 2005-05-08 21:22:31 UTC
Subject: Bug 14841

CVSROOT:	/cvs/gcc
Module name:	gcc
Changes by:	kazu@gcc.gnu.org	2005-05-08 21:22:21

Modified files:
	gcc            : ChangeLog Makefile.in tree-ssa-ccp.c 
Added files:
	gcc/testsuite/gcc.dg/tree-ssa: pr14841.c 

Log message:
	gcc/
	PR tree-optimization/14841, tree-optimization/15838
	* tree-ssa-ccp.c (fold_const_aggregate_ref): New.
	(evaluate_stmt): Call it.
	
	testsuite/
	PR tree-optimization/14841, tree-optimization/15838
	* gcc.dg/tree-ssa/pr14841.c: New.

Patches:
http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/ChangeLog.diff?cvsroot=gcc&r1=2.8663&r2=2.8664
http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/Makefile.in.diff?cvsroot=gcc&r1=1.1481&r2=1.1482
http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/tree-ssa-ccp.c.diff?cvsroot=gcc&r1=2.69&r2=2.70
http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/testsuite/gcc.dg/tree-ssa/pr14841.c.diff?cvsroot=gcc&r1=NONE&r2=1.1

Comment 21 Kazu Hirata 2005-05-08 21:30:00 UTC
Just checked in a patch.
Comment 22 Richard Biener 2006-05-08 10:07:13 UTC
Doesn't really work, it misses support for STRING_CST.  See PR22303.

static const char *foo = "?";

char foobar () { return foo[0]; }

Something like the following should fix it (once fold_read_from_constant_string is fixed):

Index: tree-ssa-ccp.c
===================================================================
*** tree-ssa-ccp.c      (revision 113606)
--- tree-ssa-ccp.c      (working copy)
*************** fold_const_aggregate_ref (tree t)
*** 1011,1020 ****
        }
  
        if (ctor == NULL_TREE
!         || TREE_CODE (ctor) != CONSTRUCTOR
          || !TREE_STATIC (ctor))
        return NULL_TREE;
  
        /* Get the index.  If we have an SSA_NAME, try to resolve it
         with the current lattice value for the SSA_NAME.  */
        idx = TREE_OPERAND (t, 1);
--- 1011,1024 ----
        }
  
        if (ctor == NULL_TREE
!         || TREE_CODE (ctor) != CONSTRUCTOR
          || !TREE_STATIC (ctor))
        return NULL_TREE;
  
        /* Get the index.  If we have an SSA_NAME, try to resolve it
         with the current lattice value for the SSA_NAME.  */
        idx = TREE_OPERAND (t, 1);
--- 1011,1024 ----
        }
  
        if (ctor == NULL_TREE
!         || (TREE_CODE (ctor) != CONSTRUCTOR
!             && TREE_CODE (ctor) != STRING_CST)
          || !TREE_STATIC (ctor))
        return NULL_TREE;
  
+       if (TREE_CODE (ctor) == STRING_CST)
+       return fold_read_from_constant_string (t);
+ 
        /* Get the index.  If we have an SSA_NAME, try to resolve it
         with the current lattice value for the SSA_NAME.  */
        idx = TREE_OPERAND (t, 1);
Comment 23 Richard Biener 2006-05-08 10:08:47 UTC
Dirk, you may want to take this one, too.
Comment 24 Andrew Pinski 2006-05-08 15:07:05 UTC
But that is not related to the orginal bug.