diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 739cdb574bedd1f1e7226e4e2202101cc2541b8d..a631aaa738d13bab456ba155055573ebfe5e27aa 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,9 @@
+2009-10-20  Richard Guenther  <rguenther@suse.de>
+
+	* gimple.c (gimple_types_compatible_p): Simplify.  Move
+	cheap checks before hashtable queries.  Add checks for
+	TYPE_NONALIASED_COMPONENT and DECL_NONADDRESSABLE_P.
+
 2009-10-20  Eric Botcazou  <ebotcazou@adacore.com>
 
 	* tree-sra.c (build_ref_for_offset_1) <RECORD_TYPE>: Skip fields
diff --git a/gcc/gimple.c b/gcc/gimple.c
index 80c2cf468315a284891940fc5c8ee9b9f275badd..d5b1cf7f1c7739fda8a402371f680d27e22554e2 100644
--- a/gcc/gimple.c
+++ b/gcc/gimple.c
@@ -3174,23 +3174,57 @@ gimple_types_compatible_p (tree t1, tree t2)
 
   /* Check first for the obvious case of pointer identity.  */
   if (t1 == t2)
-    goto same_types;
+    return 1;
 
   /* Check that we have two types to compare.  */
   if (t1 == NULL_TREE || t2 == NULL_TREE)
-    goto different_types;
+    return 0;
 
   /* Can't be the same type if the types don't have the same code.  */
   if (TREE_CODE (t1) != TREE_CODE (t2))
-    goto different_types;
+    return 0;
+
+  /* Can't be the same type if they have different CV qualifiers.  */
+  if (TYPE_QUALS (t1) != TYPE_QUALS (t2))
+    return 0;
 
   /* Void types are always the same.  */
   if (TREE_CODE (t1) == VOID_TYPE)
-    goto same_types;
+    return 1;
 
-  /* Can't be the same type if they have different CV qualifiers.  */
-  if (TYPE_QUALS (t1) != TYPE_QUALS (t2))
-    goto different_types;
+  /* For numerical types do some simple checks before doing three
+     hashtable queries.  */
+  if (INTEGRAL_TYPE_P (t1)
+      || SCALAR_FLOAT_TYPE_P (t1)
+      || FIXED_POINT_TYPE_P (t1)
+      || TREE_CODE (t1) == VECTOR_TYPE
+      || TREE_CODE (t1) == COMPLEX_TYPE)
+    {
+      /* Can't be the same type if they have different alignment,
+	 sign, precision or mode.  */
+      if (TYPE_ALIGN (t1) != TYPE_ALIGN (t2)
+	  || TYPE_PRECISION (t1) != TYPE_PRECISION (t2)
+	  || TYPE_MODE (t1) != TYPE_MODE (t2)
+	  || TYPE_UNSIGNED (t1) != TYPE_UNSIGNED (t2))
+	return 0;
+
+      if (TREE_CODE (t1) == INTEGER_TYPE
+	  && (TYPE_IS_SIZETYPE (t1) != TYPE_IS_SIZETYPE (t2)
+	      || TYPE_STRING_FLAG (t1) != TYPE_STRING_FLAG (t2)))
+	return 0;
+
+      /* That's all we need to check for float and fixed-point types.  */
+      if (SCALAR_FLOAT_TYPE_P (t1)
+	  || FIXED_POINT_TYPE_P (t1))
+	return 1;
+
+      /* Perform cheap tail-recursion for vector and complex types.  */
+      if (TREE_CODE (t1) == VECTOR_TYPE
+	  || TREE_CODE (t1) == COMPLEX_TYPE)
+	return gimple_types_compatible_p (TREE_TYPE (t1), TREE_TYPE (t2));
+
+      /* For integral types fall thru to more complex checks.  */
+    }
 
   /* If the hash values of t1 and t2 are different the types can't
      possibly be the same.  This helps keeping the type-pair hashtable
@@ -3223,71 +3257,6 @@ gimple_types_compatible_p (tree t1, tree t2)
   if (!attribute_list_equal (TYPE_ATTRIBUTES (t1), TYPE_ATTRIBUTES (t2)))
     goto different_types;
 
-  /* For numerical types, the bounds must coincide.  */
-  if (INTEGRAL_TYPE_P (t1)
-      || SCALAR_FLOAT_TYPE_P (t1)
-      || FIXED_POINT_TYPE_P (t1))
-    {
-      /* Can't be the same type if they have different size, alignment,
-	 sign, precision or mode.  Note that from now on, comparisons
-	 between *_CST nodes must be done using tree_int_cst_equal because
-	 we cannot assume that constants from T1 and T2 will be shared
-	 since T1 and T2 are distinct pointers.  */
-      if (!tree_int_cst_equal (TYPE_SIZE (t1), TYPE_SIZE (t2))
-	  || !tree_int_cst_equal (TYPE_SIZE_UNIT (t1), TYPE_SIZE_UNIT (t2))
-	  || TYPE_ALIGN (t1) != TYPE_ALIGN (t2)
-	  || TYPE_PRECISION (t1) != TYPE_PRECISION (t2)
-	  || TYPE_MODE (t1) != TYPE_MODE (t2)
-	  || TYPE_UNSIGNED (t1) != TYPE_UNSIGNED (t2))
-	goto different_types;
-
-      /* For non-enumeral types, check type bounds.  FIXME lto, we
-	 cannot check bounds on enumeral types because different front
-	 ends will produce different values.  In C, enumeral types are
-	 integers, while in C++ each element will have its own
-	 symbolic value.  We should decide how enums are to be
-	 represented in GIMPLE and have each front end lower to that.  */
-      if (TREE_CODE (t1) != ENUMERAL_TYPE)
-	{
-	  tree min1 = TYPE_MIN_VALUE (t1);
-	  tree max1 = TYPE_MAX_VALUE (t1);
-	  tree min2 = TYPE_MIN_VALUE (t2);
-	  tree max2 = TYPE_MAX_VALUE (t2);
-	  bool min_equal_p = false;
-	  bool max_equal_p = false;
-
-	  /* If either type has a minimum value, the other type must
-	     have the same.  */
-	  if (min1 == NULL_TREE && min2 == NULL_TREE)
-	    min_equal_p = true;
-	  else if (min1 && min2 && operand_equal_p (min1, min2, 0))
-	    min_equal_p = true;
-
-	  /* Likewise, if either type has a maximum value, the other
-	     type must have the same.  */
-	  if (max1 == NULL_TREE && max2 == NULL_TREE)
-	    max_equal_p = true;
-	  else if (max1 && max2 && operand_equal_p (max1, max2, 0))
-	    max_equal_p = true;
-
-	  if (!min_equal_p || !max_equal_p)
-	    goto different_types;
-	}
-
-      if (TREE_CODE (t1) == INTEGER_TYPE)
-	{
-	  if (TYPE_IS_SIZETYPE (t1) == TYPE_IS_SIZETYPE (t2)
-	      && TYPE_STRING_FLAG (t1) == TYPE_STRING_FLAG (t2))
-	    goto same_types;
-	  else
-	    goto different_types;
-	}
-      else if (TREE_CODE (t1) == BOOLEAN_TYPE)
-	goto same_types;
-      else if (TREE_CODE (t1) == REAL_TYPE)
-	goto same_types;
-    }
-
   /* Do type-specific comparisons.  */
   switch (TREE_CODE (t1))
     {
@@ -3295,7 +3264,8 @@ gimple_types_compatible_p (tree t1, tree t2)
       /* Array types are the same if the element types are the same and
 	 the number of elements are the same.  */
       if (!gimple_types_compatible_p (TREE_TYPE (t1), TREE_TYPE (t2))
-	  || TYPE_STRING_FLAG (t1) != TYPE_STRING_FLAG (t2))
+	  || TYPE_STRING_FLAG (t1) != TYPE_STRING_FLAG (t2)
+	  || TYPE_NONALIASED_COMPONENT (t1) != TYPE_NONALIASED_COMPONENT (t2))
 	goto different_types;
       else
 	{
@@ -3406,11 +3376,47 @@ gimple_types_compatible_p (tree t1, tree t2)
 	goto different_types;
       }
 
+    case INTEGER_TYPE:
+    case BOOLEAN_TYPE:
+      {
+	tree min1 = TYPE_MIN_VALUE (t1);
+	tree max1 = TYPE_MAX_VALUE (t1);
+	tree min2 = TYPE_MIN_VALUE (t2);
+	tree max2 = TYPE_MAX_VALUE (t2);
+	bool min_equal_p = false;
+	bool max_equal_p = false;
+
+	/* If either type has a minimum value, the other type must
+	   have the same.  */
+	if (min1 == NULL_TREE && min2 == NULL_TREE)
+	  min_equal_p = true;
+	else if (min1 && min2 && operand_equal_p (min1, min2, 0))
+	  min_equal_p = true;
+
+	/* Likewise, if either type has a maximum value, the other
+	   type must have the same.  */
+	if (max1 == NULL_TREE && max2 == NULL_TREE)
+	  max_equal_p = true;
+	else if (max1 && max2 && operand_equal_p (max1, max2, 0))
+	  max_equal_p = true;
+
+	if (!min_equal_p || !max_equal_p)
+	  goto different_types;
+
+	goto same_types;
+      }
+
     case ENUMERAL_TYPE:
       {
-	/* For enumeral types, all the values must be the same.  */
+	/* FIXME lto, we cannot check bounds on enumeral types because
+	   different front ends will produce different values.
+	   In C, enumeral types are integers, while in C++ each element
+	   will have its own symbolic value.  We should decide how enums
+	   are to be represented in GIMPLE and have each front end lower
+	   to that.  */
 	tree v1, v2;
 
+	/* For enumeral types, all the values must be the same.  */
 	if (TYPE_VALUES (t1) == TYPE_VALUES (t2))
 	  goto same_types;
 
@@ -3463,6 +3469,7 @@ gimple_types_compatible_p (tree t1, tree t2)
 	  {
 	    /* The fields must have the same name, offset and type.  */
 	    if (DECL_NAME (f1) != DECL_NAME (f2)
+		|| DECL_NONADDRESSABLE_P (f1) != DECL_NONADDRESSABLE_P (f2)
 		|| !compare_field_offset (f1, f2)
 		|| !gimple_types_compatible_p (TREE_TYPE (f1),
 					       TREE_TYPE (f2)))
@@ -3477,30 +3484,18 @@ gimple_types_compatible_p (tree t1, tree t2)
 	goto same_types;
       }
 
-    case VECTOR_TYPE:
-      if (TYPE_VECTOR_SUBPARTS (t1) != TYPE_VECTOR_SUBPARTS (t2))
-	goto different_types;
-
-      /* Fallthru  */
-    case COMPLEX_TYPE:
-      if (!gimple_types_compatible_p (TREE_TYPE (t1), TREE_TYPE (t2)))
-	goto different_types;
-      goto same_types;
-
     default:
-      goto different_types;
+      gcc_unreachable ();
     }
 
   /* Common exit path for types that are not compatible.  */
 different_types:
-  if (p)
-    p->same_p = 0;
+  p->same_p = 0;
   return 0;
 
   /* Common exit path for types that are compatible.  */
 same_types:
-  if (p)
-    p->same_p = 1;
+  p->same_p = 1;
   return 1;
 }