On Thu, Sep 24, 2015 at 11:07 AM, Simon Dardis <simon.dar...@imgtec.com> wrote:
> It seems to me that extending operand_equal_p to deal with the
> MEM_REF/ARRAY_REF case could help.
>
> Your recent change of:
>
>           if (TREE_CODE (arg0) == MEM_REF
>               && DECL_P (arg1)
>               && TREE_CODE (TREE_OPERAND (arg0, 0)) == ADDR_EXPR
>               && TREE_OPERAND (TREE_OPERAND (arg0, 0), 0) == arg1
>               && integer_zerop (TREE_OPERAND (arg0, 1)))
>             return 1;
>           else if (TREE_CODE (arg1) == MEM_REF
>                    && DECL_P (arg0)
>                    && TREE_CODE (TREE_OPERAND (arg1, 0)) == ADDR_EXPR
>                    && TREE_OPERAND (TREE_OPERAND (arg1, 0), 0) == arg0
>                    && integer_zerop (TREE_OPERAND (arg1, 1)))
>             return 1;
>           return 0;
>
> only seems to be handing the case of 'X' and MEM_REF[&X + 0]. Do you think
> changing this to be 'return addr_eq_p (arg0, arg1);' where addr_eq_p handles
> cases of ARRAY_(RANGED_)REF, COMPONENT_REF by checking offset as well
> would be useful?

Yes, I think so.  Note that a more general addr_eq_p implementation would
simply use get_inner_reference and compare the results (its implementation
has the drawback of building GENERIC expression trees for non-constant
offset parts, there is also get_addr_base_and_unit_offset which avoids this
but cannot handle non-constant offsets).

Note the caller I did the change above for would also be happy knowing
about offsetted (with known constant offset) bases.

> I've put together an initial version which splits out change to 
> operand_equal_p
> into its own predicate for just IDing cases of base objects and the above
> mentioned addr_eq_p. Also in that patch is the change for mem_attrs_eq_p as
> in that case the offset is not part of the TREE expression, so it has to be 
> handled
> differently.
>
> Thoughts?

   return (p->alias == q->alias
-         && p->offset_known_p == q->offset_known_p
-         && (!p->offset_known_p || p->offset == q->offset)
+         && offsets_eq_p (p, q)

previous code treated both !offset_known_p as 'true', you're now treating it as
'false'.  I think the function really tests for equality of mem_attrs and thus
all callers need to be audited on whether they really need equal mem_attrs
or just partly equal bits.  Thus I think changing mem_attrs_eq is dangerous.

@@ -334,7 +366,8 @@
          && p->addrspace == q->addrspace
          && (p->expr == q->expr
              || (p->expr != NULL_TREE && q->expr != NULL_TREE
-                 && operand_equal_p (p->expr, q->expr, 0))));
+                 && (operand_equal_p (p->expr, q->expr, 0)
+                     || base_object_eq_p (p->expr, q->expr)))));

you can just pass OEP_ADDRESS_OF to operand_equal_p then, no?
So no need to export base_object_eq_p.

Why did you need offsets_eq_p at all?

+  if (p->expr != NULL_TREE && q->expr != NULL_TREE)
+    {
+      if (TREE_CODE (p->expr) == MEM_REF)
+       {
+         if (TREE_CODE (TREE_OPERAND (p->expr, 1)) == INTEGER_CST)
+           return !compare_tree_int (TREE_OPERAND (p->expr, 1), q->offset);

MEM_REF operand 1 is always an INTEGER_CST btw.  Also p can still
have a non-zero p->offset so you can't just compare the MEM_REF offset
with q->offset and be done.  In fact the MEM_REF offset has no relation
to the MEM_ATTR offset so I'm not sure how to make sense of that function.

Richard.

> Thanks,
> Simon
>
> -----Original Message-----
> From: Richard Biener [mailto:richard.guent...@gmail.com]
> Sent: 22 September 2015 12:12
> To: Simon Dardis
> Cc: Jeff Law; gcc@gcc.gnu.org
> Subject: Re: Predictive commoning leads to register to register moves through 
> memory.
>
> On Tue, Sep 22, 2015 at 12:45 PM, Simon Dardis <simon.dar...@imgtec.com> 
> wrote:
>> I took an attempt at addressing this through the RTL GCSE pass. This
>> attempt tweaks mem_attrs_eq_p to return true if its comparing something like 
>> poly+8 and MEM [&poly + 8].
>>
>> Is this a more suitable approach?
>
> I actually recently modified stmt_kills_ref_p for a similar reason...
> not that I liked that vey much.
> I think the more suitable approach would be to not have both forms if they 
> are actually equal.
> Of course that's way more work.
>
> So splitting out a function that handles sematic equality compare of MEM_EXPR 
> sounds good to me.
> No comments on your actual implementation yet, but I think we should do it in 
> a way to be re-usable by stmt_kills_ref_p.
>
> Richard.
>
>
>> Thanks,
>> Simon
>>
>> +/* Return true if p and q reference the same location by the same name but
>> +   through VAR_DECL and MEM_REF.  */
>> +
>> +static bool
>> +mem_locations_match_p (const struct mem_attrs *p, const struct
>> +mem_attrs *q) {
>> +  HOST_WIDE_INT var_offset;
>> +  tree var, memref;
>> +
>> +  if (p->expr == NULL_TREE || q->expr == NULL_TREE)
>> +    return false;
>> +
>> +  if (TREE_CODE (p->expr) == MEM_REF && TREE_CODE (q->expr) == VAR_DECL)
>> +    {
>> +      var = q->expr;
>> +      var_offset = q->offset;
>> +      memref = p->expr;
>> +    }
>> +  else if (TREE_CODE (q->expr) == MEM_REF && TREE_CODE (p->expr) == 
>> VAR_DECL)
>> +    {
>> +      var = p->expr;
>> +      var_offset = p->offset;
>> +      memref = q->expr;
>> +    }
>> +  else
>> +    return false;
>> +
>> +  if (TREE_OPERAND (TREE_OPERAND (memref, 0), 0) != var)
>> +    return false;
>> +
>> +  if (TREE_TYPE (TREE_TYPE (var)) != TREE_TYPE (memref))
>> +    return false;
>> +
>> +  tree offset = TREE_OPERAND (memref, 1);  if ((TREE_CODE (offset) ==
>> + INTEGER_CST && tree_fits_shwi_p (offset)
>> +      && tree_to_shwi (offset) == var_offset)
>> +      || offset == NULL_TREE && var_offset == 0)
>> +    return true;
>> +
>> +  return false;
>> +
>> +}
>> +
>> /* Return true if the given memory attributes are equal.  */
>>
>>  bool
>> @@ -254,16 +298,16 @@ mem_attrs_eq_p (const struct mem_attrs *p, const 
>> struct mem_attrs *q)
>>      return false;
>>    return (p->alias == q->alias
>>           && p->offset_known_p == q->offset_known_p
>> -         && (!p->offset_known_p || p->offset == q->offset)
>>           && p->size_known_p == q->size_known_p
>>           && (!p->size_known_p || p->size == q->size)
>>           && p->align == q->align
>>           && p->addrspace == q->addrspace
>> -         && (p->expr == q->expr
>> -             || (p->expr != NULL_TREE && q->expr != NULL_TREE
>> -                 && operand_equal_p (p->expr, q->expr, 0))));
>> +         && (mem_locations_match_p (p, q)
>> +            || (!p->offset_known_p || p->offset == q->offset)
>> +                && (p->expr == q->expr
>> +                    || (p->expr != NULL_TREE && q->expr != NULL_TREE
>> +                        && operand_equal_p (p->expr, q->expr, 0)))));
>>  }

Reply via email to