> 
> The following makes us infer loop bounds for loops like
> 
>  <bb 3>:
>   # str_28 = PHI <"foo"(2), str_10(4)>
> ...
>   str_10 = str_28 + 1;
>   _4 = *str_10;
>   if (_4 != 0)
>     goto <bb 4>;
>   else
>     goto <bb 8>;
> 
>   <bb 4>:
>   goto <bb 3>;
> 
> or
> 
>   <bb 3>:
>   # p_15 = PHI <p_6(3), &a(2)>
>   p_6 = p_15 + 1;
>   *p_15 = 0;
> ...
>   if (n.1_5 > i_8)
>     goto <bb 3>;
>   else
>     goto <bb 4>;
> 
> Boostrap and regtest pending on x86_64-unknown-linux-gnu.
> 
> Honza - is there a symtab way of querying whether DECL_SIZE of
> a decl is "correct"?  I know to better exclude extern decls
> and commons, but for example C++ may have stronger rules.

Not at the moment - you can probably check availability, but that is
not strong enogh.  I can add predicate for that.

Honza
> 
> Thanks,
> Richard.
> 
> 2014-10-16  Richard Biener  <rguent...@suse.de>
> 
>       PR tree-optimization/63278
>       * tree-ssa-loop-niter.c: Include tree-dfa.h.
>       (struct ilb_data): Add pointer to outermost reference.
>       (idx_infer_loop_bounds): Handle plain MEM_REFs of STRING_CSTs
>       and DECLs.
>       (infer_loop_bounds_from_ref): Adjust.
> 
>       * gcc.dg/tree-ssa/loop-41.c: New testcase.
>       * gcc.dg/tree-ssa/loop-42.c: Likewise.
> 
> Index: gcc/tree-ssa-loop-niter.c
> ===================================================================
> --- gcc/tree-ssa-loop-niter.c (revision 216258)
> +++ gcc/tree-ssa-loop-niter.c (working copy)
> @@ -56,6 +56,7 @@ along with GCC; see the file COPYING3.
>  #include "stringpool.h"
>  #include "tree-ssanames.h"
>  #include "wide-int-print.h"
> +#include "tree-dfa.h"
>  
>  
>  #define SWAP(X, Y) do { affine_iv *tmp = (X); (X) = (Y); (Y) = tmp; } while 
> (0)
> @@ -2775,6 +2776,7 @@ struct ilb_data
>  {
>    struct loop *loop;
>    gimple stmt;
> +  tree ref;
>  };
>  
>  static bool
> @@ -2787,7 +2789,10 @@ idx_infer_loop_bounds (tree base, tree *
>    struct loop *loop = data->loop;
>    bool reliable = true;
>  
> -  if (TREE_CODE (base) != ARRAY_REF)
> +  if (TREE_CODE (base) != ARRAY_REF
> +      && (TREE_CODE (base) != MEM_REF
> +       || base != data->ref
> +       || !integer_zerop (TREE_OPERAND (base, 1))))
>      return true;
>  
>    /* For arrays at the end of the structure, we are not guaranteed that they
> @@ -2816,8 +2821,46 @@ idx_infer_loop_bounds (tree base, tree *
>        || chrec_contains_symbols_defined_in_loop (init, loop->num))
>      return true;
>  
> -  low = array_ref_low_bound (base);
> -  high = array_ref_up_bound (base);
> +  if (TREE_CODE (base) == MEM_REF)
> +    {
> +      HOST_WIDE_INT offset;
> +      tree decl;
> +      if (TREE_CODE (init) != ADDR_EXPR)
> +     return true;
> +      decl = get_addr_base_and_unit_offset (TREE_OPERAND (init, 0), &offset);
> +      if (!decl
> +       || offset != 0)
> +     return true;
> +      /* If this is a bare MEM_REF with a pointer IV that starts at
> +         offset zero of an object with known size we can easily compute
> +      an upper bound for the pointer IV.  */
> +      if (TREE_CODE (decl) == STRING_CST)
> +     {
> +       low = size_zero_node;
> +       high = size_int (TREE_STRING_LENGTH (decl));
> +     }
> +      else if (DECL_P (decl)
> +            && ((TREE_STATIC (decl) && !DECL_COMMON (decl))
> +                || auto_var_in_fn_p (decl, cfun->decl)))
> +     {
> +       low = size_zero_node;
> +       if (TREE_CODE (DECL_SIZE_UNIT (decl)) != INTEGER_CST)
> +         return true;
> +       high = DECL_SIZE_UNIT (decl);
> +     }
> +      else
> +     return true;
> +      /* We only require an upper estimate for high.  So only
> +      if we can, subtract the size of the access.  */
> +      if (TREE_CODE (TYPE_SIZE_UNIT (TREE_TYPE (base))) == INTEGER_CST)
> +     high = size_binop (MINUS_EXPR,
> +                        high, TYPE_SIZE_UNIT (TREE_TYPE (base)));
> +    }
> +  else
> +    {
> +      low = array_ref_low_bound (base);
> +      high = array_ref_up_bound (base);
> +    }
>  
>    /* The case of nonconstant bounds could be handled, but it would be
>       complicated.  */
> @@ -2879,6 +2922,7 @@ infer_loop_bounds_from_ref (struct loop
>  
>    data.loop = loop;
>    data.stmt = stmt;
> +  data.ref = ref;
>    for_each_index (&ref, idx_infer_loop_bounds, &data);
>  }
>  
> Index: gcc/testsuite/gcc.dg/tree-ssa/loop-42.c
> ===================================================================
> --- gcc/testsuite/gcc.dg/tree-ssa/loop-42.c   (revision 0)
> +++ gcc/testsuite/gcc.dg/tree-ssa/loop-42.c   (working copy)
> @@ -0,0 +1,19 @@
> +/* { dg-do run } */
> +/* { dg-options "-O2 -fdump-tree-cunroll-details" } */
> +
> +extern void abort (void);
> +int a = -1;
> +int n = sizeof (int);
> +int main()
> +{
> +  char *p;
> +  int i;
> +  for (i = 0, p = (char *)&a; i < n; ++i)
> +    *p++ = 0;
> +  if (a != 0)
> +    abort ();
> +  return 0;
> +}
> +
> +/* { dg-final { scan-tree-dump "loop with 4 iterations completely unrolled" 
> "cunroll" } } */
> +/* { dg-final { cleanup-tree-dump "cunroll" } } */
> Index: gcc/testsuite/gcc.dg/tree-ssa/loop-41.c
> ===================================================================
> --- gcc/testsuite/gcc.dg/tree-ssa/loop-41.c   (revision 0)
> +++ gcc/testsuite/gcc.dg/tree-ssa/loop-41.c   (working copy)
> @@ -0,0 +1,25 @@
> +/* { dg-do run } */
> +/* { dg-options "-O3 -fdump-tree-cunroll-details" } */
> +
> +extern void abort (void);
> +
> +static inline unsigned int hashString2(const char* str)
> +{
> +  unsigned int hash = 5381;
> +  while (*str) {
> +      hash += (hash << 5) + *str;
> +      str++;
> +  }
> +  return hash;
> +}
> +
> +int main()
> +{
> +  unsigned int hash = hashString2("foo");
> +  if (hash != 193491849)
> +    abort ();
> +  return 0;
> +}
> +
> +/* { dg-final { scan-tree-dump "loop with 4 iterations completely unrolled" 
> "cunroll" } } */
> +/* { dg-final { cleanup-tree-dump "cunroll" } } */

Reply via email to