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