Index: gcc/tree-dfa.c
===================================================================
--- gcc/tree-dfa.c	(revision 163094)
+++ gcc/tree-dfa.c	(working copy)
@@ -708,7 +708,7 @@ get_ref_base_and_extent (tree exp, HOST_
   HOST_WIDE_INT bitsize = -1;
   HOST_WIDE_INT maxsize = -1;
   tree size_tree = NULL_TREE;
-  HOST_WIDE_INT bit_offset = 0;
+  double_int bit_offset = double_int_zero;
   bool seen_variable_array_ref = false;
 
   /* First get the final access size from just the outermost expression.  */
@@ -743,7 +743,9 @@ get_ref_base_and_extent (tree exp, HOST_
       switch (TREE_CODE (exp))
 	{
 	case BIT_FIELD_REF:
-	  bit_offset += TREE_INT_CST_LOW (TREE_OPERAND (exp, 2));
+	  bit_offset
+	    = double_int_add (bit_offset,
+			      tree_to_double_int (TREE_OPERAND (exp, 2)));
 	  break;
 
 	case COMPONENT_REF:
@@ -751,15 +753,24 @@ get_ref_base_and_extent (tree exp, HOST_
 	    tree field = TREE_OPERAND (exp, 1);
 	    tree this_offset = component_ref_field_offset (exp);
 
-	    if (this_offset
-		&& TREE_CODE (this_offset) == INTEGER_CST
-		&& host_integerp (this_offset, 0))
+	    /* We should not call get_ref_base_and_extent on
+	       not layouted fields.  */
+	    if (!this_offset)
+	      gcc_unreachable ();
+
+	    if (TREE_CODE (this_offset) == INTEGER_CST)
 	      {
-		HOST_WIDE_INT hthis_offset = TREE_INT_CST_LOW (this_offset);
-		hthis_offset *= BITS_PER_UNIT;
+		double_int hthis_offset = tree_to_double_int (this_offset);
+		hthis_offset
+		  = double_int_lshift (hthis_offset,
+				       BITS_PER_UNIT == 8
+				       ? 3 : exact_log2 (BITS_PER_UNIT),
+				       HOST_BITS_PER_DOUBLE_INT, true);
 		hthis_offset
-		  += TREE_INT_CST_LOW (DECL_FIELD_BIT_OFFSET (field));
-		bit_offset += hthis_offset;
+		  = double_int_add (hthis_offset,
+				    tree_to_double_int
+				      (DECL_FIELD_BIT_OFFSET (field)));
+		bit_offset = double_int_add (bit_offset, hthis_offset);
 
 		/* If we had seen a variable array ref already and we just
 		   referenced the last field of a struct or a union member
@@ -777,11 +788,26 @@ get_ref_base_and_extent (tree exp, HOST_
 		      {
 			tree fsize = DECL_SIZE_UNIT (field);
 			tree ssize = TYPE_SIZE_UNIT (stype);
-			if (host_integerp (fsize, 0)
-			    && host_integerp (ssize, 0))
-			  maxsize += ((TREE_INT_CST_LOW (ssize)
-				       - TREE_INT_CST_LOW (fsize))
-				      * BITS_PER_UNIT - hthis_offset);
+			if (fsize && TREE_CODE (fsize) == INTEGER_CST
+			    && ssize && TREE_CODE (ssize) == INTEGER_CST)
+			  {
+			    double_int tem;
+			    tem = double_int_sub (tree_to_double_int (ssize),
+						  tree_to_double_int (fsize));
+			    tem = double_int_lshift (tem,
+						     BITS_PER_UNIT == 8
+						     ? 3 : exact_log2
+						             (BITS_PER_UNIT),
+						     HOST_BITS_PER_DOUBLE_INT,
+						     true);
+			    tem = double_int_sub (tem, hthis_offset);
+			    tem = double_int_add (shwi_to_double_int (maxsize),
+						  tem);
+			    if (double_int_fits_in_shwi_p (tem))
+			      maxsize = double_int_to_shwi (tem);
+			    else
+			      maxsize = -1;
+			  }
 			else
 			  maxsize = -1;
 		      }
@@ -793,8 +819,15 @@ get_ref_base_and_extent (tree exp, HOST_
 		/* We need to adjust maxsize to the whole structure bitsize.
 		   But we can subtract any constant offset seen so far,
 		   because that would get us out of the structure otherwise.  */
-		if (maxsize != -1 && csize && host_integerp (csize, 1))
-		  maxsize = TREE_INT_CST_LOW (csize) - bit_offset;
+		if (maxsize != -1 && csize && TREE_CODE (csize) == INTEGER_CST)
+		  {
+		    double_int tem
+		      = double_int_sub (tree_to_double_int (csize), bit_offset);
+		    if (double_int_fits_in_shwi_p (tem))
+		      maxsize = double_int_to_shwi (tem);
+		    else
+		      maxsize = -1;
+		  }
 		else
 		  maxsize = -1;
 	      }
@@ -809,18 +842,22 @@ get_ref_base_and_extent (tree exp, HOST_
 
 	    /* If the resulting bit-offset is constant, track it.  */
 	    if (TREE_CODE (index) == INTEGER_CST
-		&& host_integerp (index, 0)
 		&& (low_bound = array_ref_low_bound (exp),
-		    host_integerp (low_bound, 0))
+		    TREE_CODE (low_bound) == INTEGER_CST
 		&& (unit_size = array_ref_element_size (exp),
-		    host_integerp (unit_size, 1)))
+		    TREE_CODE (unit_size) == INTEGER_CST)))
 	      {
-		HOST_WIDE_INT hindex = TREE_INT_CST_LOW (index);
+		double_int hindex = tree_to_double_int (index);
 
-		hindex -= TREE_INT_CST_LOW (low_bound);
-		hindex *= TREE_INT_CST_LOW (unit_size);
-		hindex *= BITS_PER_UNIT;
-		bit_offset += hindex;
+		hindex = double_int_sub (hindex,
+					 tree_to_double_int (low_bound));
+		hindex = double_int_mul (hindex,
+					 tree_to_double_int (unit_size));
+		hindex = double_int_lshift (hindex,
+					    BITS_PER_UNIT == 8
+					    ? 3 : exact_log2 (BITS_PER_UNIT),
+					    HOST_BITS_PER_DOUBLE_INT, true);
+		bit_offset = double_int_add (bit_offset, hindex);
 
 		/* An array ref with a constant index up in the structure
 		   hierarchy will constrain the size of any variable array ref
@@ -833,8 +870,15 @@ get_ref_base_and_extent (tree exp, HOST_
 		/* We need to adjust maxsize to the whole array bitsize.
 		   But we can subtract any constant offset seen so far,
 		   because that would get us outside of the array otherwise.  */
-		if (maxsize != -1 && asize && host_integerp (asize, 1))
-		  maxsize = TREE_INT_CST_LOW (asize) - bit_offset;
+		if (maxsize != -1 && asize && TREE_CODE (asize) == INTEGER_CST)
+		  {
+		    double_int tem
+		      = double_int_sub (tree_to_double_int (asize), bit_offset);
+		    if (double_int_fits_in_shwi_p (tem))
+		      maxsize = double_int_to_shwi (tem);
+		    else
+		      maxsize = -1;
+		  }
 		else
 		  maxsize = -1;
 
@@ -849,7 +893,8 @@ get_ref_base_and_extent (tree exp, HOST_
 	  break;
 
 	case IMAGPART_EXPR:
-	  bit_offset += bitsize;
+	  bit_offset = double_int_add (bit_offset,
+				       shwi_to_double_int (bitsize));
 	  break;
 
 	case VIEW_CONVERT_EXPR:
@@ -868,12 +913,8 @@ get_ref_base_and_extent (tree exp, HOST_
 					   BITS_PER_UNIT == 8
 					   ? 3 : exact_log2 (BITS_PER_UNIT),
 					   HOST_BITS_PER_DOUBLE_INT, true);
-		  off = double_int_add (off, shwi_to_double_int (bit_offset));
-		  if (double_int_fits_in_shwi_p (off))
-		    {
-		      bit_offset = double_int_to_shwi (off);
-		      exp = TREE_OPERAND (TREE_OPERAND (exp, 0), 0);
-		    }
+		  bit_offset = double_int_add (off, bit_offset);
+		  exp = TREE_OPERAND (TREE_OPERAND (exp, 0), 0);
 		}
 	    }
 	  goto done;
@@ -904,22 +945,42 @@ get_ref_base_and_extent (tree exp, HOST_
       /* If maxsize is unknown adjust it according to the size of the
          base decl.  */
       if (maxsize == -1
-	  && host_integerp (DECL_SIZE (exp), 1))
-	maxsize = TREE_INT_CST_LOW (DECL_SIZE (exp)) - bit_offset;
+	  && DECL_SIZE (exp)
+	  && TREE_CODE (DECL_SIZE (exp)) == INTEGER_CST)
+	{
+	  double_int tem
+	    = double_int_sub (tree_to_double_int (DECL_SIZE (exp)), bit_offset);
+	  if (double_int_fits_in_shwi_p (tem))
+	    maxsize = double_int_to_shwi (tem);
+	}
     }
   else if (seen_variable_array_ref
 	   && maxsize != -1
-	   && (!host_integerp (TYPE_SIZE (TREE_TYPE (exp)), 1)
-	       || (bit_offset + maxsize
-		   == (signed) TREE_INT_CST_LOW (TYPE_SIZE (TREE_TYPE (exp))))))
+	   && (!TYPE_SIZE (TREE_TYPE (exp))
+	       || TREE_CODE (TYPE_SIZE (TREE_TYPE (exp))) != INTEGER_CST
+	       || double_int_equal_p
+	            (double_int_add (bit_offset, shwi_to_double_int (maxsize)),
+		     tree_to_double_int (TYPE_SIZE (TREE_TYPE (exp))))))
     maxsize = -1;
 
   /* ???  Due to negative offsets in ARRAY_REF we can end up with
      negative bit_offset here.  We might want to store a zero offset
      in this case.  */
-  *poffset = bit_offset;
+  /* ???  If bit_offset does not fit in a HOST_WIDE_INT give a
+     conservative answer.
+     ???  We really want to change get_ref_base_and_extent to return
+     a double_int for bit_offset instead.  */
+  if (!double_int_fits_in_shwi_p (bit_offset))
+    {
+      *poffset = 0;
+      *pmax_size = -1;
+    }
+  else
+    {
+      *poffset = double_int_to_shwi (bit_offset);
+      *pmax_size = maxsize;
+    }
   *psize = bitsize;
-  *pmax_size = maxsize;
 
   return exp;
 }
