On 08/07/18 17:02, Martin Sebor wrote:
> On 08/06/2018 11:45 PM, Richard Biener wrote:
>> On August 7, 2018 5:38:59 AM GMT+02:00, Martin Sebor <mse...@gmail.com> 
>> wrote:
>>> On 08/06/2018 11:40 AM, Jeff Law wrote:
>>>> On 08/06/2018 11:15 AM, Martin Sebor wrote:
>>>>>>> These examples do not aim to be valid C, they just point out
>>> limitations
>>>>>>> of the middle-end design, and a good deal of the problems are due
>>>>>>> to trying to do things that are not safe within the boundaries
>>> given
>>>>>>> by the middle-end design.
>>>>>> I really think this is important -- and as such I think we need to
>>> move
>>>>>> away from trying to describe scenarios in C because doing so keeps
>>>>>> bringing us back to the "C doesn't allow XYZ" kinds of arguments
>>> when
>>>>>> what we're really discussing are GIMPLE semantic issues.
>>>>>>
>>>>>> So examples should be GIMPLE.  You might start with (possibly
>>> invalid) C
>>>>>> code to generate the GIMPLE, but the actual discussion needs to be
>>>>>> looking at GIMPLE.  We might include the C code in case someone
>>> wants to
>>>>>> look at things in a debugger, but bringing the focus to GIMPLE is
>>> really
>>>>>> important here.
>>>>>
>>>>> I don't understand the goal of this exercise.  Unless the GIMPLE
>>>>> code is the result of a valid test case (in some language GCC
>>>>> supports), what does it matter what it looks like?  The basis of
>>>>> every single transformation done by a compiler is that the source
>>>>> code is correct.  If it isn't then all bets are off.  I'm no GIMPLE
>>>>> expert but even I can come up with any number of GIMPLE expressions
>>>>> that have undefined behavior.  What would that prove?
>>>> The GIMPLE IL is less restrictive than the original source language.
>>>> The process of translation into GIMPLE and optimization can create
>>>> situations in the GIMPLE IL that can't be validly represented in the
>>>> original source language.  Subobject crossing being one such case,
>>> there
>>>> are certainly others.  We have to handle these scenarios correctly.
>>>
>>> Sure, but a valid C test case still needs to exist to show that
>>> such a transformation is possible.  Until someone comes up with
>>> one it's all speculation.
>>
>> Jakub showed you one wrt CSE of addresses.
> 
> Sorry, there have been so many examples I've lost track.  Can
> you please copy it here or point to it in the archive?
> 

This is based on Jakubs example here: 
https://gcc.gnu.org/ml/gcc-patches/2018-08/msg00260.html

$ cat y.cc
typedef __typeof__ (sizeof 0) size_t;
void *operator new (size_t, void *p) { return p; }
void *operator new[] (size_t, void *p) { return p; }
struct S { int x; unsigned char a[1]; char b[64]; };
void baz (char *);

size_t
foo (S *p)
{
   char *q = new ((char*)p->a) char [16];
   baz (q);
   size_t x = __builtin_strlen (q);
   if (x==0)
     __builtin_abort();
   return x;
}

$ gcc -O3 -S y.cc
$ cat y.s
.LFB2:
        .cfi_startproc
        subq    $8, %rsp
        .cfi_def_cfa_offset 16
        addq    $4, %rdi
        call    _Z3bazPc
        call    abort
        .cfi_endproc



I think this is not a correct optimization.

Bernd.


> In any event, I would find it reasonable for the strlen
> optimization to be subject to the same constraints as
> the aggressive loop optimization.  If there are valid test
> cases where the strlen optimization goes beyond that then
> let's throttle those.  Doing more than that would be
> arbitrary and result in confusing inconsistencies (as
> the proposed patch does).  For example, these two equivalent
> functions should continue to result in the same optimal code:
> 
>    extern char b[2][4];
> 
>    void f (int i)
>    {
>      if (__builtin_strlen (b[i]) >= sizeof b[i])
>        __builtin_abort ();
>    }
> 
>    void g (int i)
>    {
>      unsigned n = 0;
>      while (b[i][n])
>        ++n;
>      if (n >= sizeof b[i])
>        __builtin_abort ();
>    }
> 
> Martin

Reply via email to