diff options
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 39 | ||||
-rw-r--r-- | gcc/combine.c | 19 | ||||
-rw-r--r-- | gcc/config/alpha/alpha.c | 27 | ||||
-rw-r--r-- | gcc/config/alpha/alpha.h | 20 | ||||
-rw-r--r-- | gcc/config/arm/arm-protos.h | 1 | ||||
-rw-r--r-- | gcc/config/arm/arm.c | 68 | ||||
-rw-r--r-- | gcc/config/arm/arm.h | 3 | ||||
-rw-r--r-- | gcc/config/s390/s390-protos.h | 1 | ||||
-rw-r--r-- | gcc/config/s390/s390.c | 13 | ||||
-rw-r--r-- | gcc/config/s390/s390.h | 4 | ||||
-rw-r--r-- | gcc/config/sh/sh-protos.h | 2 | ||||
-rw-r--r-- | gcc/config/sh/sh.c | 34 | ||||
-rw-r--r-- | gcc/config/sh/sh.h | 4 | ||||
-rw-r--r-- | gcc/config/spu/spu.c | 17 | ||||
-rw-r--r-- | gcc/config/spu/spu.h | 12 | ||||
-rw-r--r-- | gcc/doc/tm.texi | 20 | ||||
-rw-r--r-- | gcc/doc/tm.texi.in | 20 | ||||
-rw-r--r-- | gcc/target.def | 8 | ||||
-rw-r--r-- | gcc/targhooks.h | 2 |
19 files changed, 207 insertions, 107 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 34b5836..fe52e01 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,42 @@ +2012-12-19 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. + 2012-12-19 Jakub Jelinek <jakub@redhat.com> PR debug/55730 diff --git a/gcc/combine.c b/gcc/combine.c index abd67e8..001025c 100644 --- a/gcc/combine.c +++ b/gcc/combine.c @@ -494,6 +494,17 @@ static rtx gen_lowpart_or_truncate (enum machine_mode, rtx); 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 @@ -2944,9 +2955,7 @@ try_combine (rtx i3, rtx i2, rtx i1, rtx i0, int *new_direct_jump_p, 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 + target_canonicalize_comparison (&compare_code, &op0, &op1, 1); } /* Do the rest only if op1 is const0_rtx, which may be the @@ -11959,11 +11968,9 @@ simplify_comparison (enum rtx_code code, rtx *pop0, rtx *pop1) } } -#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 + target_canonicalize_comparison (&code, &op0, &op1, 0); *pop0 = op0; *pop1 = op1; diff --git a/gcc/config/alpha/alpha.c b/gcc/config/alpha/alpha.c index 8411218..fa2f733 100644 --- a/gcc/config/alpha/alpha.c +++ b/gcc/config/alpha/alpha.c @@ -9686,6 +9686,30 @@ alpha_conditional_register_usage (void) 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 @@ -9853,6 +9877,9 @@ alpha_conditional_register_usage (void) #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; diff --git a/gcc/config/alpha/alpha.h b/gcc/config/alpha/alpha.h index bc14d84..a70c7f8 100644 --- a/gcc/config/alpha/alpha.h +++ b/gcc/config/alpha/alpha.h @@ -922,26 +922,6 @@ do { \ #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. */ diff --git a/gcc/config/arm/arm-protos.h b/gcc/config/arm/arm-protos.h index d942c5b..4c61e35e 100644 --- a/gcc/config/arm/arm-protos.h +++ b/gcc/config/arm/arm-protos.h @@ -53,7 +53,6 @@ extern int const_ok_for_op (HOST_WIDE_INT, enum rtx_code); 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); diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c index 15f9c9b..be4428b 100644 --- a/gcc/config/arm/arm.c +++ b/gcc/config/arm/arm.c @@ -269,7 +269,8 @@ static int arm_cortex_a5_branch_cost (bool, bool); 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[] = @@ -626,6 +627,10 @@ static const struct attribute_spec arm_attribute_table[] = #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. */ @@ -3543,8 +3548,9 @@ arm_gen_constant (enum rtx_code code, enum machine_mode mode, rtx cond, 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) +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; @@ -3563,15 +3569,15 @@ arm_canonicalize_comparison (enum rtx_code code, rtx *op0, rtx *op1) { rtx tem; - if (code == GT || code == LE - || (!TARGET_ARM && (code == GTU || code == LEU))) + 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) + switch (*code) { case GT: case LE: @@ -3579,7 +3585,8 @@ arm_canonicalize_comparison (enum rtx_code code, rtx *op0, rtx *op1) && arm_const_double_by_immediates (GEN_INT (i + 1))) { *op1 = GEN_INT (i + 1); - return code == GT ? GE : LT; + *code = *code == GT ? GE : LT; + return; } break; case GTU: @@ -3588,7 +3595,8 @@ arm_canonicalize_comparison (enum rtx_code code, rtx *op0, rtx *op1) && arm_const_double_by_immediates (GEN_INT (i + 1))) { *op1 = GEN_INT (i + 1); - return code == GTU ? GEU : LTU; + *code = *code == GTU ? GEU : LTU; + return; } break; default: @@ -3597,19 +3605,22 @@ arm_canonicalize_comparison (enum rtx_code code, rtx *op0, rtx *op1) } /* If that did not work, reverse the condition. */ - tem = *op0; - *op0 = *op1; - *op1 = tem; - return swap_condition (code); + if (!op0_preserve_value) + { + tem = *op0; + *op0 = *op1; + *op1 = tem; + *code = (int)swap_condition ((enum rtx_code)*code); + } } - - return 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 (mode == SImode + if (!op0_preserve_value + && mode == SImode && GET_CODE (*op0) == ZERO_EXTEND && GET_CODE (XEXP (*op0, 0)) == SUBREG && GET_MODE (XEXP (*op0, 0)) == QImode @@ -3624,15 +3635,15 @@ arm_canonicalize_comparison (enum rtx_code code, rtx *op0, rtx *op1) if (!CONST_INT_P (*op1) || const_ok_for_arm (INTVAL (*op1)) || const_ok_for_arm (- INTVAL (*op1))) - return code; + return; i = INTVAL (*op1); - switch (code) + switch (*code) { case EQ: case NE: - return code; + return; case GT: case LE: @@ -3640,7 +3651,8 @@ arm_canonicalize_comparison (enum rtx_code code, rtx *op0, rtx *op1) && (const_ok_for_arm (i + 1) || const_ok_for_arm (-(i + 1)))) { *op1 = GEN_INT (i + 1); - return code == GT ? GE : LT; + *code = *code == GT ? GE : LT; + return; } break; @@ -3650,7 +3662,8 @@ arm_canonicalize_comparison (enum rtx_code code, rtx *op0, rtx *op1) && (const_ok_for_arm (i - 1) || const_ok_for_arm (-(i - 1)))) { *op1 = GEN_INT (i - 1); - return code == GE ? GT : LE; + *code = *code == GE ? GT : LE; + return; } break; @@ -3660,7 +3673,8 @@ arm_canonicalize_comparison (enum rtx_code code, rtx *op0, rtx *op1) && (const_ok_for_arm (i + 1) || const_ok_for_arm (-(i + 1)))) { *op1 = GEN_INT (i + 1); - return code == GTU ? GEU : LTU; + *code = *code == GTU ? GEU : LTU; + return; } break; @@ -3670,15 +3684,14 @@ arm_canonicalize_comparison (enum rtx_code code, rtx *op0, rtx *op1) && (const_ok_for_arm (i - 1) || const_ok_for_arm (-(i - 1)))) { *op1 = GEN_INT (i - 1); - return code == GEU ? GTU : LEU; + *code = *code == GEU ? GTU : LEU; + return; } break; default: gcc_unreachable (); } - - return code; } @@ -26981,7 +26994,7 @@ bool arm_validize_comparison (rtx *comparison, rtx * op1, rtx * op2) { enum rtx_code code = GET_CODE (*comparison); - enum rtx_code canonical_code; + int code_int; enum machine_mode mode = (GET_MODE (*op1) == VOIDmode) ? GET_MODE (*op2) : GET_MODE (*op1); @@ -26990,8 +27003,9 @@ arm_validize_comparison (rtx *comparison, rtx * op1, rtx * op2) if (code == UNEQ || code == LTGT) return false; - canonical_code = arm_canonicalize_comparison (code, op1, op2); - PUT_CODE (*comparison, canonical_code); + code_int = (int)code; + arm_canonicalize_comparison (&code_int, op1, op2, 0); + PUT_CODE (*comparison, (enum rtx_code)code_int); switch (mode) { diff --git a/gcc/config/arm/arm.h b/gcc/config/arm/arm.h index d0f351d..2fa945c 100644 --- a/gcc/config/arm/arm.h +++ b/gcc/config/arm/arm.h @@ -2078,9 +2078,6 @@ extern int making_const_table; ? 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) diff --git a/gcc/config/s390/s390-protos.h b/gcc/config/s390/s390-protos.h index 79673d6..9b87914 100644 --- a/gcc/config/s390/s390-protos.h +++ b/gcc/config/s390/s390-protos.h @@ -58,7 +58,6 @@ extern int tls_symbolic_operand (rtx); 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); diff --git a/gcc/config/s390/s390.c b/gcc/config/s390/s390.c index 6517bce..441d9c1 100644 --- a/gcc/config/s390/s390.c +++ b/gcc/config/s390/s390.c @@ -745,9 +745,13 @@ s390_select_ccmode (enum rtx_code code, rtx op0, rtx op1) /* 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) +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 @@ -894,7 +898,7 @@ s390_canonicalize_comparison (enum rtx_code *code, rtx *op0, rtx *op1) if (MEM_P (*op0) && REG_P (*op1)) { rtx tem = *op0; *op0 = *op1; *op1 = tem; - *code = swap_condition (*code); + *code = (int)swap_condition ((enum rtx_code)*code); } } @@ -11071,6 +11075,9 @@ s390_loop_unroll_adjust (unsigned nunroll, struct loop *loop) #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" diff --git a/gcc/config/s390/s390.h b/gcc/config/s390/s390.h index 30408f4..286046a 100644 --- a/gcc/config/s390/s390.h +++ b/gcc/config/s390/s390.h @@ -720,10 +720,6 @@ do { \ 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 diff --git a/gcc/config/sh/sh-protos.h b/gcc/config/sh/sh-protos.h index d4e97db..793aada 100644 --- a/gcc/config/sh/sh-protos.h +++ b/gcc/config/sh/sh-protos.h @@ -159,8 +159,6 @@ extern bool sh_expand_t_scc (rtx *); 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); diff --git a/gcc/config/sh/sh.c b/gcc/config/sh/sh.c index cf0abb4..4a42d7e 100644 --- a/gcc/config/sh/sh.c +++ b/gcc/config/sh/sh.c @@ -314,6 +314,9 @@ static int max_mov_insn_displacement (enum machine_mode, bool); 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; @@ -586,6 +589,9 @@ static const struct attribute_spec sh_attribute_table[] = #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) @@ -1909,12 +1915,14 @@ prepare_move_operands (rtx operands[], enum machine_mode mode) } } -/* Implement the CANONICALIZE_COMPARISON macro for the combine pass. - This function is also re-used to canonicalize comparisons in cbranch - pattern expanders. */ -void +/* 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) + 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. */ @@ -2008,6 +2016,19 @@ sh_canonicalize_comparison (enum rtx_code& cmp, rtx& op0, rtx& op1, } } +/* 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) @@ -2021,7 +2042,8 @@ prepare_cbranch_operands (rtx *operands, enum machine_mode mode, else scratch = operands[4]; - sh_canonicalize_comparison (comparison, operands[1], operands[2], mode); + 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. */ diff --git a/gcc/config/sh/sh.h b/gcc/config/sh/sh.h index 212b97d..76a5cb1 100644 --- a/gcc/config/sh/sh.h +++ b/gcc/config/sh/sh.h @@ -1873,10 +1873,6 @@ struct sh_args { 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) \ diff --git a/gcc/config/spu/spu.c b/gcc/config/spu/spu.c index 82fb434..15e7c2e2 100644 --- a/gcc/config/spu/spu.c +++ b/gcc/config/spu/spu.c @@ -7095,6 +7095,20 @@ spu_output_mi_thunk (FILE *file, tree thunk ATTRIBUTE_UNUSED, 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[] = @@ -7308,6 +7322,9 @@ static const struct attribute_spec spu_attribute_table[] = #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" diff --git a/gcc/config/spu/spu.h b/gcc/config/spu/spu.h index ce0bc8e..031b80e 100644 --- a/gcc/config/spu/spu.h +++ b/gcc/config/spu/spu.h @@ -520,18 +520,6 @@ do { \ #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 diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi index 3ab9987..75aa867 100644 --- a/gcc/doc/tm.texi +++ b/gcc/doc/tm.texi @@ -6024,25 +6024,27 @@ You should define this macro if and only if you define extra CC modes in @file{@var{machine}-modes.def}. @end defmac -@defmac CANONICALIZE_COMPARISON (@var{code}, @var{op0}, @var{op1}) +@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, 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. +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 define this macro if it would never change the comparison -code or operands. -@end defmac +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 diff --git a/gcc/doc/tm.texi.in b/gcc/doc/tm.texi.in index 6d48fe4..95fab18 100644 --- a/gcc/doc/tm.texi.in +++ b/gcc/doc/tm.texi.in @@ -5928,25 +5928,27 @@ You should define this macro if and only if you define extra CC modes in @file{@var{machine}-modes.def}. @end defmac -@defmac CANONICALIZE_COMPARISON (@var{code}, @var{op0}, @var{op1}) +@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, 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. +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 define this macro if it would never change the comparison -code or operands. -@end defmac +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 diff --git a/gcc/target.def b/gcc/target.def index 0f3164a..bbda6c2 100644 --- a/gcc/target.def +++ b/gcc/target.def @@ -2877,6 +2877,14 @@ DEFHOOK 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\ diff --git a/gcc/targhooks.h b/gcc/targhooks.h index d419602..fc13a26 100644 --- a/gcc/targhooks.h +++ b/gcc/targhooks.h @@ -179,6 +179,8 @@ extern unsigned char default_class_max_nregs (reg_class_t, enum machine_mode); 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); |