* [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).