Index: tree-ssa-sccvn.c
	* gimple.h (fold_const_array_ref): Declare.
	* tree-ssa-sccvn.c (fully_constant_vn_reference_p): Fold initialized
	readonly static vars and array references into them.
	* tree-ssa-ccp.c (fold_const_array_ref): Break out from ...; fix handling
	of lower_bound.
	(fold_const_aggregate_ref): ... here.
===================================================================
--- tree-ssa-sccvn.c	(revision 163862)
+++ tree-ssa-sccvn.c	(working copy)
@@ -1109,24 +1109,57 @@ fully_constant_vn_reference_p (vn_refere
 	    return folded;
 	}
     }
-
-  /* Simplify reads from constant strings.  */
+  else if (op->opcode == VAR_DECL
+	   || op->opcode == CONST_DECL)
+    return get_symbol_constant_value (op->op0);
   else if (op->opcode == ARRAY_REF
-	   && TREE_CODE (op->op0) == INTEGER_CST
-	   && integer_zerop (op->op1)
 	   && VEC_length (vn_reference_op_s, operands) == 2)
     {
       vn_reference_op_t arg0;
+      tree ctor = NULL_TREE;
+      tree op0;
+
       arg0 = VEC_index (vn_reference_op_s, operands, 1);
-      if (arg0->opcode == STRING_CST
-	  && (TYPE_MODE (op->type)
-	      == TYPE_MODE (TREE_TYPE (TREE_TYPE (arg0->op0))))
-	  && GET_MODE_CLASS (TYPE_MODE (op->type)) == MODE_INT
-	  && GET_MODE_SIZE (TYPE_MODE (op->type)) == 1
-	  && compare_tree_int (op->op0, TREE_STRING_LENGTH (arg0->op0)) < 0)
-	return build_int_cst_type (op->type,
-				   (TREE_STRING_POINTER (arg0->op0)
-				    [TREE_INT_CST_LOW (op->op0)]));
+      op0 = arg0->op0;
+
+      switch (arg0->opcode)
+	{
+	case MEM_REF:
+	  /* ???  We could handle this case.  */
+	  if (!integer_zerop (TREE_OPERAND (op0, 1)))
+	    return NULL_TREE;
+	  op0 = get_base_address (op0);
+	  if (!op0
+	      || TREE_CODE (op0) != VAR_DECL)
+	    return NULL_TREE;
+
+	  /* Fallthru.  */
+	case VAR_DECL:
+	  if (!TREE_READONLY (op0)
+	      || TREE_CODE (TREE_TYPE (op0)) != ARRAY_TYPE
+	      || ((TREE_STATIC (op0) || DECL_EXTERNAL (op0))
+		  && !varpool_get_node (op0)->const_value_known))
+	    return NULL_TREE;
+
+	  ctor = DECL_INITIAL (op0);
+	  break;
+
+	case ARRAY_REF:
+	case COMPONENT_REF:
+	  gcc_unreachable ();
+	  break;
+
+	case STRING_CST:
+	case CONSTRUCTOR:
+	  ctor = op0;
+	  break;
+
+	default:
+	  break;
+	}
+      gcc_assert (op->op1);
+      if (ctor)
+        return fold_const_array_ref (op->type, ctor, op->op0, op->op1);
     }
 
   return NULL_TREE;
Index: tree-ssa-ccp.c
===================================================================
--- tree-ssa-ccp.c	(revision 163862)
+++ tree-ssa-ccp.c	(working copy)
@@ -1310,6 +1310,65 @@ ccp_fold (gimple stmt)
     }
 }
 
+/* Fold array reference of TYPE into a variable with known value CTOR
+   with known index IDX.  */
+tree
+fold_const_array_ref (tree type, tree ctor, tree idx, tree low_bound)
+{
+  unsigned HOST_WIDE_INT cnt;
+  tree cfield, cval;
+  tree tem;
+
+  if (ctor == NULL_TREE
+      || (TREE_CODE (ctor) != CONSTRUCTOR
+	  && TREE_CODE (ctor) != STRING_CST)
+      || !TREE_STATIC (ctor))
+    return NULL_TREE;
+
+  /* Get the index.  If we have an SSA_NAME, try to resolve it
+     with the current lattice value for the SSA_NAME.  */
+  switch (TREE_CODE (idx))
+    {
+    case SSA_NAME:
+      if ((tem = get_constant_value (idx))
+	  && TREE_CODE (tem) == INTEGER_CST)
+	idx = tem;
+      else
+	return NULL_TREE;
+      break;
+
+    case INTEGER_CST:
+      break;
+
+    default:
+      return NULL_TREE;
+    }
+
+  /* Fold read from constant string.  */
+  if (TREE_CODE (ctor) == STRING_CST)
+    {
+      tree index = fold_convert (sizetype, idx);
+      if (low_bound && !integer_zerop (low_bound))
+	index = size_diffop (index, fold_convert (sizetype, low_bound));
+      if ((TYPE_MODE (type)
+	   == TYPE_MODE (TREE_TYPE (TREE_TYPE (ctor))))
+	  && (GET_MODE_CLASS (TYPE_MODE (TREE_TYPE (TREE_TYPE (ctor))))
+	      == MODE_INT)
+	  && GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (TREE_TYPE (ctor)))) == 1
+	  && compare_tree_int (index, TREE_STRING_LENGTH (ctor)) < 0)
+	return build_int_cst_type (type,
+				   (TREE_STRING_POINTER (ctor)
+				    [TREE_INT_CST_LOW (index)]));
+      return NULL_TREE;
+    }
+
+  /* Whoo-hoo!  I'll fold ya baby.  Yeah!  */
+  FOR_EACH_CONSTRUCTOR_ELT (CONSTRUCTOR_ELTS (ctor), cnt, cfield, cval)
+    if (tree_int_cst_equal (cfield, idx))
+     return canonicalize_constructor_val (cval);
+  return NULL_TREE;
+}
+
 /* Return the tree representing the element referenced by T if T is an
    ARRAY_REF or COMPONENT_REF into constant aggregates.  Return
    NULL_TREE otherwise.  */
@@ -1332,11 +1391,11 @@ fold_const_aggregate_ref (tree t)
   switch (TREE_CODE (t))
     {
     case ARRAY_REF:
+      base = TREE_OPERAND (t, 0);
       /* Get a CONSTRUCTOR.  If BASE is a VAR_DECL, get its
 	 DECL_INITIAL.  If BASE is a nested reference into another
 	 ARRAY_REF or COMPONENT_REF, make a recursive call to resolve
 	 the inner reference.  */
-      base = TREE_OPERAND (t, 0);
       switch (TREE_CODE (base))
 	{
 	case MEM_REF:
@@ -1373,51 +1432,10 @@ fold_const_aggregate_ref (tree t)
 	  return NULL_TREE;
 	}
 
-      if (ctor == NULL_TREE
-	  || (TREE_CODE (ctor) != CONSTRUCTOR
-	      && TREE_CODE (ctor) != STRING_CST)
-	  || !TREE_STATIC (ctor))
-	return NULL_TREE;
-
-      /* Get the index.  If we have an SSA_NAME, try to resolve it
-	 with the current lattice value for the SSA_NAME.  */
-      idx = TREE_OPERAND (t, 1);
-      switch (TREE_CODE (idx))
-	{
-	case SSA_NAME:
-	  if ((tem = get_constant_value (idx))
-	      && TREE_CODE (tem) == INTEGER_CST)
-	    idx = tem;
-	  else
-	    return NULL_TREE;
-	  break;
-
-	case INTEGER_CST:
-	  break;
-
-	default:
-	  return NULL_TREE;
-	}
-
-      /* Fold read from constant string.  */
-      if (TREE_CODE (ctor) == STRING_CST)
-	{
-	  if ((TYPE_MODE (TREE_TYPE (t))
-	       == TYPE_MODE (TREE_TYPE (TREE_TYPE (ctor))))
-	      && (GET_MODE_CLASS (TYPE_MODE (TREE_TYPE (TREE_TYPE (ctor))))
-	          == MODE_INT)
-	      && GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (TREE_TYPE (ctor)))) == 1
-	      && compare_tree_int (idx, TREE_STRING_LENGTH (ctor)) < 0)
-	    return build_int_cst_type (TREE_TYPE (t),
-				       (TREE_STRING_POINTER (ctor)
-					[TREE_INT_CST_LOW (idx)]));
-	  return NULL_TREE;
-	}
-
-      /* Whoo-hoo!  I'll fold ya baby.  Yeah!  */
-      FOR_EACH_CONSTRUCTOR_ELT (CONSTRUCTOR_ELTS (ctor), cnt, cfield, cval)
-	if (tree_int_cst_equal (cfield, idx))
-	  return canonicalize_constructor_val (cval);
+      return fold_const_array_ref (TREE_TYPE (t),
+				   ctor,
+				   TREE_OPERAND (t, 1),
+				   array_ref_low_bound (t));
       break;
 
     case COMPONENT_REF:
