On 08/08/2017 03:18 PM, Richard Biener wrote: > On Tue, Aug 8, 2017 at 1:47 PM, Martin Liška <mli...@suse.cz> wrote: >> On 11/09/2016 11:22 AM, Richard Biener wrote: >>> On Fri, Nov 4, 2016 at 2:33 PM, Martin Liška <mli...@suse.cz> wrote: >>>> On 11/03/2016 02:00 PM, Jan Hubicka wrote: >>>>>> On 11/03/2016 01:12 PM, Martin Liška wrote: >>>>>>> + tree init = DECL_INITIAL (decl); >>>>>>> + if (init >>>>>>> + && TREE_READONLY (decl) >>>>>>> + && can_convert_ctor_to_string_cst (init)) >>>>>>> + DECL_INITIAL (decl) = build_string_cst_from_ctor (init); >>>>>> >>>>>> I'd merge these two new functions since they're only ever called >>>>>> together. We'd then have something like >>>>>> >>>>>> if (init && TREE_READONLY (decl)) >>>>>> init = convert_ctor_to_string_cst (init); >>>>>> if (init) >>>>>> DECL_INITIAL (decl) = init; >>>> >>>> Done. >>>> >>>>>> >>>>>> I'll defer to Jan on whether finalize_decl seems like a good place >>>>>> to do this. >>>>> >>>>> I think finalize_decl may be bit too early because frontends may expects >>>>> the >>>>> ctors to be in a way they produced them. We only want to convert those >>>>> arrays >>>>> seen by middle-end so I would move the logic to varpool_node::analyze >>>>> >>>>> Otherwise the patch seems fine to me. >>>>> >>>>> Honza >>>>>> >>>>>>> diff --git a/gcc/testsuite/gcc.dg/tree-ssa/builtins-folding-gimple.c >>>>>>> b/gcc/testsuite/gcc.dg/tree-ssa/builtins-folding-gimple.c >>>>>>> index 283bd1c..b2d1fd5 100644 >>>>>>> --- a/gcc/testsuite/gcc.dg/tree-ssa/builtins-folding-gimple.c >>>>>>> +++ b/gcc/testsuite/gcc.dg/tree-ssa/builtins-folding-gimple.c >>>>>>> @@ -4,12 +4,15 @@ >>>>>>> char *buffer1; >>>>>>> char *buffer2; >>>>>>> >>>>>>> +const char global[] = {'a', 'b', 'c', 'd', '\0'}; >>>>>>> + >>>>>>> #define SIZE 1000 >>>>>>> >>>>>>> int >>>>>>> main (void) >>>>>>> { >>>>>>> const char* const foo1 = "hello world"; >>>>>>> + const char local[] = "abcd"; >>>>>>> >>>>>>> buffer1 = __builtin_malloc (SIZE); >>>>>>> __builtin_strcpy (buffer1, foo1); >>>>>>> @@ -45,6 +48,10 @@ main (void) >>>>>>> __builtin_abort (); >>>>>>> if (__builtin_memchr (foo1, null, 12) != foo1 + 11) >>>>>>> __builtin_abort (); >>>>>>> + if (__builtin_memchr (global, null, 5) == 0) >>>>>>> + __builtin_abort (); >>>>>>> + if (__builtin_memchr (local, null, 5) == 0) >>>>>>> + __builtin_abort (); >>>>>> >>>>>> How is that a meaningful test? This seems to work even with an >>>>>> unpatched gcc. I'd have expected something that shows a benefit for >>>>>> doing this conversion, and maybe also a test that shows it isn't >>>>>> done in cases where it's not allowed. >>>> >>>> It's meaningful as it scans that there's no __builtin_memchr in optimized >>>> dump. >>>> I'm adding new tests that does the opposite test. >>>> >>>>>> >>>>>>> tree >>>>>>> -build_string_literal (int len, const char *str) >>>>>>> +build_string_literal (int len, const char *str, bool build_addr_expr) >>>>>> >>>>>> New arguments should be documented in the function comment. >>>> >>>> Yep, improved. >>>> >>>>>> >>>>>>> +/* Return TRUE when CTOR can be converted to a string constant. */ >>>>>> >>>>>> "if", not "when". >>>> >>>> Done. >>>> >>>>>> >>>>>>> + unsigned HOST_WIDE_INT elements = CONSTRUCTOR_NELTS (ctor); >>>>>>> + FOR_EACH_CONSTRUCTOR_ELT (CONSTRUCTOR_ELTS (ctor), idx, key, value) >>>>>>> + { >>>>>>> + if (key == NULL_TREE >>>>>>> + || TREE_CODE (key) != INTEGER_CST >>>>>>> + || !tree_fits_uhwi_p (value) >>>>>>> + || !useless_type_conversion_p (TREE_TYPE (value), char_type_node)) >>>>>>> + return false; >>>>>> >>>>>> Shouldn't all elements have the same type, or do you really have to >>>>>> call useless_type_conversion in a loop? >>>>>> >>>>>>> + /* Allow zero character just at the end of a string. */ >>>>>>> + if (integer_zerop (value)) >>>>>>> + return idx == elements - 1; >>>>>> >>>>>> Don't you also have to explicitly check it's there? >>>>>> >>>>>> >>>>>> Bernd >>>> >>>> >>>> Patch can bootstrap on ppc64le-redhat-linux and survives regression tests. >>> >>> I'm curious about the >>> >>> @@ -1495,7 +1495,8 @@ gimplify_decl_expr (tree *stmt_p, gimple_seq *seq_p) >>> { >>> if (!TREE_STATIC (decl)) >>> { >>> - DECL_INITIAL (decl) = NULL_TREE; >>> + if (!TREE_READONLY (decl) || TREE_CODE (init) != STRING_CST) >>> + DECL_INITIAL (decl) = NULL_TREE; >>> init = build2 (INIT_EXPR, void_type_node, decl, init); >>> gimplify_and_add (init, seq_p); >>> ggc_free (init); >>> >>> change. Why keep DECL_INITIAL if you build a INIT_EXPR anyway? >>> >>> @@ -4438,6 +4439,19 @@ gimplify_init_constructor (tree *expr_p, >>> gimple_seq *pre_p, gimple_seq *post_p, >>> break; >>> } >>> >>> + /* Replace a ctor with a string constant with possible. */ >>> + if (TREE_READONLY (object) >>> + && VAR_P (object)) >>> + { >>> + tree string_ctor = convert_ctor_to_string_cst (ctor); >>> + if (string_ctor) >>> + { >>> + TREE_OPERAND (*expr_p, 1) = string_ctor; >>> + DECL_INITIAL (object) = string_ctor; >>> + break; >>> + } >>> + } >>> + >>> /* Fetch information about the constructor to direct later >>> processing. >>> We might want to make static versions of it in various cases, and >>> can only do so if it known to be a valid constant initializer. >>> */ >>> >>> hmm, so both these hunks will end up keeping a DECL_INITIAL >>> for non-static local consts? Usually we end up with >>> >>> main () >>> { >>> const char local[5]; >>> >>> <bb 2>: >>> local = "abcd"; >>> >>> here. So you keep DECL_INITIAL for folding? >>> >>> I believe we should create CONST_DECLs for the above (and make >>> CONST_DECLs first-class >>> symtab citizens), thus avoid runtime stack initialization for the >>> above and instead emit >>> "abcd" to the constant pool? >> >> Hi Richi. >> >> I've just returned to this in order to resolve long pending unfinished stuff. >> I have couple of questions: >> >> a) what should create a CONST_DECL, a FE or gimplifier when it identifies >> that >> it can be converted to CONST_DECL? > > The gimplifier (prototype patches of mine did it that way when trying > to get rid of > &STRING_CST). > >> b) Why do we need to put such local variables to symtab? > > We don't need to, but we eventually should? > >> c) Do we have a target that uses CONST_DECL for such (or similar) purpose? > > Not sure. gimplify_init_constructor ends up with .LC0* on for example aarch64 > for initializers of arrays for example. > > Attached old &STRING_CST -> &CONST_DECL gimplification patch (no > longer applies).
Can you please Richi send me the patch in unified format so that I can apply the rejected hunks. Looks one just needs to put it into gimple-expr.c. Thanks, Martin > > Richard. > >> Thanks, >> Martin >> >>> >>> + /* Skip constructors with a hole. */ >>> + if (CONSTRUCTOR_NELTS (ctor) != ctor_length) >>> + return false; >>> >>> not sure if that's maybe too clever ;) >>> >>> + FOR_EACH_CONSTRUCTOR_ELT (CONSTRUCTOR_ELTS (ctor), idx, key, value) >>> + { >>> + if (key == NULL_TREE >>> + || !tree_fits_uhwi_p (key) >>> + || !tree_fits_uhwi_p (value)) >>> + return false; >>> >>> I think key == NULL is very well valid (you are not using it...). I'd >>> instead do >>> >>> if (key && compare_tree_int (key, idx) != 0) >>> return false; >>> >>> for the hole check. value should always fit uhwi given the earlier >>> element type check. >>> >>> +tree >>> +convert_ctor_to_string_cst (tree ctor) >>> +{ >>> + if (!can_convert_ctor_to_string_cst (ctor)) >>> + return NULL_TREE; >>> + >>> + unsigned HOST_WIDE_INT idx; >>> + tree value; >>> + vec<constructor_elt, va_gc> *elts = CONSTRUCTOR_ELTS (ctor); >>> + char *str = XNEWVEC (char, elts->length ()); >>> + >>> + FOR_EACH_CONSTRUCTOR_VALUE (elts, idx, value) >>> + str[idx] = (char)tree_to_uhwi (value); >>> + >>> + tree init = build_string_literal (elts->length (), >>> + ggc_alloc_string (str, elts->length ()), >>> + false); >>> + free (str); >>> >>> why alloc str on the heap, copy it to gc and the copy it again? >>> That is, you can pass 'str' to build_string_literal directly I think. >>> >>> In fact as you are refactoring build_string_literal please >>> refactor build_string into a build_string_raw taking just 'len' >>> (thus leaving out the actual string initialization apart from >>> 'appending' '\0') and then avoid the heap allocation. >>> >>> Refactor build_string_literal to take a tree STRING_CST >>> and build_string_literal_addr to build it's address. >>> >>> Thanks, >>> Richard. >>> >>> >>> >>> >>>> Martin >>>> >>