diff --git a/gcc/target.def b/gcc/target.def
index 2a7fa68..cd81b4e 100644
--- a/gcc/target.def
+++ b/gcc/target.def
@@ -7107,6 +7107,20 @@ counters are incremented using atomic operations.  Targets not supporting\n\
 type.",
  HOST_WIDE_INT, (void), default_gcov_type_size)
 
+DEFHOOK
+(simplify_modecc_const,
+ "On targets that represent the result of a comparison using a\n\
+@code{MODE_CC} flags register, allow the backend to represent a known\n\
+result using a target-dependent integer constant.  This helper function\n\
+of @code{simplify_const_relational_operation} attempts to simplify a\n\
+comparison operator @var{code} that is defined by a @code{COMPARE} in mode\n\
+@var{mode}, which is known to be of class @code{MODE_CC}, and is encoded\n\
+as @var{val}, which must be a @code{CONST_INT}.  The result must be\n\
+@code{const_true_rtx}, @code{const0_rtx} or @code{NULL_RTX} if no\n\
+simplification is possible.",
+ rtx, (machine_mode mode, int code, rtx val),
+ hook_rtx_mode_int_rtx_null)
+
 /* This value represents whether the shadow call stack is implemented on
    the target platform.  */
 DEFHOOKPOD
diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi
index b0ea398..5a1231d 100644
--- a/gcc/doc/tm.texi
+++ b/gcc/doc/tm.texi
@@ -6631,6 +6631,18 @@ post-reload comparison elimination pass, or the delay slot filler pass,
 then this value should be set appropriately.
 @end deftypevr
 
+@deftypefn {Target Hook} rtx TARGET_SIMPLIFY_MODECC_CONST (machine_mode @var{mode}, int @var{code}, rtx @var{val})
+On targets that represent the result of a comparison using a
+@code{MODE_CC} flags register, allow the backend to represent a known
+result using a target-dependent integer constant.  This helper function
+of @code{simplify_const_relational_operation} attempts to simplify a
+comparison operator @var{code} that is defined by a @code{COMPARE} in mode
+@var{mode}, which is known to be of class @code{MODE_CC}, and is encoded
+as @var{val}, which must be a @code{CONST_INT}.  The result must be
+@code{const_true_rtx}, @code{const0_rtx} or @code{NULL_RTX} if no
+simplification is possible.
+@end deftypefn
+
 @node Costs
 @section Describing Relative Costs of Operations
 @cindex costs of instructions
diff --git a/gcc/doc/tm.texi.in b/gcc/doc/tm.texi.in
index f869ddd..8cecde7 100644
--- a/gcc/doc/tm.texi.in
+++ b/gcc/doc/tm.texi.in
@@ -4397,6 +4397,8 @@ like:
 
 @hook TARGET_FLAGS_REGNUM
 
+@hook TARGET_SIMPLIFY_MODECC_CONST
+
 @node Costs
 @section Describing Relative Costs of Operations
 @cindex costs of instructions
diff --git a/gcc/hooks.cc b/gcc/hooks.cc
index b29233f..90be303 100644
--- a/gcc/hooks.cc
+++ b/gcc/hooks.cc
@@ -401,6 +401,14 @@ hook_rtx_tree_int_null (tree, int)
   return NULL;
 }
 
+/* Generic hook that takes a machine mode, an int and an rtx and
+   returns NULL_RTX.  */
+rtx
+hook_rtx_mode_int_rtx_null (machine_mode, int, rtx)
+{
+  return NULL;
+}
+
 /* Generic hook that takes a machine mode and returns an unsigned int 0.  */
 unsigned int
 hook_uint_mode_0 (machine_mode)
diff --git a/gcc/hooks.h b/gcc/hooks.h
index 1056e1e..e978817 100644
--- a/gcc/hooks.h
+++ b/gcc/hooks.h
@@ -123,6 +123,7 @@ extern bool default_can_output_mi_thunk_no_vcall (const_tree, HOST_WIDE_INT,
 extern rtx hook_rtx_rtx_identity (rtx);
 extern rtx hook_rtx_rtx_null (rtx);
 extern rtx hook_rtx_tree_int_null (tree, int);
+extern rtx hook_rtx_mode_int_rtx_null (machine_mode, int, rtx);
 
 extern char *hook_charptr_void_null (void);
 extern const char *hook_constcharptr_void_null (void);
diff --git a/gcc/simplify-rtx.cc b/gcc/simplify-rtx.cc
index fa20665..699e08a 100644
--- a/gcc/simplify-rtx.cc
+++ b/gcc/simplify-rtx.cc
@@ -6012,6 +6012,13 @@ simplify_const_relational_operation (enum rtx_code code,
 	      || (GET_MODE (op0) == VOIDmode
 		  && GET_MODE (op1) == VOIDmode));
 
+  /* Handle MODE_CC comparisons that have been simplified to
+     constants.  */
+  if (GET_MODE_CLASS (mode) == MODE_CC
+      && op1 == const0_rtx
+      && CONST_INT_P (op0))
+    return targetm.simplify_modecc_const (mode, (int)code, op0);
+
   /* If op0 is a compare, extract the comparison arguments from it.  */
   if (GET_CODE (op0) == COMPARE && op1 == const0_rtx)
     {
diff --git a/gcc/config/i386/i386.cc b/gcc/config/i386/i386.cc
index e03f86d..a73c265 100644
--- a/gcc/config/i386/i386.cc
+++ b/gcc/config/i386/i386.cc
@@ -15995,6 +15995,31 @@ ix86_cc_modes_compatible (machine_mode m1, machine_mode m2)
     }
 }
 
+/* Simplify the results of comparisons with constant operands.
+   MODE is a MODE_CC, CODE is a comparison operator, and VAL is
+   a target (and mode) dependent CONST_INT.  */
+
+rtx
+ix86_simplify_modecc_const (machine_mode mode, int code, rtx val)
+{
+  /* For CCCmode, const0_rtx represents the carry flag is clear,
+     otherwise the carry flag is set.  */
+  switch ((enum rtx_code)code)
+    {
+    case LTU:
+      if (mode == E_CCCmode)
+	return val == const0_rtx ? const0_rtx : const_true_rtx;
+      break;
+    case GEU:
+      if (mode == E_CCCmode)
+	return val == const0_rtx ? const_true_rtx : const0_rtx;
+      break;
+    default:
+      break;
+    }
+  return NULL_RTX;
+}
+
 /* Return strategy to use for floating-point.  We assume that fcomi is always
    preferrable where available, since that is also true when looking at size
    (2 bytes, vs. 3 for fnstsw+sahf and at least 5 for fnstsw+test).  */
@@ -24978,6 +25003,9 @@ static bool ix86_libc_has_fast_function (int fcode ATTRIBUTE_UNUSED)
 #undef TARGET_GEN_MEMSET_SCRATCH_RTX
 #define TARGET_GEN_MEMSET_SCRATCH_RTX ix86_gen_scratch_sse_rtx
 
+#undef TARGET_SIMPLIFY_MODECC_CONST
+#define TARGET_SIMPLIFY_MODECC_CONST ix86_simplify_modecc_const
+
 #if CHECKING_P
 #undef TARGET_RUN_TARGET_SELFTESTS
 #define TARGET_RUN_TARGET_SELFTESTS selftest::ix86_run_selftests
