diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 2a4a78e16278d293474f7c21f45e1d45ce01850b..78f5ba5ae5c0eb5e659c826d6f1933f0a97ea385 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,11 @@
+2005-03-13  Roger Sayle  <roger@eyesopen.com>
+
+	PR middle-end/19331
+	* tree.c (get_unwidened): Treat CONVERT_EXPR and NOP_EXPR identically.
+	* fold-const.c (fold_sign_changed_comparison): Likewise.
+	(fold_binary): Optimize comparisons against widened operands if
+	the extension is represented by a CONVERT_EXPR, same as a NOP_EXPR.
+
 2005-03-14  Eric Botcazou  <ebotcazou@libertysurf.fr>
 
 	* config/sparc/sparc.c (struct_value_alias_set): New global variable.
diff --git a/gcc/fold-const.c b/gcc/fold-const.c
index 3fdfb92f3b215c5fa9830e38f3bd5576389aefee..6a00abe423b1d1df1fbac5d65eae47b13d85c70e 100644
--- a/gcc/fold-const.c
+++ b/gcc/fold-const.c
@@ -6148,7 +6148,8 @@ fold_sign_changed_comparison (enum tree_code code, tree type,
   tree arg0_inner, tmp;
   tree inner_type, outer_type;
 
-  if (TREE_CODE (arg0) != NOP_EXPR)
+  if (TREE_CODE (arg0) != NOP_EXPR
+      && TREE_CODE (arg0) != CONVERT_EXPR)
     return NULL_TREE;
 
   outer_type = TREE_TYPE (arg0);
@@ -6159,7 +6160,8 @@ fold_sign_changed_comparison (enum tree_code code, tree type,
     return NULL_TREE;
 
   if (TREE_CODE (arg1) != INTEGER_CST
-      && !(TREE_CODE (arg1) == NOP_EXPR
+      && !((TREE_CODE (arg1) == NOP_EXPR
+	    || TREE_CODE (arg1) == CONVERT_EXPR)
 	   && TREE_TYPE (TREE_OPERAND (arg1, 0)) == inner_type))
     return NULL_TREE;
 
@@ -6180,7 +6182,7 @@ fold_sign_changed_comparison (enum tree_code code, tree type,
   else
     arg1 = fold_convert (inner_type, arg1);
 
-  return fold (build (code, type, arg0_inner, arg1));
+  return fold (build2 (code, type, arg0_inner, arg1));
 }
 
 /* Tries to replace &a[idx] CODE s * delta with &a[idx CODE delta], if s is
@@ -9150,7 +9152,8 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
 			     TREE_OPERAND (arg0, 0), TREE_OPERAND (arg0, 1)));
 
       else if (TREE_CODE (TREE_TYPE (arg0)) == INTEGER_TYPE
-	       && TREE_CODE (arg0) == NOP_EXPR)
+	       && (TREE_CODE (arg0) == NOP_EXPR
+		   || TREE_CODE (arg0) == CONVERT_EXPR))
 	{
 	  /* If we are widening one operand of an integer comparison,
 	     see if the other operand is similarly being widened.  Perhaps we
diff --git a/gcc/tree.c b/gcc/tree.c
index 815ef7505fcb2fbca0eda55d7d7c12a8b612835e..0a99598123ad595ec2bc58f62d9c9664450cd6b0 100644
--- a/gcc/tree.c
+++ b/gcc/tree.c
@@ -4729,7 +4729,8 @@ get_unwidened (tree op, tree for_type)
        && TYPE_UNSIGNED (type));
   tree win = op;
 
-  while (TREE_CODE (op) == NOP_EXPR)
+  while (TREE_CODE (op) == NOP_EXPR
+	 || TREE_CODE (op) == CONVERT_EXPR)
     {
       int bitschange
 	= TYPE_PRECISION (TREE_TYPE (op))
@@ -4759,7 +4760,9 @@ get_unwidened (tree op, tree for_type)
 	  /* TYPE_UNSIGNED says whether this is a zero-extension.
 	     Let's avoid computing it if it does not affect WIN
 	     and if UNS will not be needed again.  */
-	  if ((uns || TREE_CODE (op) == NOP_EXPR)
+	  if ((uns
+	       || TREE_CODE (op) == NOP_EXPR
+	       || TREE_CODE (op) == CONVERT_EXPR)
 	      && TYPE_UNSIGNED (TREE_TYPE (op)))
 	    {
 	      uns = 1;