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]; }
Confirmed.
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.
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().
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.
Diego said he want to lose track of this one.
hmm for the really ambitious, of course that list_length call isn't strictly necessary...
And the related bug is for structs, see PR 15838 for that one.
Or I would lose track of it myself
> 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.
Quick question, isn't it better to do this in fold?
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.
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
mine
simple patch not good enough, and no clue how to handle "x = a.b.c.d.e[2].f[4].g"
OK. I'll put it in my queue.
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...???
I've extended Steven's patch to handle nested aggregates (i.e. any combination of ARRAY_REF and COMPONENT_REF).
(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 ?
Created attachment 8836 [details] patch
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
Just checked in a patch.
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);
Dirk, you may want to take this one, too.
But that is not related to the orginal bug.