* [PATCH] Bugfix: Additional parameter for canonicalize comparison
@ 2012-12-12 11:23 Andreas Krebbel
2012-12-19 9:53 ` [PING] " Andreas Krebbel
0 siblings, 1 reply; 6+ messages in thread
From: Andreas Krebbel @ 2012-12-12 11:23 UTC (permalink / raw)
To: rearnsha; +Cc: gcc-patches
Hi Richard,
is the attached patch ok for ARM?
Bye,
-Andreas-
2012-12-12 Andreas Krebbel <Andreas.Krebbel@de.ibm.com>
* target.def: Define canonicalize_comparison hook.
* targhooks.h (default_canonicalize_comparison): New prototype.
* targhooks.c (default_canonicalize_comparison): New function.
* doc/tm.texi: Add documentation for the new target hook.
* doc/tm.texi.in: Likewise.
* combine.c (try_combine): Adjust to use the target hook.
* config/alpha/alpha.h (CANONICALIZE_COMPARISON): Remove macro
definition.
* config/alpha/alpha.c (alpha_canonicalize_comparison): New
function.
(TARGET_CANONICALIZE_COMPARISON): New macro definition.
* config/arm/arm-protos.h (arm_canonicalize_comparison): Remove
prototype.
* config/arm/arm.c (arm_canonicalize_comparison): Add new
parameter.
(TARGET_CANONICALIZE_COMPARISON): New macro definition.
* config/arm/arm.h (CANONICALIZE_COMPARISON): Remove macro
definition.
* config/s390/s390-protos.h (s390_canonicalize_comparison): Remove
prototype.
* config/s390/s390.c (s390_canonicalize_comparison): Add new
parameter.
(TARGET_CANONICALIZE_COMPARISON): New macro definition.
* config/s390/s390.h (CANONICALIZE_COMPARISON): Remove macro
definition.
* config/sh/sh-protos.h (sh_canonicalize_comparison): Remove
prototype.
* config/sh/sh.c (sh_canonicalize_comparison): Add new prototype. New
function overloading the old one.
(TARGET_CANONICALIZE_COMPARISON): New macro definition.
* config/sh/sh.h (CANONICALIZE_COMPARISON): Remove macro
definition.
* config/spu/spu.c (spu_canonicalize_comparison): New function.
(TARGET_CANONICALIZE_COMPARISON): New macro definition.
* config/spu/spu.h (CANONICALIZE_COMPARISON): Remove macro
definition.
---
gcc/combine.c | 19 ++++++-!!!
gcc/config/alpha/alpha.c | 27 ++++++++++++++++
gcc/config/alpha/alpha.h | 20 ------------
gcc/config/arm/arm-protos.h | 1
gcc/config/arm/arm.c | 68 ++-!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
gcc/config/arm/arm.h | 3 -
gcc/config/s390/s390-protos.h | 1
gcc/config/s390/s390.c | 13 +++!!!!!
gcc/config/s390/s390.h | 4 --
gcc/config/sh/sh-protos.h | 2 -
gcc/config/sh/sh.c | 34 +++++++++++!!!!!!!!!!
gcc/config/sh/sh.h | 4 --
gcc/config/spu/spu.c | 17 ++++++++++
gcc/config/spu/spu.h | 12 -------
gcc/doc/tm.texi | 20 !!!!!!!!!!!!
gcc/doc/tm.texi.in | 20 !!!!!!!!!!!!
gcc/target.def | 8 ++++
gcc/targhooks.h | 2 +
18 files changed, 94 insertions(+), 50 deletions(-), 131 modifications(!)
Index: gcc/combine.c
===================================================================
*** gcc/combine.c.orig
--- gcc/combine.c
*************** static rtx gen_lowpart_or_truncate (enum
*** 494,499 ****
--- 494,510 ----
static const struct rtl_hooks combine_rtl_hooks = RTL_HOOKS_INITIALIZER;
\f
+ /* Convenience wrapper for the canonicalize_comparison target hook.
+ Target hooks cannot use enum rtx_code. */
+ static inline void
+ target_canonicalize_comparison (enum rtx_code *code, rtx *op0, rtx *op1,
+ bool op0_preserve_value)
+ {
+ int code_int = (int)*code;
+ targetm.canonicalize_comparison (&code_int, op0, op1, op0_preserve_value);
+ *code = (enum rtx_code)code_int;
+ }
+
/* Try to split PATTERN found in INSN. This returns NULL_RTX if
PATTERN can not be split. Otherwise, it returns an insn sequence.
This is a wrapper around split_insns which ensures that the
*************** try_combine (rtx i3, rtx i2, rtx i1, rtx
*** 2944,2952 ****
compare_code = orig_compare_code = GET_CODE (*cc_use_loc);
compare_code = simplify_compare_const (compare_code,
op0, &op1);
! #ifdef CANONICALIZE_COMPARISON
! CANONICALIZE_COMPARISON (compare_code, op0, op1);
! #endif
}
/* Do the rest only if op1 is const0_rtx, which may be the
--- 2955,2961 ----
compare_code = orig_compare_code = GET_CODE (*cc_use_loc);
compare_code = simplify_compare_const (compare_code,
op0, &op1);
! target_canonicalize_comparison (&compare_code, &op0, &op1, 1);
}
/* Do the rest only if op1 is const0_rtx, which may be the
*************** simplify_comparison (enum rtx_code code,
*** 11959,11969 ****
}
}
- #ifdef CANONICALIZE_COMPARISON
/* If this machine only supports a subset of valid comparisons, see if we
can convert an unsupported one into a supported one. */
! CANONICALIZE_COMPARISON (code, op0, op1);
! #endif
*pop0 = op0;
*pop1 = op1;
--- 11968,11976 ----
}
}
/* If this machine only supports a subset of valid comparisons, see if we
can convert an unsupported one into a supported one. */
! target_canonicalize_comparison (&code, &op0, &op1, 0);
*pop0 = op0;
*pop1 = op1;
Index: gcc/config/alpha/alpha.c
===================================================================
*** gcc/config/alpha/alpha.c.orig
--- gcc/config/alpha/alpha.c
*************** alpha_conditional_register_usage (void)
*** 9683,9688 ****
--- 9683,9712 ----
for (i = 32; i < 63; i++)
fixed_regs[i] = call_used_regs[i] = 1;
}
+
+ /* Canonicalize a comparison from one we don't have to one we do have. */
+
+ static void
+ alpha_canonicalize_comparison (int *code, rtx *op0, rtx *op1,
+ bool op0_preserve_value)
+ {
+ if (!op0_preserve_value
+ && (*code == GE || *code == GT || *code == GEU || *code == GTU)
+ && (REG_P (*op1) || *op1 == const0_rtx))
+ {
+ rtx tem = *op0;
+ *op0 = *op1;
+ *op1 = tem;
+ *code = (int)swap_condition ((enum rtx_code)*code);
+ }
+
+ if ((*code == LT || *code == LTU)
+ && CONST_INT_P (*op1) && INTVAL (*op1) == 256)
+ {
+ *code = *code == LT ? LE : LEU;
+ *op1 = GEN_INT (255);
+ }
+ }
\f
/* Initialize the GCC target structure. */
#if TARGET_ABI_OPEN_VMS
*************** alpha_conditional_register_usage (void)
*** 9850,9855 ****
--- 9874,9882 ----
#undef TARGET_CONDITIONAL_REGISTER_USAGE
#define TARGET_CONDITIONAL_REGISTER_USAGE alpha_conditional_register_usage
+ #undef TARGET_CANONICALIZE_COMPARISON
+ #define TARGET_CANONICALIZE_COMPARISON alpha_canonicalize_comparison
+
struct gcc_target targetm = TARGET_INITIALIZER;
\f
Index: gcc/config/alpha/alpha.h
===================================================================
*** gcc/config/alpha/alpha.h.orig
--- gcc/config/alpha/alpha.h
*************** do { \
*** 922,947 ****
#define FLOAT_STORE_FLAG_VALUE(MODE) \
REAL_VALUE_ATOF ((TARGET_FLOAT_VAX ? "0.5" : "2.0"), (MODE))
- /* Canonicalize a comparison from one we don't have to one we do have. */
-
- #define CANONICALIZE_COMPARISON(CODE,OP0,OP1) \
- do { \
- if (((CODE) == GE || (CODE) == GT || (CODE) == GEU || (CODE) == GTU) \
- && (REG_P (OP1) || (OP1) == const0_rtx)) \
- { \
- rtx tem = (OP0); \
- (OP0) = (OP1); \
- (OP1) = tem; \
- (CODE) = swap_condition (CODE); \
- } \
- if (((CODE) == LT || (CODE) == LTU) \
- && CONST_INT_P (OP1) && INTVAL (OP1) == 256) \
- { \
- (CODE) = (CODE) == LT ? LE : LEU; \
- (OP1) = GEN_INT (255); \
- } \
- } while (0)
-
/* Specify the machine mode that pointers have.
After generation of rtl, the compiler makes no further distinction
between pointers and any other objects of this machine mode. */
--- 922,927 ----
Index: gcc/config/arm/arm-protos.h
===================================================================
*** gcc/config/arm/arm-protos.h.orig
--- gcc/config/arm/arm-protos.h
*************** extern int const_ok_for_op (HOST_WIDE_IN
*** 53,59 ****
extern int const_ok_for_dimode_op (HOST_WIDE_INT, enum rtx_code);
extern int arm_split_constant (RTX_CODE, enum machine_mode, rtx,
HOST_WIDE_INT, rtx, rtx, int);
- extern RTX_CODE arm_canonicalize_comparison (RTX_CODE, rtx *, rtx *);
extern int legitimate_pic_operand_p (rtx);
extern rtx legitimize_pic_address (rtx, enum machine_mode, rtx);
extern rtx legitimize_tls_address (rtx, rtx);
--- 53,58 ----
Index: gcc/config/arm/arm.c
===================================================================
*** gcc/config/arm/arm.c.orig
--- gcc/config/arm/arm.c
*************** static int arm_cortex_a5_branch_cost (bo
*** 269,275 ****
static bool arm_vectorize_vec_perm_const_ok (enum machine_mode vmode,
const unsigned char *sel);
!
\f
/* Table of machine attributes. */
static const struct attribute_spec arm_attribute_table[] =
--- 269,276 ----
static bool arm_vectorize_vec_perm_const_ok (enum machine_mode vmode,
const unsigned char *sel);
! static void arm_canonicalize_comparison (int *code, rtx *op0, rtx *op1,
! bool op0_preserve_value);
\f
/* Table of machine attributes. */
static const struct attribute_spec arm_attribute_table[] =
*************** static const struct attribute_spec arm_a
*** 626,631 ****
--- 627,636 ----
#define TARGET_VECTORIZE_VEC_PERM_CONST_OK \
arm_vectorize_vec_perm_const_ok
+ #undef TARGET_CANONICALIZE_COMPARISON
+ #define TARGET_CANONICALIZE_COMPARISON \
+ arm_canonicalize_comparison
+
struct gcc_target targetm = TARGET_INITIALIZER;
\f
/* Obstack for minipool constant handling. */
*************** arm_gen_constant (enum rtx_code code, en
*** 3543,3550 ****
This can be done for a few constant compares, where we can make the
immediate value easier to load. */
! enum rtx_code
! arm_canonicalize_comparison (enum rtx_code code, rtx *op0, rtx *op1)
{
enum machine_mode mode;
unsigned HOST_WIDE_INT i, maxval;
--- 3548,3556 ----
This can be done for a few constant compares, where we can make the
immediate value easier to load. */
! static void
! arm_canonicalize_comparison (int *code, rtx *op0, rtx *op1,
! bool op0_preserve_value)
{
enum machine_mode mode;
unsigned HOST_WIDE_INT i, maxval;
*************** arm_canonicalize_comparison (enum rtx_co
*** 3563,3577 ****
{
rtx tem;
! if (code == GT || code == LE
! || (!TARGET_ARM && (code == GTU || code == LEU)))
{
/* Missing comparison. First try to use an available
comparison. */
if (CONST_INT_P (*op1))
{
i = INTVAL (*op1);
! switch (code)
{
case GT:
case LE:
--- 3569,3583 ----
{
rtx tem;
! if (*code == GT || *code == LE
! || (!TARGET_ARM && (*code == GTU || *code == LEU)))
{
/* Missing comparison. First try to use an available
comparison. */
if (CONST_INT_P (*op1))
{
i = INTVAL (*op1);
! switch (*code)
{
case GT:
case LE:
*************** arm_canonicalize_comparison (enum rtx_co
*** 3579,3585 ****
&& arm_const_double_by_immediates (GEN_INT (i + 1)))
{
*op1 = GEN_INT (i + 1);
! return code == GT ? GE : LT;
}
break;
case GTU:
--- 3585,3592 ----
&& arm_const_double_by_immediates (GEN_INT (i + 1)))
{
*op1 = GEN_INT (i + 1);
! *code = *code == GT ? GE : LT;
! return;
}
break;
case GTU:
*************** arm_canonicalize_comparison (enum rtx_co
*** 3588,3594 ****
&& arm_const_double_by_immediates (GEN_INT (i + 1)))
{
*op1 = GEN_INT (i + 1);
! return code == GTU ? GEU : LTU;
}
break;
default:
--- 3595,3602 ----
&& arm_const_double_by_immediates (GEN_INT (i + 1)))
{
*op1 = GEN_INT (i + 1);
! *code = *code == GTU ? GEU : LTU;
! return;
}
break;
default:
*************** arm_canonicalize_comparison (enum rtx_co
*** 3597,3615 ****
}
/* If that did not work, reverse the condition. */
! tem = *op0;
! *op0 = *op1;
! *op1 = tem;
! return swap_condition (code);
}
!
! return code;
}
/* If *op0 is (zero_extend:SI (subreg:QI (reg:SI) 0)) and comparing
with const0_rtx, change it to (and:SI (reg:SI) (const_int 255)),
to facilitate possible combining with a cmp into 'ands'. */
! if (mode == SImode
&& GET_CODE (*op0) == ZERO_EXTEND
&& GET_CODE (XEXP (*op0, 0)) == SUBREG
&& GET_MODE (XEXP (*op0, 0)) == QImode
--- 3605,3626 ----
}
/* If that did not work, reverse the condition. */
! if (!op0_preserve_value)
! {
! tem = *op0;
! *op0 = *op1;
! *op1 = tem;
! *code = (int)swap_condition ((enum rtx_code)*code);
! }
}
! return;
}
/* If *op0 is (zero_extend:SI (subreg:QI (reg:SI) 0)) and comparing
with const0_rtx, change it to (and:SI (reg:SI) (const_int 255)),
to facilitate possible combining with a cmp into 'ands'. */
! if (!op0_preserve_value
! && mode == SImode
&& GET_CODE (*op0) == ZERO_EXTEND
&& GET_CODE (XEXP (*op0, 0)) == SUBREG
&& GET_MODE (XEXP (*op0, 0)) == QImode
*************** arm_canonicalize_comparison (enum rtx_co
*** 3624,3638 ****
if (!CONST_INT_P (*op1)
|| const_ok_for_arm (INTVAL (*op1))
|| const_ok_for_arm (- INTVAL (*op1)))
! return code;
i = INTVAL (*op1);
! switch (code)
{
case EQ:
case NE:
! return code;
case GT:
case LE:
--- 3635,3649 ----
if (!CONST_INT_P (*op1)
|| const_ok_for_arm (INTVAL (*op1))
|| const_ok_for_arm (- INTVAL (*op1)))
! return;
i = INTVAL (*op1);
! switch (*code)
{
case EQ:
case NE:
! return;
case GT:
case LE:
*************** arm_canonicalize_comparison (enum rtx_co
*** 3640,3646 ****
&& (const_ok_for_arm (i + 1) || const_ok_for_arm (-(i + 1))))
{
*op1 = GEN_INT (i + 1);
! return code == GT ? GE : LT;
}
break;
--- 3651,3658 ----
&& (const_ok_for_arm (i + 1) || const_ok_for_arm (-(i + 1))))
{
*op1 = GEN_INT (i + 1);
! *code = *code == GT ? GE : LT;
! return;
}
break;
*************** arm_canonicalize_comparison (enum rtx_co
*** 3650,3656 ****
&& (const_ok_for_arm (i - 1) || const_ok_for_arm (-(i - 1))))
{
*op1 = GEN_INT (i - 1);
! return code == GE ? GT : LE;
}
break;
--- 3662,3669 ----
&& (const_ok_for_arm (i - 1) || const_ok_for_arm (-(i - 1))))
{
*op1 = GEN_INT (i - 1);
! *code = *code == GE ? GT : LE;
! return;
}
break;
*************** arm_canonicalize_comparison (enum rtx_co
*** 3660,3666 ****
&& (const_ok_for_arm (i + 1) || const_ok_for_arm (-(i + 1))))
{
*op1 = GEN_INT (i + 1);
! return code == GTU ? GEU : LTU;
}
break;
--- 3673,3680 ----
&& (const_ok_for_arm (i + 1) || const_ok_for_arm (-(i + 1))))
{
*op1 = GEN_INT (i + 1);
! *code = *code == GTU ? GEU : LTU;
! return;
}
break;
*************** arm_canonicalize_comparison (enum rtx_co
*** 3670,3684 ****
&& (const_ok_for_arm (i - 1) || const_ok_for_arm (-(i - 1))))
{
*op1 = GEN_INT (i - 1);
! return code == GEU ? GTU : LEU;
}
break;
default:
gcc_unreachable ();
}
-
- return code;
}
--- 3684,3697 ----
&& (const_ok_for_arm (i - 1) || const_ok_for_arm (-(i - 1))))
{
*op1 = GEN_INT (i - 1);
! *code = *code == GEU ? GTU : LEU;
! return;
}
break;
default:
gcc_unreachable ();
}
}
*************** bool
*** 26979,26985 ****
arm_validize_comparison (rtx *comparison, rtx * op1, rtx * op2)
{
enum rtx_code code = GET_CODE (*comparison);
! enum rtx_code canonical_code;
enum machine_mode mode = (GET_MODE (*op1) == VOIDmode)
? GET_MODE (*op2) : GET_MODE (*op1);
--- 26992,26998 ----
arm_validize_comparison (rtx *comparison, rtx * op1, rtx * op2)
{
enum rtx_code code = GET_CODE (*comparison);
! int code_int;
enum machine_mode mode = (GET_MODE (*op1) == VOIDmode)
? GET_MODE (*op2) : GET_MODE (*op1);
*************** arm_validize_comparison (rtx *comparison
*** 26988,26995 ****
if (code == UNEQ || code == LTGT)
return false;
! canonical_code = arm_canonicalize_comparison (code, op1, op2);
! PUT_CODE (*comparison, canonical_code);
switch (mode)
{
--- 27001,27009 ----
if (code == UNEQ || code == LTGT)
return false;
! code_int = (int)code;
! arm_canonicalize_comparison (&code_int, op1, op2, 0);
! PUT_CODE (*comparison, (enum rtx_code)code_int);
switch (mode)
{
Index: gcc/config/arm/arm.h
===================================================================
*** gcc/config/arm/arm.h.orig
--- gcc/config/arm/arm.h
*************** extern int making_const_table;
*** 2078,2086 ****
? reverse_condition_maybe_unordered (code) \
: reverse_condition (code))
- #define CANONICALIZE_COMPARISON(CODE, OP0, OP1) \
- (CODE) = arm_canonicalize_comparison (CODE, &(OP0), &(OP1))
-
/* The arm5 clz instruction returns 32. */
#define CLZ_DEFINED_VALUE_AT_ZERO(MODE, VALUE) ((VALUE) = 32, 1)
#define CTZ_DEFINED_VALUE_AT_ZERO(MODE, VALUE) ((VALUE) = 32, 1)
--- 2078,2083 ----
Index: gcc/config/s390/s390-protos.h
===================================================================
*** gcc/config/s390/s390-protos.h.orig
--- gcc/config/s390/s390-protos.h
*************** extern int tls_symbolic_operand (rtx);
*** 58,64 ****
extern bool s390_match_ccmode (rtx, enum machine_mode);
extern enum machine_mode s390_tm_ccmode (rtx, rtx, bool);
extern enum machine_mode s390_select_ccmode (enum rtx_code, rtx, rtx);
- extern void s390_canonicalize_comparison (enum rtx_code *, rtx *, rtx *);
extern rtx s390_emit_compare (enum rtx_code, rtx, rtx);
extern void s390_emit_jump (rtx, rtx);
extern bool symbolic_reference_mentioned_p (rtx);
--- 58,63 ----
Index: gcc/config/s390/s390.c
===================================================================
*** gcc/config/s390/s390.c.orig
--- gcc/config/s390/s390.c
*************** s390_select_ccmode (enum rtx_code code,
*** 745,753 ****
/* Replace the comparison OP0 CODE OP1 by a semantically equivalent one
that we can implement more efficiently. */
! void
! s390_canonicalize_comparison (enum rtx_code *code, rtx *op0, rtx *op1)
{
/* Convert ZERO_EXTRACT back to AND to enable TM patterns. */
if ((*code == EQ || *code == NE)
&& *op1 == const0_rtx
--- 745,757 ----
/* Replace the comparison OP0 CODE OP1 by a semantically equivalent one
that we can implement more efficiently. */
! static void
! s390_canonicalize_comparison (int *code, rtx *op0, rtx *op1,
! bool op0_preserve_value)
{
+ if (op0_preserve_value)
+ return;
+
/* Convert ZERO_EXTRACT back to AND to enable TM patterns. */
if ((*code == EQ || *code == NE)
&& *op1 == const0_rtx
*************** s390_canonicalize_comparison (enum rtx_c
*** 894,900 ****
if (MEM_P (*op0) && REG_P (*op1))
{
rtx tem = *op0; *op0 = *op1; *op1 = tem;
! *code = swap_condition (*code);
}
}
--- 898,904 ----
if (MEM_P (*op0) && REG_P (*op1))
{
rtx tem = *op0; *op0 = *op1; *op1 = tem;
! *code = (int)swap_condition ((enum rtx_code)*code);
}
}
*************** s390_loop_unroll_adjust (unsigned nunrol
*** 11071,11076 ****
--- 11075,11083 ----
#undef TARGET_UNWIND_WORD_MODE
#define TARGET_UNWIND_WORD_MODE s390_unwind_word_mode
+ #undef TARGET_CANONICALIZE_COMPARISON
+ #define TARGET_CANONICALIZE_COMPARISON s390_canonicalize_comparison
+
struct gcc_target targetm = TARGET_INITIALIZER;
#include "gt-s390.h"
Index: gcc/config/s390/s390.h
===================================================================
*** gcc/config/s390/s390.h.orig
--- gcc/config/s390/s390.h
*************** do { \
*** 720,729 ****
return the mode to be used for the comparison. */
#define SELECT_CC_MODE(OP, X, Y) s390_select_ccmode ((OP), (X), (Y))
- /* Canonicalize a comparison from one we don't have to one we do have. */
- #define CANONICALIZE_COMPARISON(CODE, OP0, OP1) \
- s390_canonicalize_comparison (&(CODE), &(OP0), &(OP1))
-
/* Relative costs of operations. */
/* A C expression for the cost of a branch instruction. A value of 1
--- 720,725 ----
Index: gcc/config/sh/sh-protos.h
===================================================================
*** gcc/config/sh/sh-protos.h.orig
--- gcc/config/sh/sh-protos.h
*************** extern bool sh_expand_t_scc (rtx *);
*** 159,166 ****
extern rtx sh_gen_truncate (enum machine_mode, rtx, int);
extern bool sh_vector_mode_supported_p (enum machine_mode);
extern bool sh_cfun_trap_exit_p (void);
- extern void sh_canonicalize_comparison (enum rtx_code&, rtx&, rtx&,
- enum machine_mode mode = VOIDmode);
extern rtx sh_find_equiv_gbr_addr (rtx cur_insn, rtx mem);
extern int sh_eval_treg_value (rtx op);
--- 159,164 ----
Index: gcc/config/sh/sh.c
===================================================================
*** gcc/config/sh/sh.c.orig
--- gcc/config/sh/sh.c
*************** static int max_mov_insn_displacement (en
*** 314,319 ****
--- 314,322 ----
static int mov_insn_alignment_mask (enum machine_mode, bool);
static HOST_WIDE_INT disp_addr_displacement (rtx);
static bool sequence_insn_p (rtx);
+ static void sh_canonicalize_comparison (int *, rtx *, rtx *, bool);
+ static void sh_canonicalize_comparison (enum rtx_code&, rtx&, rtx&,
+ enum machine_mode, bool);
static void sh_init_sync_libfuncs (void) ATTRIBUTE_UNUSED;
\f
*************** static const struct attribute_spec sh_at
*** 586,591 ****
--- 589,597 ----
#undef TARGET_LEGITIMATE_CONSTANT_P
#define TARGET_LEGITIMATE_CONSTANT_P sh_legitimate_constant_p
+ #undef TARGET_CANONICALIZE_COMPARISON
+ #define TARGET_CANONICALIZE_COMPARISON sh_canonicalize_comparison
+
/* Machine-specific symbol_ref flags. */
#define SYMBOL_FLAG_FUNCVEC_FUNCTION (SYMBOL_FLAG_MACH_DEP << 0)
*************** prepare_move_operands (rtx operands[], e
*** 1909,1920 ****
}
}
! /* Implement the CANONICALIZE_COMPARISON macro for the combine pass.
! This function is also re-used to canonicalize comparisons in cbranch
! pattern expanders. */
! void
sh_canonicalize_comparison (enum rtx_code& cmp, rtx& op0, rtx& op1,
! enum machine_mode mode)
{
/* When invoked from within the combine pass the mode is not specified,
so try to get it from one of the operands. */
--- 1915,1928 ----
}
}
! /* Implement the canonicalize_comparison target hook for the combine
! pass. For the target hook this function is invoked via
! sh_canonicalize_comparison. This function is also re-used to
! canonicalize comparisons in cbranch pattern expanders. */
! static void
sh_canonicalize_comparison (enum rtx_code& cmp, rtx& op0, rtx& op1,
! enum machine_mode mode,
! bool op0_preserve_value ATTRIBUTE_UNUSED)
{
/* When invoked from within the combine pass the mode is not specified,
so try to get it from one of the operands. */
*************** sh_canonicalize_comparison (enum rtx_cod
*** 2008,2013 ****
--- 2016,2034 ----
}
}
+ /* This function implements the canonicalize_comparison target hook.
+ This wrapper around the internally used sh_canonicalize_comparison
+ function is needed to do the enum rtx_code <-> int conversion.
+ Target hooks cannot use enum rtx_code in its definition. */
+ static void
+ sh_canonicalize_comparison (int *code, rtx *op0, rtx *op1,
+ bool op0_preserve_value)
+ {
+ enum rtx_code tmp_code = (enum rtx_code)*code;
+ sh_canonicalize_comparison (tmp_code, *op0, *op1,
+ VOIDmode, op0_preserve_value);
+ *code = (int)tmp_code;
+ }
enum rtx_code
prepare_cbranch_operands (rtx *operands, enum machine_mode mode,
enum rtx_code comparison)
*************** prepare_cbranch_operands (rtx *operands,
*** 2021,2027 ****
else
scratch = operands[4];
! sh_canonicalize_comparison (comparison, operands[1], operands[2], mode);
/* Notice that this function is also invoked after reload by
the cbranchdi4_i pattern, through expand_cbranchdi4. */
--- 2042,2049 ----
else
scratch = operands[4];
! sh_canonicalize_comparison (comparison, operands[1], operands[2],
! mode, false);
/* Notice that this function is also invoked after reload by
the cbranchdi4_i pattern, through expand_cbranchdi4. */
Index: gcc/config/sh/sh.h
===================================================================
*** gcc/config/sh/sh.h.orig
--- gcc/config/sh/sh.h
*************** struct sh_args {
*** 1873,1882 ****
more compact code. */
#define SHIFT_COUNT_TRUNCATED (0)
- /* CANONICALIZE_COMPARISON macro for the combine pass. */
- #define CANONICALIZE_COMPARISON(CODE, OP0, OP1) \
- sh_canonicalize_comparison ((CODE), (OP0), (OP1))
-
/* All integers have the same format so truncation is easy. */
/* But SHmedia must sign-extend DImode when truncating to SImode. */
#define TRULY_NOOP_TRUNCATION(OUTPREC,INPREC) \
--- 1873,1878 ----
Index: gcc/config/spu/spu.c
===================================================================
*** gcc/config/spu/spu.c.orig
--- gcc/config/spu/spu.c
*************** spu_output_mi_thunk (FILE *file, tree th
*** 7095,7100 ****
--- 7095,7114 ----
final_end_function ();
}
+ /* Canonicalize a comparison from one we don't have to one we do have. */
+ static void
+ spu_canonicalize_comparison (int *code, rtx *op0, rtx *op1,
+ bool op0_preserve_value)
+ {
+ if (!op0_preserve_value
+ && (*code == LE || *code == LT || *code == LEU || *code == LTU))
+ {
+ rtx tem = *op0;
+ *op0 = *op1;
+ *op1 = tem;
+ *code = (int)swap_condition ((enum rtx_code)*code);
+ }
+ }
\f
/* Table of machine attributes. */
static const struct attribute_spec spu_attribute_table[] =
*************** static const struct attribute_spec spu_a
*** 7308,7313 ****
--- 7322,7330 ----
#undef TARGET_DELAY_VARTRACK
#define TARGET_DELAY_VARTRACK true
+ #undef TARGET_CANONICALIZE_COMPARISON
+ #define TARGET_CANONICALIZE_COMPARISON spu_canonicalize_comparison
+
struct gcc_target targetm = TARGET_INITIALIZER;
#include "gt-spu.h"
Index: gcc/config/spu/spu.h
===================================================================
*** gcc/config/spu/spu.h.orig
--- gcc/config/spu/spu.h
*************** do { \
*** 520,537 ****
#define NO_IMPLICIT_EXTERN_C 1
- /* Canonicalize a comparison from one we don't have to one we do have. */
- #define CANONICALIZE_COMPARISON(CODE,OP0,OP1) \
- do { \
- if (((CODE) == LE || (CODE) == LT || (CODE) == LEU || (CODE) == LTU)) \
- { \
- rtx tem = (OP0); \
- (OP0) = (OP1); \
- (OP1) = tem; \
- (CODE) = swap_condition (CODE); \
- } \
- } while (0)
-
/* Address spaces. */
#define ADDR_SPACE_EA 1
--- 520,525 ----
Index: gcc/doc/tm.texi.in
===================================================================
*** gcc/doc/tm.texi.in.orig
--- gcc/doc/tm.texi.in
*************** You should define this macro if and only
*** 5928,5952 ****
in @file{@var{machine}-modes.def}.
@end defmac
! @defmac CANONICALIZE_COMPARISON (@var{code}, @var{op0}, @var{op1})
On some machines not all possible comparisons are defined, but you can
convert an invalid comparison into a valid one. For example, the Alpha
does not have a @code{GT} comparison, but you can use an @code{LT}
comparison instead and swap the order of the operands.
! On such machines, define this macro to be a C statement to do any
! required conversions. @var{code} is the initial comparison code
! and @var{op0} and @var{op1} are the left and right operands of the
! comparison, respectively. You should modify @var{code}, @var{op0}, and
! @var{op1} as required.
GCC will not assume that the comparison resulting from this macro is
valid but will see if the resulting insn matches a pattern in the
@file{md} file.
! You need not define this macro if it would never change the comparison
! code or operands.
! @end defmac
@defmac REVERSIBLE_CC_MODE (@var{mode})
A C expression whose value is one if it is always safe to reverse a
--- 5928,5954 ----
in @file{@var{machine}-modes.def}.
@end defmac
! @hook TARGET_CANONICALIZE_COMPARISON (@var{code}, @var{op0}, @var{op1}, @var{op0_preserve_value})
On some machines not all possible comparisons are defined, but you can
convert an invalid comparison into a valid one. For example, the Alpha
does not have a @code{GT} comparison, but you can use an @code{LT}
comparison instead and swap the order of the operands.
! On such machines, implement this hook to do any required conversions.
! @var{code} is the initial comparison code and @var{op0} and @var{op1}
! are the left and right operands of the comparison, respectively. If
! @var{op0_preserve_value} is @code{true} the implementation is not
! allowed to change the value of @var{op0} since the value might be used
! in RTXs which aren't comparisons. E.g. the implementation is not
! allowed to swap operands in that case.
GCC will not assume that the comparison resulting from this macro is
valid but will see if the resulting insn matches a pattern in the
@file{md} file.
! You need not to implement this hook if it would never change the
! comparison code or operands.
! @end deftypefn
@defmac REVERSIBLE_CC_MODE (@var{mode})
A C expression whose value is one if it is always safe to reverse a
Index: gcc/target.def
===================================================================
*** gcc/target.def.orig
--- gcc/target.def
*************** DEFHOOK
*** 2877,2882 ****
--- 2877,2890 ----
enum unwind_info_type, (void),
default_debug_unwind_info)
+ /* The code parameter should be of type enum rtx_code but this is not
+ defined at this time. */
+ DEFHOOK
+ (canonicalize_comparison,
+ "",
+ void, (int *code, rtx *op0, rtx *op1, bool op0_preserve_value),
+ default_canonicalize_comparison)
+
DEFHOOKPOD
(atomic_test_and_set_trueval,
"This value should be set if the result written by\
Index: gcc/targhooks.h
===================================================================
*** gcc/targhooks.h.orig
--- gcc/targhooks.h
*************** extern unsigned char default_class_max_n
*** 179,184 ****
--- 179,186 ----
extern enum unwind_info_type default_debug_unwind_info (void);
+ extern bool default_canonicalize_comparison (int *, rtx *, rtx *, bool);
+
extern int default_label_align_after_barrier_max_skip (rtx);
extern int default_loop_align_max_skip (rtx);
extern int default_label_align_max_skip (rtx);
Index: gcc/doc/tm.texi
===================================================================
*** gcc/doc/tm.texi.orig
--- gcc/doc/tm.texi
*************** You should define this macro if and only
*** 6024,6048 ****
in @file{@var{machine}-modes.def}.
@end defmac
! @defmac CANONICALIZE_COMPARISON (@var{code}, @var{op0}, @var{op1})
On some machines not all possible comparisons are defined, but you can
convert an invalid comparison into a valid one. For example, the Alpha
does not have a @code{GT} comparison, but you can use an @code{LT}
comparison instead and swap the order of the operands.
! On such machines, define this macro to be a C statement to do any
! required conversions. @var{code} is the initial comparison code
! and @var{op0} and @var{op1} are the left and right operands of the
! comparison, respectively. You should modify @var{code}, @var{op0}, and
! @var{op1} as required.
GCC will not assume that the comparison resulting from this macro is
valid but will see if the resulting insn matches a pattern in the
@file{md} file.
! You need not define this macro if it would never change the comparison
! code or operands.
! @end defmac
@defmac REVERSIBLE_CC_MODE (@var{mode})
A C expression whose value is one if it is always safe to reverse a
--- 6024,6050 ----
in @file{@var{machine}-modes.def}.
@end defmac
! @deftypefn {Target Hook} void TARGET_CANONICALIZE_COMPARISON (int *@var{code}, rtx *@var{op0}, rtx *@var{op1}, bool @var{op0_preserve_value}) (@var{code}, @var{op0}, @var{op1}, @var{op0_preserve_value})
On some machines not all possible comparisons are defined, but you can
convert an invalid comparison into a valid one. For example, the Alpha
does not have a @code{GT} comparison, but you can use an @code{LT}
comparison instead and swap the order of the operands.
! On such machines, implement this hook to do any required conversions.
! @var{code} is the initial comparison code and @var{op0} and @var{op1}
! are the left and right operands of the comparison, respectively. If
! @var{op0_preserve_value} is @code{true} the implementation is not
! allowed to change the value of @var{op0} since the value might be used
! in RTXs which aren't comparisons. E.g. the implementation is not
! allowed to swap operands in that case.
GCC will not assume that the comparison resulting from this macro is
valid but will see if the resulting insn matches a pattern in the
@file{md} file.
! You need not to implement this hook if it would never change the
! comparison code or operands.
! @end deftypefn
@defmac REVERSIBLE_CC_MODE (@var{mode})
A C expression whose value is one if it is always safe to reverse a
^ permalink raw reply [flat|nested] 6+ messages in thread
* [PING] Bugfix: Additional parameter for canonicalize comparison
2012-12-12 11:23 [PATCH] Bugfix: Additional parameter for canonicalize comparison Andreas Krebbel
@ 2012-12-19 9:53 ` Andreas Krebbel
2012-12-19 11:34 ` Richard Earnshaw
0 siblings, 1 reply; 6+ messages in thread
From: Andreas Krebbel @ 2012-12-19 9:53 UTC (permalink / raw)
To: nickc, richard.earnshaw, paul, ramana.radhakrishnan, gcc-patches
Hi,
are the ARM parts of the patch below ok for mainline?
I did a compile test with a cross.
Bye,
-Andreas-
-------- Original Message --------
Subject: [PATCH] Bugfix: Additional parameter for canonicalize comparison
Date: Wed, 12 Dec 2012 12:23:14 +0100
From: Andreas Krebbel <krebbel@linux.vnet.ibm.com>
To: rearnsha@arm.com
CC: gcc-patches@gcc.gnu.org
Hi Richard,
is the attached patch ok for ARM?
Bye,
-Andreas-
2012-12-12 Andreas Krebbel <Andreas.Krebbel@de.ibm.com>
* target.def: Define canonicalize_comparison hook.
* targhooks.h (default_canonicalize_comparison): New prototype.
* targhooks.c (default_canonicalize_comparison): New function.
* doc/tm.texi: Add documentation for the new target hook.
* doc/tm.texi.in: Likewise.
* combine.c (try_combine): Adjust to use the target hook.
* config/alpha/alpha.h (CANONICALIZE_COMPARISON): Remove macro
definition.
* config/alpha/alpha.c (alpha_canonicalize_comparison): New
function.
(TARGET_CANONICALIZE_COMPARISON): New macro definition.
* config/arm/arm-protos.h (arm_canonicalize_comparison): Remove
prototype.
* config/arm/arm.c (arm_canonicalize_comparison): Add new
parameter.
(TARGET_CANONICALIZE_COMPARISON): New macro definition.
* config/arm/arm.h (CANONICALIZE_COMPARISON): Remove macro
definition.
* config/s390/s390-protos.h (s390_canonicalize_comparison): Remove
prototype.
* config/s390/s390.c (s390_canonicalize_comparison): Add new
parameter.
(TARGET_CANONICALIZE_COMPARISON): New macro definition.
* config/s390/s390.h (CANONICALIZE_COMPARISON): Remove macro
definition.
* config/sh/sh-protos.h (sh_canonicalize_comparison): Remove
prototype.
* config/sh/sh.c (sh_canonicalize_comparison): Add new prototype. New
function overloading the old one.
(TARGET_CANONICALIZE_COMPARISON): New macro definition.
* config/sh/sh.h (CANONICALIZE_COMPARISON): Remove macro
definition.
* config/spu/spu.c (spu_canonicalize_comparison): New function.
(TARGET_CANONICALIZE_COMPARISON): New macro definition.
* config/spu/spu.h (CANONICALIZE_COMPARISON): Remove macro
definition.
---
gcc/combine.c | 19 ++++++-!!!
gcc/config/alpha/alpha.c | 27 ++++++++++++++++
gcc/config/alpha/alpha.h | 20 ------------
gcc/config/arm/arm-protos.h | 1
gcc/config/arm/arm.c | 68 ++-!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
gcc/config/arm/arm.h | 3 -
gcc/config/s390/s390-protos.h | 1
gcc/config/s390/s390.c | 13 +++!!!!!
gcc/config/s390/s390.h | 4 --
gcc/config/sh/sh-protos.h | 2 -
gcc/config/sh/sh.c | 34 +++++++++++!!!!!!!!!!
gcc/config/sh/sh.h | 4 --
gcc/config/spu/spu.c | 17 ++++++++++
gcc/config/spu/spu.h | 12 -------
gcc/doc/tm.texi | 20 !!!!!!!!!!!!
gcc/doc/tm.texi.in | 20 !!!!!!!!!!!!
gcc/target.def | 8 ++++
gcc/targhooks.h | 2 +
18 files changed, 94 insertions(+), 50 deletions(-), 131 modifications(!)
Index: gcc/combine.c
===================================================================
*** gcc/combine.c.orig
--- gcc/combine.c
*************** static rtx gen_lowpart_or_truncate (enum
*** 494,499 ****
--- 494,510 ----
static const struct rtl_hooks combine_rtl_hooks = RTL_HOOKS_INITIALIZER;
\f
+ /* Convenience wrapper for the canonicalize_comparison target hook.
+ Target hooks cannot use enum rtx_code. */
+ static inline void
+ target_canonicalize_comparison (enum rtx_code *code, rtx *op0, rtx *op1,
+ bool op0_preserve_value)
+ {
+ int code_int = (int)*code;
+ targetm.canonicalize_comparison (&code_int, op0, op1, op0_preserve_value);
+ *code = (enum rtx_code)code_int;
+ }
+
/* Try to split PATTERN found in INSN. This returns NULL_RTX if
PATTERN can not be split. Otherwise, it returns an insn sequence.
This is a wrapper around split_insns which ensures that the
*************** try_combine (rtx i3, rtx i2, rtx i1, rtx
*** 2944,2952 ****
compare_code = orig_compare_code = GET_CODE (*cc_use_loc);
compare_code = simplify_compare_const (compare_code,
op0, &op1);
! #ifdef CANONICALIZE_COMPARISON
! CANONICALIZE_COMPARISON (compare_code, op0, op1);
! #endif
}
/* Do the rest only if op1 is const0_rtx, which may be the
--- 2955,2961 ----
compare_code = orig_compare_code = GET_CODE (*cc_use_loc);
compare_code = simplify_compare_const (compare_code,
op0, &op1);
! target_canonicalize_comparison (&compare_code, &op0, &op1, 1);
}
/* Do the rest only if op1 is const0_rtx, which may be the
*************** simplify_comparison (enum rtx_code code,
*** 11959,11969 ****
}
}
- #ifdef CANONICALIZE_COMPARISON
/* If this machine only supports a subset of valid comparisons, see if we
can convert an unsupported one into a supported one. */
! CANONICALIZE_COMPARISON (code, op0, op1);
! #endif
*pop0 = op0;
*pop1 = op1;
--- 11968,11976 ----
}
}
/* If this machine only supports a subset of valid comparisons, see if we
can convert an unsupported one into a supported one. */
! target_canonicalize_comparison (&code, &op0, &op1, 0);
*pop0 = op0;
*pop1 = op1;
Index: gcc/config/alpha/alpha.c
===================================================================
*** gcc/config/alpha/alpha.c.orig
--- gcc/config/alpha/alpha.c
*************** alpha_conditional_register_usage (void)
*** 9683,9688 ****
--- 9683,9712 ----
for (i = 32; i < 63; i++)
fixed_regs[i] = call_used_regs[i] = 1;
}
+
+ /* Canonicalize a comparison from one we don't have to one we do have. */
+
+ static void
+ alpha_canonicalize_comparison (int *code, rtx *op0, rtx *op1,
+ bool op0_preserve_value)
+ {
+ if (!op0_preserve_value
+ && (*code == GE || *code == GT || *code == GEU || *code == GTU)
+ && (REG_P (*op1) || *op1 == const0_rtx))
+ {
+ rtx tem = *op0;
+ *op0 = *op1;
+ *op1 = tem;
+ *code = (int)swap_condition ((enum rtx_code)*code);
+ }
+
+ if ((*code == LT || *code == LTU)
+ && CONST_INT_P (*op1) && INTVAL (*op1) == 256)
+ {
+ *code = *code == LT ? LE : LEU;
+ *op1 = GEN_INT (255);
+ }
+ }
\f
/* Initialize the GCC target structure. */
#if TARGET_ABI_OPEN_VMS
*************** alpha_conditional_register_usage (void)
*** 9850,9855 ****
--- 9874,9882 ----
#undef TARGET_CONDITIONAL_REGISTER_USAGE
#define TARGET_CONDITIONAL_REGISTER_USAGE alpha_conditional_register_usage
+ #undef TARGET_CANONICALIZE_COMPARISON
+ #define TARGET_CANONICALIZE_COMPARISON alpha_canonicalize_comparison
+
struct gcc_target targetm = TARGET_INITIALIZER;
\f
Index: gcc/config/alpha/alpha.h
===================================================================
*** gcc/config/alpha/alpha.h.orig
--- gcc/config/alpha/alpha.h
*************** do { \
*** 922,947 ****
#define FLOAT_STORE_FLAG_VALUE(MODE) \
REAL_VALUE_ATOF ((TARGET_FLOAT_VAX ? "0.5" : "2.0"), (MODE))
- /* Canonicalize a comparison from one we don't have to one we do have. */
-
- #define CANONICALIZE_COMPARISON(CODE,OP0,OP1) \
- do { \
- if (((CODE) == GE || (CODE) == GT || (CODE) == GEU || (CODE) == GTU) \
- && (REG_P (OP1) || (OP1) == const0_rtx)) \
- { \
- rtx tem = (OP0); \
- (OP0) = (OP1); \
- (OP1) = tem; \
- (CODE) = swap_condition (CODE); \
- } \
- if (((CODE) == LT || (CODE) == LTU) \
- && CONST_INT_P (OP1) && INTVAL (OP1) == 256) \
- { \
- (CODE) = (CODE) == LT ? LE : LEU; \
- (OP1) = GEN_INT (255); \
- } \
- } while (0)
-
/* Specify the machine mode that pointers have.
After generation of rtl, the compiler makes no further distinction
between pointers and any other objects of this machine mode. */
--- 922,927 ----
Index: gcc/config/arm/arm-protos.h
===================================================================
*** gcc/config/arm/arm-protos.h.orig
--- gcc/config/arm/arm-protos.h
*************** extern int const_ok_for_op (HOST_WIDE_IN
*** 53,59 ****
extern int const_ok_for_dimode_op (HOST_WIDE_INT, enum rtx_code);
extern int arm_split_constant (RTX_CODE, enum machine_mode, rtx,
HOST_WIDE_INT, rtx, rtx, int);
- extern RTX_CODE arm_canonicalize_comparison (RTX_CODE, rtx *, rtx *);
extern int legitimate_pic_operand_p (rtx);
extern rtx legitimize_pic_address (rtx, enum machine_mode, rtx);
extern rtx legitimize_tls_address (rtx, rtx);
--- 53,58 ----
Index: gcc/config/arm/arm.c
===================================================================
*** gcc/config/arm/arm.c.orig
--- gcc/config/arm/arm.c
*************** static int arm_cortex_a5_branch_cost (bo
*** 269,275 ****
static bool arm_vectorize_vec_perm_const_ok (enum machine_mode vmode,
const unsigned char *sel);
!
\f
/* Table of machine attributes. */
static const struct attribute_spec arm_attribute_table[] =
--- 269,276 ----
static bool arm_vectorize_vec_perm_const_ok (enum machine_mode vmode,
const unsigned char *sel);
! static void arm_canonicalize_comparison (int *code, rtx *op0, rtx *op1,
! bool op0_preserve_value);
\f
/* Table of machine attributes. */
static const struct attribute_spec arm_attribute_table[] =
*************** static const struct attribute_spec arm_a
*** 626,631 ****
--- 627,636 ----
#define TARGET_VECTORIZE_VEC_PERM_CONST_OK \
arm_vectorize_vec_perm_const_ok
+ #undef TARGET_CANONICALIZE_COMPARISON
+ #define TARGET_CANONICALIZE_COMPARISON \
+ arm_canonicalize_comparison
+
struct gcc_target targetm = TARGET_INITIALIZER;
\f
/* Obstack for minipool constant handling. */
*************** arm_gen_constant (enum rtx_code code, en
*** 3543,3550 ****
This can be done for a few constant compares, where we can make the
immediate value easier to load. */
! enum rtx_code
! arm_canonicalize_comparison (enum rtx_code code, rtx *op0, rtx *op1)
{
enum machine_mode mode;
unsigned HOST_WIDE_INT i, maxval;
--- 3548,3556 ----
This can be done for a few constant compares, where we can make the
immediate value easier to load. */
! static void
! arm_canonicalize_comparison (int *code, rtx *op0, rtx *op1,
! bool op0_preserve_value)
{
enum machine_mode mode;
unsigned HOST_WIDE_INT i, maxval;
*************** arm_canonicalize_comparison (enum rtx_co
*** 3563,3577 ****
{
rtx tem;
! if (code == GT || code == LE
! || (!TARGET_ARM && (code == GTU || code == LEU)))
{
/* Missing comparison. First try to use an available
comparison. */
if (CONST_INT_P (*op1))
{
i = INTVAL (*op1);
! switch (code)
{
case GT:
case LE:
--- 3569,3583 ----
{
rtx tem;
! if (*code == GT || *code == LE
! || (!TARGET_ARM && (*code == GTU || *code == LEU)))
{
/* Missing comparison. First try to use an available
comparison. */
if (CONST_INT_P (*op1))
{
i = INTVAL (*op1);
! switch (*code)
{
case GT:
case LE:
*************** arm_canonicalize_comparison (enum rtx_co
*** 3579,3585 ****
&& arm_const_double_by_immediates (GEN_INT (i + 1)))
{
*op1 = GEN_INT (i + 1);
! return code == GT ? GE : LT;
}
break;
case GTU:
--- 3585,3592 ----
&& arm_const_double_by_immediates (GEN_INT (i + 1)))
{
*op1 = GEN_INT (i + 1);
! *code = *code == GT ? GE : LT;
! return;
}
break;
case GTU:
*************** arm_canonicalize_comparison (enum rtx_co
*** 3588,3594 ****
&& arm_const_double_by_immediates (GEN_INT (i + 1)))
{
*op1 = GEN_INT (i + 1);
! return code == GTU ? GEU : LTU;
}
break;
default:
--- 3595,3602 ----
&& arm_const_double_by_immediates (GEN_INT (i + 1)))
{
*op1 = GEN_INT (i + 1);
! *code = *code == GTU ? GEU : LTU;
! return;
}
break;
default:
*************** arm_canonicalize_comparison (enum rtx_co
*** 3597,3615 ****
}
/* If that did not work, reverse the condition. */
! tem = *op0;
! *op0 = *op1;
! *op1 = tem;
! return swap_condition (code);
}
!
! return code;
}
/* If *op0 is (zero_extend:SI (subreg:QI (reg:SI) 0)) and comparing
with const0_rtx, change it to (and:SI (reg:SI) (const_int 255)),
to facilitate possible combining with a cmp into 'ands'. */
! if (mode == SImode
&& GET_CODE (*op0) == ZERO_EXTEND
&& GET_CODE (XEXP (*op0, 0)) == SUBREG
&& GET_MODE (XEXP (*op0, 0)) == QImode
--- 3605,3626 ----
}
/* If that did not work, reverse the condition. */
! if (!op0_preserve_value)
! {
! tem = *op0;
! *op0 = *op1;
! *op1 = tem;
! *code = (int)swap_condition ((enum rtx_code)*code);
! }
}
! return;
}
/* If *op0 is (zero_extend:SI (subreg:QI (reg:SI) 0)) and comparing
with const0_rtx, change it to (and:SI (reg:SI) (const_int 255)),
to facilitate possible combining with a cmp into 'ands'. */
! if (!op0_preserve_value
! && mode == SImode
&& GET_CODE (*op0) == ZERO_EXTEND
&& GET_CODE (XEXP (*op0, 0)) == SUBREG
&& GET_MODE (XEXP (*op0, 0)) == QImode
*************** arm_canonicalize_comparison (enum rtx_co
*** 3624,3638 ****
if (!CONST_INT_P (*op1)
|| const_ok_for_arm (INTVAL (*op1))
|| const_ok_for_arm (- INTVAL (*op1)))
! return code;
i = INTVAL (*op1);
! switch (code)
{
case EQ:
case NE:
! return code;
case GT:
case LE:
--- 3635,3649 ----
if (!CONST_INT_P (*op1)
|| const_ok_for_arm (INTVAL (*op1))
|| const_ok_for_arm (- INTVAL (*op1)))
! return;
i = INTVAL (*op1);
! switch (*code)
{
case EQ:
case NE:
! return;
case GT:
case LE:
*************** arm_canonicalize_comparison (enum rtx_co
*** 3640,3646 ****
&& (const_ok_for_arm (i + 1) || const_ok_for_arm (-(i + 1))))
{
*op1 = GEN_INT (i + 1);
! return code == GT ? GE : LT;
}
break;
--- 3651,3658 ----
&& (const_ok_for_arm (i + 1) || const_ok_for_arm (-(i + 1))))
{
*op1 = GEN_INT (i + 1);
! *code = *code == GT ? GE : LT;
! return;
}
break;
*************** arm_canonicalize_comparison (enum rtx_co
*** 3650,3656 ****
&& (const_ok_for_arm (i - 1) || const_ok_for_arm (-(i - 1))))
{
*op1 = GEN_INT (i - 1);
! return code == GE ? GT : LE;
}
break;
--- 3662,3669 ----
&& (const_ok_for_arm (i - 1) || const_ok_for_arm (-(i - 1))))
{
*op1 = GEN_INT (i - 1);
! *code = *code == GE ? GT : LE;
! return;
}
break;
*************** arm_canonicalize_comparison (enum rtx_co
*** 3660,3666 ****
&& (const_ok_for_arm (i + 1) || const_ok_for_arm (-(i + 1))))
{
*op1 = GEN_INT (i + 1);
! return code == GTU ? GEU : LTU;
}
break;
--- 3673,3680 ----
&& (const_ok_for_arm (i + 1) || const_ok_for_arm (-(i + 1))))
{
*op1 = GEN_INT (i + 1);
! *code = *code == GTU ? GEU : LTU;
! return;
}
break;
*************** arm_canonicalize_comparison (enum rtx_co
*** 3670,3684 ****
&& (const_ok_for_arm (i - 1) || const_ok_for_arm (-(i - 1))))
{
*op1 = GEN_INT (i - 1);
! return code == GEU ? GTU : LEU;
}
break;
default:
gcc_unreachable ();
}
-
- return code;
}
--- 3684,3697 ----
&& (const_ok_for_arm (i - 1) || const_ok_for_arm (-(i - 1))))
{
*op1 = GEN_INT (i - 1);
! *code = *code == GEU ? GTU : LEU;
! return;
}
break;
default:
gcc_unreachable ();
}
}
*************** bool
*** 26979,26985 ****
arm_validize_comparison (rtx *comparison, rtx * op1, rtx * op2)
{
enum rtx_code code = GET_CODE (*comparison);
! enum rtx_code canonical_code;
enum machine_mode mode = (GET_MODE (*op1) == VOIDmode)
? GET_MODE (*op2) : GET_MODE (*op1);
--- 26992,26998 ----
arm_validize_comparison (rtx *comparison, rtx * op1, rtx * op2)
{
enum rtx_code code = GET_CODE (*comparison);
! int code_int;
enum machine_mode mode = (GET_MODE (*op1) == VOIDmode)
? GET_MODE (*op2) : GET_MODE (*op1);
*************** arm_validize_comparison (rtx *comparison
*** 26988,26995 ****
if (code == UNEQ || code == LTGT)
return false;
! canonical_code = arm_canonicalize_comparison (code, op1, op2);
! PUT_CODE (*comparison, canonical_code);
switch (mode)
{
--- 27001,27009 ----
if (code == UNEQ || code == LTGT)
return false;
! code_int = (int)code;
! arm_canonicalize_comparison (&code_int, op1, op2, 0);
! PUT_CODE (*comparison, (enum rtx_code)code_int);
switch (mode)
{
Index: gcc/config/arm/arm.h
===================================================================
*** gcc/config/arm/arm.h.orig
--- gcc/config/arm/arm.h
*************** extern int making_const_table;
*** 2078,2086 ****
? reverse_condition_maybe_unordered (code) \
: reverse_condition (code))
- #define CANONICALIZE_COMPARISON(CODE, OP0, OP1) \
- (CODE) = arm_canonicalize_comparison (CODE, &(OP0), &(OP1))
-
/* The arm5 clz instruction returns 32. */
#define CLZ_DEFINED_VALUE_AT_ZERO(MODE, VALUE) ((VALUE) = 32, 1)
#define CTZ_DEFINED_VALUE_AT_ZERO(MODE, VALUE) ((VALUE) = 32, 1)
--- 2078,2083 ----
Index: gcc/config/s390/s390-protos.h
===================================================================
*** gcc/config/s390/s390-protos.h.orig
--- gcc/config/s390/s390-protos.h
*************** extern int tls_symbolic_operand (rtx);
*** 58,64 ****
extern bool s390_match_ccmode (rtx, enum machine_mode);
extern enum machine_mode s390_tm_ccmode (rtx, rtx, bool);
extern enum machine_mode s390_select_ccmode (enum rtx_code, rtx, rtx);
- extern void s390_canonicalize_comparison (enum rtx_code *, rtx *, rtx *);
extern rtx s390_emit_compare (enum rtx_code, rtx, rtx);
extern void s390_emit_jump (rtx, rtx);
extern bool symbolic_reference_mentioned_p (rtx);
--- 58,63 ----
Index: gcc/config/s390/s390.c
===================================================================
*** gcc/config/s390/s390.c.orig
--- gcc/config/s390/s390.c
*************** s390_select_ccmode (enum rtx_code code,
*** 745,753 ****
/* Replace the comparison OP0 CODE OP1 by a semantically equivalent one
that we can implement more efficiently. */
! void
! s390_canonicalize_comparison (enum rtx_code *code, rtx *op0, rtx *op1)
{
/* Convert ZERO_EXTRACT back to AND to enable TM patterns. */
if ((*code == EQ || *code == NE)
&& *op1 == const0_rtx
--- 745,757 ----
/* Replace the comparison OP0 CODE OP1 by a semantically equivalent one
that we can implement more efficiently. */
! static void
! s390_canonicalize_comparison (int *code, rtx *op0, rtx *op1,
! bool op0_preserve_value)
{
+ if (op0_preserve_value)
+ return;
+
/* Convert ZERO_EXTRACT back to AND to enable TM patterns. */
if ((*code == EQ || *code == NE)
&& *op1 == const0_rtx
*************** s390_canonicalize_comparison (enum rtx_c
*** 894,900 ****
if (MEM_P (*op0) && REG_P (*op1))
{
rtx tem = *op0; *op0 = *op1; *op1 = tem;
! *code = swap_condition (*code);
}
}
--- 898,904 ----
if (MEM_P (*op0) && REG_P (*op1))
{
rtx tem = *op0; *op0 = *op1; *op1 = tem;
! *code = (int)swap_condition ((enum rtx_code)*code);
}
}
*************** s390_loop_unroll_adjust (unsigned nunrol
*** 11071,11076 ****
--- 11075,11083 ----
#undef TARGET_UNWIND_WORD_MODE
#define TARGET_UNWIND_WORD_MODE s390_unwind_word_mode
+ #undef TARGET_CANONICALIZE_COMPARISON
+ #define TARGET_CANONICALIZE_COMPARISON s390_canonicalize_comparison
+
struct gcc_target targetm = TARGET_INITIALIZER;
#include "gt-s390.h"
Index: gcc/config/s390/s390.h
===================================================================
*** gcc/config/s390/s390.h.orig
--- gcc/config/s390/s390.h
*************** do { \
*** 720,729 ****
return the mode to be used for the comparison. */
#define SELECT_CC_MODE(OP, X, Y) s390_select_ccmode ((OP), (X), (Y))
- /* Canonicalize a comparison from one we don't have to one we do have. */
- #define CANONICALIZE_COMPARISON(CODE, OP0, OP1) \
- s390_canonicalize_comparison (&(CODE), &(OP0), &(OP1))
-
/* Relative costs of operations. */
/* A C expression for the cost of a branch instruction. A value of 1
--- 720,725 ----
Index: gcc/config/sh/sh-protos.h
===================================================================
*** gcc/config/sh/sh-protos.h.orig
--- gcc/config/sh/sh-protos.h
*************** extern bool sh_expand_t_scc (rtx *);
*** 159,166 ****
extern rtx sh_gen_truncate (enum machine_mode, rtx, int);
extern bool sh_vector_mode_supported_p (enum machine_mode);
extern bool sh_cfun_trap_exit_p (void);
- extern void sh_canonicalize_comparison (enum rtx_code&, rtx&, rtx&,
- enum machine_mode mode = VOIDmode);
extern rtx sh_find_equiv_gbr_addr (rtx cur_insn, rtx mem);
extern int sh_eval_treg_value (rtx op);
--- 159,164 ----
Index: gcc/config/sh/sh.c
===================================================================
*** gcc/config/sh/sh.c.orig
--- gcc/config/sh/sh.c
*************** static int max_mov_insn_displacement (en
*** 314,319 ****
--- 314,322 ----
static int mov_insn_alignment_mask (enum machine_mode, bool);
static HOST_WIDE_INT disp_addr_displacement (rtx);
static bool sequence_insn_p (rtx);
+ static void sh_canonicalize_comparison (int *, rtx *, rtx *, bool);
+ static void sh_canonicalize_comparison (enum rtx_code&, rtx&, rtx&,
+ enum machine_mode, bool);
static void sh_init_sync_libfuncs (void) ATTRIBUTE_UNUSED;
\f
*************** static const struct attribute_spec sh_at
*** 586,591 ****
--- 589,597 ----
#undef TARGET_LEGITIMATE_CONSTANT_P
#define TARGET_LEGITIMATE_CONSTANT_P sh_legitimate_constant_p
+ #undef TARGET_CANONICALIZE_COMPARISON
+ #define TARGET_CANONICALIZE_COMPARISON sh_canonicalize_comparison
+
/* Machine-specific symbol_ref flags. */
#define SYMBOL_FLAG_FUNCVEC_FUNCTION (SYMBOL_FLAG_MACH_DEP << 0)
*************** prepare_move_operands (rtx operands[], e
*** 1909,1920 ****
}
}
! /* Implement the CANONICALIZE_COMPARISON macro for the combine pass.
! This function is also re-used to canonicalize comparisons in cbranch
! pattern expanders. */
! void
sh_canonicalize_comparison (enum rtx_code& cmp, rtx& op0, rtx& op1,
! enum machine_mode mode)
{
/* When invoked from within the combine pass the mode is not specified,
so try to get it from one of the operands. */
--- 1915,1928 ----
}
}
! /* Implement the canonicalize_comparison target hook for the combine
! pass. For the target hook this function is invoked via
! sh_canonicalize_comparison. This function is also re-used to
! canonicalize comparisons in cbranch pattern expanders. */
! static void
sh_canonicalize_comparison (enum rtx_code& cmp, rtx& op0, rtx& op1,
! enum machine_mode mode,
! bool op0_preserve_value ATTRIBUTE_UNUSED)
{
/* When invoked from within the combine pass the mode is not specified,
so try to get it from one of the operands. */
*************** sh_canonicalize_comparison (enum rtx_cod
*** 2008,2013 ****
--- 2016,2034 ----
}
}
+ /* This function implements the canonicalize_comparison target hook.
+ This wrapper around the internally used sh_canonicalize_comparison
+ function is needed to do the enum rtx_code <-> int conversion.
+ Target hooks cannot use enum rtx_code in its definition. */
+ static void
+ sh_canonicalize_comparison (int *code, rtx *op0, rtx *op1,
+ bool op0_preserve_value)
+ {
+ enum rtx_code tmp_code = (enum rtx_code)*code;
+ sh_canonicalize_comparison (tmp_code, *op0, *op1,
+ VOIDmode, op0_preserve_value);
+ *code = (int)tmp_code;
+ }
enum rtx_code
prepare_cbranch_operands (rtx *operands, enum machine_mode mode,
enum rtx_code comparison)
*************** prepare_cbranch_operands (rtx *operands,
*** 2021,2027 ****
else
scratch = operands[4];
! sh_canonicalize_comparison (comparison, operands[1], operands[2], mode);
/* Notice that this function is also invoked after reload by
the cbranchdi4_i pattern, through expand_cbranchdi4. */
--- 2042,2049 ----
else
scratch = operands[4];
! sh_canonicalize_comparison (comparison, operands[1], operands[2],
! mode, false);
/* Notice that this function is also invoked after reload by
the cbranchdi4_i pattern, through expand_cbranchdi4. */
Index: gcc/config/sh/sh.h
===================================================================
*** gcc/config/sh/sh.h.orig
--- gcc/config/sh/sh.h
*************** struct sh_args {
*** 1873,1882 ****
more compact code. */
#define SHIFT_COUNT_TRUNCATED (0)
- /* CANONICALIZE_COMPARISON macro for the combine pass. */
- #define CANONICALIZE_COMPARISON(CODE, OP0, OP1) \
- sh_canonicalize_comparison ((CODE), (OP0), (OP1))
-
/* All integers have the same format so truncation is easy. */
/* But SHmedia must sign-extend DImode when truncating to SImode. */
#define TRULY_NOOP_TRUNCATION(OUTPREC,INPREC) \
--- 1873,1878 ----
Index: gcc/config/spu/spu.c
===================================================================
*** gcc/config/spu/spu.c.orig
--- gcc/config/spu/spu.c
*************** spu_output_mi_thunk (FILE *file, tree th
*** 7095,7100 ****
--- 7095,7114 ----
final_end_function ();
}
+ /* Canonicalize a comparison from one we don't have to one we do have. */
+ static void
+ spu_canonicalize_comparison (int *code, rtx *op0, rtx *op1,
+ bool op0_preserve_value)
+ {
+ if (!op0_preserve_value
+ && (*code == LE || *code == LT || *code == LEU || *code == LTU))
+ {
+ rtx tem = *op0;
+ *op0 = *op1;
+ *op1 = tem;
+ *code = (int)swap_condition ((enum rtx_code)*code);
+ }
+ }
\f
/* Table of machine attributes. */
static const struct attribute_spec spu_attribute_table[] =
*************** static const struct attribute_spec spu_a
*** 7308,7313 ****
--- 7322,7330 ----
#undef TARGET_DELAY_VARTRACK
#define TARGET_DELAY_VARTRACK true
+ #undef TARGET_CANONICALIZE_COMPARISON
+ #define TARGET_CANONICALIZE_COMPARISON spu_canonicalize_comparison
+
struct gcc_target targetm = TARGET_INITIALIZER;
#include "gt-spu.h"
Index: gcc/config/spu/spu.h
===================================================================
*** gcc/config/spu/spu.h.orig
--- gcc/config/spu/spu.h
*************** do { \
*** 520,537 ****
#define NO_IMPLICIT_EXTERN_C 1
- /* Canonicalize a comparison from one we don't have to one we do have. */
- #define CANONICALIZE_COMPARISON(CODE,OP0,OP1) \
- do { \
- if (((CODE) == LE || (CODE) == LT || (CODE) == LEU || (CODE) == LTU)) \
- { \
- rtx tem = (OP0); \
- (OP0) = (OP1); \
- (OP1) = tem; \
- (CODE) = swap_condition (CODE); \
- } \
- } while (0)
-
/* Address spaces. */
#define ADDR_SPACE_EA 1
--- 520,525 ----
Index: gcc/doc/tm.texi.in
===================================================================
*** gcc/doc/tm.texi.in.orig
--- gcc/doc/tm.texi.in
*************** You should define this macro if and only
*** 5928,5952 ****
in @file{@var{machine}-modes.def}.
@end defmac
! @defmac CANONICALIZE_COMPARISON (@var{code}, @var{op0}, @var{op1})
On some machines not all possible comparisons are defined, but you can
convert an invalid comparison into a valid one. For example, the Alpha
does not have a @code{GT} comparison, but you can use an @code{LT}
comparison instead and swap the order of the operands.
! On such machines, define this macro to be a C statement to do any
! required conversions. @var{code} is the initial comparison code
! and @var{op0} and @var{op1} are the left and right operands of the
! comparison, respectively. You should modify @var{code}, @var{op0}, and
! @var{op1} as required.
GCC will not assume that the comparison resulting from this macro is
valid but will see if the resulting insn matches a pattern in the
@file{md} file.
! You need not define this macro if it would never change the comparison
! code or operands.
! @end defmac
@defmac REVERSIBLE_CC_MODE (@var{mode})
A C expression whose value is one if it is always safe to reverse a
--- 5928,5954 ----
in @file{@var{machine}-modes.def}.
@end defmac
! @hook TARGET_CANONICALIZE_COMPARISON (@var{code}, @var{op0}, @var{op1}, @var{op0_preserve_value})
On some machines not all possible comparisons are defined, but you can
convert an invalid comparison into a valid one. For example, the Alpha
does not have a @code{GT} comparison, but you can use an @code{LT}
comparison instead and swap the order of the operands.
! On such machines, implement this hook to do any required conversions.
! @var{code} is the initial comparison code and @var{op0} and @var{op1}
! are the left and right operands of the comparison, respectively. If
! @var{op0_preserve_value} is @code{true} the implementation is not
! allowed to change the value of @var{op0} since the value might be used
! in RTXs which aren't comparisons. E.g. the implementation is not
! allowed to swap operands in that case.
GCC will not assume that the comparison resulting from this macro is
valid but will see if the resulting insn matches a pattern in the
@file{md} file.
! You need not to implement this hook if it would never change the
! comparison code or operands.
! @end deftypefn
@defmac REVERSIBLE_CC_MODE (@var{mode})
A C expression whose value is one if it is always safe to reverse a
Index: gcc/target.def
===================================================================
*** gcc/target.def.orig
--- gcc/target.def
*************** DEFHOOK
*** 2877,2882 ****
--- 2877,2890 ----
enum unwind_info_type, (void),
default_debug_unwind_info)
+ /* The code parameter should be of type enum rtx_code but this is not
+ defined at this time. */
+ DEFHOOK
+ (canonicalize_comparison,
+ "",
+ void, (int *code, rtx *op0, rtx *op1, bool op0_preserve_value),
+ default_canonicalize_comparison)
+
DEFHOOKPOD
(atomic_test_and_set_trueval,
"This value should be set if the result written by\
Index: gcc/targhooks.h
===================================================================
*** gcc/targhooks.h.orig
--- gcc/targhooks.h
*************** extern unsigned char default_class_max_n
*** 179,184 ****
--- 179,186 ----
extern enum unwind_info_type default_debug_unwind_info (void);
+ extern bool default_canonicalize_comparison (int *, rtx *, rtx *, bool);
+
extern int default_label_align_after_barrier_max_skip (rtx);
extern int default_loop_align_max_skip (rtx);
extern int default_label_align_max_skip (rtx);
Index: gcc/doc/tm.texi
===================================================================
*** gcc/doc/tm.texi.orig
--- gcc/doc/tm.texi
*************** You should define this macro if and only
*** 6024,6048 ****
in @file{@var{machine}-modes.def}.
@end defmac
! @defmac CANONICALIZE_COMPARISON (@var{code}, @var{op0}, @var{op1})
On some machines not all possible comparisons are defined, but you can
convert an invalid comparison into a valid one. For example, the Alpha
does not have a @code{GT} comparison, but you can use an @code{LT}
comparison instead and swap the order of the operands.
! On such machines, define this macro to be a C statement to do any
! required conversions. @var{code} is the initial comparison code
! and @var{op0} and @var{op1} are the left and right operands of the
! comparison, respectively. You should modify @var{code}, @var{op0}, and
! @var{op1} as required.
GCC will not assume that the comparison resulting from this macro is
valid but will see if the resulting insn matches a pattern in the
@file{md} file.
! You need not define this macro if it would never change the comparison
! code or operands.
! @end defmac
@defmac REVERSIBLE_CC_MODE (@var{mode})
A C expression whose value is one if it is always safe to reverse a
--- 6024,6050 ----
in @file{@var{machine}-modes.def}.
@end defmac
! @deftypefn {Target Hook} void TARGET_CANONICALIZE_COMPARISON (int *@var{code}, rtx *@var{op0}, rtx
*@var{op1}, bool @var{op0_preserve_value}) (@var{code}, @var{op0}, @var{op1}, @var{op0_preserve_value})
On some machines not all possible comparisons are defined, but you can
convert an invalid comparison into a valid one. For example, the Alpha
does not have a @code{GT} comparison, but you can use an @code{LT}
comparison instead and swap the order of the operands.
! On such machines, implement this hook to do any required conversions.
! @var{code} is the initial comparison code and @var{op0} and @var{op1}
! are the left and right operands of the comparison, respectively. If
! @var{op0_preserve_value} is @code{true} the implementation is not
! allowed to change the value of @var{op0} since the value might be used
! in RTXs which aren't comparisons. E.g. the implementation is not
! allowed to swap operands in that case.
GCC will not assume that the comparison resulting from this macro is
valid but will see if the resulting insn matches a pattern in the
@file{md} file.
! You need not to implement this hook if it would never change the
! comparison code or operands.
! @end deftypefn
@defmac REVERSIBLE_CC_MODE (@var{mode})
A C expression whose value is one if it is always safe to reverse a
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PING] Bugfix: Additional parameter for canonicalize comparison
2012-12-19 9:53 ` [PING] " Andreas Krebbel
@ 2012-12-19 11:34 ` Richard Earnshaw
2012-12-19 14:04 ` Richard Biener
0 siblings, 1 reply; 6+ messages in thread
From: Richard Earnshaw @ 2012-12-19 11:34 UTC (permalink / raw)
To: Andreas Krebbel; +Cc: nickc, paul, Ramana Radhakrishnan, gcc-patches
On 19/12/12 09:53, Andreas Krebbel wrote:
> Hi,
>
> are the ARM parts of the patch below ok for mainline?
>
Yes.
Sorry for the delay.
R.
> I did a compile test with a cross.
>
> Bye,
>
> -Andreas-
>
>
> -------- Original Message --------
> Subject: [PATCH] Bugfix: Additional parameter for canonicalize comparison
> Date: Wed, 12 Dec 2012 12:23:14 +0100
> From: Andreas Krebbel <krebbel@linux.vnet.ibm.com>
> To: rearnsha@arm.com
> CC: gcc-patches@gcc.gnu.org
>
> Hi Richard,
>
> is the attached patch ok for ARM?
>
> Bye,
>
> -Andreas-
>
> 2012-12-12 Andreas Krebbel <Andreas.Krebbel@de.ibm.com>
>
> * target.def: Define canonicalize_comparison hook.
> * targhooks.h (default_canonicalize_comparison): New prototype.
> * targhooks.c (default_canonicalize_comparison): New function.
> * doc/tm.texi: Add documentation for the new target hook.
> * doc/tm.texi.in: Likewise.
> * combine.c (try_combine): Adjust to use the target hook.
> * config/alpha/alpha.h (CANONICALIZE_COMPARISON): Remove macro
> definition.
> * config/alpha/alpha.c (alpha_canonicalize_comparison): New
> function.
> (TARGET_CANONICALIZE_COMPARISON): New macro definition.
> * config/arm/arm-protos.h (arm_canonicalize_comparison): Remove
> prototype.
> * config/arm/arm.c (arm_canonicalize_comparison): Add new
> parameter.
> (TARGET_CANONICALIZE_COMPARISON): New macro definition.
> * config/arm/arm.h (CANONICALIZE_COMPARISON): Remove macro
> definition.
> * config/s390/s390-protos.h (s390_canonicalize_comparison): Remove
> prototype.
> * config/s390/s390.c (s390_canonicalize_comparison): Add new
> parameter.
> (TARGET_CANONICALIZE_COMPARISON): New macro definition.
> * config/s390/s390.h (CANONICALIZE_COMPARISON): Remove macro
> definition.
> * config/sh/sh-protos.h (sh_canonicalize_comparison): Remove
> prototype.
> * config/sh/sh.c (sh_canonicalize_comparison): Add new prototype. New
> function overloading the old one.
> (TARGET_CANONICALIZE_COMPARISON): New macro definition.
> * config/sh/sh.h (CANONICALIZE_COMPARISON): Remove macro
> definition.
> * config/spu/spu.c (spu_canonicalize_comparison): New function.
> (TARGET_CANONICALIZE_COMPARISON): New macro definition.
> * config/spu/spu.h (CANONICALIZE_COMPARISON): Remove macro
> definition.
>
> ---
> gcc/combine.c | 19 ++++++-!!!
> gcc/config/alpha/alpha.c | 27 ++++++++++++++++
> gcc/config/alpha/alpha.h | 20 ------------
> gcc/config/arm/arm-protos.h | 1
> gcc/config/arm/arm.c | 68 ++-!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
> gcc/config/arm/arm.h | 3 -
> gcc/config/s390/s390-protos.h | 1
> gcc/config/s390/s390.c | 13 +++!!!!!
> gcc/config/s390/s390.h | 4 --
> gcc/config/sh/sh-protos.h | 2 -
> gcc/config/sh/sh.c | 34 +++++++++++!!!!!!!!!!
> gcc/config/sh/sh.h | 4 --
> gcc/config/spu/spu.c | 17 ++++++++++
> gcc/config/spu/spu.h | 12 -------
> gcc/doc/tm.texi | 20 !!!!!!!!!!!!
> gcc/doc/tm.texi.in | 20 !!!!!!!!!!!!
> gcc/target.def | 8 ++++
> gcc/targhooks.h | 2 +
> 18 files changed, 94 insertions(+), 50 deletions(-), 131 modifications(!)
>
> Index: gcc/combine.c
> ===================================================================
> *** gcc/combine.c.orig
> --- gcc/combine.c
> *************** static rtx gen_lowpart_or_truncate (enum
> *** 494,499 ****
> --- 494,510 ----
> static const struct rtl_hooks combine_rtl_hooks = RTL_HOOKS_INITIALIZER;
>
>
> + /* Convenience wrapper for the canonicalize_comparison target hook.
> + Target hooks cannot use enum rtx_code. */
> + static inline void
> + target_canonicalize_comparison (enum rtx_code *code, rtx *op0, rtx *op1,
> + bool op0_preserve_value)
> + {
> + int code_int = (int)*code;
> + targetm.canonicalize_comparison (&code_int, op0, op1, op0_preserve_value);
> + *code = (enum rtx_code)code_int;
> + }
> +
> /* Try to split PATTERN found in INSN. This returns NULL_RTX if
> PATTERN can not be split. Otherwise, it returns an insn sequence.
> This is a wrapper around split_insns which ensures that the
> *************** try_combine (rtx i3, rtx i2, rtx i1, rtx
> *** 2944,2952 ****
> compare_code = orig_compare_code = GET_CODE (*cc_use_loc);
> compare_code = simplify_compare_const (compare_code,
> op0, &op1);
> ! #ifdef CANONICALIZE_COMPARISON
> ! CANONICALIZE_COMPARISON (compare_code, op0, op1);
> ! #endif
> }
>
> /* Do the rest only if op1 is const0_rtx, which may be the
> --- 2955,2961 ----
> compare_code = orig_compare_code = GET_CODE (*cc_use_loc);
> compare_code = simplify_compare_const (compare_code,
> op0, &op1);
> ! target_canonicalize_comparison (&compare_code, &op0, &op1, 1);
> }
>
> /* Do the rest only if op1 is const0_rtx, which may be the
> *************** simplify_comparison (enum rtx_code code,
> *** 11959,11969 ****
> }
> }
>
> - #ifdef CANONICALIZE_COMPARISON
> /* If this machine only supports a subset of valid comparisons, see if we
> can convert an unsupported one into a supported one. */
> ! CANONICALIZE_COMPARISON (code, op0, op1);
> ! #endif
>
> *pop0 = op0;
> *pop1 = op1;
> --- 11968,11976 ----
> }
> }
>
> /* If this machine only supports a subset of valid comparisons, see if we
> can convert an unsupported one into a supported one. */
> ! target_canonicalize_comparison (&code, &op0, &op1, 0);
>
> *pop0 = op0;
> *pop1 = op1;
> Index: gcc/config/alpha/alpha.c
> ===================================================================
> *** gcc/config/alpha/alpha.c.orig
> --- gcc/config/alpha/alpha.c
> *************** alpha_conditional_register_usage (void)
> *** 9683,9688 ****
> --- 9683,9712 ----
> for (i = 32; i < 63; i++)
> fixed_regs[i] = call_used_regs[i] = 1;
> }
> +
> + /* Canonicalize a comparison from one we don't have to one we do have. */
> +
> + static void
> + alpha_canonicalize_comparison (int *code, rtx *op0, rtx *op1,
> + bool op0_preserve_value)
> + {
> + if (!op0_preserve_value
> + && (*code == GE || *code == GT || *code == GEU || *code == GTU)
> + && (REG_P (*op1) || *op1 == const0_rtx))
> + {
> + rtx tem = *op0;
> + *op0 = *op1;
> + *op1 = tem;
> + *code = (int)swap_condition ((enum rtx_code)*code);
> + }
> +
> + if ((*code == LT || *code == LTU)
> + && CONST_INT_P (*op1) && INTVAL (*op1) == 256)
> + {
> + *code = *code == LT ? LE : LEU;
> + *op1 = GEN_INT (255);
> + }
> + }
>
> /* Initialize the GCC target structure. */
> #if TARGET_ABI_OPEN_VMS
> *************** alpha_conditional_register_usage (void)
> *** 9850,9855 ****
> --- 9874,9882 ----
> #undef TARGET_CONDITIONAL_REGISTER_USAGE
> #define TARGET_CONDITIONAL_REGISTER_USAGE alpha_conditional_register_usage
>
> + #undef TARGET_CANONICALIZE_COMPARISON
> + #define TARGET_CANONICALIZE_COMPARISON alpha_canonicalize_comparison
> +
> struct gcc_target targetm = TARGET_INITIALIZER;
>
>
> Index: gcc/config/alpha/alpha.h
> ===================================================================
> *** gcc/config/alpha/alpha.h.orig
> --- gcc/config/alpha/alpha.h
> *************** do { \
> *** 922,947 ****
> #define FLOAT_STORE_FLAG_VALUE(MODE) \
> REAL_VALUE_ATOF ((TARGET_FLOAT_VAX ? "0.5" : "2.0"), (MODE))
>
> - /* Canonicalize a comparison from one we don't have to one we do have. */
> -
> - #define CANONICALIZE_COMPARISON(CODE,OP0,OP1) \
> - do { \
> - if (((CODE) == GE || (CODE) == GT || (CODE) == GEU || (CODE) == GTU) \
> - && (REG_P (OP1) || (OP1) == const0_rtx)) \
> - { \
> - rtx tem = (OP0); \
> - (OP0) = (OP1); \
> - (OP1) = tem; \
> - (CODE) = swap_condition (CODE); \
> - } \
> - if (((CODE) == LT || (CODE) == LTU) \
> - && CONST_INT_P (OP1) && INTVAL (OP1) == 256) \
> - { \
> - (CODE) = (CODE) == LT ? LE : LEU; \
> - (OP1) = GEN_INT (255); \
> - } \
> - } while (0)
> -
> /* Specify the machine mode that pointers have.
> After generation of rtl, the compiler makes no further distinction
> between pointers and any other objects of this machine mode. */
> --- 922,927 ----
> Index: gcc/config/arm/arm-protos.h
> ===================================================================
> *** gcc/config/arm/arm-protos.h.orig
> --- gcc/config/arm/arm-protos.h
> *************** extern int const_ok_for_op (HOST_WIDE_IN
> *** 53,59 ****
> extern int const_ok_for_dimode_op (HOST_WIDE_INT, enum rtx_code);
> extern int arm_split_constant (RTX_CODE, enum machine_mode, rtx,
> HOST_WIDE_INT, rtx, rtx, int);
> - extern RTX_CODE arm_canonicalize_comparison (RTX_CODE, rtx *, rtx *);
> extern int legitimate_pic_operand_p (rtx);
> extern rtx legitimize_pic_address (rtx, enum machine_mode, rtx);
> extern rtx legitimize_tls_address (rtx, rtx);
> --- 53,58 ----
> Index: gcc/config/arm/arm.c
> ===================================================================
> *** gcc/config/arm/arm.c.orig
> --- gcc/config/arm/arm.c
> *************** static int arm_cortex_a5_branch_cost (bo
> *** 269,275 ****
>
> static bool arm_vectorize_vec_perm_const_ok (enum machine_mode vmode,
> const unsigned char *sel);
> !
>
> /* Table of machine attributes. */
> static const struct attribute_spec arm_attribute_table[] =
> --- 269,276 ----
>
> static bool arm_vectorize_vec_perm_const_ok (enum machine_mode vmode,
> const unsigned char *sel);
> ! static void arm_canonicalize_comparison (int *code, rtx *op0, rtx *op1,
> ! bool op0_preserve_value);
>
> /* Table of machine attributes. */
> static const struct attribute_spec arm_attribute_table[] =
> *************** static const struct attribute_spec arm_a
> *** 626,631 ****
> --- 627,636 ----
> #define TARGET_VECTORIZE_VEC_PERM_CONST_OK \
> arm_vectorize_vec_perm_const_ok
>
> + #undef TARGET_CANONICALIZE_COMPARISON
> + #define TARGET_CANONICALIZE_COMPARISON \
> + arm_canonicalize_comparison
> +
> struct gcc_target targetm = TARGET_INITIALIZER;
>
> /* Obstack for minipool constant handling. */
> *************** arm_gen_constant (enum rtx_code code, en
> *** 3543,3550 ****
> This can be done for a few constant compares, where we can make the
> immediate value easier to load. */
>
> ! enum rtx_code
> ! arm_canonicalize_comparison (enum rtx_code code, rtx *op0, rtx *op1)
> {
> enum machine_mode mode;
> unsigned HOST_WIDE_INT i, maxval;
> --- 3548,3556 ----
> This can be done for a few constant compares, where we can make the
> immediate value easier to load. */
>
> ! static void
> ! arm_canonicalize_comparison (int *code, rtx *op0, rtx *op1,
> ! bool op0_preserve_value)
> {
> enum machine_mode mode;
> unsigned HOST_WIDE_INT i, maxval;
> *************** arm_canonicalize_comparison (enum rtx_co
> *** 3563,3577 ****
> {
> rtx tem;
>
> ! if (code == GT || code == LE
> ! || (!TARGET_ARM && (code == GTU || code == LEU)))
> {
> /* Missing comparison. First try to use an available
> comparison. */
> if (CONST_INT_P (*op1))
> {
> i = INTVAL (*op1);
> ! switch (code)
> {
> case GT:
> case LE:
> --- 3569,3583 ----
> {
> rtx tem;
>
> ! if (*code == GT || *code == LE
> ! || (!TARGET_ARM && (*code == GTU || *code == LEU)))
> {
> /* Missing comparison. First try to use an available
> comparison. */
> if (CONST_INT_P (*op1))
> {
> i = INTVAL (*op1);
> ! switch (*code)
> {
> case GT:
> case LE:
> *************** arm_canonicalize_comparison (enum rtx_co
> *** 3579,3585 ****
> && arm_const_double_by_immediates (GEN_INT (i + 1)))
> {
> *op1 = GEN_INT (i + 1);
> ! return code == GT ? GE : LT;
> }
> break;
> case GTU:
> --- 3585,3592 ----
> && arm_const_double_by_immediates (GEN_INT (i + 1)))
> {
> *op1 = GEN_INT (i + 1);
> ! *code = *code == GT ? GE : LT;
> ! return;
> }
> break;
> case GTU:
> *************** arm_canonicalize_comparison (enum rtx_co
> *** 3588,3594 ****
> && arm_const_double_by_immediates (GEN_INT (i + 1)))
> {
> *op1 = GEN_INT (i + 1);
> ! return code == GTU ? GEU : LTU;
> }
> break;
> default:
> --- 3595,3602 ----
> && arm_const_double_by_immediates (GEN_INT (i + 1)))
> {
> *op1 = GEN_INT (i + 1);
> ! *code = *code == GTU ? GEU : LTU;
> ! return;
> }
> break;
> default:
> *************** arm_canonicalize_comparison (enum rtx_co
> *** 3597,3615 ****
> }
>
> /* If that did not work, reverse the condition. */
> ! tem = *op0;
> ! *op0 = *op1;
> ! *op1 = tem;
> ! return swap_condition (code);
> }
> !
> ! return code;
> }
>
> /* If *op0 is (zero_extend:SI (subreg:QI (reg:SI) 0)) and comparing
> with const0_rtx, change it to (and:SI (reg:SI) (const_int 255)),
> to facilitate possible combining with a cmp into 'ands'. */
> ! if (mode == SImode
> && GET_CODE (*op0) == ZERO_EXTEND
> && GET_CODE (XEXP (*op0, 0)) == SUBREG
> && GET_MODE (XEXP (*op0, 0)) == QImode
> --- 3605,3626 ----
> }
>
> /* If that did not work, reverse the condition. */
> ! if (!op0_preserve_value)
> ! {
> ! tem = *op0;
> ! *op0 = *op1;
> ! *op1 = tem;
> ! *code = (int)swap_condition ((enum rtx_code)*code);
> ! }
> }
> ! return;
> }
>
> /* If *op0 is (zero_extend:SI (subreg:QI (reg:SI) 0)) and comparing
> with const0_rtx, change it to (and:SI (reg:SI) (const_int 255)),
> to facilitate possible combining with a cmp into 'ands'. */
> ! if (!op0_preserve_value
> ! && mode == SImode
> && GET_CODE (*op0) == ZERO_EXTEND
> && GET_CODE (XEXP (*op0, 0)) == SUBREG
> && GET_MODE (XEXP (*op0, 0)) == QImode
> *************** arm_canonicalize_comparison (enum rtx_co
> *** 3624,3638 ****
> if (!CONST_INT_P (*op1)
> || const_ok_for_arm (INTVAL (*op1))
> || const_ok_for_arm (- INTVAL (*op1)))
> ! return code;
>
> i = INTVAL (*op1);
>
> ! switch (code)
> {
> case EQ:
> case NE:
> ! return code;
>
> case GT:
> case LE:
> --- 3635,3649 ----
> if (!CONST_INT_P (*op1)
> || const_ok_for_arm (INTVAL (*op1))
> || const_ok_for_arm (- INTVAL (*op1)))
> ! return;
>
> i = INTVAL (*op1);
>
> ! switch (*code)
> {
> case EQ:
> case NE:
> ! return;
>
> case GT:
> case LE:
> *************** arm_canonicalize_comparison (enum rtx_co
> *** 3640,3646 ****
> && (const_ok_for_arm (i + 1) || const_ok_for_arm (-(i + 1))))
> {
> *op1 = GEN_INT (i + 1);
> ! return code == GT ? GE : LT;
> }
> break;
>
> --- 3651,3658 ----
> && (const_ok_for_arm (i + 1) || const_ok_for_arm (-(i + 1))))
> {
> *op1 = GEN_INT (i + 1);
> ! *code = *code == GT ? GE : LT;
> ! return;
> }
> break;
>
> *************** arm_canonicalize_comparison (enum rtx_co
> *** 3650,3656 ****
> && (const_ok_for_arm (i - 1) || const_ok_for_arm (-(i - 1))))
> {
> *op1 = GEN_INT (i - 1);
> ! return code == GE ? GT : LE;
> }
> break;
>
> --- 3662,3669 ----
> && (const_ok_for_arm (i - 1) || const_ok_for_arm (-(i - 1))))
> {
> *op1 = GEN_INT (i - 1);
> ! *code = *code == GE ? GT : LE;
> ! return;
> }
> break;
>
> *************** arm_canonicalize_comparison (enum rtx_co
> *** 3660,3666 ****
> && (const_ok_for_arm (i + 1) || const_ok_for_arm (-(i + 1))))
> {
> *op1 = GEN_INT (i + 1);
> ! return code == GTU ? GEU : LTU;
> }
> break;
>
> --- 3673,3680 ----
> && (const_ok_for_arm (i + 1) || const_ok_for_arm (-(i + 1))))
> {
> *op1 = GEN_INT (i + 1);
> ! *code = *code == GTU ? GEU : LTU;
> ! return;
> }
> break;
>
> *************** arm_canonicalize_comparison (enum rtx_co
> *** 3670,3684 ****
> && (const_ok_for_arm (i - 1) || const_ok_for_arm (-(i - 1))))
> {
> *op1 = GEN_INT (i - 1);
> ! return code == GEU ? GTU : LEU;
> }
> break;
>
> default:
> gcc_unreachable ();
> }
> -
> - return code;
> }
>
>
> --- 3684,3697 ----
> && (const_ok_for_arm (i - 1) || const_ok_for_arm (-(i - 1))))
> {
> *op1 = GEN_INT (i - 1);
> ! *code = *code == GEU ? GTU : LEU;
> ! return;
> }
> break;
>
> default:
> gcc_unreachable ();
> }
> }
>
>
> *************** bool
> *** 26979,26985 ****
> arm_validize_comparison (rtx *comparison, rtx * op1, rtx * op2)
> {
> enum rtx_code code = GET_CODE (*comparison);
> ! enum rtx_code canonical_code;
> enum machine_mode mode = (GET_MODE (*op1) == VOIDmode)
> ? GET_MODE (*op2) : GET_MODE (*op1);
>
> --- 26992,26998 ----
> arm_validize_comparison (rtx *comparison, rtx * op1, rtx * op2)
> {
> enum rtx_code code = GET_CODE (*comparison);
> ! int code_int;
> enum machine_mode mode = (GET_MODE (*op1) == VOIDmode)
> ? GET_MODE (*op2) : GET_MODE (*op1);
>
> *************** arm_validize_comparison (rtx *comparison
> *** 26988,26995 ****
> if (code == UNEQ || code == LTGT)
> return false;
>
> ! canonical_code = arm_canonicalize_comparison (code, op1, op2);
> ! PUT_CODE (*comparison, canonical_code);
>
> switch (mode)
> {
> --- 27001,27009 ----
> if (code == UNEQ || code == LTGT)
> return false;
>
> ! code_int = (int)code;
> ! arm_canonicalize_comparison (&code_int, op1, op2, 0);
> ! PUT_CODE (*comparison, (enum rtx_code)code_int);
>
> switch (mode)
> {
> Index: gcc/config/arm/arm.h
> ===================================================================
> *** gcc/config/arm/arm.h.orig
> --- gcc/config/arm/arm.h
> *************** extern int making_const_table;
> *** 2078,2086 ****
> ? reverse_condition_maybe_unordered (code) \
> : reverse_condition (code))
>
> - #define CANONICALIZE_COMPARISON(CODE, OP0, OP1) \
> - (CODE) = arm_canonicalize_comparison (CODE, &(OP0), &(OP1))
> -
> /* The arm5 clz instruction returns 32. */
> #define CLZ_DEFINED_VALUE_AT_ZERO(MODE, VALUE) ((VALUE) = 32, 1)
> #define CTZ_DEFINED_VALUE_AT_ZERO(MODE, VALUE) ((VALUE) = 32, 1)
> --- 2078,2083 ----
> Index: gcc/config/s390/s390-protos.h
> ===================================================================
> *** gcc/config/s390/s390-protos.h.orig
> --- gcc/config/s390/s390-protos.h
> *************** extern int tls_symbolic_operand (rtx);
> *** 58,64 ****
> extern bool s390_match_ccmode (rtx, enum machine_mode);
> extern enum machine_mode s390_tm_ccmode (rtx, rtx, bool);
> extern enum machine_mode s390_select_ccmode (enum rtx_code, rtx, rtx);
> - extern void s390_canonicalize_comparison (enum rtx_code *, rtx *, rtx *);
> extern rtx s390_emit_compare (enum rtx_code, rtx, rtx);
> extern void s390_emit_jump (rtx, rtx);
> extern bool symbolic_reference_mentioned_p (rtx);
> --- 58,63 ----
> Index: gcc/config/s390/s390.c
> ===================================================================
> *** gcc/config/s390/s390.c.orig
> --- gcc/config/s390/s390.c
> *************** s390_select_ccmode (enum rtx_code code,
> *** 745,753 ****
> /* Replace the comparison OP0 CODE OP1 by a semantically equivalent one
> that we can implement more efficiently. */
>
> ! void
> ! s390_canonicalize_comparison (enum rtx_code *code, rtx *op0, rtx *op1)
> {
> /* Convert ZERO_EXTRACT back to AND to enable TM patterns. */
> if ((*code == EQ || *code == NE)
> && *op1 == const0_rtx
> --- 745,757 ----
> /* Replace the comparison OP0 CODE OP1 by a semantically equivalent one
> that we can implement more efficiently. */
>
> ! static void
> ! s390_canonicalize_comparison (int *code, rtx *op0, rtx *op1,
> ! bool op0_preserve_value)
> {
> + if (op0_preserve_value)
> + return;
> +
> /* Convert ZERO_EXTRACT back to AND to enable TM patterns. */
> if ((*code == EQ || *code == NE)
> && *op1 == const0_rtx
> *************** s390_canonicalize_comparison (enum rtx_c
> *** 894,900 ****
> if (MEM_P (*op0) && REG_P (*op1))
> {
> rtx tem = *op0; *op0 = *op1; *op1 = tem;
> ! *code = swap_condition (*code);
> }
> }
>
> --- 898,904 ----
> if (MEM_P (*op0) && REG_P (*op1))
> {
> rtx tem = *op0; *op0 = *op1; *op1 = tem;
> ! *code = (int)swap_condition ((enum rtx_code)*code);
> }
> }
>
> *************** s390_loop_unroll_adjust (unsigned nunrol
> *** 11071,11076 ****
> --- 11075,11083 ----
> #undef TARGET_UNWIND_WORD_MODE
> #define TARGET_UNWIND_WORD_MODE s390_unwind_word_mode
>
> + #undef TARGET_CANONICALIZE_COMPARISON
> + #define TARGET_CANONICALIZE_COMPARISON s390_canonicalize_comparison
> +
> struct gcc_target targetm = TARGET_INITIALIZER;
>
> #include "gt-s390.h"
> Index: gcc/config/s390/s390.h
> ===================================================================
> *** gcc/config/s390/s390.h.orig
> --- gcc/config/s390/s390.h
> *************** do { \
> *** 720,729 ****
> return the mode to be used for the comparison. */
> #define SELECT_CC_MODE(OP, X, Y) s390_select_ccmode ((OP), (X), (Y))
>
> - /* Canonicalize a comparison from one we don't have to one we do have. */
> - #define CANONICALIZE_COMPARISON(CODE, OP0, OP1) \
> - s390_canonicalize_comparison (&(CODE), &(OP0), &(OP1))
> -
> /* Relative costs of operations. */
>
> /* A C expression for the cost of a branch instruction. A value of 1
> --- 720,725 ----
> Index: gcc/config/sh/sh-protos.h
> ===================================================================
> *** gcc/config/sh/sh-protos.h.orig
> --- gcc/config/sh/sh-protos.h
> *************** extern bool sh_expand_t_scc (rtx *);
> *** 159,166 ****
> extern rtx sh_gen_truncate (enum machine_mode, rtx, int);
> extern bool sh_vector_mode_supported_p (enum machine_mode);
> extern bool sh_cfun_trap_exit_p (void);
> - extern void sh_canonicalize_comparison (enum rtx_code&, rtx&, rtx&,
> - enum machine_mode mode = VOIDmode);
> extern rtx sh_find_equiv_gbr_addr (rtx cur_insn, rtx mem);
> extern int sh_eval_treg_value (rtx op);
>
> --- 159,164 ----
> Index: gcc/config/sh/sh.c
> ===================================================================
> *** gcc/config/sh/sh.c.orig
> --- gcc/config/sh/sh.c
> *************** static int max_mov_insn_displacement (en
> *** 314,319 ****
> --- 314,322 ----
> static int mov_insn_alignment_mask (enum machine_mode, bool);
> static HOST_WIDE_INT disp_addr_displacement (rtx);
> static bool sequence_insn_p (rtx);
> + static void sh_canonicalize_comparison (int *, rtx *, rtx *, bool);
> + static void sh_canonicalize_comparison (enum rtx_code&, rtx&, rtx&,
> + enum machine_mode, bool);
>
> static void sh_init_sync_libfuncs (void) ATTRIBUTE_UNUSED;
>
> *************** static const struct attribute_spec sh_at
> *** 586,591 ****
> --- 589,597 ----
> #undef TARGET_LEGITIMATE_CONSTANT_P
> #define TARGET_LEGITIMATE_CONSTANT_P sh_legitimate_constant_p
>
> + #undef TARGET_CANONICALIZE_COMPARISON
> + #define TARGET_CANONICALIZE_COMPARISON sh_canonicalize_comparison
> +
> /* Machine-specific symbol_ref flags. */
> #define SYMBOL_FLAG_FUNCVEC_FUNCTION (SYMBOL_FLAG_MACH_DEP << 0)
>
> *************** prepare_move_operands (rtx operands[], e
> *** 1909,1920 ****
> }
> }
>
> ! /* Implement the CANONICALIZE_COMPARISON macro for the combine pass.
> ! This function is also re-used to canonicalize comparisons in cbranch
> ! pattern expanders. */
> ! void
> sh_canonicalize_comparison (enum rtx_code& cmp, rtx& op0, rtx& op1,
> ! enum machine_mode mode)
> {
> /* When invoked from within the combine pass the mode is not specified,
> so try to get it from one of the operands. */
> --- 1915,1928 ----
> }
> }
>
> ! /* Implement the canonicalize_comparison target hook for the combine
> ! pass. For the target hook this function is invoked via
> ! sh_canonicalize_comparison. This function is also re-used to
> ! canonicalize comparisons in cbranch pattern expanders. */
> ! static void
> sh_canonicalize_comparison (enum rtx_code& cmp, rtx& op0, rtx& op1,
> ! enum machine_mode mode,
> ! bool op0_preserve_value ATTRIBUTE_UNUSED)
> {
> /* When invoked from within the combine pass the mode is not specified,
> so try to get it from one of the operands. */
> *************** sh_canonicalize_comparison (enum rtx_cod
> *** 2008,2013 ****
> --- 2016,2034 ----
> }
> }
>
> + /* This function implements the canonicalize_comparison target hook.
> + This wrapper around the internally used sh_canonicalize_comparison
> + function is needed to do the enum rtx_code <-> int conversion.
> + Target hooks cannot use enum rtx_code in its definition. */
> + static void
> + sh_canonicalize_comparison (int *code, rtx *op0, rtx *op1,
> + bool op0_preserve_value)
> + {
> + enum rtx_code tmp_code = (enum rtx_code)*code;
> + sh_canonicalize_comparison (tmp_code, *op0, *op1,
> + VOIDmode, op0_preserve_value);
> + *code = (int)tmp_code;
> + }
> enum rtx_code
> prepare_cbranch_operands (rtx *operands, enum machine_mode mode,
> enum rtx_code comparison)
> *************** prepare_cbranch_operands (rtx *operands,
> *** 2021,2027 ****
> else
> scratch = operands[4];
>
> ! sh_canonicalize_comparison (comparison, operands[1], operands[2], mode);
>
> /* Notice that this function is also invoked after reload by
> the cbranchdi4_i pattern, through expand_cbranchdi4. */
> --- 2042,2049 ----
> else
> scratch = operands[4];
>
> ! sh_canonicalize_comparison (comparison, operands[1], operands[2],
> ! mode, false);
>
> /* Notice that this function is also invoked after reload by
> the cbranchdi4_i pattern, through expand_cbranchdi4. */
> Index: gcc/config/sh/sh.h
> ===================================================================
> *** gcc/config/sh/sh.h.orig
> --- gcc/config/sh/sh.h
> *************** struct sh_args {
> *** 1873,1882 ****
> more compact code. */
> #define SHIFT_COUNT_TRUNCATED (0)
>
> - /* CANONICALIZE_COMPARISON macro for the combine pass. */
> - #define CANONICALIZE_COMPARISON(CODE, OP0, OP1) \
> - sh_canonicalize_comparison ((CODE), (OP0), (OP1))
> -
> /* All integers have the same format so truncation is easy. */
> /* But SHmedia must sign-extend DImode when truncating to SImode. */
> #define TRULY_NOOP_TRUNCATION(OUTPREC,INPREC) \
> --- 1873,1878 ----
> Index: gcc/config/spu/spu.c
> ===================================================================
> *** gcc/config/spu/spu.c.orig
> --- gcc/config/spu/spu.c
> *************** spu_output_mi_thunk (FILE *file, tree th
> *** 7095,7100 ****
> --- 7095,7114 ----
> final_end_function ();
> }
>
> + /* Canonicalize a comparison from one we don't have to one we do have. */
> + static void
> + spu_canonicalize_comparison (int *code, rtx *op0, rtx *op1,
> + bool op0_preserve_value)
> + {
> + if (!op0_preserve_value
> + && (*code == LE || *code == LT || *code == LEU || *code == LTU))
> + {
> + rtx tem = *op0;
> + *op0 = *op1;
> + *op1 = tem;
> + *code = (int)swap_condition ((enum rtx_code)*code);
> + }
> + }
>
> /* Table of machine attributes. */
> static const struct attribute_spec spu_attribute_table[] =
> *************** static const struct attribute_spec spu_a
> *** 7308,7313 ****
> --- 7322,7330 ----
> #undef TARGET_DELAY_VARTRACK
> #define TARGET_DELAY_VARTRACK true
>
> + #undef TARGET_CANONICALIZE_COMPARISON
> + #define TARGET_CANONICALIZE_COMPARISON spu_canonicalize_comparison
> +
> struct gcc_target targetm = TARGET_INITIALIZER;
>
> #include "gt-spu.h"
> Index: gcc/config/spu/spu.h
> ===================================================================
> *** gcc/config/spu/spu.h.orig
> --- gcc/config/spu/spu.h
> *************** do { \
> *** 520,537 ****
>
> #define NO_IMPLICIT_EXTERN_C 1
>
> - /* Canonicalize a comparison from one we don't have to one we do have. */
> - #define CANONICALIZE_COMPARISON(CODE,OP0,OP1) \
> - do { \
> - if (((CODE) == LE || (CODE) == LT || (CODE) == LEU || (CODE) == LTU)) \
> - { \
> - rtx tem = (OP0); \
> - (OP0) = (OP1); \
> - (OP1) = tem; \
> - (CODE) = swap_condition (CODE); \
> - } \
> - } while (0)
> -
>
> /* Address spaces. */
> #define ADDR_SPACE_EA 1
> --- 520,525 ----
> Index: gcc/doc/tm.texi.in
> ===================================================================
> *** gcc/doc/tm.texi.in.orig
> --- gcc/doc/tm.texi.in
> *************** You should define this macro if and only
> *** 5928,5952 ****
> in @file{@var{machine}-modes.def}.
> @end defmac
>
> ! @defmac CANONICALIZE_COMPARISON (@var{code}, @var{op0}, @var{op1})
> On some machines not all possible comparisons are defined, but you can
> convert an invalid comparison into a valid one. For example, the Alpha
> does not have a @code{GT} comparison, but you can use an @code{LT}
> comparison instead and swap the order of the operands.
>
> ! On such machines, define this macro to be a C statement to do any
> ! required conversions. @var{code} is the initial comparison code
> ! and @var{op0} and @var{op1} are the left and right operands of the
> ! comparison, respectively. You should modify @var{code}, @var{op0}, and
> ! @var{op1} as required.
>
> GCC will not assume that the comparison resulting from this macro is
> valid but will see if the resulting insn matches a pattern in the
> @file{md} file.
>
> ! You need not define this macro if it would never change the comparison
> ! code or operands.
> ! @end defmac
>
> @defmac REVERSIBLE_CC_MODE (@var{mode})
> A C expression whose value is one if it is always safe to reverse a
> --- 5928,5954 ----
> in @file{@var{machine}-modes.def}.
> @end defmac
>
> ! @hook TARGET_CANONICALIZE_COMPARISON (@var{code}, @var{op0}, @var{op1}, @var{op0_preserve_value})
> On some machines not all possible comparisons are defined, but you can
> convert an invalid comparison into a valid one. For example, the Alpha
> does not have a @code{GT} comparison, but you can use an @code{LT}
> comparison instead and swap the order of the operands.
>
> ! On such machines, implement this hook to do any required conversions.
> ! @var{code} is the initial comparison code and @var{op0} and @var{op1}
> ! are the left and right operands of the comparison, respectively. If
> ! @var{op0_preserve_value} is @code{true} the implementation is not
> ! allowed to change the value of @var{op0} since the value might be used
> ! in RTXs which aren't comparisons. E.g. the implementation is not
> ! allowed to swap operands in that case.
>
> GCC will not assume that the comparison resulting from this macro is
> valid but will see if the resulting insn matches a pattern in the
> @file{md} file.
>
> ! You need not to implement this hook if it would never change the
> ! comparison code or operands.
> ! @end deftypefn
>
> @defmac REVERSIBLE_CC_MODE (@var{mode})
> A C expression whose value is one if it is always safe to reverse a
> Index: gcc/target.def
> ===================================================================
> *** gcc/target.def.orig
> --- gcc/target.def
> *************** DEFHOOK
> *** 2877,2882 ****
> --- 2877,2890 ----
> enum unwind_info_type, (void),
> default_debug_unwind_info)
>
> + /* The code parameter should be of type enum rtx_code but this is not
> + defined at this time. */
> + DEFHOOK
> + (canonicalize_comparison,
> + "",
> + void, (int *code, rtx *op0, rtx *op1, bool op0_preserve_value),
> + default_canonicalize_comparison)
> +
> DEFHOOKPOD
> (atomic_test_and_set_trueval,
> "This value should be set if the result written by\
> Index: gcc/targhooks.h
> ===================================================================
> *** gcc/targhooks.h.orig
> --- gcc/targhooks.h
> *************** extern unsigned char default_class_max_n
> *** 179,184 ****
> --- 179,186 ----
>
> extern enum unwind_info_type default_debug_unwind_info (void);
>
> + extern bool default_canonicalize_comparison (int *, rtx *, rtx *, bool);
> +
> extern int default_label_align_after_barrier_max_skip (rtx);
> extern int default_loop_align_max_skip (rtx);
> extern int default_label_align_max_skip (rtx);
> Index: gcc/doc/tm.texi
> ===================================================================
> *** gcc/doc/tm.texi.orig
> --- gcc/doc/tm.texi
> *************** You should define this macro if and only
> *** 6024,6048 ****
> in @file{@var{machine}-modes.def}.
> @end defmac
>
> ! @defmac CANONICALIZE_COMPARISON (@var{code}, @var{op0}, @var{op1})
> On some machines not all possible comparisons are defined, but you can
> convert an invalid comparison into a valid one. For example, the Alpha
> does not have a @code{GT} comparison, but you can use an @code{LT}
> comparison instead and swap the order of the operands.
>
> ! On such machines, define this macro to be a C statement to do any
> ! required conversions. @var{code} is the initial comparison code
> ! and @var{op0} and @var{op1} are the left and right operands of the
> ! comparison, respectively. You should modify @var{code}, @var{op0}, and
> ! @var{op1} as required.
>
> GCC will not assume that the comparison resulting from this macro is
> valid but will see if the resulting insn matches a pattern in the
> @file{md} file.
>
> ! You need not define this macro if it would never change the comparison
> ! code or operands.
> ! @end defmac
>
> @defmac REVERSIBLE_CC_MODE (@var{mode})
> A C expression whose value is one if it is always safe to reverse a
> --- 6024,6050 ----
> in @file{@var{machine}-modes.def}.
> @end defmac
>
> ! @deftypefn {Target Hook} void TARGET_CANONICALIZE_COMPARISON (int *@var{code}, rtx *@var{op0}, rtx
> *@var{op1}, bool @var{op0_preserve_value}) (@var{code}, @var{op0}, @var{op1}, @var{op0_preserve_value})
> On some machines not all possible comparisons are defined, but you can
> convert an invalid comparison into a valid one. For example, the Alpha
> does not have a @code{GT} comparison, but you can use an @code{LT}
> comparison instead and swap the order of the operands.
>
> ! On such machines, implement this hook to do any required conversions.
> ! @var{code} is the initial comparison code and @var{op0} and @var{op1}
> ! are the left and right operands of the comparison, respectively. If
> ! @var{op0_preserve_value} is @code{true} the implementation is not
> ! allowed to change the value of @var{op0} since the value might be used
> ! in RTXs which aren't comparisons. E.g. the implementation is not
> ! allowed to swap operands in that case.
>
> GCC will not assume that the comparison resulting from this macro is
> valid but will see if the resulting insn matches a pattern in the
> @file{md} file.
>
> ! You need not to implement this hook if it would never change the
> ! comparison code or operands.
> ! @end deftypefn
>
> @defmac REVERSIBLE_CC_MODE (@var{mode})
> A C expression whose value is one if it is always safe to reverse a
>
>
>
>
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PING] Bugfix: Additional parameter for canonicalize comparison
2012-12-19 11:34 ` Richard Earnshaw
@ 2012-12-19 14:04 ` Richard Biener
2012-12-19 14:05 ` Richard Biener
2012-12-19 18:57 ` Jan-Benedict Glaw
0 siblings, 2 replies; 6+ messages in thread
From: Richard Biener @ 2012-12-19 14:04 UTC (permalink / raw)
To: Richard Earnshaw
Cc: Andreas Krebbel, nickc, paul, Ramana Radhakrishnan, gcc-patches
On Wed, Dec 19, 2012 at 12:34 PM, Richard Earnshaw <rearnsha@arm.com> wrote:
> On 19/12/12 09:53, Andreas Krebbel wrote:
>>
>> Hi,
>>
>> are the ARM parts of the patch below ok for mainline?
>>
>
> Yes.
>
> Sorry for the delay.
I think this broke bootstrap on x86_64:
/space/rguenther/src/svn/trunk/gcc/config/i386/i386.c: At global scope:
/space/rguenther/src/svn/trunk/gcc/config/i386/i386.c:42503: error:
invalid conversion from 'bool (*)(int*, rtx_def**, rtx_def**, bool)'
to 'void (*)(int*, rtx_def**, rtx_def**, bool)'
make[3]: *** [i386.o] Error 1
or maybe even everywhere. Yeah, bool vs. void return value in the default
implementation.
Please fix.
Richard.
> R.
>
>
>> I did a compile test with a cross.
>>
>> Bye,
>>
>> -Andreas-
>>
>>
>> -------- Original Message --------
>> Subject: [PATCH] Bugfix: Additional parameter for canonicalize comparison
>> Date: Wed, 12 Dec 2012 12:23:14 +0100
>> From: Andreas Krebbel <krebbel@linux.vnet.ibm.com>
>> To: rearnsha@arm.com
>> CC: gcc-patches@gcc.gnu.org
>>
>> Hi Richard,
>>
>> is the attached patch ok for ARM?
>>
>> Bye,
>>
>> -Andreas-
>>
>> 2012-12-12 Andreas Krebbel <Andreas.Krebbel@de.ibm.com>
>>
>> * target.def: Define canonicalize_comparison hook.
>> * targhooks.h (default_canonicalize_comparison): New prototype.
>> * targhooks.c (default_canonicalize_comparison): New function.
>> * doc/tm.texi: Add documentation for the new target hook.
>> * doc/tm.texi.in: Likewise.
>> * combine.c (try_combine): Adjust to use the target hook.
>> * config/alpha/alpha.h (CANONICALIZE_COMPARISON): Remove macro
>> definition.
>> * config/alpha/alpha.c (alpha_canonicalize_comparison): New
>> function.
>> (TARGET_CANONICALIZE_COMPARISON): New macro definition.
>> * config/arm/arm-protos.h (arm_canonicalize_comparison): Remove
>> prototype.
>> * config/arm/arm.c (arm_canonicalize_comparison): Add new
>> parameter.
>> (TARGET_CANONICALIZE_COMPARISON): New macro definition.
>> * config/arm/arm.h (CANONICALIZE_COMPARISON): Remove macro
>> definition.
>> * config/s390/s390-protos.h (s390_canonicalize_comparison):
>> Remove
>> prototype.
>> * config/s390/s390.c (s390_canonicalize_comparison): Add new
>> parameter.
>> (TARGET_CANONICALIZE_COMPARISON): New macro definition.
>> * config/s390/s390.h (CANONICALIZE_COMPARISON): Remove macro
>> definition.
>> * config/sh/sh-protos.h (sh_canonicalize_comparison): Remove
>> prototype.
>> * config/sh/sh.c (sh_canonicalize_comparison): Add new prototype.
>> New
>> function overloading the old one.
>> (TARGET_CANONICALIZE_COMPARISON): New macro definition.
>> * config/sh/sh.h (CANONICALIZE_COMPARISON): Remove macro
>> definition.
>> * config/spu/spu.c (spu_canonicalize_comparison): New function.
>> (TARGET_CANONICALIZE_COMPARISON): New macro definition.
>> * config/spu/spu.h (CANONICALIZE_COMPARISON): Remove macro
>> definition.
>>
>> ---
>> gcc/combine.c | 19 ++++++-!!!
>> gcc/config/alpha/alpha.c | 27 ++++++++++++++++
>> gcc/config/alpha/alpha.h | 20 ------------
>> gcc/config/arm/arm-protos.h | 1
>> gcc/config/arm/arm.c | 68
>> ++-!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
>> gcc/config/arm/arm.h | 3 -
>> gcc/config/s390/s390-protos.h | 1
>> gcc/config/s390/s390.c | 13 +++!!!!!
>> gcc/config/s390/s390.h | 4 --
>> gcc/config/sh/sh-protos.h | 2 -
>> gcc/config/sh/sh.c | 34 +++++++++++!!!!!!!!!!
>> gcc/config/sh/sh.h | 4 --
>> gcc/config/spu/spu.c | 17 ++++++++++
>> gcc/config/spu/spu.h | 12 -------
>> gcc/doc/tm.texi | 20 !!!!!!!!!!!!
>> gcc/doc/tm.texi.in | 20 !!!!!!!!!!!!
>> gcc/target.def | 8 ++++
>> gcc/targhooks.h | 2 +
>> 18 files changed, 94 insertions(+), 50 deletions(-), 131
>> modifications(!)
>>
>> Index: gcc/combine.c
>> ===================================================================
>> *** gcc/combine.c.orig
>> --- gcc/combine.c
>> *************** static rtx gen_lowpart_or_truncate (enum
>> *** 494,499 ****
>> --- 494,510 ----
>> static const struct rtl_hooks combine_rtl_hooks =
>> RTL_HOOKS_INITIALIZER;
>>
>>
>> + /* Convenience wrapper for the canonicalize_comparison target hook.
>> + Target hooks cannot use enum rtx_code. */
>> + static inline void
>> + target_canonicalize_comparison (enum rtx_code *code, rtx *op0, rtx *op1,
>> + bool op0_preserve_value)
>> + {
>> + int code_int = (int)*code;
>> + targetm.canonicalize_comparison (&code_int, op0, op1,
>> op0_preserve_value);
>> + *code = (enum rtx_code)code_int;
>> + }
>> +
>> /* Try to split PATTERN found in INSN. This returns NULL_RTX if
>> PATTERN can not be split. Otherwise, it returns an insn sequence.
>> This is a wrapper around split_insns which ensures that the
>> *************** try_combine (rtx i3, rtx i2, rtx i1, rtx
>> *** 2944,2952 ****
>> compare_code = orig_compare_code = GET_CODE (*cc_use_loc);
>> compare_code = simplify_compare_const (compare_code,
>> op0, &op1);
>> ! #ifdef CANONICALIZE_COMPARISON
>> ! CANONICALIZE_COMPARISON (compare_code, op0, op1);
>> ! #endif
>> }
>>
>> /* Do the rest only if op1 is const0_rtx, which may be the
>> --- 2955,2961 ----
>> compare_code = orig_compare_code = GET_CODE (*cc_use_loc);
>> compare_code = simplify_compare_const (compare_code,
>> op0, &op1);
>> ! target_canonicalize_comparison (&compare_code, &op0, &op1, 1);
>> }
>>
>> /* Do the rest only if op1 is const0_rtx, which may be the
>> *************** simplify_comparison (enum rtx_code code,
>> *** 11959,11969 ****
>> }
>> }
>>
>> - #ifdef CANONICALIZE_COMPARISON
>> /* If this machine only supports a subset of valid comparisons, see
>> if we
>> can convert an unsupported one into a supported one. */
>> ! CANONICALIZE_COMPARISON (code, op0, op1);
>> ! #endif
>>
>> *pop0 = op0;
>> *pop1 = op1;
>> --- 11968,11976 ----
>> }
>> }
>>
>> /* If this machine only supports a subset of valid comparisons, see
>> if we
>> can convert an unsupported one into a supported one. */
>> ! target_canonicalize_comparison (&code, &op0, &op1, 0);
>>
>> *pop0 = op0;
>> *pop1 = op1;
>> Index: gcc/config/alpha/alpha.c
>> ===================================================================
>> *** gcc/config/alpha/alpha.c.orig
>> --- gcc/config/alpha/alpha.c
>> *************** alpha_conditional_register_usage (void)
>> *** 9683,9688 ****
>> --- 9683,9712 ----
>> for (i = 32; i < 63; i++)
>> fixed_regs[i] = call_used_regs[i] = 1;
>> }
>> +
>> + /* Canonicalize a comparison from one we don't have to one we do have.
>> */
>> +
>> + static void
>> + alpha_canonicalize_comparison (int *code, rtx *op0, rtx *op1,
>> + bool op0_preserve_value)
>> + {
>> + if (!op0_preserve_value
>> + && (*code == GE || *code == GT || *code == GEU || *code == GTU)
>> + && (REG_P (*op1) || *op1 == const0_rtx))
>> + {
>> + rtx tem = *op0;
>> + *op0 = *op1;
>> + *op1 = tem;
>> + *code = (int)swap_condition ((enum rtx_code)*code);
>> + }
>> +
>> + if ((*code == LT || *code == LTU)
>> + && CONST_INT_P (*op1) && INTVAL (*op1) == 256)
>> + {
>> + *code = *code == LT ? LE : LEU;
>> + *op1 = GEN_INT (255);
>> + }
>> + }
>>
>> /* Initialize the GCC target structure. */
>> #if TARGET_ABI_OPEN_VMS
>> *************** alpha_conditional_register_usage (void)
>> *** 9850,9855 ****
>> --- 9874,9882 ----
>> #undef TARGET_CONDITIONAL_REGISTER_USAGE
>> #define TARGET_CONDITIONAL_REGISTER_USAGE
>> alpha_conditional_register_usage
>>
>> + #undef TARGET_CANONICALIZE_COMPARISON
>> + #define TARGET_CANONICALIZE_COMPARISON alpha_canonicalize_comparison
>> +
>> struct gcc_target targetm = TARGET_INITIALIZER;
>>
>>
>> Index: gcc/config/alpha/alpha.h
>> ===================================================================
>> *** gcc/config/alpha/alpha.h.orig
>> --- gcc/config/alpha/alpha.h
>> *************** do {
>> \
>> *** 922,947 ****
>> #define FLOAT_STORE_FLAG_VALUE(MODE) \
>> REAL_VALUE_ATOF ((TARGET_FLOAT_VAX ? "0.5" : "2.0"), (MODE))
>>
>> - /* Canonicalize a comparison from one we don't have to one we do have.
>> */
>> -
>> - #define CANONICALIZE_COMPARISON(CODE,OP0,OP1) \
>> - do {
>> \
>> - if (((CODE) == GE || (CODE) == GT || (CODE) == GEU || (CODE) == GTU)
>> \
>> - && (REG_P (OP1) || (OP1) == const0_rtx)) \
>> - {
>> \
>> - rtx tem = (OP0); \
>> - (OP0) = (OP1); \
>> - (OP1) = tem; \
>> - (CODE) = swap_condition (CODE); \
>> - }
>> \
>> - if (((CODE) == LT || (CODE) == LTU)
>> \
>> - && CONST_INT_P (OP1) && INTVAL (OP1) == 256) \
>> - {
>> \
>> - (CODE) = (CODE) == LT ? LE : LEU; \
>> - (OP1) = GEN_INT (255); \
>> - }
>> \
>> - } while (0)
>> -
>> /* Specify the machine mode that pointers have.
>> After generation of rtl, the compiler makes no further distinction
>> between pointers and any other objects of this machine mode. */
>> --- 922,927 ----
>> Index: gcc/config/arm/arm-protos.h
>> ===================================================================
>> *** gcc/config/arm/arm-protos.h.orig
>> --- gcc/config/arm/arm-protos.h
>> *************** extern int const_ok_for_op (HOST_WIDE_IN
>> *** 53,59 ****
>> extern int const_ok_for_dimode_op (HOST_WIDE_INT, enum rtx_code);
>> extern int arm_split_constant (RTX_CODE, enum machine_mode, rtx,
>> HOST_WIDE_INT, rtx, rtx, int);
>> - extern RTX_CODE arm_canonicalize_comparison (RTX_CODE, rtx *, rtx *);
>> extern int legitimate_pic_operand_p (rtx);
>> extern rtx legitimize_pic_address (rtx, enum machine_mode, rtx);
>> extern rtx legitimize_tls_address (rtx, rtx);
>> --- 53,58 ----
>> Index: gcc/config/arm/arm.c
>> ===================================================================
>> *** gcc/config/arm/arm.c.orig
>> --- gcc/config/arm/arm.c
>> *************** static int arm_cortex_a5_branch_cost (bo
>> *** 269,275 ****
>>
>> static bool arm_vectorize_vec_perm_const_ok (enum machine_mode vmode,
>> const unsigned char *sel);
>> !
>>
>> /* Table of machine attributes. */
>> static const struct attribute_spec arm_attribute_table[] =
>> --- 269,276 ----
>>
>> static bool arm_vectorize_vec_perm_const_ok (enum machine_mode vmode,
>> const unsigned char *sel);
>> ! static void arm_canonicalize_comparison (int *code, rtx *op0, rtx *op1,
>> ! bool op0_preserve_value);
>>
>> /* Table of machine attributes. */
>> static const struct attribute_spec arm_attribute_table[] =
>> *************** static const struct attribute_spec arm_a
>> *** 626,631 ****
>> --- 627,636 ----
>> #define TARGET_VECTORIZE_VEC_PERM_CONST_OK \
>> arm_vectorize_vec_perm_const_ok
>>
>> + #undef TARGET_CANONICALIZE_COMPARISON
>> + #define TARGET_CANONICALIZE_COMPARISON \
>> + arm_canonicalize_comparison
>> +
>> struct gcc_target targetm = TARGET_INITIALIZER;
>>
>> /* Obstack for minipool constant handling. */
>> *************** arm_gen_constant (enum rtx_code code, en
>> *** 3543,3550 ****
>> This can be done for a few constant compares, where we can make the
>> immediate value easier to load. */
>>
>> ! enum rtx_code
>> ! arm_canonicalize_comparison (enum rtx_code code, rtx *op0, rtx *op1)
>> {
>> enum machine_mode mode;
>> unsigned HOST_WIDE_INT i, maxval;
>> --- 3548,3556 ----
>> This can be done for a few constant compares, where we can make the
>> immediate value easier to load. */
>>
>> ! static void
>> ! arm_canonicalize_comparison (int *code, rtx *op0, rtx *op1,
>> ! bool op0_preserve_value)
>> {
>> enum machine_mode mode;
>> unsigned HOST_WIDE_INT i, maxval;
>> *************** arm_canonicalize_comparison (enum rtx_co
>> *** 3563,3577 ****
>> {
>> rtx tem;
>>
>> ! if (code == GT || code == LE
>> ! || (!TARGET_ARM && (code == GTU || code == LEU)))
>> {
>> /* Missing comparison. First try to use an available
>> comparison. */
>> if (CONST_INT_P (*op1))
>> {
>> i = INTVAL (*op1);
>> ! switch (code)
>> {
>> case GT:
>> case LE:
>> --- 3569,3583 ----
>> {
>> rtx tem;
>>
>> ! if (*code == GT || *code == LE
>> ! || (!TARGET_ARM && (*code == GTU || *code == LEU)))
>> {
>> /* Missing comparison. First try to use an available
>> comparison. */
>> if (CONST_INT_P (*op1))
>> {
>> i = INTVAL (*op1);
>> ! switch (*code)
>> {
>> case GT:
>> case LE:
>> *************** arm_canonicalize_comparison (enum rtx_co
>> *** 3579,3585 ****
>> && arm_const_double_by_immediates (GEN_INT (i +
>> 1)))
>> {
>> *op1 = GEN_INT (i + 1);
>> ! return code == GT ? GE : LT;
>> }
>> break;
>> case GTU:
>> --- 3585,3592 ----
>> && arm_const_double_by_immediates (GEN_INT (i +
>> 1)))
>> {
>> *op1 = GEN_INT (i + 1);
>> ! *code = *code == GT ? GE : LT;
>> ! return;
>> }
>> break;
>> case GTU:
>> *************** arm_canonicalize_comparison (enum rtx_co
>> *** 3588,3594 ****
>> && arm_const_double_by_immediates (GEN_INT (i +
>> 1)))
>> {
>> *op1 = GEN_INT (i + 1);
>> ! return code == GTU ? GEU : LTU;
>> }
>> break;
>> default:
>> --- 3595,3602 ----
>> && arm_const_double_by_immediates (GEN_INT (i +
>> 1)))
>> {
>> *op1 = GEN_INT (i + 1);
>> ! *code = *code == GTU ? GEU : LTU;
>> ! return;
>> }
>> break;
>> default:
>> *************** arm_canonicalize_comparison (enum rtx_co
>> *** 3597,3615 ****
>> }
>>
>> /* If that did not work, reverse the condition. */
>> ! tem = *op0;
>> ! *op0 = *op1;
>> ! *op1 = tem;
>> ! return swap_condition (code);
>> }
>> !
>> ! return code;
>> }
>>
>> /* If *op0 is (zero_extend:SI (subreg:QI (reg:SI) 0)) and comparing
>> with const0_rtx, change it to (and:SI (reg:SI) (const_int 255)),
>> to facilitate possible combining with a cmp into 'ands'. */
>> ! if (mode == SImode
>> && GET_CODE (*op0) == ZERO_EXTEND
>> && GET_CODE (XEXP (*op0, 0)) == SUBREG
>> && GET_MODE (XEXP (*op0, 0)) == QImode
>> --- 3605,3626 ----
>> }
>>
>> /* If that did not work, reverse the condition. */
>> ! if (!op0_preserve_value)
>> ! {
>> ! tem = *op0;
>> ! *op0 = *op1;
>> ! *op1 = tem;
>> ! *code = (int)swap_condition ((enum rtx_code)*code);
>> ! }
>> }
>> ! return;
>> }
>>
>> /* If *op0 is (zero_extend:SI (subreg:QI (reg:SI) 0)) and comparing
>> with const0_rtx, change it to (and:SI (reg:SI) (const_int 255)),
>> to facilitate possible combining with a cmp into 'ands'. */
>> ! if (!op0_preserve_value
>> ! && mode == SImode
>> && GET_CODE (*op0) == ZERO_EXTEND
>> && GET_CODE (XEXP (*op0, 0)) == SUBREG
>> && GET_MODE (XEXP (*op0, 0)) == QImode
>> *************** arm_canonicalize_comparison (enum rtx_co
>> *** 3624,3638 ****
>> if (!CONST_INT_P (*op1)
>> || const_ok_for_arm (INTVAL (*op1))
>> || const_ok_for_arm (- INTVAL (*op1)))
>> ! return code;
>>
>> i = INTVAL (*op1);
>>
>> ! switch (code)
>> {
>> case EQ:
>> case NE:
>> ! return code;
>>
>> case GT:
>> case LE:
>> --- 3635,3649 ----
>> if (!CONST_INT_P (*op1)
>> || const_ok_for_arm (INTVAL (*op1))
>> || const_ok_for_arm (- INTVAL (*op1)))
>> ! return;
>>
>> i = INTVAL (*op1);
>>
>> ! switch (*code)
>> {
>> case EQ:
>> case NE:
>> ! return;
>>
>> case GT:
>> case LE:
>> *************** arm_canonicalize_comparison (enum rtx_co
>> *** 3640,3646 ****
>> && (const_ok_for_arm (i + 1) || const_ok_for_arm (-(i + 1))))
>> {
>> *op1 = GEN_INT (i + 1);
>> ! return code == GT ? GE : LT;
>> }
>> break;
>>
>> --- 3651,3658 ----
>> && (const_ok_for_arm (i + 1) || const_ok_for_arm (-(i + 1))))
>> {
>> *op1 = GEN_INT (i + 1);
>> ! *code = *code == GT ? GE : LT;
>> ! return;
>> }
>> break;
>>
>> *************** arm_canonicalize_comparison (enum rtx_co
>> *** 3650,3656 ****
>> && (const_ok_for_arm (i - 1) || const_ok_for_arm (-(i - 1))))
>> {
>> *op1 = GEN_INT (i - 1);
>> ! return code == GE ? GT : LE;
>> }
>> break;
>>
>> --- 3662,3669 ----
>> && (const_ok_for_arm (i - 1) || const_ok_for_arm (-(i - 1))))
>> {
>> *op1 = GEN_INT (i - 1);
>> ! *code = *code == GE ? GT : LE;
>> ! return;
>> }
>> break;
>>
>> *************** arm_canonicalize_comparison (enum rtx_co
>> *** 3660,3666 ****
>> && (const_ok_for_arm (i + 1) || const_ok_for_arm (-(i + 1))))
>> {
>> *op1 = GEN_INT (i + 1);
>> ! return code == GTU ? GEU : LTU;
>> }
>> break;
>>
>> --- 3673,3680 ----
>> && (const_ok_for_arm (i + 1) || const_ok_for_arm (-(i + 1))))
>> {
>> *op1 = GEN_INT (i + 1);
>> ! *code = *code == GTU ? GEU : LTU;
>> ! return;
>> }
>> break;
>>
>> *************** arm_canonicalize_comparison (enum rtx_co
>> *** 3670,3684 ****
>> && (const_ok_for_arm (i - 1) || const_ok_for_arm (-(i - 1))))
>> {
>> *op1 = GEN_INT (i - 1);
>> ! return code == GEU ? GTU : LEU;
>> }
>> break;
>>
>> default:
>> gcc_unreachable ();
>> }
>> -
>> - return code;
>> }
>>
>>
>> --- 3684,3697 ----
>> && (const_ok_for_arm (i - 1) || const_ok_for_arm (-(i - 1))))
>> {
>> *op1 = GEN_INT (i - 1);
>> ! *code = *code == GEU ? GTU : LEU;
>> ! return;
>> }
>> break;
>>
>> default:
>> gcc_unreachable ();
>> }
>> }
>>
>>
>> *************** bool
>> *** 26979,26985 ****
>> arm_validize_comparison (rtx *comparison, rtx * op1, rtx * op2)
>> {
>> enum rtx_code code = GET_CODE (*comparison);
>> ! enum rtx_code canonical_code;
>> enum machine_mode mode = (GET_MODE (*op1) == VOIDmode)
>> ? GET_MODE (*op2) : GET_MODE (*op1);
>>
>> --- 26992,26998 ----
>> arm_validize_comparison (rtx *comparison, rtx * op1, rtx * op2)
>> {
>> enum rtx_code code = GET_CODE (*comparison);
>> ! int code_int;
>> enum machine_mode mode = (GET_MODE (*op1) == VOIDmode)
>> ? GET_MODE (*op2) : GET_MODE (*op1);
>>
>> *************** arm_validize_comparison (rtx *comparison
>> *** 26988,26995 ****
>> if (code == UNEQ || code == LTGT)
>> return false;
>>
>> ! canonical_code = arm_canonicalize_comparison (code, op1, op2);
>> ! PUT_CODE (*comparison, canonical_code);
>>
>> switch (mode)
>> {
>> --- 27001,27009 ----
>> if (code == UNEQ || code == LTGT)
>> return false;
>>
>> ! code_int = (int)code;
>> ! arm_canonicalize_comparison (&code_int, op1, op2, 0);
>> ! PUT_CODE (*comparison, (enum rtx_code)code_int);
>>
>> switch (mode)
>> {
>> Index: gcc/config/arm/arm.h
>> ===================================================================
>> *** gcc/config/arm/arm.h.orig
>> --- gcc/config/arm/arm.h
>> *************** extern int making_const_table;
>> *** 2078,2086 ****
>> ? reverse_condition_maybe_unordered (code) \
>> : reverse_condition (code))
>>
>> - #define CANONICALIZE_COMPARISON(CODE, OP0, OP1)
>> \
>> - (CODE) = arm_canonicalize_comparison (CODE, &(OP0), &(OP1))
>> -
>> /* The arm5 clz instruction returns 32. */
>> #define CLZ_DEFINED_VALUE_AT_ZERO(MODE, VALUE) ((VALUE) = 32, 1)
>> #define CTZ_DEFINED_VALUE_AT_ZERO(MODE, VALUE) ((VALUE) = 32, 1)
>> --- 2078,2083 ----
>> Index: gcc/config/s390/s390-protos.h
>> ===================================================================
>> *** gcc/config/s390/s390-protos.h.orig
>> --- gcc/config/s390/s390-protos.h
>> *************** extern int tls_symbolic_operand (rtx);
>> *** 58,64 ****
>> extern bool s390_match_ccmode (rtx, enum machine_mode);
>> extern enum machine_mode s390_tm_ccmode (rtx, rtx, bool);
>> extern enum machine_mode s390_select_ccmode (enum rtx_code, rtx, rtx);
>> - extern void s390_canonicalize_comparison (enum rtx_code *, rtx *, rtx
>> *);
>> extern rtx s390_emit_compare (enum rtx_code, rtx, rtx);
>> extern void s390_emit_jump (rtx, rtx);
>> extern bool symbolic_reference_mentioned_p (rtx);
>> --- 58,63 ----
>> Index: gcc/config/s390/s390.c
>> ===================================================================
>> *** gcc/config/s390/s390.c.orig
>> --- gcc/config/s390/s390.c
>> *************** s390_select_ccmode (enum rtx_code code,
>> *** 745,753 ****
>> /* Replace the comparison OP0 CODE OP1 by a semantically equivalent one
>> that we can implement more efficiently. */
>>
>> ! void
>> ! s390_canonicalize_comparison (enum rtx_code *code, rtx *op0, rtx *op1)
>> {
>> /* Convert ZERO_EXTRACT back to AND to enable TM patterns. */
>> if ((*code == EQ || *code == NE)
>> && *op1 == const0_rtx
>> --- 745,757 ----
>> /* Replace the comparison OP0 CODE OP1 by a semantically equivalent one
>> that we can implement more efficiently. */
>>
>> ! static void
>> ! s390_canonicalize_comparison (int *code, rtx *op0, rtx *op1,
>> ! bool op0_preserve_value)
>> {
>> + if (op0_preserve_value)
>> + return;
>> +
>> /* Convert ZERO_EXTRACT back to AND to enable TM patterns. */
>> if ((*code == EQ || *code == NE)
>> && *op1 == const0_rtx
>> *************** s390_canonicalize_comparison (enum rtx_c
>> *** 894,900 ****
>> if (MEM_P (*op0) && REG_P (*op1))
>> {
>> rtx tem = *op0; *op0 = *op1; *op1 = tem;
>> ! *code = swap_condition (*code);
>> }
>> }
>>
>> --- 898,904 ----
>> if (MEM_P (*op0) && REG_P (*op1))
>> {
>> rtx tem = *op0; *op0 = *op1; *op1 = tem;
>> ! *code = (int)swap_condition ((enum rtx_code)*code);
>> }
>> }
>>
>> *************** s390_loop_unroll_adjust (unsigned nunrol
>> *** 11071,11076 ****
>> --- 11075,11083 ----
>> #undef TARGET_UNWIND_WORD_MODE
>> #define TARGET_UNWIND_WORD_MODE s390_unwind_word_mode
>>
>> + #undef TARGET_CANONICALIZE_COMPARISON
>> + #define TARGET_CANONICALIZE_COMPARISON s390_canonicalize_comparison
>> +
>> struct gcc_target targetm = TARGET_INITIALIZER;
>>
>> #include "gt-s390.h"
>> Index: gcc/config/s390/s390.h
>> ===================================================================
>> *** gcc/config/s390/s390.h.orig
>> --- gcc/config/s390/s390.h
>> *************** do {
>> \
>> *** 720,729 ****
>> return the mode to be used for the comparison. */
>> #define SELECT_CC_MODE(OP, X, Y) s390_select_ccmode ((OP), (X), (Y))
>>
>> - /* Canonicalize a comparison from one we don't have to one we do have.
>> */
>> - #define CANONICALIZE_COMPARISON(CODE, OP0, OP1) \
>> - s390_canonicalize_comparison (&(CODE), &(OP0), &(OP1))
>> -
>> /* Relative costs of operations. */
>>
>> /* A C expression for the cost of a branch instruction. A value of 1
>> --- 720,725 ----
>> Index: gcc/config/sh/sh-protos.h
>> ===================================================================
>> *** gcc/config/sh/sh-protos.h.orig
>> --- gcc/config/sh/sh-protos.h
>> *************** extern bool sh_expand_t_scc (rtx *);
>> *** 159,166 ****
>> extern rtx sh_gen_truncate (enum machine_mode, rtx, int);
>> extern bool sh_vector_mode_supported_p (enum machine_mode);
>> extern bool sh_cfun_trap_exit_p (void);
>> - extern void sh_canonicalize_comparison (enum rtx_code&, rtx&, rtx&,
>> - enum machine_mode mode =
>> VOIDmode);
>> extern rtx sh_find_equiv_gbr_addr (rtx cur_insn, rtx mem);
>> extern int sh_eval_treg_value (rtx op);
>>
>> --- 159,164 ----
>> Index: gcc/config/sh/sh.c
>> ===================================================================
>> *** gcc/config/sh/sh.c.orig
>> --- gcc/config/sh/sh.c
>> *************** static int max_mov_insn_displacement (en
>> *** 314,319 ****
>> --- 314,322 ----
>> static int mov_insn_alignment_mask (enum machine_mode, bool);
>> static HOST_WIDE_INT disp_addr_displacement (rtx);
>> static bool sequence_insn_p (rtx);
>> + static void sh_canonicalize_comparison (int *, rtx *, rtx *, bool);
>> + static void sh_canonicalize_comparison (enum rtx_code&, rtx&, rtx&,
>> + enum machine_mode, bool);
>>
>> static void sh_init_sync_libfuncs (void) ATTRIBUTE_UNUSED;
>>
>> *************** static const struct attribute_spec sh_at
>> *** 586,591 ****
>> --- 589,597 ----
>> #undef TARGET_LEGITIMATE_CONSTANT_P
>> #define TARGET_LEGITIMATE_CONSTANT_P sh_legitimate_constant_p
>>
>> + #undef TARGET_CANONICALIZE_COMPARISON
>> + #define TARGET_CANONICALIZE_COMPARISON sh_canonicalize_comparison
>> +
>> /* Machine-specific symbol_ref flags. */
>> #define SYMBOL_FLAG_FUNCVEC_FUNCTION (SYMBOL_FLAG_MACH_DEP << 0)
>>
>> *************** prepare_move_operands (rtx operands[], e
>> *** 1909,1920 ****
>> }
>> }
>>
>> ! /* Implement the CANONICALIZE_COMPARISON macro for the combine pass.
>> ! This function is also re-used to canonicalize comparisons in cbranch
>> ! pattern expanders. */
>> ! void
>> sh_canonicalize_comparison (enum rtx_code& cmp, rtx& op0, rtx& op1,
>> ! enum machine_mode mode)
>> {
>> /* When invoked from within the combine pass the mode is not
>> specified,
>> so try to get it from one of the operands. */
>> --- 1915,1928 ----
>> }
>> }
>>
>> ! /* Implement the canonicalize_comparison target hook for the combine
>> ! pass. For the target hook this function is invoked via
>> ! sh_canonicalize_comparison. This function is also re-used to
>> ! canonicalize comparisons in cbranch pattern expanders. */
>> ! static void
>> sh_canonicalize_comparison (enum rtx_code& cmp, rtx& op0, rtx& op1,
>> ! enum machine_mode mode,
>> ! bool op0_preserve_value ATTRIBUTE_UNUSED)
>> {
>> /* When invoked from within the combine pass the mode is not
>> specified,
>> so try to get it from one of the operands. */
>> *************** sh_canonicalize_comparison (enum rtx_cod
>> *** 2008,2013 ****
>> --- 2016,2034 ----
>> }
>> }
>>
>> + /* This function implements the canonicalize_comparison target hook.
>> + This wrapper around the internally used sh_canonicalize_comparison
>> + function is needed to do the enum rtx_code <-> int conversion.
>> + Target hooks cannot use enum rtx_code in its definition. */
>> + static void
>> + sh_canonicalize_comparison (int *code, rtx *op0, rtx *op1,
>> + bool op0_preserve_value)
>> + {
>> + enum rtx_code tmp_code = (enum rtx_code)*code;
>> + sh_canonicalize_comparison (tmp_code, *op0, *op1,
>> + VOIDmode, op0_preserve_value);
>> + *code = (int)tmp_code;
>> + }
>> enum rtx_code
>> prepare_cbranch_operands (rtx *operands, enum machine_mode mode,
>> enum rtx_code comparison)
>> *************** prepare_cbranch_operands (rtx *operands,
>> *** 2021,2027 ****
>> else
>> scratch = operands[4];
>>
>> ! sh_canonicalize_comparison (comparison, operands[1], operands[2],
>> mode);
>>
>> /* Notice that this function is also invoked after reload by
>> the cbranchdi4_i pattern, through expand_cbranchdi4. */
>> --- 2042,2049 ----
>> else
>> scratch = operands[4];
>>
>> ! sh_canonicalize_comparison (comparison, operands[1], operands[2],
>> ! mode, false);
>>
>> /* Notice that this function is also invoked after reload by
>> the cbranchdi4_i pattern, through expand_cbranchdi4. */
>> Index: gcc/config/sh/sh.h
>> ===================================================================
>> *** gcc/config/sh/sh.h.orig
>> --- gcc/config/sh/sh.h
>> *************** struct sh_args {
>> *** 1873,1882 ****
>> more compact code. */
>> #define SHIFT_COUNT_TRUNCATED (0)
>>
>> - /* CANONICALIZE_COMPARISON macro for the combine pass. */
>> - #define CANONICALIZE_COMPARISON(CODE, OP0, OP1) \
>> - sh_canonicalize_comparison ((CODE), (OP0), (OP1))
>> -
>> /* All integers have the same format so truncation is easy. */
>> /* But SHmedia must sign-extend DImode when truncating to SImode. */
>> #define TRULY_NOOP_TRUNCATION(OUTPREC,INPREC) \
>> --- 1873,1878 ----
>> Index: gcc/config/spu/spu.c
>> ===================================================================
>> *** gcc/config/spu/spu.c.orig
>> --- gcc/config/spu/spu.c
>> *************** spu_output_mi_thunk (FILE *file, tree th
>> *** 7095,7100 ****
>> --- 7095,7114 ----
>> final_end_function ();
>> }
>>
>> + /* Canonicalize a comparison from one we don't have to one we do have.
>> */
>> + static void
>> + spu_canonicalize_comparison (int *code, rtx *op0, rtx *op1,
>> + bool op0_preserve_value)
>> + {
>> + if (!op0_preserve_value
>> + && (*code == LE || *code == LT || *code == LEU || *code == LTU))
>> + {
>> + rtx tem = *op0;
>> + *op0 = *op1;
>> + *op1 = tem;
>> + *code = (int)swap_condition ((enum rtx_code)*code);
>> + }
>> + }
>>
>> /* Table of machine attributes. */
>> static const struct attribute_spec spu_attribute_table[] =
>> *************** static const struct attribute_spec spu_a
>> *** 7308,7313 ****
>> --- 7322,7330 ----
>> #undef TARGET_DELAY_VARTRACK
>> #define TARGET_DELAY_VARTRACK true
>>
>> + #undef TARGET_CANONICALIZE_COMPARISON
>> + #define TARGET_CANONICALIZE_COMPARISON spu_canonicalize_comparison
>> +
>> struct gcc_target targetm = TARGET_INITIALIZER;
>>
>> #include "gt-spu.h"
>> Index: gcc/config/spu/spu.h
>> ===================================================================
>> *** gcc/config/spu/spu.h.orig
>> --- gcc/config/spu/spu.h
>> *************** do {
>> \
>> *** 520,537 ****
>>
>> #define NO_IMPLICIT_EXTERN_C 1
>>
>> - /* Canonicalize a comparison from one we don't have to one we do have.
>> */
>> - #define CANONICALIZE_COMPARISON(CODE,OP0,OP1) \
>> - do {
>> \
>> - if (((CODE) == LE || (CODE) == LT || (CODE) == LEU || (CODE) ==
>> LTU)) \
>> - {
>> \
>> - rtx tem = (OP0);
>> \
>> - (OP0) = (OP1);
>> \
>> - (OP1) = tem;
>> \
>> - (CODE) = swap_condition (CODE);
>> \
>> - }
>> \
>> - } while (0)
>> -
>>
>> /* Address spaces. */
>> #define ADDR_SPACE_EA 1
>> --- 520,525 ----
>> Index: gcc/doc/tm.texi.in
>> ===================================================================
>> *** gcc/doc/tm.texi.in.orig
>> --- gcc/doc/tm.texi.in
>> *************** You should define this macro if and only
>> *** 5928,5952 ****
>> in @file{@var{machine}-modes.def}.
>> @end defmac
>>
>> ! @defmac CANONICALIZE_COMPARISON (@var{code}, @var{op0}, @var{op1})
>> On some machines not all possible comparisons are defined, but you can
>> convert an invalid comparison into a valid one. For example, the Alpha
>> does not have a @code{GT} comparison, but you can use an @code{LT}
>> comparison instead and swap the order of the operands.
>>
>> ! On such machines, define this macro to be a C statement to do any
>> ! required conversions. @var{code} is the initial comparison code
>> ! and @var{op0} and @var{op1} are the left and right operands of the
>> ! comparison, respectively. You should modify @var{code}, @var{op0}, and
>> ! @var{op1} as required.
>>
>> GCC will not assume that the comparison resulting from this macro is
>> valid but will see if the resulting insn matches a pattern in the
>> @file{md} file.
>>
>> ! You need not define this macro if it would never change the comparison
>> ! code or operands.
>> ! @end defmac
>>
>> @defmac REVERSIBLE_CC_MODE (@var{mode})
>> A C expression whose value is one if it is always safe to reverse a
>> --- 5928,5954 ----
>> in @file{@var{machine}-modes.def}.
>> @end defmac
>>
>> ! @hook TARGET_CANONICALIZE_COMPARISON (@var{code}, @var{op0}, @var{op1},
>> @var{op0_preserve_value})
>> On some machines not all possible comparisons are defined, but you can
>> convert an invalid comparison into a valid one. For example, the Alpha
>> does not have a @code{GT} comparison, but you can use an @code{LT}
>> comparison instead and swap the order of the operands.
>>
>> ! On such machines, implement this hook to do any required conversions.
>> ! @var{code} is the initial comparison code and @var{op0} and @var{op1}
>> ! are the left and right operands of the comparison, respectively. If
>> ! @var{op0_preserve_value} is @code{true} the implementation is not
>> ! allowed to change the value of @var{op0} since the value might be used
>> ! in RTXs which aren't comparisons. E.g. the implementation is not
>> ! allowed to swap operands in that case.
>>
>> GCC will not assume that the comparison resulting from this macro is
>> valid but will see if the resulting insn matches a pattern in the
>> @file{md} file.
>>
>> ! You need not to implement this hook if it would never change the
>> ! comparison code or operands.
>> ! @end deftypefn
>>
>> @defmac REVERSIBLE_CC_MODE (@var{mode})
>> A C expression whose value is one if it is always safe to reverse a
>> Index: gcc/target.def
>> ===================================================================
>> *** gcc/target.def.orig
>> --- gcc/target.def
>> *************** DEFHOOK
>> *** 2877,2882 ****
>> --- 2877,2890 ----
>> enum unwind_info_type, (void),
>> default_debug_unwind_info)
>>
>> + /* The code parameter should be of type enum rtx_code but this is not
>> + defined at this time. */
>> + DEFHOOK
>> + (canonicalize_comparison,
>> + "",
>> + void, (int *code, rtx *op0, rtx *op1, bool op0_preserve_value),
>> + default_canonicalize_comparison)
>> +
>> DEFHOOKPOD
>> (atomic_test_and_set_trueval,
>> "This value should be set if the result written by\
>> Index: gcc/targhooks.h
>> ===================================================================
>> *** gcc/targhooks.h.orig
>> --- gcc/targhooks.h
>> *************** extern unsigned char default_class_max_n
>> *** 179,184 ****
>> --- 179,186 ----
>>
>> extern enum unwind_info_type default_debug_unwind_info (void);
>>
>> + extern bool default_canonicalize_comparison (int *, rtx *, rtx *, bool);
>> +
>> extern int default_label_align_after_barrier_max_skip (rtx);
>> extern int default_loop_align_max_skip (rtx);
>> extern int default_label_align_max_skip (rtx);
>> Index: gcc/doc/tm.texi
>> ===================================================================
>> *** gcc/doc/tm.texi.orig
>> --- gcc/doc/tm.texi
>> *************** You should define this macro if and only
>> *** 6024,6048 ****
>> in @file{@var{machine}-modes.def}.
>> @end defmac
>>
>> ! @defmac CANONICALIZE_COMPARISON (@var{code}, @var{op0}, @var{op1})
>> On some machines not all possible comparisons are defined, but you can
>> convert an invalid comparison into a valid one. For example, the Alpha
>> does not have a @code{GT} comparison, but you can use an @code{LT}
>> comparison instead and swap the order of the operands.
>>
>> ! On such machines, define this macro to be a C statement to do any
>> ! required conversions. @var{code} is the initial comparison code
>> ! and @var{op0} and @var{op1} are the left and right operands of the
>> ! comparison, respectively. You should modify @var{code}, @var{op0}, and
>> ! @var{op1} as required.
>>
>> GCC will not assume that the comparison resulting from this macro is
>> valid but will see if the resulting insn matches a pattern in the
>> @file{md} file.
>>
>> ! You need not define this macro if it would never change the comparison
>> ! code or operands.
>> ! @end defmac
>>
>> @defmac REVERSIBLE_CC_MODE (@var{mode})
>> A C expression whose value is one if it is always safe to reverse a
>> --- 6024,6050 ----
>> in @file{@var{machine}-modes.def}.
>> @end defmac
>>
>> ! @deftypefn {Target Hook} void TARGET_CANONICALIZE_COMPARISON (int
>> *@var{code}, rtx *@var{op0}, rtx
>> *@var{op1}, bool @var{op0_preserve_value}) (@var{code}, @var{op0},
>> @var{op1}, @var{op0_preserve_value})
>> On some machines not all possible comparisons are defined, but you can
>> convert an invalid comparison into a valid one. For example, the Alpha
>> does not have a @code{GT} comparison, but you can use an @code{LT}
>> comparison instead and swap the order of the operands.
>>
>> ! On such machines, implement this hook to do any required conversions.
>> ! @var{code} is the initial comparison code and @var{op0} and @var{op1}
>> ! are the left and right operands of the comparison, respectively. If
>> ! @var{op0_preserve_value} is @code{true} the implementation is not
>> ! allowed to change the value of @var{op0} since the value might be used
>> ! in RTXs which aren't comparisons. E.g. the implementation is not
>> ! allowed to swap operands in that case.
>>
>> GCC will not assume that the comparison resulting from this macro is
>> valid but will see if the resulting insn matches a pattern in the
>> @file{md} file.
>>
>> ! You need not to implement this hook if it would never change the
>> ! comparison code or operands.
>> ! @end deftypefn
>>
>> @defmac REVERSIBLE_CC_MODE (@var{mode})
>> A C expression whose value is one if it is always safe to reverse a
>>
>>
>>
>>
>
>
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PING] Bugfix: Additional parameter for canonicalize comparison
2012-12-19 14:04 ` Richard Biener
@ 2012-12-19 14:05 ` Richard Biener
2012-12-19 18:57 ` Jan-Benedict Glaw
1 sibling, 0 replies; 6+ messages in thread
From: Richard Biener @ 2012-12-19 14:05 UTC (permalink / raw)
To: Richard Earnshaw
Cc: Andreas Krebbel, nickc, paul, Ramana Radhakrishnan, gcc-patches
On Wed, Dec 19, 2012 at 3:04 PM, Richard Biener
<richard.guenther@gmail.com> wrote:
> On Wed, Dec 19, 2012 at 12:34 PM, Richard Earnshaw <rearnsha@arm.com> wrote:
>> On 19/12/12 09:53, Andreas Krebbel wrote:
>>>
>>> Hi,
>>>
>>> are the ARM parts of the patch below ok for mainline?
>>>
>>
>> Yes.
>>
>> Sorry for the delay.
>
> I think this broke bootstrap on x86_64:
>
> /space/rguenther/src/svn/trunk/gcc/config/i386/i386.c: At global scope:
> /space/rguenther/src/svn/trunk/gcc/config/i386/i386.c:42503: error:
> invalid conversion from 'bool (*)(int*, rtx_def**, rtx_def**, bool)'
> to 'void (*)(int*, rtx_def**, rtx_def**, bool)'
> make[3]: *** [i386.o] Error 1
>
> or maybe even everywhere. Yeah, bool vs. void return value in the default
> implementation.
>
> Please fix.
I also can't find a definition of default_canonicalize_comparison - did you
forget to commit a part of the patch?
Thanks,
Richard.
> Richard.
>
>> R.
>>
>>
>>> I did a compile test with a cross.
>>>
>>> Bye,
>>>
>>> -Andreas-
>>>
>>>
>>> -------- Original Message --------
>>> Subject: [PATCH] Bugfix: Additional parameter for canonicalize comparison
>>> Date: Wed, 12 Dec 2012 12:23:14 +0100
>>> From: Andreas Krebbel <krebbel@linux.vnet.ibm.com>
>>> To: rearnsha@arm.com
>>> CC: gcc-patches@gcc.gnu.org
>>>
>>> Hi Richard,
>>>
>>> is the attached patch ok for ARM?
>>>
>>> Bye,
>>>
>>> -Andreas-
>>>
>>> 2012-12-12 Andreas Krebbel <Andreas.Krebbel@de.ibm.com>
>>>
>>> * target.def: Define canonicalize_comparison hook.
>>> * targhooks.h (default_canonicalize_comparison): New prototype.
>>> * targhooks.c (default_canonicalize_comparison): New function.
>>> * doc/tm.texi: Add documentation for the new target hook.
>>> * doc/tm.texi.in: Likewise.
>>> * combine.c (try_combine): Adjust to use the target hook.
>>> * config/alpha/alpha.h (CANONICALIZE_COMPARISON): Remove macro
>>> definition.
>>> * config/alpha/alpha.c (alpha_canonicalize_comparison): New
>>> function.
>>> (TARGET_CANONICALIZE_COMPARISON): New macro definition.
>>> * config/arm/arm-protos.h (arm_canonicalize_comparison): Remove
>>> prototype.
>>> * config/arm/arm.c (arm_canonicalize_comparison): Add new
>>> parameter.
>>> (TARGET_CANONICALIZE_COMPARISON): New macro definition.
>>> * config/arm/arm.h (CANONICALIZE_COMPARISON): Remove macro
>>> definition.
>>> * config/s390/s390-protos.h (s390_canonicalize_comparison):
>>> Remove
>>> prototype.
>>> * config/s390/s390.c (s390_canonicalize_comparison): Add new
>>> parameter.
>>> (TARGET_CANONICALIZE_COMPARISON): New macro definition.
>>> * config/s390/s390.h (CANONICALIZE_COMPARISON): Remove macro
>>> definition.
>>> * config/sh/sh-protos.h (sh_canonicalize_comparison): Remove
>>> prototype.
>>> * config/sh/sh.c (sh_canonicalize_comparison): Add new prototype.
>>> New
>>> function overloading the old one.
>>> (TARGET_CANONICALIZE_COMPARISON): New macro definition.
>>> * config/sh/sh.h (CANONICALIZE_COMPARISON): Remove macro
>>> definition.
>>> * config/spu/spu.c (spu_canonicalize_comparison): New function.
>>> (TARGET_CANONICALIZE_COMPARISON): New macro definition.
>>> * config/spu/spu.h (CANONICALIZE_COMPARISON): Remove macro
>>> definition.
>>>
>>> ---
>>> gcc/combine.c | 19 ++++++-!!!
>>> gcc/config/alpha/alpha.c | 27 ++++++++++++++++
>>> gcc/config/alpha/alpha.h | 20 ------------
>>> gcc/config/arm/arm-protos.h | 1
>>> gcc/config/arm/arm.c | 68
>>> ++-!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
>>> gcc/config/arm/arm.h | 3 -
>>> gcc/config/s390/s390-protos.h | 1
>>> gcc/config/s390/s390.c | 13 +++!!!!!
>>> gcc/config/s390/s390.h | 4 --
>>> gcc/config/sh/sh-protos.h | 2 -
>>> gcc/config/sh/sh.c | 34 +++++++++++!!!!!!!!!!
>>> gcc/config/sh/sh.h | 4 --
>>> gcc/config/spu/spu.c | 17 ++++++++++
>>> gcc/config/spu/spu.h | 12 -------
>>> gcc/doc/tm.texi | 20 !!!!!!!!!!!!
>>> gcc/doc/tm.texi.in | 20 !!!!!!!!!!!!
>>> gcc/target.def | 8 ++++
>>> gcc/targhooks.h | 2 +
>>> 18 files changed, 94 insertions(+), 50 deletions(-), 131
>>> modifications(!)
>>>
>>> Index: gcc/combine.c
>>> ===================================================================
>>> *** gcc/combine.c.orig
>>> --- gcc/combine.c
>>> *************** static rtx gen_lowpart_or_truncate (enum
>>> *** 494,499 ****
>>> --- 494,510 ----
>>> static const struct rtl_hooks combine_rtl_hooks =
>>> RTL_HOOKS_INITIALIZER;
>>>
>>>
>>> + /* Convenience wrapper for the canonicalize_comparison target hook.
>>> + Target hooks cannot use enum rtx_code. */
>>> + static inline void
>>> + target_canonicalize_comparison (enum rtx_code *code, rtx *op0, rtx *op1,
>>> + bool op0_preserve_value)
>>> + {
>>> + int code_int = (int)*code;
>>> + targetm.canonicalize_comparison (&code_int, op0, op1,
>>> op0_preserve_value);
>>> + *code = (enum rtx_code)code_int;
>>> + }
>>> +
>>> /* Try to split PATTERN found in INSN. This returns NULL_RTX if
>>> PATTERN can not be split. Otherwise, it returns an insn sequence.
>>> This is a wrapper around split_insns which ensures that the
>>> *************** try_combine (rtx i3, rtx i2, rtx i1, rtx
>>> *** 2944,2952 ****
>>> compare_code = orig_compare_code = GET_CODE (*cc_use_loc);
>>> compare_code = simplify_compare_const (compare_code,
>>> op0, &op1);
>>> ! #ifdef CANONICALIZE_COMPARISON
>>> ! CANONICALIZE_COMPARISON (compare_code, op0, op1);
>>> ! #endif
>>> }
>>>
>>> /* Do the rest only if op1 is const0_rtx, which may be the
>>> --- 2955,2961 ----
>>> compare_code = orig_compare_code = GET_CODE (*cc_use_loc);
>>> compare_code = simplify_compare_const (compare_code,
>>> op0, &op1);
>>> ! target_canonicalize_comparison (&compare_code, &op0, &op1, 1);
>>> }
>>>
>>> /* Do the rest only if op1 is const0_rtx, which may be the
>>> *************** simplify_comparison (enum rtx_code code,
>>> *** 11959,11969 ****
>>> }
>>> }
>>>
>>> - #ifdef CANONICALIZE_COMPARISON
>>> /* If this machine only supports a subset of valid comparisons, see
>>> if we
>>> can convert an unsupported one into a supported one. */
>>> ! CANONICALIZE_COMPARISON (code, op0, op1);
>>> ! #endif
>>>
>>> *pop0 = op0;
>>> *pop1 = op1;
>>> --- 11968,11976 ----
>>> }
>>> }
>>>
>>> /* If this machine only supports a subset of valid comparisons, see
>>> if we
>>> can convert an unsupported one into a supported one. */
>>> ! target_canonicalize_comparison (&code, &op0, &op1, 0);
>>>
>>> *pop0 = op0;
>>> *pop1 = op1;
>>> Index: gcc/config/alpha/alpha.c
>>> ===================================================================
>>> *** gcc/config/alpha/alpha.c.orig
>>> --- gcc/config/alpha/alpha.c
>>> *************** alpha_conditional_register_usage (void)
>>> *** 9683,9688 ****
>>> --- 9683,9712 ----
>>> for (i = 32; i < 63; i++)
>>> fixed_regs[i] = call_used_regs[i] = 1;
>>> }
>>> +
>>> + /* Canonicalize a comparison from one we don't have to one we do have.
>>> */
>>> +
>>> + static void
>>> + alpha_canonicalize_comparison (int *code, rtx *op0, rtx *op1,
>>> + bool op0_preserve_value)
>>> + {
>>> + if (!op0_preserve_value
>>> + && (*code == GE || *code == GT || *code == GEU || *code == GTU)
>>> + && (REG_P (*op1) || *op1 == const0_rtx))
>>> + {
>>> + rtx tem = *op0;
>>> + *op0 = *op1;
>>> + *op1 = tem;
>>> + *code = (int)swap_condition ((enum rtx_code)*code);
>>> + }
>>> +
>>> + if ((*code == LT || *code == LTU)
>>> + && CONST_INT_P (*op1) && INTVAL (*op1) == 256)
>>> + {
>>> + *code = *code == LT ? LE : LEU;
>>> + *op1 = GEN_INT (255);
>>> + }
>>> + }
>>>
>>> /* Initialize the GCC target structure. */
>>> #if TARGET_ABI_OPEN_VMS
>>> *************** alpha_conditional_register_usage (void)
>>> *** 9850,9855 ****
>>> --- 9874,9882 ----
>>> #undef TARGET_CONDITIONAL_REGISTER_USAGE
>>> #define TARGET_CONDITIONAL_REGISTER_USAGE
>>> alpha_conditional_register_usage
>>>
>>> + #undef TARGET_CANONICALIZE_COMPARISON
>>> + #define TARGET_CANONICALIZE_COMPARISON alpha_canonicalize_comparison
>>> +
>>> struct gcc_target targetm = TARGET_INITIALIZER;
>>>
>>>
>>> Index: gcc/config/alpha/alpha.h
>>> ===================================================================
>>> *** gcc/config/alpha/alpha.h.orig
>>> --- gcc/config/alpha/alpha.h
>>> *************** do {
>>> \
>>> *** 922,947 ****
>>> #define FLOAT_STORE_FLAG_VALUE(MODE) \
>>> REAL_VALUE_ATOF ((TARGET_FLOAT_VAX ? "0.5" : "2.0"), (MODE))
>>>
>>> - /* Canonicalize a comparison from one we don't have to one we do have.
>>> */
>>> -
>>> - #define CANONICALIZE_COMPARISON(CODE,OP0,OP1) \
>>> - do {
>>> \
>>> - if (((CODE) == GE || (CODE) == GT || (CODE) == GEU || (CODE) == GTU)
>>> \
>>> - && (REG_P (OP1) || (OP1) == const0_rtx)) \
>>> - {
>>> \
>>> - rtx tem = (OP0); \
>>> - (OP0) = (OP1); \
>>> - (OP1) = tem; \
>>> - (CODE) = swap_condition (CODE); \
>>> - }
>>> \
>>> - if (((CODE) == LT || (CODE) == LTU)
>>> \
>>> - && CONST_INT_P (OP1) && INTVAL (OP1) == 256) \
>>> - {
>>> \
>>> - (CODE) = (CODE) == LT ? LE : LEU; \
>>> - (OP1) = GEN_INT (255); \
>>> - }
>>> \
>>> - } while (0)
>>> -
>>> /* Specify the machine mode that pointers have.
>>> After generation of rtl, the compiler makes no further distinction
>>> between pointers and any other objects of this machine mode. */
>>> --- 922,927 ----
>>> Index: gcc/config/arm/arm-protos.h
>>> ===================================================================
>>> *** gcc/config/arm/arm-protos.h.orig
>>> --- gcc/config/arm/arm-protos.h
>>> *************** extern int const_ok_for_op (HOST_WIDE_IN
>>> *** 53,59 ****
>>> extern int const_ok_for_dimode_op (HOST_WIDE_INT, enum rtx_code);
>>> extern int arm_split_constant (RTX_CODE, enum machine_mode, rtx,
>>> HOST_WIDE_INT, rtx, rtx, int);
>>> - extern RTX_CODE arm_canonicalize_comparison (RTX_CODE, rtx *, rtx *);
>>> extern int legitimate_pic_operand_p (rtx);
>>> extern rtx legitimize_pic_address (rtx, enum machine_mode, rtx);
>>> extern rtx legitimize_tls_address (rtx, rtx);
>>> --- 53,58 ----
>>> Index: gcc/config/arm/arm.c
>>> ===================================================================
>>> *** gcc/config/arm/arm.c.orig
>>> --- gcc/config/arm/arm.c
>>> *************** static int arm_cortex_a5_branch_cost (bo
>>> *** 269,275 ****
>>>
>>> static bool arm_vectorize_vec_perm_const_ok (enum machine_mode vmode,
>>> const unsigned char *sel);
>>> !
>>>
>>> /* Table of machine attributes. */
>>> static const struct attribute_spec arm_attribute_table[] =
>>> --- 269,276 ----
>>>
>>> static bool arm_vectorize_vec_perm_const_ok (enum machine_mode vmode,
>>> const unsigned char *sel);
>>> ! static void arm_canonicalize_comparison (int *code, rtx *op0, rtx *op1,
>>> ! bool op0_preserve_value);
>>>
>>> /* Table of machine attributes. */
>>> static const struct attribute_spec arm_attribute_table[] =
>>> *************** static const struct attribute_spec arm_a
>>> *** 626,631 ****
>>> --- 627,636 ----
>>> #define TARGET_VECTORIZE_VEC_PERM_CONST_OK \
>>> arm_vectorize_vec_perm_const_ok
>>>
>>> + #undef TARGET_CANONICALIZE_COMPARISON
>>> + #define TARGET_CANONICALIZE_COMPARISON \
>>> + arm_canonicalize_comparison
>>> +
>>> struct gcc_target targetm = TARGET_INITIALIZER;
>>>
>>> /* Obstack for minipool constant handling. */
>>> *************** arm_gen_constant (enum rtx_code code, en
>>> *** 3543,3550 ****
>>> This can be done for a few constant compares, where we can make the
>>> immediate value easier to load. */
>>>
>>> ! enum rtx_code
>>> ! arm_canonicalize_comparison (enum rtx_code code, rtx *op0, rtx *op1)
>>> {
>>> enum machine_mode mode;
>>> unsigned HOST_WIDE_INT i, maxval;
>>> --- 3548,3556 ----
>>> This can be done for a few constant compares, where we can make the
>>> immediate value easier to load. */
>>>
>>> ! static void
>>> ! arm_canonicalize_comparison (int *code, rtx *op0, rtx *op1,
>>> ! bool op0_preserve_value)
>>> {
>>> enum machine_mode mode;
>>> unsigned HOST_WIDE_INT i, maxval;
>>> *************** arm_canonicalize_comparison (enum rtx_co
>>> *** 3563,3577 ****
>>> {
>>> rtx tem;
>>>
>>> ! if (code == GT || code == LE
>>> ! || (!TARGET_ARM && (code == GTU || code == LEU)))
>>> {
>>> /* Missing comparison. First try to use an available
>>> comparison. */
>>> if (CONST_INT_P (*op1))
>>> {
>>> i = INTVAL (*op1);
>>> ! switch (code)
>>> {
>>> case GT:
>>> case LE:
>>> --- 3569,3583 ----
>>> {
>>> rtx tem;
>>>
>>> ! if (*code == GT || *code == LE
>>> ! || (!TARGET_ARM && (*code == GTU || *code == LEU)))
>>> {
>>> /* Missing comparison. First try to use an available
>>> comparison. */
>>> if (CONST_INT_P (*op1))
>>> {
>>> i = INTVAL (*op1);
>>> ! switch (*code)
>>> {
>>> case GT:
>>> case LE:
>>> *************** arm_canonicalize_comparison (enum rtx_co
>>> *** 3579,3585 ****
>>> && arm_const_double_by_immediates (GEN_INT (i +
>>> 1)))
>>> {
>>> *op1 = GEN_INT (i + 1);
>>> ! return code == GT ? GE : LT;
>>> }
>>> break;
>>> case GTU:
>>> --- 3585,3592 ----
>>> && arm_const_double_by_immediates (GEN_INT (i +
>>> 1)))
>>> {
>>> *op1 = GEN_INT (i + 1);
>>> ! *code = *code == GT ? GE : LT;
>>> ! return;
>>> }
>>> break;
>>> case GTU:
>>> *************** arm_canonicalize_comparison (enum rtx_co
>>> *** 3588,3594 ****
>>> && arm_const_double_by_immediates (GEN_INT (i +
>>> 1)))
>>> {
>>> *op1 = GEN_INT (i + 1);
>>> ! return code == GTU ? GEU : LTU;
>>> }
>>> break;
>>> default:
>>> --- 3595,3602 ----
>>> && arm_const_double_by_immediates (GEN_INT (i +
>>> 1)))
>>> {
>>> *op1 = GEN_INT (i + 1);
>>> ! *code = *code == GTU ? GEU : LTU;
>>> ! return;
>>> }
>>> break;
>>> default:
>>> *************** arm_canonicalize_comparison (enum rtx_co
>>> *** 3597,3615 ****
>>> }
>>>
>>> /* If that did not work, reverse the condition. */
>>> ! tem = *op0;
>>> ! *op0 = *op1;
>>> ! *op1 = tem;
>>> ! return swap_condition (code);
>>> }
>>> !
>>> ! return code;
>>> }
>>>
>>> /* If *op0 is (zero_extend:SI (subreg:QI (reg:SI) 0)) and comparing
>>> with const0_rtx, change it to (and:SI (reg:SI) (const_int 255)),
>>> to facilitate possible combining with a cmp into 'ands'. */
>>> ! if (mode == SImode
>>> && GET_CODE (*op0) == ZERO_EXTEND
>>> && GET_CODE (XEXP (*op0, 0)) == SUBREG
>>> && GET_MODE (XEXP (*op0, 0)) == QImode
>>> --- 3605,3626 ----
>>> }
>>>
>>> /* If that did not work, reverse the condition. */
>>> ! if (!op0_preserve_value)
>>> ! {
>>> ! tem = *op0;
>>> ! *op0 = *op1;
>>> ! *op1 = tem;
>>> ! *code = (int)swap_condition ((enum rtx_code)*code);
>>> ! }
>>> }
>>> ! return;
>>> }
>>>
>>> /* If *op0 is (zero_extend:SI (subreg:QI (reg:SI) 0)) and comparing
>>> with const0_rtx, change it to (and:SI (reg:SI) (const_int 255)),
>>> to facilitate possible combining with a cmp into 'ands'. */
>>> ! if (!op0_preserve_value
>>> ! && mode == SImode
>>> && GET_CODE (*op0) == ZERO_EXTEND
>>> && GET_CODE (XEXP (*op0, 0)) == SUBREG
>>> && GET_MODE (XEXP (*op0, 0)) == QImode
>>> *************** arm_canonicalize_comparison (enum rtx_co
>>> *** 3624,3638 ****
>>> if (!CONST_INT_P (*op1)
>>> || const_ok_for_arm (INTVAL (*op1))
>>> || const_ok_for_arm (- INTVAL (*op1)))
>>> ! return code;
>>>
>>> i = INTVAL (*op1);
>>>
>>> ! switch (code)
>>> {
>>> case EQ:
>>> case NE:
>>> ! return code;
>>>
>>> case GT:
>>> case LE:
>>> --- 3635,3649 ----
>>> if (!CONST_INT_P (*op1)
>>> || const_ok_for_arm (INTVAL (*op1))
>>> || const_ok_for_arm (- INTVAL (*op1)))
>>> ! return;
>>>
>>> i = INTVAL (*op1);
>>>
>>> ! switch (*code)
>>> {
>>> case EQ:
>>> case NE:
>>> ! return;
>>>
>>> case GT:
>>> case LE:
>>> *************** arm_canonicalize_comparison (enum rtx_co
>>> *** 3640,3646 ****
>>> && (const_ok_for_arm (i + 1) || const_ok_for_arm (-(i + 1))))
>>> {
>>> *op1 = GEN_INT (i + 1);
>>> ! return code == GT ? GE : LT;
>>> }
>>> break;
>>>
>>> --- 3651,3658 ----
>>> && (const_ok_for_arm (i + 1) || const_ok_for_arm (-(i + 1))))
>>> {
>>> *op1 = GEN_INT (i + 1);
>>> ! *code = *code == GT ? GE : LT;
>>> ! return;
>>> }
>>> break;
>>>
>>> *************** arm_canonicalize_comparison (enum rtx_co
>>> *** 3650,3656 ****
>>> && (const_ok_for_arm (i - 1) || const_ok_for_arm (-(i - 1))))
>>> {
>>> *op1 = GEN_INT (i - 1);
>>> ! return code == GE ? GT : LE;
>>> }
>>> break;
>>>
>>> --- 3662,3669 ----
>>> && (const_ok_for_arm (i - 1) || const_ok_for_arm (-(i - 1))))
>>> {
>>> *op1 = GEN_INT (i - 1);
>>> ! *code = *code == GE ? GT : LE;
>>> ! return;
>>> }
>>> break;
>>>
>>> *************** arm_canonicalize_comparison (enum rtx_co
>>> *** 3660,3666 ****
>>> && (const_ok_for_arm (i + 1) || const_ok_for_arm (-(i + 1))))
>>> {
>>> *op1 = GEN_INT (i + 1);
>>> ! return code == GTU ? GEU : LTU;
>>> }
>>> break;
>>>
>>> --- 3673,3680 ----
>>> && (const_ok_for_arm (i + 1) || const_ok_for_arm (-(i + 1))))
>>> {
>>> *op1 = GEN_INT (i + 1);
>>> ! *code = *code == GTU ? GEU : LTU;
>>> ! return;
>>> }
>>> break;
>>>
>>> *************** arm_canonicalize_comparison (enum rtx_co
>>> *** 3670,3684 ****
>>> && (const_ok_for_arm (i - 1) || const_ok_for_arm (-(i - 1))))
>>> {
>>> *op1 = GEN_INT (i - 1);
>>> ! return code == GEU ? GTU : LEU;
>>> }
>>> break;
>>>
>>> default:
>>> gcc_unreachable ();
>>> }
>>> -
>>> - return code;
>>> }
>>>
>>>
>>> --- 3684,3697 ----
>>> && (const_ok_for_arm (i - 1) || const_ok_for_arm (-(i - 1))))
>>> {
>>> *op1 = GEN_INT (i - 1);
>>> ! *code = *code == GEU ? GTU : LEU;
>>> ! return;
>>> }
>>> break;
>>>
>>> default:
>>> gcc_unreachable ();
>>> }
>>> }
>>>
>>>
>>> *************** bool
>>> *** 26979,26985 ****
>>> arm_validize_comparison (rtx *comparison, rtx * op1, rtx * op2)
>>> {
>>> enum rtx_code code = GET_CODE (*comparison);
>>> ! enum rtx_code canonical_code;
>>> enum machine_mode mode = (GET_MODE (*op1) == VOIDmode)
>>> ? GET_MODE (*op2) : GET_MODE (*op1);
>>>
>>> --- 26992,26998 ----
>>> arm_validize_comparison (rtx *comparison, rtx * op1, rtx * op2)
>>> {
>>> enum rtx_code code = GET_CODE (*comparison);
>>> ! int code_int;
>>> enum machine_mode mode = (GET_MODE (*op1) == VOIDmode)
>>> ? GET_MODE (*op2) : GET_MODE (*op1);
>>>
>>> *************** arm_validize_comparison (rtx *comparison
>>> *** 26988,26995 ****
>>> if (code == UNEQ || code == LTGT)
>>> return false;
>>>
>>> ! canonical_code = arm_canonicalize_comparison (code, op1, op2);
>>> ! PUT_CODE (*comparison, canonical_code);
>>>
>>> switch (mode)
>>> {
>>> --- 27001,27009 ----
>>> if (code == UNEQ || code == LTGT)
>>> return false;
>>>
>>> ! code_int = (int)code;
>>> ! arm_canonicalize_comparison (&code_int, op1, op2, 0);
>>> ! PUT_CODE (*comparison, (enum rtx_code)code_int);
>>>
>>> switch (mode)
>>> {
>>> Index: gcc/config/arm/arm.h
>>> ===================================================================
>>> *** gcc/config/arm/arm.h.orig
>>> --- gcc/config/arm/arm.h
>>> *************** extern int making_const_table;
>>> *** 2078,2086 ****
>>> ? reverse_condition_maybe_unordered (code) \
>>> : reverse_condition (code))
>>>
>>> - #define CANONICALIZE_COMPARISON(CODE, OP0, OP1)
>>> \
>>> - (CODE) = arm_canonicalize_comparison (CODE, &(OP0), &(OP1))
>>> -
>>> /* The arm5 clz instruction returns 32. */
>>> #define CLZ_DEFINED_VALUE_AT_ZERO(MODE, VALUE) ((VALUE) = 32, 1)
>>> #define CTZ_DEFINED_VALUE_AT_ZERO(MODE, VALUE) ((VALUE) = 32, 1)
>>> --- 2078,2083 ----
>>> Index: gcc/config/s390/s390-protos.h
>>> ===================================================================
>>> *** gcc/config/s390/s390-protos.h.orig
>>> --- gcc/config/s390/s390-protos.h
>>> *************** extern int tls_symbolic_operand (rtx);
>>> *** 58,64 ****
>>> extern bool s390_match_ccmode (rtx, enum machine_mode);
>>> extern enum machine_mode s390_tm_ccmode (rtx, rtx, bool);
>>> extern enum machine_mode s390_select_ccmode (enum rtx_code, rtx, rtx);
>>> - extern void s390_canonicalize_comparison (enum rtx_code *, rtx *, rtx
>>> *);
>>> extern rtx s390_emit_compare (enum rtx_code, rtx, rtx);
>>> extern void s390_emit_jump (rtx, rtx);
>>> extern bool symbolic_reference_mentioned_p (rtx);
>>> --- 58,63 ----
>>> Index: gcc/config/s390/s390.c
>>> ===================================================================
>>> *** gcc/config/s390/s390.c.orig
>>> --- gcc/config/s390/s390.c
>>> *************** s390_select_ccmode (enum rtx_code code,
>>> *** 745,753 ****
>>> /* Replace the comparison OP0 CODE OP1 by a semantically equivalent one
>>> that we can implement more efficiently. */
>>>
>>> ! void
>>> ! s390_canonicalize_comparison (enum rtx_code *code, rtx *op0, rtx *op1)
>>> {
>>> /* Convert ZERO_EXTRACT back to AND to enable TM patterns. */
>>> if ((*code == EQ || *code == NE)
>>> && *op1 == const0_rtx
>>> --- 745,757 ----
>>> /* Replace the comparison OP0 CODE OP1 by a semantically equivalent one
>>> that we can implement more efficiently. */
>>>
>>> ! static void
>>> ! s390_canonicalize_comparison (int *code, rtx *op0, rtx *op1,
>>> ! bool op0_preserve_value)
>>> {
>>> + if (op0_preserve_value)
>>> + return;
>>> +
>>> /* Convert ZERO_EXTRACT back to AND to enable TM patterns. */
>>> if ((*code == EQ || *code == NE)
>>> && *op1 == const0_rtx
>>> *************** s390_canonicalize_comparison (enum rtx_c
>>> *** 894,900 ****
>>> if (MEM_P (*op0) && REG_P (*op1))
>>> {
>>> rtx tem = *op0; *op0 = *op1; *op1 = tem;
>>> ! *code = swap_condition (*code);
>>> }
>>> }
>>>
>>> --- 898,904 ----
>>> if (MEM_P (*op0) && REG_P (*op1))
>>> {
>>> rtx tem = *op0; *op0 = *op1; *op1 = tem;
>>> ! *code = (int)swap_condition ((enum rtx_code)*code);
>>> }
>>> }
>>>
>>> *************** s390_loop_unroll_adjust (unsigned nunrol
>>> *** 11071,11076 ****
>>> --- 11075,11083 ----
>>> #undef TARGET_UNWIND_WORD_MODE
>>> #define TARGET_UNWIND_WORD_MODE s390_unwind_word_mode
>>>
>>> + #undef TARGET_CANONICALIZE_COMPARISON
>>> + #define TARGET_CANONICALIZE_COMPARISON s390_canonicalize_comparison
>>> +
>>> struct gcc_target targetm = TARGET_INITIALIZER;
>>>
>>> #include "gt-s390.h"
>>> Index: gcc/config/s390/s390.h
>>> ===================================================================
>>> *** gcc/config/s390/s390.h.orig
>>> --- gcc/config/s390/s390.h
>>> *************** do {
>>> \
>>> *** 720,729 ****
>>> return the mode to be used for the comparison. */
>>> #define SELECT_CC_MODE(OP, X, Y) s390_select_ccmode ((OP), (X), (Y))
>>>
>>> - /* Canonicalize a comparison from one we don't have to one we do have.
>>> */
>>> - #define CANONICALIZE_COMPARISON(CODE, OP0, OP1) \
>>> - s390_canonicalize_comparison (&(CODE), &(OP0), &(OP1))
>>> -
>>> /* Relative costs of operations. */
>>>
>>> /* A C expression for the cost of a branch instruction. A value of 1
>>> --- 720,725 ----
>>> Index: gcc/config/sh/sh-protos.h
>>> ===================================================================
>>> *** gcc/config/sh/sh-protos.h.orig
>>> --- gcc/config/sh/sh-protos.h
>>> *************** extern bool sh_expand_t_scc (rtx *);
>>> *** 159,166 ****
>>> extern rtx sh_gen_truncate (enum machine_mode, rtx, int);
>>> extern bool sh_vector_mode_supported_p (enum machine_mode);
>>> extern bool sh_cfun_trap_exit_p (void);
>>> - extern void sh_canonicalize_comparison (enum rtx_code&, rtx&, rtx&,
>>> - enum machine_mode mode =
>>> VOIDmode);
>>> extern rtx sh_find_equiv_gbr_addr (rtx cur_insn, rtx mem);
>>> extern int sh_eval_treg_value (rtx op);
>>>
>>> --- 159,164 ----
>>> Index: gcc/config/sh/sh.c
>>> ===================================================================
>>> *** gcc/config/sh/sh.c.orig
>>> --- gcc/config/sh/sh.c
>>> *************** static int max_mov_insn_displacement (en
>>> *** 314,319 ****
>>> --- 314,322 ----
>>> static int mov_insn_alignment_mask (enum machine_mode, bool);
>>> static HOST_WIDE_INT disp_addr_displacement (rtx);
>>> static bool sequence_insn_p (rtx);
>>> + static void sh_canonicalize_comparison (int *, rtx *, rtx *, bool);
>>> + static void sh_canonicalize_comparison (enum rtx_code&, rtx&, rtx&,
>>> + enum machine_mode, bool);
>>>
>>> static void sh_init_sync_libfuncs (void) ATTRIBUTE_UNUSED;
>>>
>>> *************** static const struct attribute_spec sh_at
>>> *** 586,591 ****
>>> --- 589,597 ----
>>> #undef TARGET_LEGITIMATE_CONSTANT_P
>>> #define TARGET_LEGITIMATE_CONSTANT_P sh_legitimate_constant_p
>>>
>>> + #undef TARGET_CANONICALIZE_COMPARISON
>>> + #define TARGET_CANONICALIZE_COMPARISON sh_canonicalize_comparison
>>> +
>>> /* Machine-specific symbol_ref flags. */
>>> #define SYMBOL_FLAG_FUNCVEC_FUNCTION (SYMBOL_FLAG_MACH_DEP << 0)
>>>
>>> *************** prepare_move_operands (rtx operands[], e
>>> *** 1909,1920 ****
>>> }
>>> }
>>>
>>> ! /* Implement the CANONICALIZE_COMPARISON macro for the combine pass.
>>> ! This function is also re-used to canonicalize comparisons in cbranch
>>> ! pattern expanders. */
>>> ! void
>>> sh_canonicalize_comparison (enum rtx_code& cmp, rtx& op0, rtx& op1,
>>> ! enum machine_mode mode)
>>> {
>>> /* When invoked from within the combine pass the mode is not
>>> specified,
>>> so try to get it from one of the operands. */
>>> --- 1915,1928 ----
>>> }
>>> }
>>>
>>> ! /* Implement the canonicalize_comparison target hook for the combine
>>> ! pass. For the target hook this function is invoked via
>>> ! sh_canonicalize_comparison. This function is also re-used to
>>> ! canonicalize comparisons in cbranch pattern expanders. */
>>> ! static void
>>> sh_canonicalize_comparison (enum rtx_code& cmp, rtx& op0, rtx& op1,
>>> ! enum machine_mode mode,
>>> ! bool op0_preserve_value ATTRIBUTE_UNUSED)
>>> {
>>> /* When invoked from within the combine pass the mode is not
>>> specified,
>>> so try to get it from one of the operands. */
>>> *************** sh_canonicalize_comparison (enum rtx_cod
>>> *** 2008,2013 ****
>>> --- 2016,2034 ----
>>> }
>>> }
>>>
>>> + /* This function implements the canonicalize_comparison target hook.
>>> + This wrapper around the internally used sh_canonicalize_comparison
>>> + function is needed to do the enum rtx_code <-> int conversion.
>>> + Target hooks cannot use enum rtx_code in its definition. */
>>> + static void
>>> + sh_canonicalize_comparison (int *code, rtx *op0, rtx *op1,
>>> + bool op0_preserve_value)
>>> + {
>>> + enum rtx_code tmp_code = (enum rtx_code)*code;
>>> + sh_canonicalize_comparison (tmp_code, *op0, *op1,
>>> + VOIDmode, op0_preserve_value);
>>> + *code = (int)tmp_code;
>>> + }
>>> enum rtx_code
>>> prepare_cbranch_operands (rtx *operands, enum machine_mode mode,
>>> enum rtx_code comparison)
>>> *************** prepare_cbranch_operands (rtx *operands,
>>> *** 2021,2027 ****
>>> else
>>> scratch = operands[4];
>>>
>>> ! sh_canonicalize_comparison (comparison, operands[1], operands[2],
>>> mode);
>>>
>>> /* Notice that this function is also invoked after reload by
>>> the cbranchdi4_i pattern, through expand_cbranchdi4. */
>>> --- 2042,2049 ----
>>> else
>>> scratch = operands[4];
>>>
>>> ! sh_canonicalize_comparison (comparison, operands[1], operands[2],
>>> ! mode, false);
>>>
>>> /* Notice that this function is also invoked after reload by
>>> the cbranchdi4_i pattern, through expand_cbranchdi4. */
>>> Index: gcc/config/sh/sh.h
>>> ===================================================================
>>> *** gcc/config/sh/sh.h.orig
>>> --- gcc/config/sh/sh.h
>>> *************** struct sh_args {
>>> *** 1873,1882 ****
>>> more compact code. */
>>> #define SHIFT_COUNT_TRUNCATED (0)
>>>
>>> - /* CANONICALIZE_COMPARISON macro for the combine pass. */
>>> - #define CANONICALIZE_COMPARISON(CODE, OP0, OP1) \
>>> - sh_canonicalize_comparison ((CODE), (OP0), (OP1))
>>> -
>>> /* All integers have the same format so truncation is easy. */
>>> /* But SHmedia must sign-extend DImode when truncating to SImode. */
>>> #define TRULY_NOOP_TRUNCATION(OUTPREC,INPREC) \
>>> --- 1873,1878 ----
>>> Index: gcc/config/spu/spu.c
>>> ===================================================================
>>> *** gcc/config/spu/spu.c.orig
>>> --- gcc/config/spu/spu.c
>>> *************** spu_output_mi_thunk (FILE *file, tree th
>>> *** 7095,7100 ****
>>> --- 7095,7114 ----
>>> final_end_function ();
>>> }
>>>
>>> + /* Canonicalize a comparison from one we don't have to one we do have.
>>> */
>>> + static void
>>> + spu_canonicalize_comparison (int *code, rtx *op0, rtx *op1,
>>> + bool op0_preserve_value)
>>> + {
>>> + if (!op0_preserve_value
>>> + && (*code == LE || *code == LT || *code == LEU || *code == LTU))
>>> + {
>>> + rtx tem = *op0;
>>> + *op0 = *op1;
>>> + *op1 = tem;
>>> + *code = (int)swap_condition ((enum rtx_code)*code);
>>> + }
>>> + }
>>>
>>> /* Table of machine attributes. */
>>> static const struct attribute_spec spu_attribute_table[] =
>>> *************** static const struct attribute_spec spu_a
>>> *** 7308,7313 ****
>>> --- 7322,7330 ----
>>> #undef TARGET_DELAY_VARTRACK
>>> #define TARGET_DELAY_VARTRACK true
>>>
>>> + #undef TARGET_CANONICALIZE_COMPARISON
>>> + #define TARGET_CANONICALIZE_COMPARISON spu_canonicalize_comparison
>>> +
>>> struct gcc_target targetm = TARGET_INITIALIZER;
>>>
>>> #include "gt-spu.h"
>>> Index: gcc/config/spu/spu.h
>>> ===================================================================
>>> *** gcc/config/spu/spu.h.orig
>>> --- gcc/config/spu/spu.h
>>> *************** do {
>>> \
>>> *** 520,537 ****
>>>
>>> #define NO_IMPLICIT_EXTERN_C 1
>>>
>>> - /* Canonicalize a comparison from one we don't have to one we do have.
>>> */
>>> - #define CANONICALIZE_COMPARISON(CODE,OP0,OP1) \
>>> - do {
>>> \
>>> - if (((CODE) == LE || (CODE) == LT || (CODE) == LEU || (CODE) ==
>>> LTU)) \
>>> - {
>>> \
>>> - rtx tem = (OP0);
>>> \
>>> - (OP0) = (OP1);
>>> \
>>> - (OP1) = tem;
>>> \
>>> - (CODE) = swap_condition (CODE);
>>> \
>>> - }
>>> \
>>> - } while (0)
>>> -
>>>
>>> /* Address spaces. */
>>> #define ADDR_SPACE_EA 1
>>> --- 520,525 ----
>>> Index: gcc/doc/tm.texi.in
>>> ===================================================================
>>> *** gcc/doc/tm.texi.in.orig
>>> --- gcc/doc/tm.texi.in
>>> *************** You should define this macro if and only
>>> *** 5928,5952 ****
>>> in @file{@var{machine}-modes.def}.
>>> @end defmac
>>>
>>> ! @defmac CANONICALIZE_COMPARISON (@var{code}, @var{op0}, @var{op1})
>>> On some machines not all possible comparisons are defined, but you can
>>> convert an invalid comparison into a valid one. For example, the Alpha
>>> does not have a @code{GT} comparison, but you can use an @code{LT}
>>> comparison instead and swap the order of the operands.
>>>
>>> ! On such machines, define this macro to be a C statement to do any
>>> ! required conversions. @var{code} is the initial comparison code
>>> ! and @var{op0} and @var{op1} are the left and right operands of the
>>> ! comparison, respectively. You should modify @var{code}, @var{op0}, and
>>> ! @var{op1} as required.
>>>
>>> GCC will not assume that the comparison resulting from this macro is
>>> valid but will see if the resulting insn matches a pattern in the
>>> @file{md} file.
>>>
>>> ! You need not define this macro if it would never change the comparison
>>> ! code or operands.
>>> ! @end defmac
>>>
>>> @defmac REVERSIBLE_CC_MODE (@var{mode})
>>> A C expression whose value is one if it is always safe to reverse a
>>> --- 5928,5954 ----
>>> in @file{@var{machine}-modes.def}.
>>> @end defmac
>>>
>>> ! @hook TARGET_CANONICALIZE_COMPARISON (@var{code}, @var{op0}, @var{op1},
>>> @var{op0_preserve_value})
>>> On some machines not all possible comparisons are defined, but you can
>>> convert an invalid comparison into a valid one. For example, the Alpha
>>> does not have a @code{GT} comparison, but you can use an @code{LT}
>>> comparison instead and swap the order of the operands.
>>>
>>> ! On such machines, implement this hook to do any required conversions.
>>> ! @var{code} is the initial comparison code and @var{op0} and @var{op1}
>>> ! are the left and right operands of the comparison, respectively. If
>>> ! @var{op0_preserve_value} is @code{true} the implementation is not
>>> ! allowed to change the value of @var{op0} since the value might be used
>>> ! in RTXs which aren't comparisons. E.g. the implementation is not
>>> ! allowed to swap operands in that case.
>>>
>>> GCC will not assume that the comparison resulting from this macro is
>>> valid but will see if the resulting insn matches a pattern in the
>>> @file{md} file.
>>>
>>> ! You need not to implement this hook if it would never change the
>>> ! comparison code or operands.
>>> ! @end deftypefn
>>>
>>> @defmac REVERSIBLE_CC_MODE (@var{mode})
>>> A C expression whose value is one if it is always safe to reverse a
>>> Index: gcc/target.def
>>> ===================================================================
>>> *** gcc/target.def.orig
>>> --- gcc/target.def
>>> *************** DEFHOOK
>>> *** 2877,2882 ****
>>> --- 2877,2890 ----
>>> enum unwind_info_type, (void),
>>> default_debug_unwind_info)
>>>
>>> + /* The code parameter should be of type enum rtx_code but this is not
>>> + defined at this time. */
>>> + DEFHOOK
>>> + (canonicalize_comparison,
>>> + "",
>>> + void, (int *code, rtx *op0, rtx *op1, bool op0_preserve_value),
>>> + default_canonicalize_comparison)
>>> +
>>> DEFHOOKPOD
>>> (atomic_test_and_set_trueval,
>>> "This value should be set if the result written by\
>>> Index: gcc/targhooks.h
>>> ===================================================================
>>> *** gcc/targhooks.h.orig
>>> --- gcc/targhooks.h
>>> *************** extern unsigned char default_class_max_n
>>> *** 179,184 ****
>>> --- 179,186 ----
>>>
>>> extern enum unwind_info_type default_debug_unwind_info (void);
>>>
>>> + extern bool default_canonicalize_comparison (int *, rtx *, rtx *, bool);
>>> +
>>> extern int default_label_align_after_barrier_max_skip (rtx);
>>> extern int default_loop_align_max_skip (rtx);
>>> extern int default_label_align_max_skip (rtx);
>>> Index: gcc/doc/tm.texi
>>> ===================================================================
>>> *** gcc/doc/tm.texi.orig
>>> --- gcc/doc/tm.texi
>>> *************** You should define this macro if and only
>>> *** 6024,6048 ****
>>> in @file{@var{machine}-modes.def}.
>>> @end defmac
>>>
>>> ! @defmac CANONICALIZE_COMPARISON (@var{code}, @var{op0}, @var{op1})
>>> On some machines not all possible comparisons are defined, but you can
>>> convert an invalid comparison into a valid one. For example, the Alpha
>>> does not have a @code{GT} comparison, but you can use an @code{LT}
>>> comparison instead and swap the order of the operands.
>>>
>>> ! On such machines, define this macro to be a C statement to do any
>>> ! required conversions. @var{code} is the initial comparison code
>>> ! and @var{op0} and @var{op1} are the left and right operands of the
>>> ! comparison, respectively. You should modify @var{code}, @var{op0}, and
>>> ! @var{op1} as required.
>>>
>>> GCC will not assume that the comparison resulting from this macro is
>>> valid but will see if the resulting insn matches a pattern in the
>>> @file{md} file.
>>>
>>> ! You need not define this macro if it would never change the comparison
>>> ! code or operands.
>>> ! @end defmac
>>>
>>> @defmac REVERSIBLE_CC_MODE (@var{mode})
>>> A C expression whose value is one if it is always safe to reverse a
>>> --- 6024,6050 ----
>>> in @file{@var{machine}-modes.def}.
>>> @end defmac
>>>
>>> ! @deftypefn {Target Hook} void TARGET_CANONICALIZE_COMPARISON (int
>>> *@var{code}, rtx *@var{op0}, rtx
>>> *@var{op1}, bool @var{op0_preserve_value}) (@var{code}, @var{op0},
>>> @var{op1}, @var{op0_preserve_value})
>>> On some machines not all possible comparisons are defined, but you can
>>> convert an invalid comparison into a valid one. For example, the Alpha
>>> does not have a @code{GT} comparison, but you can use an @code{LT}
>>> comparison instead and swap the order of the operands.
>>>
>>> ! On such machines, implement this hook to do any required conversions.
>>> ! @var{code} is the initial comparison code and @var{op0} and @var{op1}
>>> ! are the left and right operands of the comparison, respectively. If
>>> ! @var{op0_preserve_value} is @code{true} the implementation is not
>>> ! allowed to change the value of @var{op0} since the value might be used
>>> ! in RTXs which aren't comparisons. E.g. the implementation is not
>>> ! allowed to swap operands in that case.
>>>
>>> GCC will not assume that the comparison resulting from this macro is
>>> valid but will see if the resulting insn matches a pattern in the
>>> @file{md} file.
>>>
>>> ! You need not to implement this hook if it would never change the
>>> ! comparison code or operands.
>>> ! @end deftypefn
>>>
>>> @defmac REVERSIBLE_CC_MODE (@var{mode})
>>> A C expression whose value is one if it is always safe to reverse a
>>>
>>>
>>>
>>>
>>
>>
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PING] Bugfix: Additional parameter for canonicalize comparison
2012-12-19 14:04 ` Richard Biener
2012-12-19 14:05 ` Richard Biener
@ 2012-12-19 18:57 ` Jan-Benedict Glaw
1 sibling, 0 replies; 6+ messages in thread
From: Jan-Benedict Glaw @ 2012-12-19 18:57 UTC (permalink / raw)
To: Richard Biener
Cc: Richard Earnshaw, Andreas Krebbel, nickc, paul,
Ramana Radhakrishnan, gcc-patches
[-- Attachment #1: Type: text/plain, Size: 1298 bytes --]
On Wed, 2012-12-19 15:04:02 +0100, Richard Biener <richard.guenther@gmail.com> wrote:
> On Wed, Dec 19, 2012 at 12:34 PM, Richard Earnshaw <rearnsha@arm.com> wrote:
> > On 19/12/12 09:53, Andreas Krebbel wrote:
> >>
> >> Hi,
> >>
> >> are the ARM parts of the patch below ok for mainline?
> >>
> >
> > Yes.
> >
> > Sorry for the delay.
>
> I think this broke bootstrap on x86_64:
>
> /space/rguenther/src/svn/trunk/gcc/config/i386/i386.c: At global scope:
> /space/rguenther/src/svn/trunk/gcc/config/i386/i386.c:42503: error:
> invalid conversion from 'bool (*)(int*, rtx_def**, rtx_def**, bool)'
> to 'void (*)(int*, rtx_def**, rtx_def**, bool)'
> make[3]: *** [i386.o] Error 1
>
> or maybe even everywhere. Yeah, bool vs. void return value in the default
> implementation.
My build robot already found aarch64-elf, avr, bfin-elf and frv-linux
broken by this. Probably every target affected that use the default
function.
MfG, JBG
--
Jan-Benedict Glaw jbglaw@lug-owl.de +49-172-7608481
Signature of: Ich hatte in letzter Zeit ein bißchen viel Realitycheck.
the second : Langsam möchte ich mal wieder weiterträumen können.
-- Maximilian Wilhelm (18. Mai 2005, #lug-owl.de)
[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 198 bytes --]
^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2012-12-19 18:57 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-12-12 11:23 [PATCH] Bugfix: Additional parameter for canonicalize comparison Andreas Krebbel
2012-12-19 9:53 ` [PING] " Andreas Krebbel
2012-12-19 11:34 ` Richard Earnshaw
2012-12-19 14:04 ` Richard Biener
2012-12-19 14:05 ` Richard Biener
2012-12-19 18:57 ` Jan-Benedict Glaw
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).