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. 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 >> >> >> >> > >