Merge with trunk.
authorrsandifo <rsandifo@138bc75d-0d04-0410-961f-82ee72b054a4>
Sat, 9 Nov 2013 13:55:27 +0000 (13:55 +0000)
committerrsandifo <rsandifo@138bc75d-0d04-0410-961f-82ee72b054a4>
Sat, 9 Nov 2013 13:55:27 +0000 (13:55 +0000)
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/branches/wide-int@204616 138bc75d-0d04-0410-961f-82ee72b054a4

60 files changed:
1  2 
gcc/Makefile.in
gcc/asan.c
gcc/builtins.c
gcc/c-family/c-common.c
gcc/c-family/c-cppbuiltin.c
gcc/c-family/c-format.c
gcc/c-family/c-pretty-print.c
gcc/c/c-decl.c
gcc/c/c-parser.c
gcc/c/c-typeck.c
gcc/cfgexpand.c
gcc/config/aarch64/aarch64.c
gcc/config/arc/arc.c
gcc/config/arm/arm.c
gcc/config/i386/i386.c
gcc/config/mips/mips.c
gcc/config/msp430/msp430.c
gcc/config/picochip/picochip.c
gcc/config/rs6000/rs6000.c
gcc/config/sparc/sparc.c
gcc/cp/init.c
gcc/doc/tm.texi
gcc/doc/tm.texi.in
gcc/explow.c
gcc/expr.c
gcc/fold-const.c
gcc/function.c
gcc/gdbinit.in
gcc/gimple-fold.c
gcc/gimplify.c
gcc/go/gofrontend/expressions.cc
gcc/graphite-sese-to-poly.c
gcc/objc/objc-act.c
gcc/print-tree.c
gcc/stmt.c
gcc/target.def
gcc/targhooks.c
gcc/targhooks.h
gcc/trans-mem.c
gcc/tree-affine.c
gcc/tree-affine.h
gcc/tree-core.h
gcc/tree-dfa.c
gcc/tree-object-size.c
gcc/tree-predcom.c
gcc/tree-pretty-print.c
gcc/tree-ssa-ccp.c
gcc/tree-ssa-loop-im.c
gcc/tree-ssa-loop-ivopts.c
gcc/tree-ssa-loop-niter.c
gcc/tree-ssa-pre.c
gcc/tree-vect-data-refs.c
gcc/tree-vect-loop-manip.c
gcc/tree-vect-loop.c
gcc/tree-vect-stmts.c
gcc/tree-vectorizer.h
gcc/tree-vrp.c
gcc/tree.c
gcc/tree.h
gcc/varasm.c

diff --cc gcc/Makefile.in
Simple merge
diff --cc gcc/asan.c
Simple merge
diff --cc gcc/builtins.c
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
diff --cc gcc/c/c-decl.c
Simple merge
Simple merge
Simple merge
diff --cc gcc/cfgexpand.c
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
diff --cc gcc/cp/init.c
Simple merge
diff --cc gcc/doc/tm.texi
@@@ -11494,49 -11500,6 +11494,52 @@@ The support includes the assembler, lin
  The default value of this hook is based on target's libc.
  @end deftypefn
  
+ @deftypefn {Target Hook} void TARGET_ATOMIC_ASSIGN_EXPAND_FENV (tree *@var{hold}, tree *@var{clear}, tree *@var{update})
+ ISO C11 requires atomic compound assignments that may raise floating-point exceptions to raise exceptions corresponding to the arithmetic operation whose result was successfully stored in a compare-and-exchange sequence.  This requires code equivalent to calls to @code{feholdexcept}, @code{feclearexcept} and @code{feupdateenv} to be generated at appropriate points in the compare-and-exchange sequence.  This hook should set @code{*@var{hold}} to an expression equivalent to the call to @code{feholdexcept}, @code{*@var{clear}} to an expression equivalent to the call to @code{feclearexcept} and @code{*@var{update}} to an expression equivalent to the call to @code{feupdateenv}.  The three expressions are @code{NULL_TREE} on entry to the hook and may be left as @code{NULL_TREE} if no code is required in a particular place.  The default implementation leaves all three expressions as @code{NULL_TREE}.  The @code{__atomic_feraiseexcept} function from @code{libatomic} may be of use as part of the code generated in @code{*@var{update}}.
+ @end deftypefn
++
 +@defmac TARGET_SUPPORTS_WIDE_INT
 +
 +On older ports, large integers are stored in @code{CONST_DOUBLE} rtl
 +objects.  Newer ports define @code{TARGET_SUPPORTS_WIDE_INT} to be non
 +zero to indicate that large integers are stored in
 +@code{CONST_WIDE_INT} rtl objects.  The @code{CONST_WIDE_INT} allows
 +very large integer constants to be represented.  @code{CONST_DOUBLE}
 +are limited to twice the size of host's @code{HOST_WIDE_INT}
 +representation.
 +
 +Converting a port mostly requires looking for the places where
 +@code{CONST_DOUBLES} are used with @code{VOIDmode} and replacing that
 +code with code that accesses @code{CONST_WIDE_INT}s.  @samp{"grep -i
 +const_double"} at the port level gets you to 95% of the changes that
 +need to be made.  There are a few places that require a deeper look.
 +
 +@itemize @bullet
 +@item
 +There is no equivalent to @code{hval} and @code{lval} for
 +@code{CONST_WIDE_INT}s.  This would be difficult to express in the md
 +language since there are a variable number of elements.
 +
 +Most ports only check that @code{hval} is either 0 or -1 to see if the
 +value is small.  As mentioned above, this will no longer be necessary
 +since small constants are always @code{CONST_INT}.  Of course there
 +are still a few exceptions, the alpha's constraint used by the zap
 +instruction certainly requires careful examination by C code.
 +However, all the current code does is pass the hval and lval to C
 +code, so evolving the c code to look at the @code{CONST_WIDE_INT} is
 +not really a large change.
 +
 +@item
 +Because there is no standard template that ports use to materialize
 +constants, there is likely to be some futzing that is unique to each
 +port in this code.
 +
 +@item
 +The rtx costs may have to be adjusted to properly account for larger
 +constants that are represented as @code{CONST_WIDE_INT}.
 +@end itemize
 +
 +All and all it does not takes long to convert ports that the
 +maintainer is familiar with.
 +
 +@end defmac
@@@ -8401,49 -8407,4 +8401,50 @@@ and the associated definitions of thos
  
  @hook TARGET_HAS_IFUNC_P
  
+ @hook TARGET_ATOMIC_ASSIGN_EXPAND_FENV
++
 +@defmac TARGET_SUPPORTS_WIDE_INT
 +
 +On older ports, large integers are stored in @code{CONST_DOUBLE} rtl
 +objects.  Newer ports define @code{TARGET_SUPPORTS_WIDE_INT} to be non
 +zero to indicate that large integers are stored in
 +@code{CONST_WIDE_INT} rtl objects.  The @code{CONST_WIDE_INT} allows
 +very large integer constants to be represented.  @code{CONST_DOUBLE}
 +are limited to twice the size of host's @code{HOST_WIDE_INT}
 +representation.
 +
 +Converting a port mostly requires looking for the places where
 +@code{CONST_DOUBLES} are used with @code{VOIDmode} and replacing that
 +code with code that accesses @code{CONST_WIDE_INT}s.  @samp{"grep -i
 +const_double"} at the port level gets you to 95% of the changes that
 +need to be made.  There are a few places that require a deeper look.
 +
 +@itemize @bullet
 +@item
 +There is no equivalent to @code{hval} and @code{lval} for
 +@code{CONST_WIDE_INT}s.  This would be difficult to express in the md
 +language since there are a variable number of elements.
 +
 +Most ports only check that @code{hval} is either 0 or -1 to see if the
 +value is small.  As mentioned above, this will no longer be necessary
 +since small constants are always @code{CONST_INT}.  Of course there
 +are still a few exceptions, the alpha's constraint used by the zap
 +instruction certainly requires careful examination by C code.
 +However, all the current code does is pass the hval and lval to C
 +code, so evolving the c code to look at the @code{CONST_WIDE_INT} is
 +not really a large change.
 +
 +@item
 +Because there is no standard template that ports use to materialize
 +constants, there is likely to be some futzing that is unique to each
 +port in this code.
 +
 +@item
 +The rtx costs may have to be adjusted to properly account for larger
 +constants that are represented as @code{CONST_WIDE_INT}.
 +@end itemize
 +
 +All and all it does not takes long to convert ports that the
 +maintainer is familiar with.
 +
 +@end defmac
diff --cc gcc/explow.c
Simple merge
diff --cc gcc/expr.c
@@@ -4536,19 -4566,18 +4536,18 @@@ get_bit_range (unsigned HOST_WIDE_INT *
       relative to the representative.  DECL_FIELD_OFFSET of field and
       repr are the same by construction if they are not constants,
       see finish_bitfield_layout.  */
 -  if (host_integerp (DECL_FIELD_OFFSET (field), 1)
 -      && host_integerp (DECL_FIELD_OFFSET (repr), 1))
 -    bitoffset = (tree_low_cst (DECL_FIELD_OFFSET (field), 1)
 -               - tree_low_cst (DECL_FIELD_OFFSET (repr), 1)) * BITS_PER_UNIT;
 +  if (tree_fits_uhwi_p (DECL_FIELD_OFFSET (field))
 +      && tree_fits_uhwi_p (DECL_FIELD_OFFSET (repr)))
 +    bitoffset = (tree_to_uhwi (DECL_FIELD_OFFSET (field))
 +               - tree_to_uhwi (DECL_FIELD_OFFSET (repr))) * BITS_PER_UNIT;
    else
      bitoffset = 0;
 -  bitoffset += (tree_low_cst (DECL_FIELD_BIT_OFFSET (field), 1)
 -              - tree_low_cst (DECL_FIELD_BIT_OFFSET (repr), 1));
 +  bitoffset += (tree_to_uhwi (DECL_FIELD_BIT_OFFSET (field))
 +              - tree_to_uhwi (DECL_FIELD_BIT_OFFSET (repr)));
  
    /* If the adjustment is larger than bitpos, we would have a negative bit
-      position for the lower bound and this may wreak havoc later.  This can
-      occur only if we have a non-null offset, so adjust offset and bitpos
-      to make the lower bound non-negative.  */
+      position for the lower bound and this may wreak havoc later.  Adjust
+      offset and bitpos to make the lower bound non-negative in that case.  */
    if (bitoffset > *bitpos)
      {
        HOST_WIDE_INT adjust = bitoffset - *bitpos;
@@@ -8892,9 -8941,20 +8892,23 @@@ pointer_may_wrap_p (tree base, tree off
        size = base_size;
      }
  
 -  return total.low > (unsigned HOST_WIDE_INT) size;
 +  return total.to_uhwi () > (unsigned HOST_WIDE_INT) size;
  }
  
 -  double_int d = tree_to_double_int (t);
 -  return d.sext (TYPE_PRECISION (TREE_TYPE (t))).low;
+ /* Return the HOST_WIDE_INT least significant bits of T, a sizetype
+    kind INTEGER_CST.  This makes sure to properly sign-extend the
+    constant.  */
+ static HOST_WIDE_INT
+ size_low_cst (const_tree t)
+ {
++  HOST_WIDE_INT w = TREE_INT_CST_ELT (t, 0);
++  int prec = TYPE_PRECISION (TREE_TYPE (t));
++  if (prec < HOST_BITS_PER_WIDE_INT)
++    return sext_hwi (w, prec);
++  return w;
+ }
  /* Subroutine of fold_binary.  This routine performs all of the
     transformations that are common to the equality/inequality
     operators (EQ_EXPR and NE_EXPR) and the ordering operators
diff --cc gcc/function.c
Simple merge
diff --cc gcc/gdbinit.in
Simple merge
Simple merge
diff --cc gcc/gimplify.c
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
diff --cc gcc/stmt.c
Simple merge
diff --cc gcc/target.def
Simple merge
diff --cc gcc/targhooks.c
@@@ -272,16 -272,7 +272,6 @@@ default_cxx_guard_type (void
    return long_long_integer_type_node;
  }
  
- /* An implementation of TARGET_CAN_USE_DOLOOP_P for targets that do
-    not support nested low-overhead loops.  */
- bool
- can_use_doloop_if_innermost (const widest_int &, const widest_int &,
-                            unsigned int loop_depth, bool)
- {
-   return loop_depth == 1;
- }
--
  /* Returns the size of the cookie to use when allocating an array
     whose elements have the indicated TYPE.  Assumes that it is already
     known that a cookie is needed.  */
@@@ -1740,5 -1738,14 +1737,14 @@@ default_builtin_chkp_function (unsigne
    return NULL_TREE;
  }
  
 -can_use_doloop_if_innermost (double_int, double_int,
+ /* An implementation of TARGET_CAN_USE_DOLOOP_P for targets that do
+    not support nested low-overhead loops.  */
+ bool
++can_use_doloop_if_innermost (const widest_int &, const widest_int &,
+                            unsigned int loop_depth, bool)
+ {
+   return loop_depth == 1;
+ }
  
  #include "gt-targhooks.h"
diff --cc gcc/targhooks.h
Simple merge
diff --cc gcc/trans-mem.c
Simple merge
@@@ -870,11 -874,12 +870,12 @@@ debug_aff (aff_tree *val
    fprintf (stderr, "\n");
  }
  
- /* Returns address of the reference REF in ADDR.  The size of the accessed
-    location is stored to SIZE.  */
+ /* Computes address of the reference REF in ADDR.  The size of the accessed
+    location is stored to SIZE.  Returns the ultimate containing object to
+    which REF refers.  */
  
- void
+ tree
 -get_inner_reference_aff (tree ref, aff_tree *addr, double_int *size)
 +get_inner_reference_aff (tree ref, aff_tree *addr, widest_int *size)
  {
    HOST_WIDE_INT bitsize, bitpos;
    tree toff;
        aff_combination_add (addr, &tmp);
      }
  
 -  aff_combination_const (&tmp, sizetype,
 -                       double_int::from_shwi (bitpos / BITS_PER_UNIT));
 +  aff_combination_const (&tmp, sizetype, bitpos / BITS_PER_UNIT);
    aff_combination_add (addr, &tmp);
  
 -  *size = double_int::from_shwi ((bitsize + BITS_PER_UNIT - 1) / BITS_PER_UNIT);
 +  *size = (bitsize + BITS_PER_UNIT - 1) / BITS_PER_UNIT;
+   return base;
  }
  
  /* Returns true if a region of size SIZE1 at position 0 and a region of
@@@ -76,10 -74,9 +76,10 @@@ bool aff_combination_constant_multiple_
  void aff_combination_expand (aff_tree *, struct pointer_map_t **);
  void tree_to_aff_combination_expand (tree, tree, aff_tree *,
                                     struct pointer_map_t **);
- void get_inner_reference_aff (tree, aff_tree *, widest_int *);
 -tree get_inner_reference_aff (tree, aff_tree *, double_int *);
++tree get_inner_reference_aff (tree, aff_tree *, widest_int *);
  void free_affine_expand_cache (struct pointer_map_t **);
 -bool aff_comb_cannot_overlap_p (aff_tree *, double_int, double_int);
 +bool aff_comb_cannot_overlap_p (aff_tree *, const widest_int &,
 +                              const widest_int &);
  
  /* Debugging functions.  */
  void debug_aff (aff_tree *);
diff --cc gcc/tree-core.h
Simple merge
diff --cc gcc/tree-dfa.c
@@@ -567,10 -566,10 +567,10 @@@ get_ref_base_and_extent (tree exp, HOST
             padding that is there for alignment purposes.  */
          if (seen_variable_array_ref
              && maxsize != -1
 -            && (!bit_offset.fits_shwi ()
 -                || !host_integerp (TYPE_SIZE (TREE_TYPE (exp)), 1)
 +            && (!wi::fits_shwi_p (bit_offset)
 +                || !tree_fits_uhwi_p (TYPE_SIZE (TREE_TYPE (exp)))
                  || (bit_offset.to_shwi () + maxsize
-                     == (signed) tree_to_uhwi
 -                    == (HOST_WIDE_INT) TREE_INT_CST_LOW
++                    == (HOST_WIDE_INT) tree_to_uhwi
                            (TYPE_SIZE (TREE_TYPE (exp))))))
            maxsize = -1;
  
    /* We need to deal with variable arrays ending structures.  */
    if (seen_variable_array_ref
        && maxsize != -1
 -      && (!bit_offset.fits_shwi ()
 -        || !host_integerp (TYPE_SIZE (TREE_TYPE (exp)), 1)
 +      && (!wi::fits_shwi_p (bit_offset)
 +        || !tree_fits_uhwi_p (TYPE_SIZE (TREE_TYPE (exp)))
          || (bit_offset.to_shwi () + maxsize
-             == (signed) tree_to_uhwi (TYPE_SIZE (TREE_TYPE (exp))))))
 -            == (HOST_WIDE_INT) TREE_INT_CST_LOW
 -                 (TYPE_SIZE (TREE_TYPE (exp))))))
++            == (HOST_WIDE_INT) tree_to_uhwi (TYPE_SIZE (TREE_TYPE (exp))))))
      maxsize = -1;
  
   done:
Simple merge
Simple merge
Simple merge
@@@ -576,8 -575,8 +583,8 @@@ get_value_for_expr (tree expr, bool for
      {
        val.lattice_val = CONSTANT;
        val.value = expr;
 -      val.mask = double_int_zero;
 +      val.mask = 0;
-       canonicalize_float_value (&val);
+       canonicalize_value (&val);
      }
    else if (TREE_CODE (expr) == ADDR_EXPR)
      val = get_value_from_alignment (expr);
Simple merge
@@@ -927,8 -928,26 +928,26 @@@ alloc_iv (tree base, tree step
    struct iv *iv = XCNEW (struct iv);
    gcc_assert (step != NULL_TREE);
  
 -      double_int size;
+   /* Lower all address expressions except ones with DECL_P as operand.
+      By doing this:
+        1) More accurate cost can be computed for address expressions;
+        2) Duplicate candidates won't be created for bases in different
+           forms, like &a[0] and &a.  */
+   STRIP_NOPS (base_object);
+   if (TREE_CODE (base_object) == ADDR_EXPR
+       && !DECL_P (TREE_OPERAND (base_object, 0)))
+     {
+       aff_tree comb;
++      widest_int size;
+       base_object = get_inner_reference_aff (TREE_OPERAND (base_object, 0),
+                                            &comb, &size);
+       gcc_assert (base_object != NULL_TREE);
+       base_object = build_fold_addr_expr (base_object);
+       base = fold_convert (TREE_TYPE (base), aff_combination_to_tree (&comb));
+     }
    iv->base = base;
-   iv->base_object = determine_base_object (base);
+   iv->base_object = determine_base_object (base_object);
    iv->step = step;
    iv->biv_p = false;
    iv->have_use_for = false;
@@@ -45,7 -45,7 +45,8 @@@ along with GCC; see the file COPYING3
  #include "diagnostic-core.h"
  #include "tree-inline.h"
  #include "tree-pass.h"
+ #include "tree-ssanames.h"
 +#include "wide-int-print.h"
  
  
  #define SWAP(X, Y) do { affine_iv *tmp = (X); (X) = (Y); (Y) = tmp; } while (0)
@@@ -116,9 -120,12 +117,12 @@@ split_to_var_and_offset (tree expr, tre
     in TYPE to MIN and MAX.  */
  
  static void
- determine_value_range (tree type, tree var, mpz_t off,
+ determine_value_range (struct loop *loop, tree type, tree var, mpz_t off,
                       mpz_t min, mpz_t max)
  {
 -  double_int minv, maxv;
++  widest_int minv, maxv;
+   enum value_range_type rtype = VR_VARYING;
    /* If the expression is a constant, we know its value exactly.  */
    if (integer_zerop (var))
      {
        return;
      }
  
 -        double_int minc, maxc;
+   get_type_static_bounds (type, min, max);
+   /* See if we have some range info from VRP.  */
+   if (TREE_CODE (var) == SSA_NAME && INTEGRAL_TYPE_P (type))
+     {
+       edge e = loop_preheader_edge (loop);
+       gimple_stmt_iterator gsi;
+       /* Either for VAR itself...  */
+       rtype = get_range_info (var, &minv, &maxv);
+       /* Or for PHI results in loop->header where VAR is used as
+        PHI argument from the loop preheader edge.  */
+       for (gsi = gsi_start_phis (loop->header); !gsi_end_p (gsi); gsi_next (&gsi))
+       {
+         gimple phi = gsi_stmt (gsi);
 -                minv = minv.max (minc, TYPE_UNSIGNED (type));
 -                maxv = maxv.min (maxc, TYPE_UNSIGNED (type));
 -                gcc_assert (minv.cmp (maxv, TYPE_UNSIGNED (type)) <= 0);
++        widest_int minc, maxc;
+         if (PHI_ARG_DEF_FROM_EDGE (phi, e) == var
+             && (get_range_info (gimple_phi_result (phi), &minc, &maxc)
+                 == VR_RANGE))
+           {
+             if (rtype != VR_RANGE)
+               {
+                 rtype = VR_RANGE;
+                 minv = minc;
+                 maxv = maxc;
+               }
+             else
+               {
 -        gcc_assert (minv.cmp (maxv, TYPE_UNSIGNED (type)) <= 0);
++                minv = wi::smax (minv, minc);
++                maxv = wi::smin (maxv, maxc);
++                gcc_assert (wi::les_p (minv, maxv));
+               }
+           }
+       }
+       if (rtype == VR_RANGE)
+       {
+         mpz_t minm, maxm;
 -        mpz_set_double_int (minm, minv, TYPE_UNSIGNED (type));
 -        mpz_set_double_int (maxm, maxv, TYPE_UNSIGNED (type));
++        gcc_assert (wi::les_p (minv, maxv));
+         mpz_init (minm);
+         mpz_init (maxm);
++        wi::to_mpz (minv, minm, SIGNED);
++        wi::to_mpz (maxv, maxm, SIGNED);
+         mpz_add (minm, minm, off);
+         mpz_add (maxm, maxm, off);
+         /* If the computation may not wrap or off is zero, then this
+            is always fine.  If off is negative and minv + off isn't
+            smaller than type's minimum, or off is positive and
+            maxv + off isn't bigger than type's maximum, use the more
+            precise range too.  */
+         if (nowrap_type_p (type)
+             || mpz_sgn (off) == 0
+             || (mpz_sgn (off) < 0 && mpz_cmp (minm, min) >= 0)
+             || (mpz_sgn (off) > 0 && mpz_cmp (maxm, max) <= 0))
+           {
+             mpz_set (min, minm);
+             mpz_set (max, maxm);
+             mpz_clear (minm);
+             mpz_clear (maxm);
+             return;
+           }
+         mpz_clear (minm);
+         mpz_clear (maxm);
+       }
+     }
    /* If the computation may wrap, we know nothing about the value, except for
       the range of the type.  */
-   get_type_static_bounds (type, min, max);
    if (!nowrap_type_p (type))
      return;
  
Simple merge
@@@ -2671,52 -2757,182 +2757,180 @@@ vect_prune_runtime_alias_test_list (loo
      dump_printf_loc (MSG_NOTE, vect_location,
                       "=== vect_prune_runtime_alias_test_list ===\n");
  
-   for (i = 0; i < ddrs.length (); )
+   if (may_alias_ddrs.is_empty ())
+     return true;
+   /* Basically, for each pair of dependent data refs store_ptr_0
+      and load_ptr_0, we create an expression:
+      ((store_ptr_0 + store_segment_length_0) <= load_ptr_0)
+      || (load_ptr_0 + load_segment_length_0) <= store_ptr_0))
+      for aliasing checks.  However, in some cases we can decrease
+      the number of checks by combining two checks into one.  For
+      example, suppose we have another pair of data refs store_ptr_0
+      and load_ptr_1, and if the following condition is satisfied:
+      load_ptr_0 < load_ptr_1  &&
+      load_ptr_1 - load_ptr_0 - load_segment_length_0 < store_segment_length_0
+      (this condition means, in each iteration of vectorized loop,
+      the accessed memory of store_ptr_0 cannot be between the memory
+      of load_ptr_0 and load_ptr_1.)
+      we then can use only the following expression to finish the
+      alising checks between store_ptr_0 & load_ptr_0 and
+      store_ptr_0 & load_ptr_1:
+      ((store_ptr_0 + store_segment_length_0) <= load_ptr_0)
+      || (load_ptr_1 + load_segment_length_1 <= store_ptr_0))
+      Note that we only consider that load_ptr_0 and load_ptr_1 have the
+      same basic address.  */
+   comp_alias_ddrs.create (may_alias_ddrs.length ());
+   /* First, we collect all data ref pairs for aliasing checks.  */
+   FOR_EACH_VEC_ELT (may_alias_ddrs, i, ddr)
      {
-       bool found;
-       ddr_p ddr_i;
+       struct data_reference *dr_a, *dr_b;
+       gimple dr_group_first_a, dr_group_first_b;
+       tree segment_length_a, segment_length_b;
+       gimple stmt_a, stmt_b;
+       dr_a = DDR_A (ddr);
+       stmt_a = DR_STMT (DDR_A (ddr));
+       dr_group_first_a = GROUP_FIRST_ELEMENT (vinfo_for_stmt (stmt_a));
+       if (dr_group_first_a)
+       {
+         stmt_a = dr_group_first_a;
+         dr_a = STMT_VINFO_DATA_REF (vinfo_for_stmt (stmt_a));
+       }
  
-       ddr_i = ddrs[i];
-       found = false;
+       dr_b = DDR_B (ddr);
+       stmt_b = DR_STMT (DDR_B (ddr));
+       dr_group_first_b = GROUP_FIRST_ELEMENT (vinfo_for_stmt (stmt_b));
+       if (dr_group_first_b)
+       {
+         stmt_b = dr_group_first_b;
+         dr_b = STMT_VINFO_DATA_REF (vinfo_for_stmt (stmt_b));
+       }
  
-       for (j = 0; j < i; j++)
-         {
-         ddr_p ddr_j = ddrs[j];
+       if (!operand_equal_p (DR_STEP (dr_a), DR_STEP (dr_b), 0))
+       length_factor = scalar_loop_iters;
+       else
+       length_factor = size_int (vect_factor);
+       segment_length_a = vect_vfa_segment_size (dr_a, length_factor);
+       segment_length_b = vect_vfa_segment_size (dr_b, length_factor);
+       dr_addr_with_seg_len_pair_t dr_with_seg_len_pair
+         (dr_addr_with_seg_len
+              (dr_a, DR_BASE_ADDRESS (dr_a),
+               size_binop (PLUS_EXPR, DR_OFFSET (dr_a), DR_INIT (dr_a)),
+               segment_length_a),
+          dr_addr_with_seg_len
+              (dr_b, DR_BASE_ADDRESS (dr_b),
+               size_binop (PLUS_EXPR, DR_OFFSET (dr_b), DR_INIT (dr_b)),
+               segment_length_b));
+       if (compare_tree (dr_with_seg_len_pair.first.basic_addr,
+                       dr_with_seg_len_pair.second.basic_addr) > 0)
+       swap (dr_with_seg_len_pair.first, dr_with_seg_len_pair.second);
+       comp_alias_ddrs.safe_push (dr_with_seg_len_pair);
+     }
+   /* Second, we sort the collected data ref pairs so that we can scan
+      them once to combine all possible aliasing checks.  */
+   comp_alias_ddrs.qsort (comp_dr_addr_with_seg_len_pair);
  
-         if (vect_vfa_range_equal (ddr_i, ddr_j))
+   /* Third, we scan the sorted dr pairs and check if we can combine
+      alias checks of two neighbouring dr pairs.  */
+   for (size_t i = 1; i < comp_alias_ddrs.length (); ++i)
+     {
+       /* Deal with two ddrs (dr_a1, dr_b1) and (dr_a2, dr_b2).  */
+       dr_addr_with_seg_len *dr_a1 = &comp_alias_ddrs[i-1].first,
+                          *dr_b1 = &comp_alias_ddrs[i-1].second,
+                          *dr_a2 = &comp_alias_ddrs[i].first,
+                          *dr_b2 = &comp_alias_ddrs[i].second;
+       /* Remove duplicate data ref pairs.  */
+       if (*dr_a1 == *dr_a2 && *dr_b1 == *dr_b2)
+       {
+         if (dump_enabled_p ())
            {
-             if (dump_enabled_p ())
-               {
-                 dump_printf_loc (MSG_NOTE, vect_location,
-                                  "found equal ranges ");
-                 dump_generic_expr (MSG_NOTE, TDF_SLIM,
-                                    DR_REF (DDR_A (ddr_i)));
-                 dump_printf (MSG_NOTE,  ", ");
-                 dump_generic_expr (MSG_NOTE, TDF_SLIM,
-                                    DR_REF (DDR_B (ddr_i)));
-                 dump_printf (MSG_NOTE,  " and ");
-                 dump_generic_expr (MSG_NOTE, TDF_SLIM,
-                                    DR_REF (DDR_A (ddr_j)));
-                 dump_printf (MSG_NOTE,  ", ");
-                 dump_generic_expr (MSG_NOTE, TDF_SLIM,
-                                    DR_REF (DDR_B (ddr_j)));
-                 dump_printf (MSG_NOTE, "\n");
-               }
-             found = true;
-             break;
+             dump_printf_loc (MSG_NOTE, vect_location,
+                              "found equal ranges ");
+             dump_generic_expr (MSG_NOTE, TDF_SLIM,
+                                DR_REF (dr_a1->dr));
+             dump_printf (MSG_NOTE,  ", ");
+             dump_generic_expr (MSG_NOTE, TDF_SLIM,
+                                DR_REF (dr_b1->dr));
+             dump_printf (MSG_NOTE,  " and ");
+             dump_generic_expr (MSG_NOTE, TDF_SLIM,
+                                DR_REF (dr_a2->dr));
+             dump_printf (MSG_NOTE,  ", ");
+             dump_generic_expr (MSG_NOTE, TDF_SLIM,
+                                DR_REF (dr_b2->dr));
+             dump_printf (MSG_NOTE, "\n");
            }
+         comp_alias_ddrs.ordered_remove (i--);
+         continue;
        }
  
-       if (found)
-       {
-       ddrs.ordered_remove (i);
-       continue;
-       }
-       i++;
+       if (*dr_a1 == *dr_a2 || *dr_b1 == *dr_b2)
+       {
+         /* We consider the case that DR_B1 and DR_B2 are same memrefs,
+            and DR_A1 and DR_A2 are two consecutive memrefs.  */
+         if (*dr_a1 == *dr_a2)
+           {
+             swap (dr_a1, dr_b1);
+             swap (dr_a2, dr_b2);
+           }
+         if (!operand_equal_p (dr_a1->basic_addr, dr_a2->basic_addr, 0)
 -            || !host_integerp (dr_a1->offset, 0)
 -            || !host_integerp (dr_a2->offset, 0))
++            || !tree_fits_shwi_p (dr_a1->offset)
++            || !tree_fits_shwi_p (dr_a2->offset))
+           continue;
 -        HOST_WIDE_INT diff = TREE_INT_CST_LOW (dr_a2->offset) -
 -                             TREE_INT_CST_LOW (dr_a1->offset);
++        HOST_WIDE_INT diff = (tree_to_shwi (dr_a2->offset)
++                              - tree_to_shwi (dr_a1->offset));
+         /* Now we check if the following condition is satisfied:
+            DIFF - SEGMENT_LENGTH_A < SEGMENT_LENGTH_B
+            where DIFF = DR_A2->OFFSET - DR_A1->OFFSET.  However,
+            SEGMENT_LENGTH_A or SEGMENT_LENGTH_B may not be constant so we
+            have to make a best estimation.  We can get the minimum value
+            of SEGMENT_LENGTH_B as a constant, represented by MIN_SEG_LEN_B,
+            then either of the following two conditions can guarantee the
+            one above:
+            1: DIFF <= MIN_SEG_LEN_B
+            2: DIFF - SEGMENT_LENGTH_A < MIN_SEG_LEN_B
+            */
 -        HOST_WIDE_INT
 -        min_seg_len_b = (TREE_CODE (dr_b1->seg_len) == INTEGER_CST) ?
 -                            TREE_INT_CST_LOW (dr_b1->seg_len) :
 -                            vect_factor;
++        HOST_WIDE_INT  min_seg_len_b = (tree_fits_shwi_p (dr_b1->seg_len)
++                                        ? tree_to_shwi (dr_b1->seg_len)
++                                        : vect_factor);
+         if (diff <= min_seg_len_b
 -            || (TREE_CODE (dr_a1->seg_len) == INTEGER_CST
 -                && diff - (HOST_WIDE_INT) TREE_INT_CST_LOW (dr_a1->seg_len) <
 -                   min_seg_len_b))
++            || (tree_fits_shwi_p (dr_a1->seg_len)
++                && diff - tree_to_shwi (dr_a1->seg_len) < min_seg_len_b))
+           {
+             dr_a1->seg_len = size_binop (PLUS_EXPR,
+                                          dr_a2->seg_len, size_int (diff));
+             comp_alias_ddrs.ordered_remove (i--);
+           }
+       }
      }
  
-   if (ddrs.length () >
-        (unsigned) PARAM_VALUE (PARAM_VECT_MAX_VERSION_FOR_ALIAS_CHECKS))
+   if ((int) comp_alias_ddrs.length () >
+       PARAM_VALUE (PARAM_VECT_MAX_VERSION_FOR_ALIAS_CHECKS))
      {
        if (dump_enabled_p ())
        {
Simple merge
Simple merge
Simple merge
Simple merge
diff --cc gcc/tree-vrp.c
@@@ -1986,16 -1973,15 +1968,16 @@@ vrp_int_const_binop (enum tree_code cod
     the bit is 1, otherwise it might be 0 or 1.  */
  
  static bool
 -zero_nonzero_bits_from_vr (value_range_t *vr,
 -                         double_int *may_be_nonzero,
 -                         double_int *must_be_nonzero)
 +zero_nonzero_bits_from_vr (const tree expr_type,
 +                         value_range_t *vr,
 +                         wide_int *may_be_nonzero,
 +                         wide_int *must_be_nonzero)
  {
 -  *may_be_nonzero = double_int_minus_one;
 -  *must_be_nonzero = double_int_zero;
 +  *may_be_nonzero = wi::minus_one (TYPE_PRECISION (expr_type));
 +  *must_be_nonzero = wi::zero (TYPE_PRECISION (expr_type));
    if (!range_int_cst_p (vr)
-       || TREE_OVERFLOW (vr->min)
-       || TREE_OVERFLOW (vr->max))
+       || is_overflow_infinity (vr->min)
+       || is_overflow_infinity (vr->max))
      return false;
  
    if (range_int_cst_singleton_p (vr))
diff --cc gcc/tree.c
@@@ -589,85 -588,9 +589,9 @@@ decl_assembler_name (tree decl
    return DECL_WITH_VIS_CHECK (decl)->decl_with_vis.assembler_name;
  }
  
- /* Compare ASMNAME with the DECL_ASSEMBLER_NAME of DECL.  */
- bool
- decl_assembler_name_equal (tree decl, const_tree asmname)
- {
-   tree decl_asmname = DECL_ASSEMBLER_NAME (decl);
-   const char *decl_str;
-   const char *asmname_str;
-   bool test = false;
-   if (decl_asmname == asmname)
-     return true;
-   decl_str = IDENTIFIER_POINTER (decl_asmname);
-   asmname_str = IDENTIFIER_POINTER (asmname);
-   /* If the target assembler name was set by the user, things are trickier.
-      We have a leading '*' to begin with.  After that, it's arguable what
-      is the correct thing to do with -fleading-underscore.  Arguably, we've
-      historically been doing the wrong thing in assemble_alias by always
-      printing the leading underscore.  Since we're not changing that, make
-      sure user_label_prefix follows the '*' before matching.  */
-   if (decl_str[0] == '*')
-     {
-       size_t ulp_len = strlen (user_label_prefix);
-       decl_str ++;
-       if (ulp_len == 0)
-       test = true;
-       else if (strncmp (decl_str, user_label_prefix, ulp_len) == 0)
-       decl_str += ulp_len, test=true;
-       else
-       decl_str --;
-     }
-   if (asmname_str[0] == '*')
-     {
-       size_t ulp_len = strlen (user_label_prefix);
-       asmname_str ++;
-       if (ulp_len == 0)
-       test = true;
-       else if (strncmp (asmname_str, user_label_prefix, ulp_len) == 0)
-       asmname_str += ulp_len, test=true;
-       else
-       asmname_str --;
-     }
-   if (!test)
-     return false;
-   return strcmp (decl_str, asmname_str) == 0;
- }
- /* Hash asmnames ignoring the user specified marks.  */
- hashval_t
- decl_assembler_name_hash (const_tree asmname)
- {
-   if (IDENTIFIER_POINTER (asmname)[0] == '*')
-     {
-       const char *decl_str = IDENTIFIER_POINTER (asmname) + 1;
-       size_t ulp_len = strlen (user_label_prefix);
-       if (ulp_len == 0)
-       ;
-       else if (strncmp (decl_str, user_label_prefix, ulp_len) == 0)
-       decl_str += ulp_len;
-       return htab_hash_string (decl_str);
-     }
-   return htab_hash_string (IDENTIFIER_POINTER (asmname));
- }
  /* Compute the number of bytes occupied by a tree with code CODE.
     This function cannot be used for nodes that have variable sizes,
 -   including TREE_VEC, STRING_CST, and CALL_EXPR.  */
 +   including TREE_VEC, INTEGER_CST, STRING_CST, and CALL_EXPR.  */
  size_t
  tree_code_size (enum tree_code code)
  {
@@@ -6245,6 -6084,48 +6094,48 @@@ check_aligned_type (const_tree cand, co
                                   TYPE_ATTRIBUTES (base)));
  }
  
 -  HOST_WIDE_INT type_size = tree_low_cst (TYPE_SIZE (type), 1);
+ /* This function checks to see if TYPE matches the size one of the built-in 
+    atomic types, and returns that core atomic type.  */
+ static tree
+ find_atomic_core_type (tree type)
+ {
+   tree base_atomic_type;
+   /* Only handle complete types.  */
+   if (TYPE_SIZE (type) == NULL_TREE)
+     return NULL_TREE;
++  HOST_WIDE_INT type_size = tree_to_uhwi (TYPE_SIZE (type));
+   switch (type_size)
+     {
+     case 8:
+       base_atomic_type = atomicQI_type_node;
+       break;
+     case 16:
+       base_atomic_type = atomicHI_type_node;
+       break;
+     case 32:
+       base_atomic_type = atomicSI_type_node;
+       break;
+     case 64:
+       base_atomic_type = atomicDI_type_node;
+       break;
+     case 128:
+       base_atomic_type = atomicTI_type_node;
+       break;
+     default:
+       base_atomic_type = NULL_TREE;
+     }
+   return base_atomic_type;
+ }
  /* Return a version of the TYPE, qualified as indicated by the
     TYPE_QUALS, if one exists.  If no qualified version exists yet,
     return NULL_TREE.  */
@@@ -7026,23 -6938,45 +6930,9 @@@ tree_int_cst_lt (const_tree t1, const_t
  int
  tree_int_cst_compare (const_tree t1, const_tree t2)
  {
 -  if (tree_int_cst_lt (t1, t2))
 -    return -1;
 -  else if (tree_int_cst_lt (t2, t1))
 -    return 1;
 -  else
 -    return 0;
 -}
 -
 -/* Return 1 if T is an INTEGER_CST that can be manipulated efficiently on
 -   the host.  If POS is zero, the value can be represented in a single
 -   HOST_WIDE_INT.  If POS is nonzero, the value must be non-negative and can
 -   be represented in a single unsigned HOST_WIDE_INT.  */
 -
 -int
 -host_integerp (const_tree t, int pos)
 -{
 -  if (t == NULL_TREE)
 -    return 0;
 -
 -  return (TREE_CODE (t) == INTEGER_CST
 -        && ((TREE_INT_CST_HIGH (t) == 0
 -             && (HOST_WIDE_INT) TREE_INT_CST_LOW (t) >= 0)
 -            || (! pos && TREE_INT_CST_HIGH (t) == -1
 -                && (HOST_WIDE_INT) TREE_INT_CST_LOW (t) < 0
 -                && !TYPE_UNSIGNED (TREE_TYPE (t)))
 -            || (pos && TREE_INT_CST_HIGH (t) == 0)));
 -}
 -
 -/* Return the HOST_WIDE_INT least significant bits of T if it is an
 -   INTEGER_CST and there is no overflow.  POS is nonzero if the result must
 -   be non-negative.  We must be able to satisfy the above conditions.  */
 -
 -HOST_WIDE_INT
 -tree_low_cst (const_tree t, int pos)
 -{
 -  gcc_assert (host_integerp (t, pos));
 -  return TREE_INT_CST_LOW (t);
 +  return wi::cmps (wi::to_widest (t1), wi::to_widest (t2));
  }
  
- /* Return the HOST_WIDE_INT least significant bits of T, a sizetype
-    kind INTEGER_CST.  This makes sure to properly sign-extend the
-    constant.  */
- HOST_WIDE_INT
- size_low_cst (const_tree t)
- {
-   HOST_WIDE_INT w = TREE_INT_CST_ELT (t, 0);
-   int prec = TYPE_PRECISION (TREE_TYPE (t));
-   if (prec < HOST_BITS_PER_WIDE_INT)
-     return sext_hwi (w, prec);
-   return w;
- }
  /* Return the most significant (sign) bit of T.  */
  
  int
@@@ -7092,27 -7035,9 +6982,9 @@@ tree_int_cst_min_precision (tree value
    if (integer_zerop (value))
      return 1;
    else
 -    return tree_floor_log2 (value) + 1 + !unsignedp;
 +    return tree_floor_log2 (value) + 1 + (sgn == SIGNED ? 1 : 0) ;
  }
  
- /* Compare two constructor-element-type constants.  Return 1 if the lists
-    are known to be equal; otherwise return 0.  */
- int
- simple_cst_list_equal (const_tree l1, const_tree l2)
- {
-   while (l1 != NULL_TREE && l2 != NULL_TREE)
-     {
-       if (simple_cst_equal (TREE_VALUE (l1), TREE_VALUE (l2)) != 1)
-       return 0;
-       l1 = TREE_CHAIN (l1);
-       l2 = TREE_CHAIN (l2);
-     }
-   return l1 == l2;
- }
  /* Return truthvalue of whether T1 is the same tree structure as T2.
     Return 1 if they are the same.
     Return 0 if they are understandably different.
@@@ -12406,4 -12224,23 +12085,22 @@@ get_tree_code_name (enum tree_code code
    return tree_code_name[code];
  }
  
 -    return build_int_cst_wide (TREE_TYPE (t),
 -                             TREE_INT_CST_LOW (t), TREE_INT_CST_HIGH (t));
+ /* Drops the TREE_OVERFLOW flag from T.  */
+ tree
+ drop_tree_overflow (tree t)
+ {
+   gcc_checking_assert (TREE_OVERFLOW (t));
+   /* For tree codes with a sharing machinery re-build the result.  */
+   if (TREE_CODE (t) == INTEGER_CST)
++    return wide_int_to_tree (TREE_TYPE (t), t);
+   /* Otherwise, as all tcc_constants are possibly shared, copy the node
+      and drop the flag.  */
+   t = copy_node (t);
+   TREE_OVERFLOW (t) = 0;
+   return t;
+ }
  #include "gt-tree.h"
diff --cc gcc/tree.h
@@@ -3824,10 -3647,23 +3836,9 @@@ extern int attribute_list_contained (co
  extern int tree_int_cst_equal (const_tree, const_tree);
  extern int tree_int_cst_lt (const_tree, const_tree);
  extern int tree_int_cst_compare (const_tree, const_tree);
- extern HOST_WIDE_INT size_low_cst (const_tree);
 -extern int host_integerp (const_tree, int)
 -#ifndef ENABLE_TREE_CHECKING
 -  ATTRIBUTE_PURE /* host_integerp is pure only when checking is disabled.  */
 -#endif
 -  ;
 -extern HOST_WIDE_INT tree_low_cst (const_tree, int);
 -#if !defined ENABLE_TREE_CHECKING && (GCC_VERSION >= 4003)
 -extern inline __attribute__ ((__gnu_inline__)) HOST_WIDE_INT
 -tree_low_cst (const_tree t, int pos)
 -{
 -  gcc_assert (host_integerp (t, pos));
 -  return TREE_INT_CST_LOW (t);
 -}
 -#endif
  extern int tree_int_cst_sgn (const_tree);
  extern int tree_int_cst_sign_bit (const_tree);
 -extern unsigned int tree_int_cst_min_precision (tree, bool);
 +extern unsigned int tree_int_cst_min_precision (tree, signop);
  extern bool tree_expr_nonnegative_p (tree);
  extern bool tree_expr_nonnegative_warnv_p (tree, bool *);
  extern bool may_negate_without_overflow_p (const_tree);
diff --cc gcc/varasm.c
Simple merge