On Thu, Apr 28, 2016 at 2:56 PM, Bin Cheng <bin.ch...@arm.com> wrote:
> Hi,
> Tree if-conversion sometimes cannot convert conditional array reference into 
> unconditional one.  Root cause is GCC conservatively assumes newly introduced 
> array reference could be out of array bound and thus trapping.  This patch 
> improves the situation by proving the converted unconditional array reference 
> is within array bound using loop niter information.  To be specific, it 
> checks every index of array reference to see if it's within bound in 
> ifcvt_memrefs_wont_trap.  This patch also factors out base_object_writable 
> checking if the base object is writable or not.
> Bootstrap and test on x86_64 and aarch64, is it OK?

I think you miss to handle the case optimally where the only
non-ARRAY_REF idx is the dereference of the
base-pointer for, say, p->a[i].  In this case we can use
base_master_dr to see if p is unconditionally dereferenced
in the loop.  You also fail to handle the case where we have
MEM_REF[&x].a[i] that is, you see a decl base.
I suppose for_each_index should be fixed for this particular case (to
return true), same for TARGET_MEM_REF TMR_BASE.

+  /* The case of nonconstant bounds could be handled, but it would be
+     complicated.  */
+  if (TREE_CODE (low) != INTEGER_CST || !integer_zerop (low)
+      || !high || TREE_CODE (high) != INTEGER_CST)
+    return false;
+

handling of a non-zero but constant low bound is important - otherwise
all this is a no-op for Fortran.  It
shouldn't be too difficult to handle after all.  In fact I think your
code does handle it correctly already.

+  if (!init || TREE_CODE (init) != INTEGER_CST
+      || !step || TREE_CODE (step) != INTEGER_CST || integer_zerop (step))
+    return false;

step == 0 should be easy to handle as well, no?  The index will simply
always be 'init' ...

+  /* In case the relevant bound of the array does not fit in type, or
+     it does, but bound + step (in type) still belongs into the range of the
+     array, the index may wrap and still stay within the range of the array
+     (consider e.g. if the array is indexed by the full range of
+     unsigned char).
+
+     To make things simpler, we require both bounds to fit into type, although
+     there are cases where this would not be strictly necessary.  */
+  if (!int_fits_type_p (high, type) || !int_fits_type_p (low, type))
+    return false;
+
+  low = fold_convert (type, low);

please use wide_int for all of this.

I wonder if we can do sth for wrapping IVs like

int a[2048];

for (int i = 0; i < 4096; ++i)
  ... a[(unsigned char)i];

as well.  Like if the IVs type max and min value are within the array bounds
simply return true?

Thanks,
Richard.

> Thanks,
> bin
>
> 2016-04-28  Bin Cheng  <bin.ch...@arm.com>
>
>         * tree-if-conv.c (tree-ssa-loop.h): Include header file.
>         (tree-ssa-loop-niter.h): Ditto.
>         (idx_within_array_bound, ref_within_array_bound): New functions.
>         (ifcvt_memrefs_wont_trap): Check if array ref is within bound.
>         Factor out check on writable base object to ...
>         (base_object_writable): ... here.

Reply via email to