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.


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.

The catch is that adjust_address updates memory attributes, too, and it
sets size to 2 and clears MEM_EXPR on this occasion.  According to Richard
this is only correct behaviour because the size must represent size of memory
load (and thus has meaning only for BLKmodes).

This patch simply drops the original cast, because as far as I can tell
all the following paths that does handle MEM also will update the mode
once the location was correclty offseted. (It is bit hard to follow all
possible paths as it goes down to different ways of bitfield processing,
but if some path is missing and not tested by x86_64 bootstrap, we should
update it to change the mode later).

This significantly improves alignment tracking.

Bootstrapped/regstested x86_64-linux (including Ada), OK?

expr.c (expand_assignment): Do not change memory mode.
Index: expr.c
===
--- expr.c  (revision 240109)
+++ expr.c  (working copy)
@@ -5010,18 +5010,6 @@ expand_assignment (tree to, tree from, b
}
 
   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)
{