diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 036f8f373bd64f895c0992bbcd5f24b84a1fc6c5..66176e1f2ad4e10d16060630363e9af4286f9c5f 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,39 @@
+2007-07-02  Richard Guenther  <rguenther@suse.de>
+
+	* tree-flow.h (types_compatible_p): Declare.
+	* tree-ssa.c (types_compatible_p): New function.
+	* ipa-type-escape.c (discover_unique_type): Use
+	types_compatible_p instead of lang_hooks.types_compatible_p.
+	* tree-ssa-copyrename.c (copy_rename_partition_coalesce): Likewise.
+	* tree-vn.c (expressions_equal_p): Likewise.
+	* tree.c (fields_compatible_p): Likewise.
+	* tree-ssa-dom.c (avail_expr_eq): Likewise.
+	(cprop_operand): Use useless_type_conversion_p instead of
+	lang_hooks.types_compatible_p.
+	* tree-inline.c (setup_one_parameter): Likewise.
+	(declare_return_variable): Likewise.
+	* tree-nrv.c (tree_nrv): Likewise.
+	* tree-ssa-ccp.c (maybe_fold_offset_to_array_ref): Likewise.
+	(maybe_fold_offset_to_component_ref): Likewise.
+	(maybe_fold_offset_to_reference): Likewise.
+	* tree-ssa-copy.c (may_propagate_copy): Likewise.
+	(merge_alias_info): Likewise.
+	* tree-ssa-forwprop.c (forward_propagate_addr_expr_1): Likewise.
+	* tree-ssa-phiopt.c (conditional_replacement): Likewise.
+	* tree-ssa-reassoc.c (optimize_ops_list): Likewise.
+	* tree-tailcall.c (find_tail_calls): Likewise.
+	* tree-vect-generic.c (expand_vector_operations_1): Likewise.
+	* gimplify.c (canonicalize_addr_expr): Likewise.
+	(fold_indirect_ref_rhs): Likewise.
+	(gimplify_addr_expr): Likewise.  Swap parameters to cpt_same_type.
+	(cpt_same_type): Likewise.
+	(check_pointer_types_r): Swap parameters to cpt_same_type
+	where appropriate.
+	* fold-const.c (fold_convert): Revert fix for PR15988.
+	* tree-inline.c (setup_one_parameter): Instead fix it here by
+	using fold_build1 instead of fold_convert and checking for
+	error_mark_node.  Convert only if the conversion is necessary.
+
 2007-07-02  Joseph Myers  <joseph@codesourcery.com>
 
 	* configure.ac: Check for .gnu_attribute on Power.
diff --git a/gcc/fold-const.c b/gcc/fold-const.c
index 9dfd07fb8559f451b898e914b15ec14e0d0e91b9..e69945fcba4076bd525daed455d43cabf68ff693 100644
--- a/gcc/fold-const.c
+++ b/gcc/fold-const.c
@@ -2262,9 +2262,7 @@ fold_convert (tree type, tree arg)
       || TREE_CODE (orig) == ERROR_MARK)
     return error_mark_node;
 
-  if (TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (orig)
-      || lang_hooks.types_compatible_p (TYPE_MAIN_VARIANT (type),
-					TYPE_MAIN_VARIANT (orig)))
+  if (TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (orig))
     return fold_build1 (NOP_EXPR, type, arg);
 
   switch (TREE_CODE (type))
diff --git a/gcc/gimplify.c b/gcc/gimplify.c
index a7669acc9680f0dd7e03419651103d37d910fcc1..5510f6008db6e34e174a3cd6a59eb90e445ef200 100644
--- a/gcc/gimplify.c
+++ b/gcc/gimplify.c
@@ -1599,13 +1599,13 @@ canonicalize_addr_expr (tree *expr_p)
   /* Both cast and addr_expr types should address the same object type.  */
   dctype = TREE_TYPE (ctype);
   ddatype = TREE_TYPE (datype);
-  if (!lang_hooks.types_compatible_p (ddatype, dctype))
+  if (!useless_type_conversion_p (dctype, ddatype))
     return;
 
   /* The addr_expr and the object type should match.  */
   obj_expr = TREE_OPERAND (addr_expr, 0);
   otype = TREE_TYPE (obj_expr);
-  if (!lang_hooks.types_compatible_p (otype, datype))
+  if (!useless_type_conversion_p (datype, otype))
     return;
 
   /* The lower bound and element sizes must be constant.  */
@@ -3304,11 +3304,11 @@ fold_indirect_ref_rhs (tree t)
       tree op = TREE_OPERAND (sub, 0);
       tree optype = TREE_TYPE (op);
       /* *&p => p */
-      if (lang_hooks.types_compatible_p (type, optype))
+      if (useless_type_conversion_p (type, optype))
         return op;
       /* *(foo *)&fooarray => fooarray[0] */
       else if (TREE_CODE (optype) == ARRAY_TYPE
-	       && lang_hooks.types_compatible_p (type, TREE_TYPE (optype)))
+	       && useless_type_conversion_p (type, TREE_TYPE (optype)))
        {
          tree type_domain = TYPE_DOMAIN (optype);
          tree min_val = size_zero_node;
@@ -3320,7 +3320,7 @@ fold_indirect_ref_rhs (tree t)
 
   /* *(foo *)fooarrptr => (*fooarrptr)[0] */
   if (TREE_CODE (TREE_TYPE (subtype)) == ARRAY_TYPE
-      && lang_hooks.types_compatible_p (type, TREE_TYPE (TREE_TYPE (subtype))))
+      && useless_type_conversion_p (type, TREE_TYPE (TREE_TYPE (subtype))))
     {
       tree type_domain;
       tree min_val = size_zero_node;
@@ -3974,14 +3974,15 @@ gimplify_addr_expr (tree *expr_p, tree *pre_p, tree *post_p)
 	tree t_expr = TREE_TYPE (expr);
 	tree t_op00 = TREE_TYPE (op00);
 
-        if (!lang_hooks.types_compatible_p (t_expr, t_op00))
+        if (!useless_type_conversion_p (t_expr, t_op00))
 	  {
 #ifdef ENABLE_CHECKING
 	    tree t_op0 = TREE_TYPE (op0);
 	    gcc_assert (POINTER_TYPE_P (t_expr)
-			&& cpt_same_type (TREE_CODE (t_op0) == ARRAY_TYPE
-					  ? TREE_TYPE (t_op0) : t_op0,
-					  TREE_TYPE (t_expr))
+			&& (cpt_same_type (TREE_TYPE (t_expr), t_op0)
+			    || (TREE_CODE (t_op0) == ARRAY_TYPE
+				&& cpt_same_type (TREE_TYPE (t_expr),
+						  TREE_TYPE (t_op0))))
 			&& POINTER_TYPE_P (t_op00)
 			&& cpt_same_type (t_op0, TREE_TYPE (t_op00)));
 #endif
@@ -6385,7 +6386,7 @@ gimplify_one_sizepos (tree *expr_p, tree *stmt_p)
 static bool
 cpt_same_type (tree a, tree b)
 {
-  if (lang_hooks.types_compatible_p (a, b))
+  if (useless_type_conversion_p (a, b))
     return true;
 
   /* ??? The C++ FE decomposes METHOD_TYPES to FUNCTION_TYPES and doesn't
@@ -6436,7 +6437,7 @@ check_pointer_types_r (tree *tp, int *walk_subtrees ATTRIBUTE_UNUSED,
       ptype = TREE_TYPE (t);
       otype = TREE_TYPE (TREE_OPERAND (t, 0));
       dtype = TREE_TYPE (ptype);
-      if (!cpt_same_type (otype, dtype))
+      if (!cpt_same_type (dtype, otype))
 	{
 	  /* &array is allowed to produce a pointer to the element, rather than
 	     a pointer to the array type.  We must allow this in order to
@@ -6444,7 +6445,7 @@ check_pointer_types_r (tree *tp, int *walk_subtrees ATTRIBUTE_UNUSED,
 	     pointer to the element type.  */
 	  gcc_assert (TREE_CODE (otype) == ARRAY_TYPE
 		      && POINTER_TYPE_P (ptype)
-		      && cpt_same_type (TREE_TYPE (otype), dtype));
+		      && cpt_same_type (dtype, TREE_TYPE (otype)));
 	  break;
 	}
       break;
diff --git a/gcc/ipa-type-escape.c b/gcc/ipa-type-escape.c
index a2d459ab6902f8a1a2c0fa36f869cb23fb7f6d65..d9d464d624230a20ccd2c1b6c88448e29e92c693 100644
--- a/gcc/ipa-type-escape.c
+++ b/gcc/ipa-type-escape.c
@@ -219,7 +219,7 @@ discover_unique_type (tree type)
 	  /* Create an alias since this is just the same as
 	     other_type.  */
 	  tree other_type = (tree) result->value;
-	  if (lang_hooks.types_compatible_p (type, other_type) == 1)
+	  if (types_compatible_p (type, other_type))
 	    {
 	      free (brand);
 	      /* Insert this new type as an alias for other_type.  */
diff --git a/gcc/tree-flow.h b/gcc/tree-flow.h
index 375b1786165f670ff56626f605b45096a8ecb8ac..542f5f85f3d56c82e571f97b7c4d0e4f160276c8 100644
--- a/gcc/tree-flow.h
+++ b/gcc/tree-flow.h
@@ -869,6 +869,7 @@ extern edge ssa_redirect_edge (edge, basic_block);
 extern void flush_pending_stmts (edge);
 extern bool tree_ssa_useless_type_conversion (tree);
 extern bool useless_type_conversion_p (tree, tree);
+extern bool types_compatible_p (tree, tree);
 extern void verify_ssa (bool);
 extern void delete_tree_ssa (void);
 extern void walk_use_def_chains (tree, walk_use_def_chains_fn, void *, bool);
diff --git a/gcc/tree-inline.c b/gcc/tree-inline.c
index 054ca8cc7d53569a94218a22fda4c1f9e4a2acde..244b5b075593583ad96195314ea430464ae66ac1 100644
--- a/gcc/tree-inline.c
+++ b/gcc/tree-inline.c
@@ -1278,10 +1278,15 @@ setup_one_parameter (copy_body_data *id, tree p, tree value, tree fn,
   tree init_stmt;
   tree var;
   tree var_sub;
-  tree rhs = value ? fold_convert (TREE_TYPE (p), value) : NULL;
+  tree rhs = value;
   tree def = (gimple_in_ssa_p (cfun)
 	      ? gimple_default_def (id->src_cfun, p) : NULL);
 
+  if (value
+      && value != error_mark_node
+      && !useless_type_conversion_p (TREE_TYPE (p), TREE_TYPE (value)))
+    rhs = fold_build1 (NOP_EXPR, TREE_TYPE (p), value);
+
   /* If the parameter is never assigned to, has no SSA_NAMEs created,
      we may not need to create a new variable here at all.  Instead, we may
      be able to just use the argument value.  */
@@ -1295,7 +1300,8 @@ setup_one_parameter (copy_body_data *id, tree p, tree value, tree fn,
 	 It is not big deal to prohibit constant propagation here as
 	 we will constant propagate in DOM1 pass anyway.  */
       if (is_gimple_min_invariant (value)
-	  && lang_hooks.types_compatible_p (TREE_TYPE (value), TREE_TYPE (p))
+	  && useless_type_conversion_p (TREE_TYPE (p),
+						 TREE_TYPE (value))
 	  /* We have to be very careful about ADDR_EXPR.  Make sure
 	     the base variable isn't a local variable of the inlined
 	     function, e.g., when doing recursive inlining, direct or
@@ -1573,7 +1579,7 @@ declare_return_variable (copy_body_data *id, tree return_slot, tree modify_dest,
       bool use_it = false;
 
       /* We can't use MODIFY_DEST if there's type promotion involved.  */
-      if (!lang_hooks.types_compatible_p (caller_type, callee_type))
+      if (!useless_type_conversion_p (callee_type, caller_type))
 	use_it = false;
 
       /* ??? If we're assigning to a variable sized type, then we must
@@ -1637,7 +1643,7 @@ declare_return_variable (copy_body_data *id, tree return_slot, tree modify_dest,
   /* Build the use expr.  If the return type of the function was
      promoted, convert it back to the expected type.  */
   use = var;
-  if (!lang_hooks.types_compatible_p (TREE_TYPE (var), caller_type))
+  if (!useless_type_conversion_p (caller_type, TREE_TYPE (var)))
     use = fold_convert (caller_type, var);
     
   STRIP_USELESS_TYPE_CONVERSION (use);
diff --git a/gcc/tree-nrv.c b/gcc/tree-nrv.c
index 906b98fbc8ad639aac816a2d5cf1dbd357445b06..5a0db8972522f7552cbdd664b1d88d8f2e84aab3 100644
--- a/gcc/tree-nrv.c
+++ b/gcc/tree-nrv.c
@@ -159,8 +159,8 @@ tree_nrv (void)
 		  || TREE_STATIC (found)
 		  || TREE_ADDRESSABLE (found)
 		  || DECL_ALIGN (found) > DECL_ALIGN (result)
-		  || !lang_hooks.types_compatible_p (TREE_TYPE (found), 
-						     result_type))
+		  || !useless_type_conversion_p (result_type,
+					        TREE_TYPE (found)))
 		return 0;
 	    }
 	  else if (TREE_CODE (stmt) == GIMPLE_MODIFY_STMT)
diff --git a/gcc/tree-ssa-ccp.c b/gcc/tree-ssa-ccp.c
index 1188f86484a4296fccb86a0794903e2533bedb37..272a4f857414a25e9fab1242ac47d5ed829d67e1 100644
--- a/gcc/tree-ssa-ccp.c
+++ b/gcc/tree-ssa-ccp.c
@@ -1575,7 +1575,7 @@ maybe_fold_offset_to_array_ref (tree base, tree offset, tree orig_type)
   if (TREE_CODE (array_type) != ARRAY_TYPE)
     return NULL_TREE;
   elt_type = TREE_TYPE (array_type);
-  if (!lang_hooks.types_compatible_p (orig_type, elt_type))
+  if (!useless_type_conversion_p (orig_type, elt_type))
     return NULL_TREE;
 
   /* Use signed size type for intermediate computation on the index.  */
@@ -1666,7 +1666,7 @@ maybe_fold_offset_to_component_ref (tree record_type, tree base, tree offset,
     return NULL_TREE;
 
   /* Short-circuit silly cases.  */
-  if (lang_hooks.types_compatible_p (record_type, orig_type))
+  if (useless_type_conversion_p (record_type, orig_type))
     return NULL_TREE;
 
   tail_array_field = NULL_TREE;
@@ -1704,7 +1704,7 @@ maybe_fold_offset_to_component_ref (tree record_type, tree base, tree offset,
       /* Here we exactly match the offset being checked.  If the types match,
 	 then we can return that field.  */
       if (cmp == 0
-	  && lang_hooks.types_compatible_p (orig_type, field_type))
+	  && useless_type_conversion_p (orig_type, field_type))
 	{
 	  if (base_is_ptr)
 	    base = build1 (INDIRECT_REF, record_type, base);
@@ -1809,7 +1809,7 @@ maybe_fold_offset_to_reference (tree base, tree offset, tree orig_type)
 					  sub_offset / BITS_PER_UNIT), 1);
 	    }
 	}
-      if (lang_hooks.types_compatible_p (orig_type, TREE_TYPE (base))
+      if (useless_type_conversion_p (orig_type, TREE_TYPE (base))
 	  && integer_zerop (offset))
 	return base;
       type = TREE_TYPE (base);
diff --git a/gcc/tree-ssa-copy.c b/gcc/tree-ssa-copy.c
index b44db5238b7e043b6fef5ee2a4fed676544ff45b..e791459f2d3b7c6c77463663257f5a1d5843e822 100644
--- a/gcc/tree-ssa-copy.c
+++ b/gcc/tree-ssa-copy.c
@@ -130,7 +130,7 @@ may_propagate_copy (tree dest, tree orig)
       tree mt_orig = symbol_mem_tag (SSA_NAME_VAR (orig));
       if (mt_dest && mt_orig && mt_dest != mt_orig)
 	return false;
-      else if (!lang_hooks.types_compatible_p (type_d, type_o))
+      else if (!useless_type_conversion_p (type_d, type_o))
 	return false;
       else if (get_alias_set (TREE_TYPE (type_d)) != 
 	       get_alias_set (TREE_TYPE (type_o)))
@@ -222,8 +222,8 @@ merge_alias_info (tree orig_name, tree new_name)
   gcc_assert (POINTER_TYPE_P (TREE_TYPE (new_name)));
 
 #if defined ENABLE_CHECKING
-  gcc_assert (lang_hooks.types_compatible_p (TREE_TYPE (orig_name),
-					     TREE_TYPE (new_name)));
+  gcc_assert (useless_type_conversion_p (TREE_TYPE (orig_name),
+					TREE_TYPE (new_name)));
 
   /* If the pointed-to alias sets are different, these two pointers
      would never have the same memory tag.  In this case, NEW should
diff --git a/gcc/tree-ssa-copyrename.c b/gcc/tree-ssa-copyrename.c
index e06de4caaf6894ccf55088241ea1f070ed60be70..812ebe195089b5db1af563c0d1e3b1932d90327e 100644
--- a/gcc/tree-ssa-copyrename.c
+++ b/gcc/tree-ssa-copyrename.c
@@ -240,7 +240,7 @@ copy_rename_partition_coalesce (var_map map, tree var1, tree var2, FILE *debug)
     }
 
   /* Don't coalesce if the two variables aren't type compatible.  */
-  if (!lang_hooks.types_compatible_p (TREE_TYPE (root1), TREE_TYPE (root2)))
+  if (!types_compatible_p (TREE_TYPE (root1), TREE_TYPE (root2)))
     {
       if (debug)
 	fprintf (debug, " : Incompatible types.  No coalesce.\n");
diff --git a/gcc/tree-ssa-dom.c b/gcc/tree-ssa-dom.c
index 3b7bacd9660f39a4ad1f21b9751c3ae30bfb333c..b0bfbba882a0dbc65a5d8d28963811f2007cb33e 100644
--- a/gcc/tree-ssa-dom.c
+++ b/gcc/tree-ssa-dom.c
@@ -1680,7 +1680,7 @@ cprop_operand (tree stmt, use_operand_p op_p)
 	 propagation opportunity.  */
       if (TREE_CODE (val) != SSA_NAME)
 	{
-	  if (!lang_hooks.types_compatible_p (op_type, val_type))
+	  if (!useless_type_conversion_p (op_type, val_type))
 	    {
 	      val = fold_convert (TREE_TYPE (op), val);
 	      if (!is_gimple_min_invariant (val))
@@ -2048,8 +2048,7 @@ avail_expr_eq (const void *p1, const void *p2)
 
   /* In case of a collision, both RHS have to be identical and have the
      same VUSE operands.  */
-  if ((TREE_TYPE (rhs1) == TREE_TYPE (rhs2)
-       || lang_hooks.types_compatible_p (TREE_TYPE (rhs1), TREE_TYPE (rhs2)))
+  if (types_compatible_p (TREE_TYPE (rhs1), TREE_TYPE (rhs2))
       && operand_equal_p (rhs1, rhs2, OEP_PURE_SAME))
     {
       bool ret = compare_ssa_operands_equal (stmt1, stmt2, SSA_OP_VUSE);
diff --git a/gcc/tree-ssa-forwprop.c b/gcc/tree-ssa-forwprop.c
index 07d682fba09c386e8fb76e6d4515a01d7f7af95e..effa93dd0cf467f7a61a6cac0e9650dfbbcdbc40 100644
--- a/gcc/tree-ssa-forwprop.c
+++ b/gcc/tree-ssa-forwprop.c
@@ -670,7 +670,7 @@ forward_propagate_addr_expr_1 (tree name, tree def_rhs, tree use_stmt,
       && TREE_CODE (TREE_OPERAND (rhs, 1)) == SSA_NAME
       /* Avoid problems with IVopts creating PLUS_EXPRs with a
 	 different type than their operands.  */
-      && lang_hooks.types_compatible_p (TREE_TYPE (name), TREE_TYPE (rhs)))
+      && useless_type_conversion_p (TREE_TYPE (rhs), TREE_TYPE (name)))
     {
       bool res;
       
diff --git a/gcc/tree-ssa-phiopt.c b/gcc/tree-ssa-phiopt.c
index 8cdd3c80da947ac5d6b1575d5e23b23631338e18..8e91cc23865bc540ec9e3264f0dd0c61768ba977 100644
--- a/gcc/tree-ssa-phiopt.c
+++ b/gcc/tree-ssa-phiopt.c
@@ -401,7 +401,7 @@ conditional_replacement (basic_block cond_bb, basic_block middle_bb,
   cond = COND_EXPR_COND (last_stmt (cond_bb));
   result = PHI_RESULT (phi);
   if (TREE_CODE (cond) != SSA_NAME
-      && !lang_hooks.types_compatible_p (TREE_TYPE (cond), TREE_TYPE (result)))
+      && !useless_type_conversion_p (TREE_TYPE (result), TREE_TYPE (cond)))
     {
       tree tmp;
 
@@ -418,7 +418,7 @@ conditional_replacement (basic_block cond_bb, basic_block middle_bb,
   /* If the condition was a naked SSA_NAME and the type is not the
      same as the type of the result, then convert the type of the
      condition.  */
-  if (!lang_hooks.types_compatible_p (TREE_TYPE (cond), TREE_TYPE (result)))
+  if (!useless_type_conversion_p (TREE_TYPE (result), TREE_TYPE (cond)))
     cond = fold_convert (TREE_TYPE (result), cond);
 
   /* We need to know which is the true edge and which is the false
diff --git a/gcc/tree-ssa-reassoc.c b/gcc/tree-ssa-reassoc.c
index bc0de6db0b0f2eb41a6278d919d7bbad5934e1f5..448107b2d720cd5e5ff9275151b3c3bd1c52b20a 100644
--- a/gcc/tree-ssa-reassoc.c
+++ b/gcc/tree-ssa-reassoc.c
@@ -727,8 +727,8 @@ optimize_ops_list (enum tree_code opcode,
 
       if (oelm1->rank == 0
 	  && is_gimple_min_invariant (oelm1->op)
-	  && lang_hooks.types_compatible_p (TREE_TYPE (oelm1->op),
-					    TREE_TYPE (oelast->op)))
+	  && useless_type_conversion_p (TREE_TYPE (oelm1->op),
+				       TREE_TYPE (oelast->op)))
 	{
 	  tree folded = fold_binary (opcode, TREE_TYPE (oelm1->op),
 				     oelm1->op, oelast->op);
diff --git a/gcc/tree-ssa.c b/gcc/tree-ssa.c
index b6ac9c68ba86519888424dbc68df2db47ed7165b..9e7160606e320833a2c68f1629d89739baf9eb61 100644
--- a/gcc/tree-ssa.c
+++ b/gcc/tree-ssa.c
@@ -971,6 +971,17 @@ useless_type_conversion_p (tree outer_type, tree inner_type)
   return false;
 }
 
+/* Return true if a conversion from either type of TYPE1 and TYPE2
+   to the other is not required.  Otherwise return false.  */
+
+bool
+types_compatible_p (tree type1, tree type2)
+{
+  return (type1 == type2
+	  || (useless_type_conversion_p (type1, type2)
+	      && useless_type_conversion_p (type2, type1)));
+}
+
 /* Return true if EXPR is a useless type conversion, otherwise return
    false.  */
 
diff --git a/gcc/tree-tailcall.c b/gcc/tree-tailcall.c
index bf13f537ede092c93d741611dae9bc4c9083a075..135cf1ed78c498bf9cab392ffe92d03028987437 100644
--- a/gcc/tree-tailcall.c
+++ b/gcc/tree-tailcall.c
@@ -448,8 +448,8 @@ find_tail_calls (basic_block bb, struct tailcall **ret)
 	         equivalent types.  The latter requirement could be relaxed if
 	         we emitted a suitable type conversion statement.  */
 	      if (!is_gimple_reg_type (TREE_TYPE (param))
-		  || !lang_hooks.types_compatible_p (TREE_TYPE (param),
-						     TREE_TYPE (arg)))
+		  || !useless_type_conversion_p (TREE_TYPE (param),
+					        TREE_TYPE (arg)))
 		break;
 
 	      /* The parameter should be a real operand, so that phi node
diff --git a/gcc/tree-vect-generic.c b/gcc/tree-vect-generic.c
index 8c0bbd556fa76502ebc22dfb14b15b80aafac1f5..582998916e143f3f5e9c1e474a2b7710b4f355fe 100644
--- a/gcc/tree-vect-generic.c
+++ b/gcc/tree-vect-generic.c
@@ -469,7 +469,7 @@ expand_vector_operations_1 (block_stmt_iterator *bsi)
 
   gcc_assert (code != VEC_LSHIFT_EXPR && code != VEC_RSHIFT_EXPR);
   rhs = expand_vector_operation (bsi, type, compute_type, rhs, code);
-  if (lang_hooks.types_compatible_p (TREE_TYPE (lhs), TREE_TYPE (rhs)))
+  if (useless_type_conversion_p (TREE_TYPE (lhs), TREE_TYPE (rhs)))
     *p_rhs = rhs;
   else
     *p_rhs = gimplify_build1 (bsi, VIEW_CONVERT_EXPR, TREE_TYPE (lhs), rhs);
diff --git a/gcc/tree-vn.c b/gcc/tree-vn.c
index a000ca2815c1792a478081e8a44870bae85385bc..d62aeea9398664022dc44ef0f6e50e86f6bca55a 100644
--- a/gcc/tree-vn.c
+++ b/gcc/tree-vn.c
@@ -84,7 +84,8 @@ expressions_equal_p (tree e1, tree e2)
 
     }
   else if (TREE_CODE (e1) == TREE_CODE (e2) 
-	   && (te1 == te2 || lang_hooks.types_compatible_p (te1, te2))
+	   && (te1 == te2
+	       || types_compatible_p (te1, te2))
 	   && operand_equal_p (e1, e2, OEP_PURE_SAME))
     return true;
 
diff --git a/gcc/tree.c b/gcc/tree.c
index 9bf7d4889727dc5509178f5017fecd53e4203dd0..72a2593ee5f32ad9ed78fbf5bcfadf6742bf26bc 100644
--- a/gcc/tree.c
+++ b/gcc/tree.c
@@ -7714,7 +7714,7 @@ fields_compatible_p (tree f1, tree f2)
                         DECL_FIELD_OFFSET (f2), OEP_ONLY_CONST))
     return false;
 
-  if (!lang_hooks.types_compatible_p (TREE_TYPE (f1), TREE_TYPE (f2)))
+  if (!types_compatible_p (TREE_TYPE (f1), TREE_TYPE (f2)))
     return false;
 
   return true;