On August 9, 2017 11:15:44 AM GMT+02:00, "Martin Liška" <mli...@suse.cz> wrote:
>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.

I only have the patch I sent you so I can't re-diff.

Richard.

>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
>>>>>
>>>

Reply via email to