On 04/24/2015 10:18 AM, Jiong Wang wrote:
2015-04-21  Jiong Wang  <jiong.w...@arm.com>

gcc/
    * loop-invariant.c (find_defs): Enable DF_DU_CHAIN build.
    (vfp_const_iv): New hash table.
    (expensive_addr_check_p): New boolean.
    (init_inv_motion_data): Initialize new variables.>
    (free_inv_motion_data): Release hash table.
    (create_new_invariant): Set cheap_address to false for iv in
    vfp_const_iv table.
    (find_invariant_insn): Skip dependencies check for iv in vfp_const_iv
    table.
    (use_for_single_du): New function.
    (reshuffle_insn_with_vfp): Likewise.
    (find_invariants_bb): Call reshuffle_insn_with_vfp.

gcc/testsuite/
     * gcc.dg/pr62173.c: New testcase.
So ultimately isn't this just a specialized version of reassociation of
pointer arithmetic?  And if so, don't we have all the usual problems
around introducing overflow?


ISTM if this is going to go forward (ie, we somehow convince ourselves
that this kind of reassociation is OK), then should it be made to apply
on pointers in general rather than restricting to stack, frame,
virtual-frame?


Jeff,

   Thanks for the review.

   This transformation is not reassociation of pointer arithmetic.
                            ^^^



   The idea of this patch is, given two instructions with variable value,
   we may get new instruction sequences with fixed value by reassociating
   their operands. And currently GCC only generate such instruction
   sequences for local array accessing as far as I known.
Which is precisely reassociation of pointer arithmetic.

Given:
x = a + b
y = *(x + c)

You're generating:
x = a + c
y = *(x + b)

That's reassociation of pointer arithmetic.

For all kinds of reassociation we have to concern ourselves with adding overflow where it didn't already occur. Assuming a 32 bit architecture we could get overflow if A is 0x7fffffff, b is -4 and and c = 3

0x7fffffff + -4 = 0x7ffffffb
0x7ffffffb + 3 = 0x7ffffffe


If you make the transformation you're suggesting we get

0x7fffffff + 3 = 0x80000002  OVERFLOW
0x80000002 - 4 = 0x7ffffffe

Now if you always know pointers are unsigned, then the overflow is defined and you'd be OK. But that's a property of the target and one that's not well modeled within GCC (we have POINTER_EXTEND_UNSIGNED which kind of tells us something in this space).

In addition to worrying about overflow, you have to worry about segmented architectures with implicit segment selection -- especially if the segment selection comes from the base register than the entire effective address.

On such architectures a + b != b + a when used in a memory reference. The HPPA and mn103 ports immediately come to mind. I'm sure there's at least one more since I recall helping someone with these issues in the past. Anyway

So given
x = a + b;
y = *(x + c)

Can only be transformed into
x = a + c
y = *(x + b)

If and only if a + b would choose the same segment as a + c. On the PA that wouldn't be true for something like

a = 0x4000000
b = 0x10
c = -4

a + b is 0x40000010
a + c is 0x3ffffffc

Those select different segments. Even though the full address is the same (0x4000000c).

Sadly we don't expose this aspect of target characteristics at all.


To proceed, you'd probably need ways to conditionalize these transformations. ie, target hooks.

Jeff

Reply via email to