Index: gcc/config/rs6000/rs6000.c
===================================================================
--- gcc/config/rs6000/rs6000.c	(revision 183628)
+++ gcc/config/rs6000/rs6000.c	(working copy)
@@ -15588,6 +15588,22 @@ rs6000_reverse_condition (enum machine_m
     return reverse_condition (code);
 }
 
+static bool
+rs6000_unsigned_reg_p (rtx op)
+{
+  enum rtx_code code = GET_CODE (op);
+
+  if (code == REG
+      && REG_EXPR (op)
+      && TYPE_UNSIGNED (TREE_TYPE (REG_EXPR (op))))
+    return true;
+
+  if (code == SUBREG && SUBREG_PROMOTED_UNSIGNED_P (op))
+    return true;
+
+  return false;
+}
+
 /* Generate a compare for CODE.  Return a brand-new rtx that
    represents the result of the compare.  */
 
@@ -15606,14 +15622,11 @@ rs6000_generate_compare (rtx cmp, enum m
 	   || code == GEU || code == LEU)
     comp_mode = CCUNSmode;
   else if ((code == EQ || code == NE)
-	   && GET_CODE (op0) == SUBREG
-	   && GET_CODE (op1) == SUBREG
-	   && SUBREG_PROMOTED_UNSIGNED_P (op0)
-	   && SUBREG_PROMOTED_UNSIGNED_P (op1))
+	   && rs6000_unsigned_reg_p (op0)
+	   && (rs6000_unsigned_reg_p (op1)
+	       || (CONST_INT_P (op1) && INTVAL (op1) != 0)))
     /* These are unsigned values, perhaps there will be a later
-       ordering compare that can be shared with this one.
-       Unfortunately we cannot detect the signedness of the operands
-       for non-subregs.  */
+       ordering compare that can be shared with this one.  */
     comp_mode = CCUNSmode;
   else
     comp_mode = CCmode;
Index: gcc/testsuite/gcc.target/powerpc/pr16458-1.c
===================================================================
--- gcc/testsuite/gcc.target/powerpc/pr16458-1.c	(revision 0)
+++ gcc/testsuite/gcc.target/powerpc/pr16458-1.c	(revision 0)
@@ -0,0 +1,18 @@
+/* Test cse'ing of unsigned compares.  */
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+/* { dg-final { scan-assembler-not "cmpw" } } */
+/* { dg-final { scan-assembler-times "cmplw" 1 } } */
+
+unsigned int a, b;
+
+int
+foo (void)
+{
+  if (a == b) return 1;
+  if (a > b)  return 2;
+  if (a < b)  return 3;
+  if (a != b) return 4;
+  return 0;
+}
Index: gcc/testsuite/gcc.target/powerpc/pr16458-2.c
===================================================================
--- gcc/testsuite/gcc.target/powerpc/pr16458-2.c	(revision 0)
+++ gcc/testsuite/gcc.target/powerpc/pr16458-2.c	(revision 0)
@@ -0,0 +1,18 @@
+/* Test cse'ing of unsigned compares.  */
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+/* { dg-final { scan-assembler-not "cmpw" } } */
+/* { dg-final { scan-assembler-times "cmplw" 1 } } */
+
+unsigned int *a, *b;
+
+int
+foo (void)
+{
+  if (*a == *b) return 1;
+  if (*a > *b)  return 2;
+  if (*a < *b)  return 3;
+  if (*a != *b) return 4;
+  return 0;
+}
Index: gcc/testsuite/gcc.target/powerpc/pr16458-3.c
===================================================================
--- gcc/testsuite/gcc.target/powerpc/pr16458-3.c	(revision 0)
+++ gcc/testsuite/gcc.target/powerpc/pr16458-3.c	(revision 0)
@@ -0,0 +1,41 @@
+/* Test cse'ing of unsigned compares.  */
+/* { dg-do compile } */
+/* { dg-options "-O2 -fno-jump-tables" } */
+
+/* { dg-final { scan-assembler-not "cmpwi" } } */
+/* { dg-final { scan-assembler-times "cmplwi" 5 } } */
+
+extern int case0 (void);
+extern int case1 (void);
+extern int case2 (void);
+extern int case3 (void);
+extern int case4 (void);
+
+enum CASE_VALUES
+{
+  CASE0 = 0,
+  CASE1,
+  CASE2,
+  CASE3,
+  CASE4
+};
+
+int
+foo (enum CASE_VALUES index)
+{
+  switch (index)
+    {
+    case CASE0:
+      return case0 ();
+    case CASE1:
+      return case1 ();
+    case CASE2:
+      return case2 ();
+    case CASE3:
+      return case3 ();
+    case CASE4:
+      return case4 ();
+    }
+
+  return 0;
+}
Index: gcc/testsuite/gcc.target/powerpc/pr16458-4.c
===================================================================
--- gcc/testsuite/gcc.target/powerpc/pr16458-4.c	(revision 0)
+++ gcc/testsuite/gcc.target/powerpc/pr16458-4.c	(revision 0)
@@ -0,0 +1,44 @@
+/* Test cse'ing of unsigned compares.  */
+/* { dg-do compile } */
+/* { dg-options "-O2 -fno-jump-tables" } */
+
+/* The following tests fail due to an issue in expand not
+   attaching an type expression information on *index's reg rtx.  */
+
+/* { dg-final { scan-assembler-not "cmpwi" { xfail *-*-* } } } */
+/* { dg-final { scan-assembler-times "cmplwi" 5 { xfail *-*-* } } } */
+
+extern int case0 (void);
+extern int case1 (void);
+extern int case2 (void);
+extern int case3 (void);
+extern int case4 (void);
+
+enum CASE_VALUES
+{
+  CASE0 = 0,
+  CASE1,
+  CASE2,
+  CASE3,
+  CASE4
+};
+
+int
+foo (enum CASE_VALUES *index)
+{
+  switch (*index)
+    {
+    case CASE0:
+      return case0 ();
+    case CASE1:
+      return case1 ();
+    case CASE2:
+      return case2 ();
+    case CASE3:
+      return case3 ();
+    case CASE4:
+      return case4 ();
+    }
+
+  return 0;
+}
