On Thu, 11 Jan 2018, Jakub Jelinek wrote: > Hi! > > My recent C FE lval folding improvements apparently broke OpenMP/OpenACC > handling of constant size VLAs, e.g. > const int size = 4096; > int array[size]; > The problem is that the OpenMP/ACC gimplification/lowering/expansion relies > on TREE_CODE (DECL_SIZE_UNIT ()) != INTEGER_CST, or !TREE_CONSTANT > (TYPE_SIZE_UNIT ()) or variably_modified_type_p predicates to find VLAs that > have been processed by gimplify_vla_decl and need special handling. > The problem is that as the C FE got better at folding stuff, we end up with > decls that have non-INTEGER_CST DECL_SIZE_UNIT which after > gimplify_one_sizepos becomes INTEGER_CST, so the only way to distinguish it > from non-vlas is that it has certain DECL_VALUE_EXPR. There are many other > reasons why something could have a DECL_VALUE_EXPR, so checking that sounds > very error-prone. > > This patch instead treats such arrays as non-VLAs, by first gimplifying > DECL_SIZE_UNIT and only then checking if it is non-INTEGER_CST. > It will surely result in better code, even when not using OpenMP/OpenACC, > some people think const in C is the same thing as C++, on the other side, > there might be some carefully crafted code that uses these weirdo constant > VLAs and expect them to be deallocated every time. > { const int n = 4096*4096; int vla[n]; foo (vla); } > { const int n = 4096*4096; float vla[n]; bar (vla); } > ... > even when for some reason we wouldn't be able to share the constant size > array stack memory. > > Is this acceptable optimization anyway? Bootstrapped/regtested on > x86_64-linux and i686-linux. > > The alternative would be to add some bit on the decls that would tell the > rest of gimplifier and middle-end that gimplify_vla_decl has been done on it > and it needs to be treated specially.
Or another workaround would be to make sure non-constant sizepos stay non-constant by doing sth like the following? FEs can mark expressions as TREE_CONSTANT if they don't want this behavior for things that might optimize to constants during gimplification. Index: gcc/gimplify.c =================================================================== --- gcc/gimplify.c (revision 256535) +++ gcc/gimplify.c (working copy) @@ -12567,9 +12567,13 @@ gimplify_one_sizepos (tree *expr_p, gimp *expr_p = unshare_expr (expr); + bool non_constant_p = ! TREE_CONSTANT (*expr_p); /* SSA names in decl/type fields are a bad idea - they'll get reclaimed if the def vanishes. */ gimplify_expr (expr_p, stmt_p, NULL, is_gimple_val, fb_rvalue, false); + if (non_constant_p + && is_gimple_constant (*expr_p)) + *expr_p = get_initialized_tmp_var (*expr_p, stmt_p, NULL, false); } /* Gimplify the body of statements of FNDECL and return a GIMPLE_BIND node > 2018-01-11 Jakub Jelinek <ja...@redhat.com> > > PR libgomp/83590 > * gimplify.c (gimplify_vla_decl): Don't call gimplify_one_sizepos > for DEC_SIZE and DECL_SIZE_UNIT here... > (gimplify_decl_expr): ... but here before testing if DECL_SIZE_UNIT > is INTEGER_CST. > (gimplify_target_expr): And here too. Call gimplify_type_sizes > always, not just for VLAs. Check DECL_SIZE_UNIT rather than DECL_SIZE > for consistency with gimplify_decl_expr. > > * gcc.target/i386/stack-check-18.c (main): Drop const from size > variable. > > --- gcc/gimplify.c.jj 2018-01-03 10:19:55.887534074 +0100 > +++ gcc/gimplify.c 2018-01-11 10:10:37.733519519 +0100 > @@ -1587,9 +1587,6 @@ gimplify_vla_decl (tree decl, gimple_seq > for deferred expansion. */ > tree t, addr, ptr_type; > > - gimplify_one_sizepos (&DECL_SIZE (decl), seq_p); > - gimplify_one_sizepos (&DECL_SIZE_UNIT (decl), seq_p); > - > /* Don't mess with a DECL_VALUE_EXPR set by the front-end. */ > if (DECL_HAS_VALUE_EXPR_P (decl)) > return; > @@ -1673,6 +1670,9 @@ gimplify_decl_expr (tree *stmt_p, gimple > tree init = DECL_INITIAL (decl); > bool is_vla = false; > > + gimplify_one_sizepos (&DECL_SIZE (decl), seq_p); > + gimplify_one_sizepos (&DECL_SIZE_UNIT (decl), seq_p); > + > if (TREE_CODE (DECL_SIZE_UNIT (decl)) != INTEGER_CST > || (!TREE_STATIC (decl) > && flag_stack_check == GENERIC_STACK_CHECK > @@ -6548,14 +6548,15 @@ gimplify_target_expr (tree *expr_p, gimp > { > tree cleanup = NULL_TREE; > > + if (!TYPE_SIZES_GIMPLIFIED (TREE_TYPE (temp))) > + gimplify_type_sizes (TREE_TYPE (temp), pre_p); > + gimplify_one_sizepos (&DECL_SIZE (temp), pre_p); > + gimplify_one_sizepos (&DECL_SIZE_UNIT (temp), pre_p); > + > /* TARGET_EXPR temps aren't part of the enclosing block, so add it > to the temps list. Handle also variable length TARGET_EXPRs. */ > - if (TREE_CODE (DECL_SIZE (temp)) != INTEGER_CST) > - { > - if (!TYPE_SIZES_GIMPLIFIED (TREE_TYPE (temp))) > - gimplify_type_sizes (TREE_TYPE (temp), pre_p); > - gimplify_vla_decl (temp, pre_p); > - } > + if (TREE_CODE (DECL_SIZE_UNIT (temp)) != INTEGER_CST) > + gimplify_vla_decl (temp, pre_p); > else > { > /* Save location where we need to place unpoisoning. It's possible > --- gcc/testsuite/gcc.target/i386/stack-check-18.c.jj 2018-01-03 > 21:21:38.707907706 +0100 > +++ gcc/testsuite/gcc.target/i386/stack-check-18.c 2018-01-11 > 19:10:11.933703006 +0100 > @@ -7,7 +7,7 @@ int f1 (char *); > int > f2 (void) > { > - const int size = 4096; > + int size = 4096; > char buffer[size]; > return f1 (buffer); > } > > Jakub > > -- Richard Biener <rguent...@suse.de> SUSE LINUX GmbH, GF: Felix Imendoerffer, Jane Smithard, Graham Norton, HRB 21284 (AG Nuernberg)