Re: Do not drom MEM_EXPR when accessing structure fields

2016-09-19 Thread Bernd Edlinger
On 09/19/16 16:23, Richard Biener wrote:
> On 19/09/16 15:49, Bernd Edlinger wrote:
>> On 09/19/16 11:28, Richard Biener wrote:
>>> On Sun, 18 Sep 2016, Jan Hubicka wrote:
>>>
> Hi,
>
>> when expanding code for
>> struct a {short a,b,c,d;} *a;
>> a->c;
>>
>> we first produce correct BLKmode MEM rtx representing the whole
>> structure *a,
>> then we use adjust_address to turn it into HImode MEM and finally
>> extract_bitfield is used to offset it by 32 bits to get correct 
> value.
>
> I tried to create a test case as follows and stepped thru the code.
>
> cat test.c
> struct a {short a,b,c,d;};
> void foo (struct a *a)
> {
>  a->c = 1;
> }
>
>
> First I get a DImode MEM rtx not BLKmode:
>
> (mem:DI (reg/f:DI 87) [2 *a_2(D)+0 S8 A16])
>
> and adjust_address does not clear the MEM_EXPR
>>>
>>> it's only cleared when later offsetted
>>>
> thus to_rtx = adjust_address (to_rtx, mode1, 0) returns:
>
> (mem:HI (reg/f:DI 87) [2 *a_2(D)+0 S2 A16])
>
> and then set_mem_attributes_minus_bitpos (to_rtx, to, 0, bitpos) does:
>
> (mem:HI (reg/f:DI 87) [3 a_2(D)->c+-4 S6 A16])
>
> which looks perfectly OK.
>>>
>>> Sure you quoted the correct RTL?  MEM_SIZE == 6 looks wrong.  Note
>>> we don't do set_mem_attributes_minus_bitpos when we go the bitfield
>>> extraction path.
>>>
>>
>> I think it is correct, to_rtx points 4 bytes before a->c "+-4", and
>> sizeof(a->c) is 2. So 4+2 is 6 there will be no access beyond that.
>
> Hmm, but if the MEM is HImode then doesn't this imply it will access
> 2 bytes starting at to_rtx (aka a->c "+-4").  At this point the offset
> doesn't seem to be accounted for yet (thus the MEM isn't accessing a->c
> yet).
>

Yes here to_rtx points still at a, and the MEM_EXPR means >c - 4b,
when the constant offset of 4 bytes gets added later in store_field,
and also there it looks like everything is working correctly.

6813  && TREE_CODE (exp) == MEM_REF
(gdb)
6770  if (mode == VOIDmode
(gdb)
6939  rtx to_rtx = adjust_address (target, mode, bitpos / 
BITS_PER_UNIT);
(gdb) call debug(target)
(mem:HI (reg/v/f:DI 87 [ a ]) [2 a_2(D)->c+-4 S6 A16])
(gdb) p mode
$1 = HImode
(gdb) p bitpos
$2 = 32
(gdb) n
6941  if (to_rtx == target)
(gdb) call debug(to_rtx)
(mem:HI (plus:DI (reg/v/f:DI 87 [ a ])
 (const_int 4 [0x4])) [2 a_2(D)->c+0 S2 A16])
(gdb)


>> And yes the RTL is correct: this is what I did:
>>
>> (gdb) n
>> 5152   to_rtx = shallow_copy_rtx (to_rtx);
>> (gdb) call debug(to_rtx)
>> (mem:HI (reg/v/f:DI 87 [ a ]) [1 *a_2(D)+0 S2 A16])
>> (gdb) n
>> 5153   set_mem_attributes_minus_bitpos (to_rtx, to, 0, bitpos);
>> (gdb) call debug(to_rtx)
>> (mem:HI (reg/v/f:DI 87 [ a ]) [1 *a_2(D)+0 S2 A16])
>> (gdb) n
>> 5154   if (volatilep)
>> (gdb) call debug(to_rtx)
>> (mem:HI (reg/v/f:DI 87 [ a ]) [2 a_2(D)->c+-4 S6 A16])
>> (gdb)
>
> So set_mem_attributes_minus_bitpos seems to try making later adjustment
> by bitpos "valid" if we at the same time shrink size to what was
> originally intended.
>
>> It is not about bitfield extraction, as we are in expand_assignment.
>> next is the call to optimize_bitfield_assignment_op and
>> store_field.
>>
>> I believe, that with Jan's patch we have at this point only
>> a different mode on the to_rtx.  And it is possible that
>> store_field or store_bit_field takes a different decision
>> dependent on GET_MODE(to_rtx), which may accidentally delete
>> the MEM_EXPR.
>
> It offsets the MEM which causes it to go "out of bounds" (no such
> "fancy" too large MEM_SIZE is present) which causes us to drop the
> MEM_EXPR.
>
> IMHO this piecewise (re-)construction of MEM_ATTRS is quite fragile...
> But refactoring this area of the compiler is fragile as well...
>

Yes...


Bernd.


Re: Do not drom MEM_EXPR when accessing structure fields

2016-09-19 Thread Richard Biener
On 19/09/16 15:49, Bernd Edlinger wrote:
> On 09/19/16 11:28, Richard Biener wrote:
>> On Sun, 18 Sep 2016, Jan Hubicka wrote:
>>
 Hi,

   > when expanding code for
   > struct a {short a,b,c,d;} *a;
   > a->c;
   >
   > we first produce correct BLKmode MEM rtx representing the whole
   > structure *a,
   > then we use adjust_address to turn it into HImode MEM and finally
   > extract_bitfield is used to offset it by 32 bits to get correct value.

 I tried to create a test case as follows and stepped thru the code.

 cat test.c
 struct a {short a,b,c,d;};
 void foo (struct a *a)
 {
 a->c = 1;
 }


 First I get a DImode MEM rtx not BLKmode:

 (mem:DI (reg/f:DI 87) [2 *a_2(D)+0 S8 A16])

 and adjust_address does not clear the MEM_EXPR
>>
>> it's only cleared when later offsetted
>>
 thus to_rtx = adjust_address (to_rtx, mode1, 0) returns:

 (mem:HI (reg/f:DI 87) [2 *a_2(D)+0 S2 A16])

 and then set_mem_attributes_minus_bitpos (to_rtx, to, 0, bitpos) does:

 (mem:HI (reg/f:DI 87) [3 a_2(D)->c+-4 S6 A16])

 which looks perfectly OK.
>>
>> Sure you quoted the correct RTL?  MEM_SIZE == 6 looks wrong.  Note
>> we don't do set_mem_attributes_minus_bitpos when we go the bitfield
>> extraction path.
>>
> 
> I think it is correct, to_rtx points 4 bytes before a->c "+-4", and
> sizeof(a->c) is 2. So 4+2 is 6 there will be no access beyond that.

Hmm, but if the MEM is HImode then doesn't this imply it will access
2 bytes starting at to_rtx (aka a->c "+-4").  At this point the offset
doesn't seem to be accounted for yet (thus the MEM isn't accessing a->c
yet).

> And yes the RTL is correct: this is what I did:
> 
> (gdb) n
> 5152to_rtx = shallow_copy_rtx (to_rtx);
> (gdb) call debug(to_rtx)
> (mem:HI (reg/v/f:DI 87 [ a ]) [1 *a_2(D)+0 S2 A16])
> (gdb) n
> 5153set_mem_attributes_minus_bitpos (to_rtx, to, 0, bitpos);
> (gdb) call debug(to_rtx)
> (mem:HI (reg/v/f:DI 87 [ a ]) [1 *a_2(D)+0 S2 A16])
> (gdb) n
> 5154if (volatilep)
> (gdb) call debug(to_rtx)
> (mem:HI (reg/v/f:DI 87 [ a ]) [2 a_2(D)->c+-4 S6 A16])
> (gdb)

So set_mem_attributes_minus_bitpos seems to try making later adjustment
by bitpos "valid" if we at the same time shrink size to what was
originally intended.

> It is not about bitfield extraction, as we are in expand_assignment.
> next is the call to optimize_bitfield_assignment_op and
> store_field.
> 
> I believe, that with Jan's patch we have at this point only
> a different mode on the to_rtx.  And it is possible that
> store_field or store_bit_field takes a different decision
> dependent on GET_MODE(to_rtx), which may accidentally delete
> the MEM_EXPR.

It offsets the MEM which causes it to go "out of bounds" (no such
"fancy" too large MEM_SIZE is present) which causes us to drop the
MEM_EXPR.

IMHO this piecewise (re-)construction of MEM_ATTRS is quite fragile...
But refactoring this area of the compiler is fragile as well...

Richard.

> 
> Bernd.
> 

 But with your patch the RTX looks different:

 (mem:DI (reg/f:DI 87) [3 a_2(D)->c+-4 S6 A16])

 which looks inconsistent, and not like an improvement.
>>>
>>> Hmm,
>>> the memory reference does point to a_2(D)->c+-4 so I would say it is OK.  
>>> The
>>> memory refernece is not adjusted yet to be reg87+4 and this is where memory
>>> attributes got lost for me (because the pointer becames out of range of 
>>> (mem:HI
>>> (reg87))).  I see this does not happen on x86_64, I will try to see why
>>> tomorrow.
>>
>> I think if you don't go the bitfield path nothing ends up chaning the
>> mode.  The inconsistency is for MEM_SIZE vs. GET_MODE of the MEM.
>>
>> mem:DI certainly looks wrong for a HImode access.
>>
>> Richard.
>>
> 



Re: Do not drom MEM_EXPR when accessing structure fields

2016-09-19 Thread Bernd Edlinger
On 09/19/16 11:28, Richard Biener wrote:
> On Sun, 18 Sep 2016, Jan Hubicka wrote:
>
>>> Hi,
>>>
>>>   > when expanding code for
>>>   > struct a {short a,b,c,d;} *a;
>>>   > a->c;
>>>   >
>>>   > we first produce correct BLKmode MEM rtx representing the whole
>>>   > structure *a,
>>>   > then we use adjust_address to turn it into HImode MEM and finally
>>>   > extract_bitfield is used to offset it by 32 bits to get correct value.
>>>
>>> I tried to create a test case as follows and stepped thru the code.
>>>
>>> cat test.c
>>> struct a {short a,b,c,d;};
>>> void foo (struct a *a)
>>> {
>>> a->c = 1;
>>> }
>>>
>>>
>>> First I get a DImode MEM rtx not BLKmode:
>>>
>>> (mem:DI (reg/f:DI 87) [2 *a_2(D)+0 S8 A16])
>>>
>>> and adjust_address does not clear the MEM_EXPR
>
> it's only cleared when later offsetted
>
>>> thus to_rtx = adjust_address (to_rtx, mode1, 0) returns:
>>>
>>> (mem:HI (reg/f:DI 87) [2 *a_2(D)+0 S2 A16])
>>>
>>> and then set_mem_attributes_minus_bitpos (to_rtx, to, 0, bitpos) does:
>>>
>>> (mem:HI (reg/f:DI 87) [3 a_2(D)->c+-4 S6 A16])
>>>
>>> which looks perfectly OK.
>
> Sure you quoted the correct RTL?  MEM_SIZE == 6 looks wrong.  Note
> we don't do set_mem_attributes_minus_bitpos when we go the bitfield
> extraction path.
>

I think it is correct, to_rtx points 4 bytes before a->c "+-4", and
sizeof(a->c) is 2. So 4+2 is 6 there will be no access beyond that.

And yes the RTL is correct: this is what I did:

(gdb) n
5152  to_rtx = shallow_copy_rtx (to_rtx);
(gdb) call debug(to_rtx)
(mem:HI (reg/v/f:DI 87 [ a ]) [1 *a_2(D)+0 S2 A16])
(gdb) n
5153  set_mem_attributes_minus_bitpos (to_rtx, to, 0, bitpos);
(gdb) call debug(to_rtx)
(mem:HI (reg/v/f:DI 87 [ a ]) [1 *a_2(D)+0 S2 A16])
(gdb) n
5154  if (volatilep)
(gdb) call debug(to_rtx)
(mem:HI (reg/v/f:DI 87 [ a ]) [2 a_2(D)->c+-4 S6 A16])
(gdb)


It is not about bitfield extraction, as we are in expand_assignment.
next is the call to optimize_bitfield_assignment_op and
store_field.

I believe, that with Jan's patch we have at this point only
a different mode on the to_rtx.  And it is possible that
store_field or store_bit_field takes a different decision
dependent on GET_MODE(to_rtx), which may accidentally delete
the MEM_EXPR.


Bernd.

>>>
>>> But with your patch the RTX looks different:
>>>
>>> (mem:DI (reg/f:DI 87) [3 a_2(D)->c+-4 S6 A16])
>>>
>>> which looks inconsistent, and not like an improvement.
>>
>> Hmm,
>> the memory reference does point to a_2(D)->c+-4 so I would say it is OK.  The
>> memory refernece is not adjusted yet to be reg87+4 and this is where memory
>> attributes got lost for me (because the pointer becames out of range of 
>> (mem:HI
>> (reg87))).  I see this does not happen on x86_64, I will try to see why
>> tomorrow.
>
> I think if you don't go the bitfield path nothing ends up chaning the
> mode.  The inconsistency is for MEM_SIZE vs. GET_MODE of the MEM.
>
> mem:DI certainly looks wrong for a HImode access.
>
> Richard.
>


Re: Do not drom MEM_EXPR when accessing structure fields

2016-09-19 Thread Bernd Schmidt

On 09/18/2016 02:51 PM, Jan Hubicka wrote:


   to_rtx = expand_expr (tem, NULL_RTX, VOIDmode, EXPAND_WRITE);
-
-  /* If the field has a mode, we want to access it in the
-field's mode, not the computed mode.
-If a MEM has VOIDmode (external with incomplete type),
-use BLKmode for it instead.  */
-  if (MEM_P (to_rtx))
-   {
- if (mode1 != VOIDmode)
-   to_rtx = adjust_address (to_rtx, mode1, 0);
- else if (GET_MODE (to_rtx) == VOIDmode)
-   to_rtx = adjust_address (to_rtx, BLKmode, 0);
-   }

   if (offset != 0)
{


This was added by Jakub in r166603, referencing PR46388. Have you looked 
at that?



Bernd


Re: Do not drom MEM_EXPR when accessing structure fields

2016-09-19 Thread Richard Biener
On Sun, 18 Sep 2016, Jan Hubicka wrote:

> > Hi,
> > 
> >  > when expanding code for
> >  > struct a {short a,b,c,d;} *a;
> >  > a->c;
> >  >
> >  > we first produce correct BLKmode MEM rtx representing the whole
> >  > structure *a,
> >  > then we use adjust_address to turn it into HImode MEM and finally
> >  > extract_bitfield is used to offset it by 32 bits to get correct value.
> > 
> > I tried to create a test case as follows and stepped thru the code.
> > 
> > cat test.c
> > struct a {short a,b,c,d;};
> > void foo (struct a *a)
> > {
> >a->c = 1;
> > }
> > 
> > 
> > First I get a DImode MEM rtx not BLKmode:
> > 
> > (mem:DI (reg/f:DI 87) [2 *a_2(D)+0 S8 A16])
> > 
> > and adjust_address does not clear the MEM_EXPR

it's only cleared when later offsetted

> > thus to_rtx = adjust_address (to_rtx, mode1, 0) returns:
> > 
> > (mem:HI (reg/f:DI 87) [2 *a_2(D)+0 S2 A16])
> > 
> > and then set_mem_attributes_minus_bitpos (to_rtx, to, 0, bitpos) does:
> > 
> > (mem:HI (reg/f:DI 87) [3 a_2(D)->c+-4 S6 A16])
> > 
> > which looks perfectly OK.

Sure you quoted the correct RTL?  MEM_SIZE == 6 looks wrong.  Note
we don't do set_mem_attributes_minus_bitpos when we go the bitfield
extraction path.

> > 
> > But with your patch the RTX looks different:
> > 
> > (mem:DI (reg/f:DI 87) [3 a_2(D)->c+-4 S6 A16])
> > 
> > which looks inconsistent, and not like an improvement.
> 
> Hmm,
> the memory reference does point to a_2(D)->c+-4 so I would say it is OK.  The
> memory refernece is not adjusted yet to be reg87+4 and this is where memory
> attributes got lost for me (because the pointer becames out of range of 
> (mem:HI
> (reg87))).  I see this does not happen on x86_64, I will try to see why
> tomorrow.

I think if you don't go the bitfield path nothing ends up chaning the
mode.  The inconsistency is for MEM_SIZE vs. GET_MODE of the MEM.

mem:DI certainly looks wrong for a HImode access.

Richard.


Re: Do not drom MEM_EXPR when accessing structure fields

2016-09-18 Thread Jan Hubicka
> Hi,
> 
>  > when expanding code for
>  > struct a {short a,b,c,d;} *a;
>  > a->c;
>  >
>  > we first produce correct BLKmode MEM rtx representing the whole
>  > structure *a,
>  > then we use adjust_address to turn it into HImode MEM and finally
>  > extract_bitfield is used to offset it by 32 bits to get correct value.
> 
> I tried to create a test case as follows and stepped thru the code.
> 
> cat test.c
> struct a {short a,b,c,d;};
> void foo (struct a *a)
> {
>a->c = 1;
> }
> 
> 
> First I get a DImode MEM rtx not BLKmode:
> 
> (mem:DI (reg/f:DI 87) [2 *a_2(D)+0 S8 A16])
> 
> and adjust_address does not clear the MEM_EXPR
> 
> thus to_rtx = adjust_address (to_rtx, mode1, 0) returns:
> 
> 
> (mem:HI (reg/f:DI 87) [2 *a_2(D)+0 S2 A16])
> 
> and then set_mem_attributes_minus_bitpos (to_rtx, to, 0, bitpos) does:
> 
> (mem:HI (reg/f:DI 87) [3 a_2(D)->c+-4 S6 A16])
> 
> which looks perfectly OK.
> 
> But with your patch the RTX looks different:
> 
> (mem:DI (reg/f:DI 87) [3 a_2(D)->c+-4 S6 A16])
> 
> which looks inconsistent, and not like an improvement.

Hmm,
the memory reference does point to a_2(D)->c+-4 so I would say it is OK.  The
memory refernece is not adjusted yet to be reg87+4 and this is where memory
attributes got lost for me (because the pointer becames out of range of (mem:HI
(reg87))).  I see this does not happen on x86_64, I will try to see why
tomorrow.

Honza


Re: Do not drom MEM_EXPR when accessing structure fields

2016-09-18 Thread Bernd Edlinger
Hi,

 > when expanding code for
 > struct a {short a,b,c,d;} *a;
 > a->c;
 >
 > we first produce correct BLKmode MEM rtx representing the whole
 > structure *a,
 > then we use adjust_address to turn it into HImode MEM and finally
 > extract_bitfield is used to offset it by 32 bits to get correct value.

I tried to create a test case as follows and stepped thru the code.

cat test.c
struct a {short a,b,c,d;};
void foo (struct a *a)
{
   a->c = 1;
}


First I get a DImode MEM rtx not BLKmode:

(mem:DI (reg/f:DI 87) [2 *a_2(D)+0 S8 A16])

and adjust_address does not clear the MEM_EXPR

thus to_rtx = adjust_address (to_rtx, mode1, 0) returns:


(mem:HI (reg/f:DI 87) [2 *a_2(D)+0 S2 A16])

and then set_mem_attributes_minus_bitpos (to_rtx, to, 0, bitpos) does:

(mem:HI (reg/f:DI 87) [3 a_2(D)->c+-4 S6 A16])

which looks perfectly OK.

But with your patch the RTX looks different:

(mem:DI (reg/f:DI 87) [3 a_2(D)->c+-4 S6 A16])

which looks inconsistent, and not like an improvement.


Especially when the mode of the target_rtx may be used
somewhere in store_field:

   /* If TEMP is not a PARALLEL (see below) and its mode and that of 
TARGET
  are both BLKmode, both must be in memory and BITPOS must be 
aligned
  on a byte boundary.  If so, we simply do a block copy. 
Likewise for
  a BLKmode-like TARGET.  */
   if (GET_CODE (temp) != PARALLEL
   && GET_MODE (temp) == BLKmode
   || (MEM_P (target)
   && GET_MODE_CLASS (GET_MODE (target)) == MODE_INT


and I see store_fixed_bit_field also looks at the memory mode:
   if (MEM_P (op0))
 {
   machine_mode mode = GET_MODE (op0);
   if (GET_MODE_BITSIZE (mode) == 0
   || GET_MODE_BITSIZE (mode) > GET_MODE_BITSIZE (word_mode))
 mode = word_mode;
   mode = get_best_mode (bitsize, bitnum, bitregion_start, 
bitregion_end,
 MEM_ALIGN (op0), mode, MEM_VOLATILE_P (op0));




Bernd.