diff options
-rw-r--r-- | gcc/ChangeLog | 24 | ||||
-rw-r--r-- | gcc/expmed.c | 2 | ||||
-rw-r--r-- | gcc/expr.c | 34 | ||||
-rw-r--r-- | gcc/expr.h | 26 | ||||
-rw-r--r-- | gcc/genopinit.c | 3 | ||||
-rw-r--r-- | gcc/optabs.c | 89 |
6 files changed, 118 insertions, 60 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index a381ea8..912eee5 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,27 @@ +Thu Sep 23 11:15:36 1999 Bernd Schmidt <bernds@cygnus.co.uk> + + * expmed.c (do_cmp_and_jump): Pass ccp_jump to can_compare_p. + * expr.c (expand_expr): Likewise. + (do_jump): Likewise. + (do_store_flag): Pass ccp_store_flag to can_compare_p. + * expr.h (enum optab_index): Add cbranch, cmov, cstore optabs and + accessor macros. + (enum can_compare_purpose): New. + (can_compare_p): Adjust prototype. + (prepare_cmp_insn, prepare_operand): Declare. + * genopinit.c (optabs): Add cbranch_optab, cmov_optab, cstore_optab. + * optabs.c (cmp_available_p): Deleted. + (expand_abs): Pass ccp_jump to can_compare_p. + (can_compare_p): New arg PURPOSE. Check for combined optabs. + (prepare_cmp_insn): No longer static. Add arg PURPOSE. + Call can_compare_p rather than cmp_available_p. + (prepare_operand): No longer static. + (emit_cmp_and_jump_insn): Check for and use cbranch patterns. + (emit_cmp_and_jump_insns): Pass ccp_jump to prepare_cmp_insn. + (expand_float): Fix a slightly broken emit_cmp_insn/emit_jump_insn + sequence to use emit_cmp_and_jump_insns. + (init_optabs): Initialize cbranch_optab, cmov_optab, cstore_optab. + Wed Sep 22 17:58:01 1999 Stan Cox <scox@cygnus.com> * mips.h (GO_IF_LEGITIMATE_ADDRESS): Don't accept large diff --git a/gcc/expmed.c b/gcc/expmed.c index c0fa722..291d766 100644 --- a/gcc/expmed.c +++ b/gcc/expmed.c @@ -4548,7 +4548,7 @@ do_cmp_and_jump (arg1, arg2, op, mode, label) /* If this mode is an integer too wide to compare properly, compare word by word. Rely on cse to optimize constant cases. */ - if (GET_MODE_CLASS (mode) == MODE_INT && ! can_compare_p (mode)) + if (GET_MODE_CLASS (mode) == MODE_INT && ! can_compare_p (mode, ccp_jump)) { rtx label2 = gen_label_rtx (); @@ -7388,7 +7388,7 @@ expand_expr (exp, target, tmode, modifier) /* If this mode is an integer too wide to compare properly, compare word by word. Rely on cse to optimize constant cases. */ - if (GET_MODE_CLASS (mode) == MODE_INT && ! can_compare_p (mode)) + if (GET_MODE_CLASS (mode) == MODE_INT && ! can_compare_p (mode, ccp_jump)) { if (code == MAX_EXPR) do_jump_by_parts_greater_rtx (mode, TREE_UNSIGNED (type), @@ -8938,7 +8938,7 @@ do_jump (exp, if_false_label, if_true_label) do_jump (TREE_OPERAND (exp, 0), if_true_label, if_false_label); else if (GET_MODE_CLASS (TYPE_MODE (inner_type)) == MODE_INT - && !can_compare_p (TYPE_MODE (inner_type))) + && !can_compare_p (TYPE_MODE (inner_type), ccp_jump)) do_jump_by_parts_equality (exp, if_false_label, if_true_label); else do_compare_and_jump (exp, EQ, EQ, if_false_label, if_true_label); @@ -8978,7 +8978,7 @@ do_jump (exp, if_false_label, if_true_label) do_jump (TREE_OPERAND (exp, 0), if_false_label, if_true_label); else if (GET_MODE_CLASS (TYPE_MODE (inner_type)) == MODE_INT - && !can_compare_p (TYPE_MODE (inner_type))) + && !can_compare_p (TYPE_MODE (inner_type), ccp_jump)) do_jump_by_parts_equality (exp, if_true_label, if_false_label); else do_compare_and_jump (exp, NE, NE, if_false_label, if_true_label); @@ -8986,36 +8986,36 @@ do_jump (exp, if_false_label, if_true_label) } case LT_EXPR: - if ((GET_MODE_CLASS (TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0)))) - == MODE_INT) - && !can_compare_p (TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0))))) + mode = TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0))); + if (GET_MODE_CLASS (mode) == MODE_INT + && ! can_compare_p (mode, ccp_jump)) do_jump_by_parts_greater (exp, 1, if_false_label, if_true_label); else do_compare_and_jump (exp, LT, LTU, if_false_label, if_true_label); break; case LE_EXPR: - if ((GET_MODE_CLASS (TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0)))) - == MODE_INT) - && !can_compare_p (TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0))))) + mode = TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0))); + if (GET_MODE_CLASS (mode) == MODE_INT + && ! can_compare_p (mode, ccp_jump)) do_jump_by_parts_greater (exp, 0, if_true_label, if_false_label); else do_compare_and_jump (exp, LE, LEU, if_false_label, if_true_label); break; case GT_EXPR: - if ((GET_MODE_CLASS (TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0)))) - == MODE_INT) - && !can_compare_p (TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0))))) + mode = TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0))); + if (GET_MODE_CLASS (mode) == MODE_INT + && ! can_compare_p (mode, ccp_jump)) do_jump_by_parts_greater (exp, 0, if_false_label, if_true_label); else do_compare_and_jump (exp, GT, GTU, if_false_label, if_true_label); break; case GE_EXPR: - if ((GET_MODE_CLASS (TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0)))) - == MODE_INT) - && !can_compare_p (TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0))))) + mode = TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0))); + if (GET_MODE_CLASS (mode) == MODE_INT + && ! can_compare_p (mode, ccp_jump)) do_jump_by_parts_greater (exp, 1, if_true_label, if_false_label); else do_compare_and_jump (exp, GE, GEU, if_false_label, if_true_label); @@ -9044,7 +9044,7 @@ do_jump (exp, if_false_label, if_true_label) emit_jump (target); } else if (GET_MODE_CLASS (GET_MODE (temp)) == MODE_INT - && ! can_compare_p (GET_MODE (temp))) + && ! can_compare_p (GET_MODE (temp), ccp_jump)) /* Note swapping the labels gives us not-equal. */ do_jump_by_parts_equality_rtx (temp, if_true_label, if_false_label); else if (GET_MODE (temp) != VOIDmode) @@ -9658,7 +9658,7 @@ do_store_flag (exp, target, mode, only_cheap) } /* Now see if we are likely to be able to do this. Return if not. */ - if (! can_compare_p (operand_mode)) + if (! can_compare_p (operand_mode, ccp_store_flag)) return 0; icode = setcc_gen_code[(int) code]; if (icode == CODE_FOR_nothing @@ -377,6 +377,11 @@ enum optab_index /* String length */ OTI_strlen, + /* Combined compare & jump/store flags/move operations. */ + OTI_cbranch, + OTI_cmov, + OTI_cstore, + OTI_MAX }; @@ -427,6 +432,10 @@ extern optab optab_table[OTI_MAX]; #define strlen_optab (optab_table[OTI_strlen]) +#define cbranch_optab (optab_table[OTI_cbranch]) +#define cmov_optab (optab_table[OTI_cmov]) +#define cstore_optab (optab_table[OTI_cstore]) + /* Tables of patterns for extending one integer mode to another. */ extern enum insn_code extendtab[MAX_MACHINE_MODE][MAX_MACHINE_MODE][2]; @@ -778,9 +787,24 @@ extern void emit_cmp_insn PROTO((rtx, rtx, enum rtx_code, rtx, extern void emit_cmp_and_jump_insns PROTO((rtx, rtx, enum rtx_code, rtx, enum machine_mode, int, int, rtx)); +/* The various uses that a comparison can have; used by can_compare_p: + jumps, conditional moves, store flag operations. */ +enum can_compare_purpose +{ + ccp_jump, + ccp_cmov, + ccp_store_flag +}; /* Nonzero if a compare of mode MODE can be done straightforwardly (without splitting it into pieces). */ -extern int can_compare_p PROTO((enum machine_mode)); +extern int can_compare_p PROTO((enum machine_mode, enum can_compare_purpose)); + +extern void prepare_cmp_insn PROTO((rtx *, rtx *, enum rtx_code *, rtx, + enum machine_mode *, int *, int, + enum can_compare_purpose)); + +extern rtx prepare_operand PROTO((int, rtx, int, enum machine_mode, + enum machine_mode, int)); /* Generate code to indirectly jump to a location given in the rtx LOC. */ extern void emit_indirect_jump PROTO((rtx)); diff --git a/gcc/genopinit.c b/gcc/genopinit.c index 5884691..81366f0 100644 --- a/gcc/genopinit.c +++ b/gcc/genopinit.c @@ -113,6 +113,9 @@ const char * const optabs[] = "bcc_gen_fctn[(int) %C] = gen_%(b%c%)", "setcc_gen_code[(int) %C] = CODE_FOR_%(s%c%)", "movcc_gen_code[(int) %A] = CODE_FOR_%(mov%acc%)", + "cbranch_optab->handlers[(int) %A].insn_code = CODE_FOR_%(cbranch%a4%)", + "cmov_optab->handlers[(int) %A].insn_code = CODE_FOR_%(cmov%a6%)", + "cstore_optab->handlers[(int) %A].insn_code = CODE_FOR_%(cstore%a4%)", "reload_in_optab[(int) %A] = CODE_FOR_%(reload_in%a%)", "reload_out_optab[(int) %A] = CODE_FOR_%(reload_out%a%)", "movstr_optab[(int) %A] = CODE_FOR_%(movstr%a%)", diff --git a/gcc/optabs.c b/gcc/optabs.c index a683fef..b424f1b 100644 --- a/gcc/optabs.c +++ b/gcc/optabs.c @@ -105,13 +105,8 @@ static void init_floating_libfuncs PROTO((optab, const char *, int)); #ifdef HAVE_conditional_trap static void init_traps PROTO((void)); #endif -static int cmp_available_p PROTO((enum machine_mode, int)); static void emit_cmp_and_jump_insn_1 PROTO((rtx, rtx, enum machine_mode, enum rtx_code, int, rtx)); -static void prepare_cmp_insn PROTO((rtx *, rtx *, enum rtx_code *, rtx, - enum machine_mode *, int *, int)); -static rtx prepare_operand PROTO((int, rtx, int, enum machine_mode, - enum machine_mode, int)); static void prepare_float_lib_cmp PROTO((rtx *, rtx *, enum rtx_code *, enum machine_mode *, int *)); @@ -2309,7 +2304,7 @@ expand_abs (mode, op0, target, safe) /* If this mode is an integer too wide to compare properly, compare word by word. Rely on CSE to optimize constant cases. */ - if (GET_MODE_CLASS (mode) == MODE_INT && ! can_compare_p (mode)) + if (GET_MODE_CLASS (mode) == MODE_INT && ! can_compare_p (mode, ccp_jump)) do_jump_by_parts_greater_rtx (mode, 0, target, const0_rtx, NULL_RTX, op1); else @@ -2823,22 +2818,32 @@ emit_0_to_1_insn (x) emit_move_insn (x, const1_rtx); } -/* Nonzero if we can perform a comparison of mode MODE for a conditional jump - straightforwardly. */ - -static int -cmp_available_p (mode, can_use_tst_p) +/* Nonzero if we can perform a comparison of mode MODE straightforwardly. + If FOR_JUMP is nonzero, we will be generating a jump based on this + comparison, otherwise a store-flags operation. */ + +int +can_compare_p (mode, purpose) enum machine_mode mode; - int can_use_tst_p; + enum can_compare_purpose purpose; { do { - if (cmp_optab->handlers[(int)mode].insn_code != CODE_FOR_nothing - || (can_use_tst_p - && tst_optab->handlers[(int)mode].insn_code != CODE_FOR_nothing)) + if (cmp_optab->handlers[(int)mode].insn_code != CODE_FOR_nothing) return 1; + if (purpose == ccp_jump + && cbranch_optab->handlers[(int)mode].insn_code != CODE_FOR_nothing) + return 1; + if (purpose == ccp_cmov + && cmov_optab->handlers[(int)mode].insn_code != CODE_FOR_nothing) + return 1; + if (purpose == ccp_store_flag + && cstore_optab->handlers[(int)mode].insn_code != CODE_FOR_nothing) + return 1; + mode = GET_MODE_WIDER_MODE (mode); - } while (mode != VOIDmode); + } + while (mode != VOIDmode); return 0; } @@ -2860,14 +2865,16 @@ cmp_available_p (mode, can_use_tst_p) The values which are passed in through pointers can be modified; the caller should perform the comparison on the modified values. */ -static void -prepare_cmp_insn (px, py, pcomparison, size, pmode, punsignedp, align) +void +prepare_cmp_insn (px, py, pcomparison, size, pmode, punsignedp, align, + purpose) rtx *px, *py; enum rtx_code *pcomparison; rtx size; enum machine_mode *pmode; int *punsignedp; int align; + enum can_compare_purpose purpose; { enum machine_mode mode = *pmode; rtx x = *px, y = *py; @@ -2988,7 +2995,7 @@ prepare_cmp_insn (px, py, pcomparison, size, pmode, punsignedp, align) *px = x; *py = y; - if (cmp_available_p (mode, y == CONST0_RTX (mode))) + if (can_compare_p (mode, purpose)) return; /* Handle a lib call just for the mode we are using. */ @@ -3032,7 +3039,7 @@ prepare_cmp_insn (px, py, pcomparison, size, pmode, punsignedp, align) to be used for operand OPNUM of the insn, is converted from mode MODE to WIDER_MODE (UNSIGNEDP determines whether it is a unsigned conversion), and that it is accepted by the operand predicate. Return the new value. */ -static rtx +rtx prepare_operand (icode, x, opnum, mode, wider_mode, unsignedp) int icode; rtx x; @@ -3074,6 +3081,20 @@ emit_cmp_and_jump_insn_1 (x, y, mode, comparison, unsignedp, label) enum insn_code icode; PUT_MODE (test, wider_mode); + if (label) + { + icode = cbranch_optab->handlers[(int)wider_mode].insn_code; + + if (icode != CODE_FOR_nothing + && (*insn_data[icode].operand[0].predicate) (test, wider_mode)) + { + x = prepare_operand (icode, x, 1, mode, wider_mode, unsignedp); + y = prepare_operand (icode, y, 2, mode, wider_mode, unsignedp); + emit_jump_insn (GEN_FCN (icode) (test, x, y, label)); + return; + } + } + /* Handle some compares against zero. */ icode = (int) tst_optab->handlers[(int) wider_mode].insn_code; if (y == CONST0_RTX (mode) && icode != CODE_FOR_nothing) @@ -3164,7 +3185,8 @@ emit_cmp_and_jump_insns (x, y, comparison, size, mode, unsignedp, align, label) emit_queue (); if (unsignedp) comparison = unsigned_condition (comparison); - prepare_cmp_insn (&op0, &op1, &comparison, size, &mode, &unsignedp, align); + prepare_cmp_insn (&op0, &op1, &comparison, size, &mode, &unsignedp, align, + ccp_jump); emit_cmp_and_jump_insn_1 (op0, op1, mode, comparison, unsignedp, label); } @@ -3180,24 +3202,6 @@ emit_cmp_insn (x, y, comparison, size, mode, unsignedp, align) { emit_cmp_and_jump_insns (x, y, comparison, size, mode, unsignedp, align, 0); } - - -/* Nonzero if a compare of mode MODE can be done straightforwardly - (without splitting it into pieces). */ - -int -can_compare_p (mode) - enum machine_mode mode; -{ - do - { - if (cmp_optab->handlers[(int)mode].insn_code != CODE_FOR_nothing) - return 1; - mode = GET_MODE_WIDER_MODE (mode); - } while (mode != VOIDmode); - - return 0; -} /* Emit a library call comparison between floating point X and Y. COMPARISON is the rtl operator to compare with (EQ, NE, GT, etc.). */ @@ -3876,8 +3880,8 @@ expand_float (to, from, unsignedp) do_pending_stack_adjust (); /* Test whether the sign bit is set. */ - emit_cmp_insn (from, const0_rtx, GE, NULL_RTX, imode, 0, 0); - emit_jump_insn (gen_blt (neglabel)); + emit_cmp_and_jump_insns (from, const0_rtx, LT, NULL_RTX, imode, + 0, 0, neglabel); /* The sign bit is not set. Convert as signed. */ expand_float (target, from, 0); @@ -4467,6 +4471,9 @@ init_optabs () sin_optab = init_optab (UNKNOWN); cos_optab = init_optab (UNKNOWN); strlen_optab = init_optab (UNKNOWN); + cbranch_optab = init_optab (UNKNOWN); + cmov_optab = init_optab (UNKNOWN); + cstore_optab = init_optab (UNKNOWN); for (i = 0; i < NUM_MACHINE_MODES; i++) { |