From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 3141 invoked by alias); 12 Dec 2012 11:23:41 -0000 Received: (qmail 3125 invoked by uid 22791); 12 Dec 2012 11:23:40 -0000 X-SWARE-Spam-Status: No, hits=-3.0 required=5.0 tests=AWL,BAYES_00,KAM_STOCKGEN,KHOP_RCVD_UNTRUST,RCVD_IN_HOSTKARMA_W,RCVD_IN_HOSTKARMA_WL,RP_MATCHES_RCVD,TW_CL X-Spam-Check-By: sourceware.org Received: from e06smtp14.uk.ibm.com (HELO e06smtp14.uk.ibm.com) (195.75.94.110) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Wed, 12 Dec 2012 11:23:20 +0000 Received: from /spool/local by e06smtp14.uk.ibm.com with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted for from ; Wed, 12 Dec 2012 11:22:52 -0000 Received: from b06cxnps4074.portsmouth.uk.ibm.com (9.149.109.196) by e06smtp14.uk.ibm.com (192.168.101.144) with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted; Wed, 12 Dec 2012 11:22:51 -0000 Received: from d06av09.portsmouth.uk.ibm.com (d06av09.portsmouth.uk.ibm.com [9.149.37.250]) by b06cxnps4074.portsmouth.uk.ibm.com (8.13.8/8.13.8/NCO v10.0) with ESMTP id qBCBN8Sk64094350 for ; Wed, 12 Dec 2012 11:23:09 GMT Received: from d06av09.portsmouth.uk.ibm.com (loopback [127.0.0.1]) by d06av09.portsmouth.uk.ibm.com (8.14.4/8.13.1/NCO v10.0 AVout) with ESMTP id qBCBNGRt021829 for ; Wed, 12 Dec 2012 04:23:16 -0700 Received: from bart (icon-9-167-213-92.megacenter.de.ibm.com [9.167.213.92]) by d06av09.portsmouth.uk.ibm.com (8.14.4/8.13.1/NCO v10.0 AVin) with SMTP id qBCBNF8h021819; Wed, 12 Dec 2012 04:23:15 -0700 Received: by bart (sSMTP sendmail emulation); Wed, 12 Dec 2012 12:23:14 +0100 Date: Wed, 12 Dec 2012 11:23:00 -0000 From: Andreas Krebbel To: rearnsha@arm.com Cc: gcc-patches@gcc.gnu.org Subject: [PATCH] Bugfix: Additional parameter for canonicalize comparison Message-ID: <20121212112314.GA5131@bart> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline User-Agent: Mutt/1.5.21 (2010-09-15) x-cbid: 12121211-1948-0000-0000-000003C58E1D X-IsSubscribed: yes Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org X-SW-Source: 2012-12/txt/msg00786.txt.bz2 Hi Richard, is the attached patch ok for ARM? Bye, -Andreas- 2012-12-12 Andreas Krebbel * 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