On Wed, Dec 19, 2012 at 3:04 PM, Richard Biener <richard.guent...@gmail.com> wrote: > On Wed, Dec 19, 2012 at 12:34 PM, Richard Earnshaw <rearn...@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 <kreb...@linux.vnet.ibm.com> >>> To: rearn...@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.kreb...@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 >>> >>> >>> >>> >> >>