diff options
author | bonzini <bonzini@138bc75d-0d04-0410-961f-82ee72b054a4> | 2009-05-12 09:43:48 +0000 |
---|---|---|
committer | bonzini <bonzini@138bc75d-0d04-0410-961f-82ee72b054a4> | 2009-05-12 09:43:48 +0000 |
commit | 74f4459c661b0597a1cb1080a1e6c34db40f921d (patch) | |
tree | 06c940a96a184a178bfadd53e04213225655a68d /gcc/config | |
parent | 58b52637eb213c90766269829beb56b15f621af8 (diff) | |
download | gcc-74f4459c661b0597a1cb1080a1e6c34db40f921d.tar.gz |
Merge cond-optab branch.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@147425 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/config')
132 files changed, 4007 insertions, 9570 deletions
diff --git a/gcc/config/alpha/alpha-protos.h b/gcc/config/alpha/alpha-protos.h index 66c68aebc91..7a12d498246 100644 --- a/gcc/config/alpha/alpha-protos.h +++ b/gcc/config/alpha/alpha-protos.h @@ -88,8 +88,8 @@ extern int check_float_value (enum machine_mode, REAL_VALUE_TYPE *, int); #endif #ifdef RTX_CODE -extern rtx alpha_emit_conditional_branch (enum rtx_code); -extern rtx alpha_emit_setcc (enum rtx_code); +extern void alpha_emit_conditional_branch (rtx[], enum machine_mode); +extern bool alpha_emit_setcc (rtx[], enum machine_mode); extern int alpha_split_conditional_move (enum rtx_code, rtx, rtx, rtx, rtx); extern void alpha_emit_xfloating_arith (enum rtx_code, rtx[]); extern void alpha_emit_xfloating_cvt (enum rtx_code, rtx[]); diff --git a/gcc/config/alpha/alpha.c b/gcc/config/alpha/alpha.c index bb6542a37f9..512599d0982 100644 --- a/gcc/config/alpha/alpha.c +++ b/gcc/config/alpha/alpha.c @@ -81,11 +81,6 @@ enum alpha_fp_rounding_mode alpha_fprm; enum alpha_fp_trap_mode alpha_fptm; -/* Save information from a "cmpxx" operation until the branch or scc is - emitted. */ - -struct alpha_compare alpha_compare; - /* Nonzero if inside of a function, because the Alpha asm can't handle .files inside of functions. */ @@ -2424,19 +2419,20 @@ alpha_emit_floatuns (rtx operands[2]) /* Generate the comparison for a conditional branch. */ -rtx -alpha_emit_conditional_branch (enum rtx_code code) +void +alpha_emit_conditional_branch (rtx operands[], enum machine_mode cmp_mode) { enum rtx_code cmp_code, branch_code; - enum machine_mode cmp_mode, branch_mode = VOIDmode; - rtx op0 = alpha_compare.op0, op1 = alpha_compare.op1; + enum machine_mode branch_mode = VOIDmode; + enum rtx_code code = GET_CODE (operands[0]); + rtx op0 = operands[1], op1 = operands[2]; rtx tem; - if (alpha_compare.fp_p && GET_MODE (op0) == TFmode) + if (cmp_mode == TFmode) { op0 = alpha_emit_xfloating_compare (&code, op0, op1); op1 = const0_rtx; - alpha_compare.fp_p = 0; + cmp_mode = DImode; } /* The general case: fold the comparison code to the types of compares @@ -2457,7 +2453,7 @@ alpha_emit_conditional_branch (enum rtx_code code) case GE: case GT: case GEU: case GTU: /* For FP, we swap them, for INT, we reverse them. */ - if (alpha_compare.fp_p) + if (cmp_mode == DFmode) { cmp_code = swap_condition (code); branch_code = NE; @@ -2474,9 +2470,8 @@ alpha_emit_conditional_branch (enum rtx_code code) gcc_unreachable (); } - if (alpha_compare.fp_p) + if (cmp_mode == DFmode) { - cmp_mode = DFmode; if (flag_unsafe_math_optimizations && cmp_code != UNORDERED) { /* When we are not as concerned about non-finite values, and we @@ -2501,8 +2496,6 @@ alpha_emit_conditional_branch (enum rtx_code code) } else { - cmp_mode = DImode; - /* The following optimizations are only for signed compares. */ if (code != LEU && code != LTU && code != GEU && code != GTU) { @@ -2544,36 +2537,38 @@ alpha_emit_conditional_branch (enum rtx_code code) emit_move_insn (tem, gen_rtx_fmt_ee (cmp_code, cmp_mode, op0, op1)); } - /* Zero the operands. */ - memset (&alpha_compare, 0, sizeof (alpha_compare)); - - /* Return the branch comparison. */ - return gen_rtx_fmt_ee (branch_code, branch_mode, tem, CONST0_RTX (cmp_mode)); + /* Emit the branch instruction. */ + tem = gen_rtx_SET (VOIDmode, pc_rtx, + gen_rtx_IF_THEN_ELSE (VOIDmode, + gen_rtx_fmt_ee (branch_code, + branch_mode, tem, + CONST0_RTX (cmp_mode)), + gen_rtx_LABEL_REF (VOIDmode, + operands[3]), + pc_rtx)); + emit_jump_insn (tem); } /* Certain simplifications can be done to make invalid setcc operations valid. Return the final comparison, or NULL if we can't work. */ -rtx -alpha_emit_setcc (enum rtx_code code) +bool +alpha_emit_setcc (rtx operands[], enum machine_mode cmp_mode) { enum rtx_code cmp_code; - rtx op0 = alpha_compare.op0, op1 = alpha_compare.op1; - int fp_p = alpha_compare.fp_p; + enum rtx_code code = GET_CODE (operands[1]); + rtx op0 = operands[2], op1 = operands[3]; rtx tmp; - /* Zero the operands. */ - memset (&alpha_compare, 0, sizeof (alpha_compare)); - - if (fp_p && GET_MODE (op0) == TFmode) + if (cmp_mode == TFmode) { op0 = alpha_emit_xfloating_compare (&code, op0, op1); op1 = const0_rtx; - fp_p = 0; + cmp_mode = DImode; } - if (fp_p && !TARGET_FIX) - return NULL_RTX; + if (cmp_mode == DFmode && !TARGET_FIX) + return 0; /* The general case: fold the comparison code to the types of compares that we have, choosing the branch as necessary. */ @@ -2584,12 +2579,12 @@ alpha_emit_setcc (enum rtx_code code) case EQ: case LE: case LT: case LEU: case LTU: case UNORDERED: /* We have these compares. */ - if (fp_p) + if (cmp_mode == DFmode) cmp_code = code, code = NE; break; case NE: - if (!fp_p && op1 == const0_rtx) + if (cmp_mode == DImode && op1 == const0_rtx) break; /* FALLTHRU */ @@ -2601,10 +2596,10 @@ alpha_emit_setcc (enum rtx_code code) case GE: case GT: case GEU: case GTU: /* These normally need swapping, but for integer zero we have special patterns that recognize swapped operands. */ - if (!fp_p && op1 == const0_rtx) + if (cmp_mode == DImode && op1 == const0_rtx) break; code = swap_condition (code); - if (fp_p) + if (cmp_mode == DFmode) cmp_code = code, code = NE; tmp = op0, op0 = op1, op1 = tmp; break; @@ -2613,7 +2608,7 @@ alpha_emit_setcc (enum rtx_code code) gcc_unreachable (); } - if (!fp_p) + if (cmp_mode == DImode) { if (!register_operand (op0, DImode)) op0 = force_reg (DImode, op0); @@ -2624,18 +2619,18 @@ alpha_emit_setcc (enum rtx_code code) /* Emit an initial compare instruction, if necessary. */ if (cmp_code != UNKNOWN) { - enum machine_mode mode = fp_p ? DFmode : DImode; - - tmp = gen_reg_rtx (mode); + tmp = gen_reg_rtx (cmp_mode); emit_insn (gen_rtx_SET (VOIDmode, tmp, - gen_rtx_fmt_ee (cmp_code, mode, op0, op1))); + gen_rtx_fmt_ee (cmp_code, cmp_mode, op0, op1))); - op0 = fp_p ? gen_lowpart (DImode, tmp) : tmp; + op0 = cmp_mode == DImode ? gen_lowpart (DImode, tmp) : tmp; op1 = const0_rtx; } - /* Return the setcc comparison. */ - return gen_rtx_fmt_ee (code, DImode, op0, op1); + /* Emit the setcc instruction. */ + emit_insn (gen_rtx_SET (VOIDmode, operands[0], + gen_rtx_fmt_ee (code, DImode, op0, op1))); + return true; } @@ -2651,20 +2646,17 @@ alpha_emit_conditional_move (rtx cmp, enum machine_mode mode) { enum rtx_code code = GET_CODE (cmp); enum rtx_code cmov_code = NE; - rtx op0 = alpha_compare.op0; - rtx op1 = alpha_compare.op1; - int fp_p = alpha_compare.fp_p; + rtx op0 = XEXP (cmp, 0); + rtx op1 = XEXP (cmp, 1); enum machine_mode cmp_mode = (GET_MODE (op0) == VOIDmode ? DImode : GET_MODE (op0)); - enum machine_mode cmp_op_mode = fp_p ? DFmode : DImode; enum machine_mode cmov_mode = VOIDmode; int local_fast_math = flag_unsafe_math_optimizations; rtx tem; - /* Zero the operands. */ - memset (&alpha_compare, 0, sizeof (alpha_compare)); + gcc_assert (cmp_mode == DFmode || cmp_mode == DImode); - if (fp_p != FLOAT_MODE_P (mode)) + if (FLOAT_MODE_P (cmp_mode) != FLOAT_MODE_P (mode)) { enum rtx_code cmp_code; @@ -2691,7 +2683,7 @@ alpha_emit_conditional_move (rtx cmp, enum machine_mode mode) case GE: case GT: case GEU: case GTU: /* These normally need swapping, but for integer zero we have special patterns that recognize swapped operands. */ - if (!fp_p && op1 == const0_rtx) + if (cmp_mode == DImode && op1 == const0_rtx) cmp_code = code, code = NE; else { @@ -2705,22 +2697,21 @@ alpha_emit_conditional_move (rtx cmp, enum machine_mode mode) gcc_unreachable (); } - tem = gen_reg_rtx (cmp_op_mode); + tem = gen_reg_rtx (cmp_mode); emit_insn (gen_rtx_SET (VOIDmode, tem, - gen_rtx_fmt_ee (cmp_code, cmp_op_mode, + gen_rtx_fmt_ee (cmp_code, cmp_mode, op0, op1))); - cmp_mode = cmp_op_mode = fp_p ? DImode : DFmode; - op0 = gen_lowpart (cmp_op_mode, tem); - op1 = CONST0_RTX (cmp_op_mode); - fp_p = !fp_p; + cmp_mode = cmp_mode == DImode ? DFmode : DImode; + op0 = gen_lowpart (cmp_mode, tem); + op1 = CONST0_RTX (cmp_mode); local_fast_math = 1; } /* We may be able to use a conditional move directly. This avoids emitting spurious compares. */ if (signed_comparison_operator (cmp, VOIDmode) - && (!fp_p || local_fast_math) + && (cmp_mode == DImode || local_fast_math) && (op0 == CONST0_RTX (cmp_mode) || op1 == CONST0_RTX (cmp_mode))) return gen_rtx_fmt_ee (code, VOIDmode, op0, op1); @@ -2757,7 +2748,7 @@ alpha_emit_conditional_move (rtx cmp, enum machine_mode mode) gcc_unreachable (); } - if (!fp_p) + if (cmp_mode == DImode) { if (!reg_or_0_operand (op0, DImode)) op0 = force_reg (DImode, op0); @@ -2768,12 +2759,12 @@ alpha_emit_conditional_move (rtx cmp, enum machine_mode mode) /* ??? We mark the branch mode to be CCmode to prevent the compare and cmov from being combined, since the compare insn follows IEEE rules that the cmov does not. */ - if (fp_p && !local_fast_math) + if (cmp_mode == DFmode && !local_fast_math) cmov_mode = CCmode; - tem = gen_reg_rtx (cmp_op_mode); - emit_move_insn (tem, gen_rtx_fmt_ee (code, cmp_op_mode, op0, op1)); - return gen_rtx_fmt_ee (cmov_code, cmov_mode, tem, CONST0_RTX (cmp_op_mode)); + tem = gen_reg_rtx (cmp_mode); + emit_move_insn (tem, gen_rtx_fmt_ee (code, cmp_mode, op0, op1)); + return gen_rtx_fmt_ee (cmov_code, cmov_mode, tem, CONST0_RTX (cmp_mode)); } /* Simplify a conditional move of two constants into a setcc with diff --git a/gcc/config/alpha/alpha.h b/gcc/config/alpha/alpha.h index f33e8e63854..ed9bd747f39 100644 --- a/gcc/config/alpha/alpha.h +++ b/gcc/config/alpha/alpha.h @@ -803,24 +803,6 @@ extern int alpha_memory_latency; #define FUNCTION_ARG(CUM, MODE, TYPE, NAMED) \ function_arg((CUM), (MODE), (TYPE), (NAMED)) -/* Try to output insns to set TARGET equal to the constant C if it can be - done in less than N insns. Do all computations in MODE. Returns the place - where the output has been placed if it can be done and the insns have been - emitted. If it would take more than N insns, zero is returned and no - insns and emitted. */ - -/* Define the information needed to generate branch and scc insns. This is - stored from the compare operation. Note that we can't use "rtx" here - since it hasn't been defined! */ - -struct alpha_compare -{ - struct rtx_def *op0, *op1; - int fp_p; -}; - -extern struct alpha_compare alpha_compare; - /* Make (or fake) .linkage entry for function call. IS_LOCAL is 0 if name is used in call, 1 if name is used in definition. */ diff --git a/gcc/config/alpha/alpha.md b/gcc/config/alpha/alpha.md index 543ed533080..e6a05780bba 100644 --- a/gcc/config/alpha/alpha.md +++ b/gcc/config/alpha/alpha.md @@ -3963,206 +3963,53 @@ ;; These are the main define_expand's used to make conditional branches ;; and compares. -(define_expand "cmpdf" - [(set (cc0) (compare (match_operand:DF 0 "reg_or_0_operand" "") - (match_operand:DF 1 "reg_or_0_operand" "")))] +(define_expand "cbranchdf4" + [(use (match_operator 0 "alpha_cbranch_operator" + [(match_operand:DF 1 "reg_or_0_operand" "") + (match_operand:DF 2 "reg_or_0_operand" "")])) + (use (match_operand 3 ""))] "TARGET_FP" -{ - alpha_compare.op0 = operands[0]; - alpha_compare.op1 = operands[1]; - alpha_compare.fp_p = 1; - DONE; -}) + { alpha_emit_conditional_branch (operands, DFmode); DONE; }) -(define_expand "cmptf" - [(set (cc0) (compare (match_operand:TF 0 "general_operand" "") - (match_operand:TF 1 "general_operand" "")))] +(define_expand "cbranchtf4" + [(use (match_operator 0 "alpha_cbranch_operator" + [(match_operand:TF 1 "general_operand") + (match_operand:TF 2 "general_operand")])) + (use (match_operand 3 ""))] "TARGET_HAS_XFLOATING_LIBS" -{ - alpha_compare.op0 = operands[0]; - alpha_compare.op1 = operands[1]; - alpha_compare.fp_p = 1; - DONE; -}) - -(define_expand "cmpdi" - [(set (cc0) (compare (match_operand:DI 0 "some_operand" "") - (match_operand:DI 1 "some_operand" "")))] - "" -{ - alpha_compare.op0 = operands[0]; - alpha_compare.op1 = operands[1]; - alpha_compare.fp_p = 0; - DONE; -}) - -(define_expand "beq" - [(set (pc) - (if_then_else (match_dup 1) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "{ operands[1] = alpha_emit_conditional_branch (EQ); }") - -(define_expand "bne" - [(set (pc) - (if_then_else (match_dup 1) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "{ operands[1] = alpha_emit_conditional_branch (NE); }") - -(define_expand "blt" - [(set (pc) - (if_then_else (match_dup 1) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "{ operands[1] = alpha_emit_conditional_branch (LT); }") + { alpha_emit_conditional_branch (operands, TFmode); DONE; }) -(define_expand "ble" - [(set (pc) - (if_then_else (match_dup 1) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "{ operands[1] = alpha_emit_conditional_branch (LE); }") - -(define_expand "bgt" - [(set (pc) - (if_then_else (match_dup 1) - (label_ref (match_operand 0 "" "")) - (pc)))] +(define_expand "cbranchdi4" + [(use (match_operator 0 "alpha_cbranch_operator" + [(match_operand:DI 1 "some_operand") + (match_operand:DI 2 "some_operand")])) + (use (match_operand 3 ""))] "" - "{ operands[1] = alpha_emit_conditional_branch (GT); }") + { alpha_emit_conditional_branch (operands, DImode); DONE; }) -(define_expand "bge" - [(set (pc) - (if_then_else (match_dup 1) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "{ operands[1] = alpha_emit_conditional_branch (GE); }") - -(define_expand "bltu" - [(set (pc) - (if_then_else (match_dup 1) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "{ operands[1] = alpha_emit_conditional_branch (LTU); }") - -(define_expand "bleu" - [(set (pc) - (if_then_else (match_dup 1) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "{ operands[1] = alpha_emit_conditional_branch (LEU); }") - -(define_expand "bgtu" - [(set (pc) - (if_then_else (match_dup 1) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "{ operands[1] = alpha_emit_conditional_branch (GTU); }") - -(define_expand "bgeu" - [(set (pc) - (if_then_else (match_dup 1) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "{ operands[1] = alpha_emit_conditional_branch (GEU); }") - -(define_expand "bunordered" - [(set (pc) - (if_then_else (match_dup 1) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "{ operands[1] = alpha_emit_conditional_branch (UNORDERED); }") - -(define_expand "bordered" - [(set (pc) - (if_then_else (match_dup 1) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "{ operands[1] = alpha_emit_conditional_branch (ORDERED); }") - -(define_expand "seq" - [(set (match_operand:DI 0 "register_operand" "") - (match_dup 1))] - "" - "{ if ((operands[1] = alpha_emit_setcc (EQ)) == NULL_RTX) FAIL; }") - -(define_expand "sne" - [(set (match_operand:DI 0 "register_operand" "") - (match_dup 1))] - "" - "{ if ((operands[1] = alpha_emit_setcc (NE)) == NULL_RTX) FAIL; }") - -(define_expand "slt" - [(set (match_operand:DI 0 "register_operand" "") - (match_dup 1))] - "" - "{ if ((operands[1] = alpha_emit_setcc (LT)) == NULL_RTX) FAIL; }") - -(define_expand "sle" - [(set (match_operand:DI 0 "register_operand" "") - (match_dup 1))] - "" - "{ if ((operands[1] = alpha_emit_setcc (LE)) == NULL_RTX) FAIL; }") - -(define_expand "sgt" - [(set (match_operand:DI 0 "register_operand" "") - (match_dup 1))] - "" - "{ if ((operands[1] = alpha_emit_setcc (GT)) == NULL_RTX) FAIL; }") - -(define_expand "sge" - [(set (match_operand:DI 0 "register_operand" "") - (match_dup 1))] - "" - "{ if ((operands[1] = alpha_emit_setcc (GE)) == NULL_RTX) FAIL; }") - -(define_expand "sltu" - [(set (match_operand:DI 0 "register_operand" "") - (match_dup 1))] - "" - "{ if ((operands[1] = alpha_emit_setcc (LTU)) == NULL_RTX) FAIL; }") - -(define_expand "sleu" - [(set (match_operand:DI 0 "register_operand" "") - (match_dup 1))] - "" - "{ if ((operands[1] = alpha_emit_setcc (LEU)) == NULL_RTX) FAIL; }") - -(define_expand "sgtu" - [(set (match_operand:DI 0 "register_operand" "") - (match_dup 1))] - "" - "{ if ((operands[1] = alpha_emit_setcc (GTU)) == NULL_RTX) FAIL; }") - -(define_expand "sgeu" - [(set (match_operand:DI 0 "register_operand" "") - (match_dup 1))] - "" - "{ if ((operands[1] = alpha_emit_setcc (GEU)) == NULL_RTX) FAIL; }") +(define_expand "cstoredf4" + [(use (match_operator:DI 1 "alpha_cbranch_operator" + [(match_operand:DF 2 "reg_or_0_operand") + (match_operand:DF 3 "reg_or_0_operand")])) + (clobber (match_operand:DI 0 "register_operand"))] + "TARGET_FP" + { if (!alpha_emit_setcc (operands, DFmode)) FAIL; else DONE; }) -(define_expand "sunordered" - [(set (match_operand:DI 0 "register_operand" "") - (match_dup 1))] - "" - "{ if ((operands[1] = alpha_emit_setcc (UNORDERED)) == NULL_RTX) FAIL; }") +(define_expand "cstoretf4" + [(use (match_operator:DI 1 "alpha_cbranch_operator" + [(match_operand:TF 2 "general_operand") + (match_operand:TF 3 "general_operand")])) + (clobber (match_operand:DI 0 "register_operand"))] + "TARGET_HAS_XFLOATING_LIBS" + { if (!alpha_emit_setcc (operands, TFmode)) FAIL; else DONE; }) -(define_expand "sordered" - [(set (match_operand:DI 0 "register_operand" "") - (match_dup 1))] +(define_expand "cstoredi4" + [(use (match_operator:DI 1 "alpha_cbranch_operator" + [(match_operand:DI 2 "some_operand") + (match_operand:DI 3 "some_operand")])) + (clobber (match_operand:DI 0 "register_operand"))] "" - "{ if ((operands[1] = alpha_emit_setcc (ORDERED)) == NULL_RTX) FAIL; }") + { if (!alpha_emit_setcc (operands, DImode)) FAIL; else DONE; }) ;; These are the main define_expand's used to make conditional moves. @@ -6766,7 +6613,7 @@ rtx loop_label = gen_label_rtx (); rtx want = gen_reg_rtx (Pmode); rtx tmp = gen_reg_rtx (Pmode); - rtx memref; + rtx memref, test; emit_insn (gen_subdi3 (want, stack_pointer_rtx, force_reg (Pmode, operands[1]))); @@ -6775,8 +6622,8 @@ if (!CONST_INT_P (operands[1])) { out_label = gen_label_rtx (); - emit_insn (gen_cmpdi (want, tmp)); - emit_jump_insn (gen_bgeu (out_label)); + test = gen_rtx_GEU (VOIDmode, want, tmp); + emit_jump_insn (gen_cbranchdi4 (test, want, tmp, out_label)); } emit_label (loop_label); @@ -6784,8 +6631,8 @@ MEM_VOLATILE_P (memref) = 1; emit_move_insn (memref, const0_rtx); emit_insn (gen_adddi3 (tmp, tmp, GEN_INT(-8192))); - emit_insn (gen_cmpdi (tmp, want)); - emit_jump_insn (gen_bgtu (loop_label)); + test = gen_rtx_GTU (VOIDmode, tmp, want); + emit_jump_insn (gen_cbranchdi4 (test, tmp, want, loop_label)); memref = gen_rtx_MEM (DImode, want); MEM_VOLATILE_P (memref) = 1; diff --git a/gcc/config/alpha/predicates.md b/gcc/config/alpha/predicates.md index 425134ac820..ec11eaa3d1f 100644 --- a/gcc/config/alpha/predicates.md +++ b/gcc/config/alpha/predicates.md @@ -543,6 +543,12 @@ (and (match_code "reg") (match_operand 0 "register_operand"))) +;; Return 1 if OP is a valid Alpha comparison operator for "cbranch" +;; instructions. +(define_predicate "alpha_cbranch_operator" + (ior (match_operand 0 "ordered_comparison_operator") + (match_code "ordered,unordered"))) + ;; Return 1 if OP is a valid Alpha comparison operator for "cmp" style ;; instructions. (define_predicate "alpha_comparison_operator" diff --git a/gcc/config/arc/arc.c b/gcc/config/arc/arc.c index 3f81f611f80..1f456b63cd7 100644 --- a/gcc/config/arc/arc.c +++ b/gcc/config/arc/arc.c @@ -49,10 +49,6 @@ int arc_cpu_type; cpu (or NULL). */ const char *arc_mangle_cpu; -/* Save the operands last given to a compare for use when we - generate a scc or bcc insn. */ -rtx arc_compare_op0, arc_compare_op1; - /* Name of text, data, and rodata sections used in varasm.c. */ const char *arc_text_section; const char *arc_data_section; @@ -729,21 +725,14 @@ proper_comparison_operator (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED) /* Misc. utilities. */ -/* X and Y are two things to compare using CODE. Emit the compare insn and - return the rtx for the cc reg in the proper mode. */ +/* X and Y are two things to compare using CODE. Return the rtx + for the cc reg in the proper mode. */ rtx gen_compare_reg (enum rtx_code code, rtx x, rtx y) { enum machine_mode mode = SELECT_CC_MODE (code, x, y); - rtx cc_reg; - - cc_reg = gen_rtx_REG (mode, 61); - - emit_insn (gen_rtx_SET (VOIDmode, cc_reg, - gen_rtx_COMPARE (mode, x, y))); - - return cc_reg; + return gen_rtx_REG (mode, 61); } /* Return 1 if VALUE, a const_double, will fit in a limm (4 byte number). diff --git a/gcc/config/arc/arc.h b/gcc/config/arc/arc.h index db6829bc560..4153ad6f6b6 100644 --- a/gcc/config/arc/arc.h +++ b/gcc/config/arc/arc.h @@ -1067,11 +1067,6 @@ do { if ((LOG) != 0) fprintf (FILE, "\t.align %d\n", 1 << (LOG)); } while (0) /* ??? Not defined in tm.texi. */ #define SETJMP_VIA_SAVE_AREA -/* Define the information needed to generate branch and scc insns. This is - stored from the compare operation. Note that we can't use "rtx" here - since it hasn't been defined! */ -extern struct rtx_def *arc_compare_op0, *arc_compare_op1; - /* ARC function types. */ enum arc_function_type { ARC_FUNCTION_UNKNOWN, ARC_FUNCTION_NORMAL, diff --git a/gcc/config/arc/arc.md b/gcc/config/arc/arc.md index b67984babbb..09e47daf1d1 100644 --- a/gcc/config/arc/arc.md +++ b/gcc/config/arc/arc.md @@ -585,29 +585,11 @@ " { enum rtx_code code = GET_CODE (operands[1]); - rtx ccreg - = gen_rtx_REG (SELECT_CC_MODE (code, arc_compare_op0, arc_compare_op1), - 61); - - operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx); + rtx cc_reg = gen_compare_reg (code, XEXP (operands[1], 0), + XEXP (operands[1], 1)); + operands[1] = gen_rtx_fmt_ee (code, VOIDmode, cc_reg, const0_rtx); }") -;(define_expand "movdicc" -; [(set (match_operand:DI 0 "register_operand" "") -; (if_then_else:DI (match_operand 1 "comparison_operator" "") -; (match_operand:DI 2 "nonmemory_operand" "") -; (match_operand:DI 3 "register_operand" "")))] -; "0 /* ??? this would work better if we had cmpdi */" -; " -;{ -; enum rtx_code code = GET_CODE (operands[1]); -; rtx ccreg -; = gen_rtx_REG (SELECT_CC_MODE (code, arc_compare_op0, arc_compare_op1), -; 61); -; -; operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx); -;}") - (define_expand "movsfcc" [(set (match_operand:SF 0 "register_operand" "") (if_then_else:SF (match_operand 1 "comparison_operator" "") @@ -617,29 +599,11 @@ " { enum rtx_code code = GET_CODE (operands[1]); - rtx ccreg - = gen_rtx_REG (SELECT_CC_MODE (code, arc_compare_op0, arc_compare_op1), - 61); - - operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx); + rtx cc_reg = gen_compare_reg (code, XEXP (operands[1], 0), + XEXP (operands[1], 1)); + operands[1] = gen_rtx_fmt_ee (code, VOIDmode, cc_reg, const0_rtx); }") -;(define_expand "movdfcc" -; [(set (match_operand:DF 0 "register_operand" "") -; (if_then_else:DF (match_operand 1 "comparison_operator" "") -; (match_operand:DF 2 "nonmemory_operand" "") -; (match_operand:DF 3 "register_operand" "")))] -; "0 /* ??? can generate less efficient code if constants involved */" -; " -;{ -; enum rtx_code code = GET_CODE (operands[1]); -; rtx ccreg -; = gen_rtx_REG (SELECT_CC_MODE (code, arc_compare_op0, arc_compare_op1), -; 61); -; -; operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx); -;}") - (define_insn "*movsicc_insn" [(set (match_operand:SI 0 "register_operand" "=r") (if_then_else:SI (match_operand 1 "comparison_operator" "") @@ -649,32 +613,6 @@ "mov.%d1 %0,%S2" [(set_attr "type" "cmove")]) -; ??? This doesn't properly handle constants. -;(define_insn "*movdicc_insn" -; [(set (match_operand:DI 0 "register_operand" "=r,r") -; (if_then_else:DI (match_operand 1 "comparison_operator" "") -; (match_operand:DI 2 "nonmemory_operand" "r,Ji") -; (match_operand:DI 3 "register_operand" "0,0")))] -; "0" -; "* -;{ -; switch (which_alternative) -; { -; case 0 : -; /* We normally copy the low-numbered register first. However, if -; the first register operand 0 is the same as the second register of -; operand 1, we must copy in the opposite order. */ -; if (REGNO (operands[0]) == REGNO (operands[2]) + 1) -; return \"mov.%d1 %R0,%R2\;mov.%d1 %0,%2\"; -; else -; return \"mov.%d1 %0,%2\;mov.%d1 %R0,%R2\"; -; case 1 : -; return \"mov.%d1 %0,%2\;mov.%d1 %R0,%R2\"; -; } -;}" -; [(set_attr "type" "cmove,cmove") -; (set_attr "length" "2,4")]) - (define_insn "*movsfcc_insn" [(set (match_operand:SF 0 "register_operand" "=r,r") (if_then_else:SF (match_operand 1 "comparison_operator" "") @@ -686,30 +624,6 @@ mov.%d1 %0,%2 ; %A2" [(set_attr "type" "cmove,cmove")]) -;(define_insn "*movdfcc_insn" -; [(set (match_operand:DF 0 "register_operand" "=r,r") -; (if_then_else:DF (match_operand 1 "comparison_operator" "") -; (match_operand:DF 2 "nonmemory_operand" "r,E") -; (match_operand:DF 3 "register_operand" "0,0")))] -; "0" -; "* -;{ -; switch (which_alternative) -; { -; case 0 : -; /* We normally copy the low-numbered register first. However, if -; the first register operand 0 is the same as the second register of -; operand 1, we must copy in the opposite order. */ -; if (REGNO (operands[0]) == REGNO (operands[2]) + 1) -; return \"mov.%d1 %R0,%R2\;mov.%d1 %0,%2\"; -; else -; return \"mov.%d1 %0,%2\;mov.%d1 %R0,%R2\"; -; case 1 : -; return \"mov.%d1 %0,%L2\;mov.%d1 %R0,%H2 ; %A2\"; -; } -;}" -; [(set_attr "type" "cmove,cmove") -; (set_attr "length" "2,4")]) ;; Zero extension instructions. ;; ??? We don't support volatile memrefs here, but I'm not sure why. @@ -1156,22 +1070,6 @@ ;; Compare instructions. ;; This controls RTL generation and register allocation. -;; We generate RTL for comparisons and branches by having the cmpxx -;; patterns store away the operands. Then, the scc and bcc patterns -;; emit RTL for both the compare and the branch. - -(define_expand "cmpsi" - [(set (reg:CC 61) - (compare:CC (match_operand:SI 0 "register_operand" "") - (match_operand:SI 1 "nonmemory_operand" "")))] - "" - " -{ - arc_compare_op0 = operands[0]; - arc_compare_op1 = operands[1]; - DONE; -}") - ;; ??? We may be able to relax this a bit by adding a new constant 'K' for 0. ;; This assumes sub.f 0,symbol,0 is a valid insn. ;; Note that "sub.f 0,r0,1" is an 8 byte insn. To avoid unnecessarily @@ -1211,96 +1109,25 @@ sub.f 0,%0,%1" [(set_attr "type" "compare,compare,compare")]) -;; Next come the scc insns. - -(define_expand "seq" - [(set (match_operand:SI 0 "register_operand" "=r") - (eq:SI (match_dup 1) (const_int 0)))] - "" - " -{ - operands[1] = gen_compare_reg (EQ, arc_compare_op0, arc_compare_op1); -}") +;; Next come the scc insn and its expander. -(define_expand "sne" - [(set (match_operand:SI 0 "register_operand" "=r") - (ne:SI (match_dup 1) (const_int 0)))] - "" - " -{ - operands[1] = gen_compare_reg (NE, arc_compare_op0, arc_compare_op1); -}") - -(define_expand "sgt" - [(set (match_operand:SI 0 "register_operand" "=r") - (gt:SI (match_dup 1) (const_int 0)))] - "" - " -{ - operands[1] = gen_compare_reg (GT, arc_compare_op0, arc_compare_op1); -}") - -(define_expand "sle" - [(set (match_operand:SI 0 "register_operand" "=r") - (le:SI (match_dup 1) (const_int 0)))] - "" - " -{ - operands[1] = gen_compare_reg (LE, arc_compare_op0, arc_compare_op1); -}") - -(define_expand "sge" - [(set (match_operand:SI 0 "register_operand" "=r") - (ge:SI (match_dup 1) (const_int 0)))] - "" - " -{ - operands[1] = gen_compare_reg (GE, arc_compare_op0, arc_compare_op1); -}") - -(define_expand "slt" - [(set (match_operand:SI 0 "register_operand" "=r") - (lt:SI (match_dup 1) (const_int 0)))] - "" - " -{ - operands[1] = gen_compare_reg (LT, arc_compare_op0, arc_compare_op1); -}") - -(define_expand "sgtu" - [(set (match_operand:SI 0 "register_operand" "=r") - (gtu:SI (match_dup 1) (const_int 0)))] - "" - " -{ - operands[1] = gen_compare_reg (GTU, arc_compare_op0, arc_compare_op1); -}") - -(define_expand "sleu" - [(set (match_operand:SI 0 "register_operand" "=r") - (leu:SI (match_dup 1) (const_int 0)))] - "" - " -{ - operands[1] = gen_compare_reg (LEU, arc_compare_op0, arc_compare_op1); -}") - -(define_expand "sgeu" - [(set (match_operand:SI 0 "register_operand" "=r") - (geu:SI (match_dup 1) (const_int 0)))] - "" - " -{ - operands[1] = gen_compare_reg (GEU, arc_compare_op0, arc_compare_op1); -}") - -(define_expand "sltu" - [(set (match_operand:SI 0 "register_operand" "=r") - (ltu:SI (match_dup 1) (const_int 0)))] +(define_expand "cstoresi4" + [(set (match_dup 4) + (match_op_dup 5 + [(match_operand:SI 2 "register_operand" "") + (match_operand:SI 3 "nonmemory_operand" "")])) + (set (match_operand:SI 0 "register_operand") + (match_operator:SI 1 "ordered_comparison_operator" + [(match_dup 4) + (const_int 0)]))] "" " { - operands[1] = gen_compare_reg (LTU, arc_compare_op0, arc_compare_op1); + operands[4] = gen_compare_reg (GET_CODE (operands[1]), + operands[2], operands[3]); + operands[5] = gen_rtx_fmt_ee (COMPARE, + GET_MODE (operands[4]), + operands[2], operands[3]); }") (define_insn "*scc_insn" @@ -1332,114 +1159,26 @@ ;; These control RTL generation for conditional jump insns -(define_expand "beq" - [(set (pc) - (if_then_else (eq (match_dup 1) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - operands[1] = gen_compare_reg (EQ, arc_compare_op0, arc_compare_op1); -}") - -(define_expand "bne" - [(set (pc) - (if_then_else (ne (match_dup 1) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - operands[1] = gen_compare_reg (NE, arc_compare_op0, arc_compare_op1); -}") - -(define_expand "bgt" - [(set (pc) - (if_then_else (gt (match_dup 1) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - operands[1] = gen_compare_reg (GT, arc_compare_op0, arc_compare_op1); -}") - -(define_expand "ble" - [(set (pc) - (if_then_else (le (match_dup 1) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - operands[1] = gen_compare_reg (LE, arc_compare_op0, arc_compare_op1); -}") - -(define_expand "bge" - [(set (pc) - (if_then_else (ge (match_dup 1) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - operands[1] = gen_compare_reg (GE, arc_compare_op0, arc_compare_op1); -}") - -(define_expand "blt" - [(set (pc) - (if_then_else (lt (match_dup 1) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - operands[1] = gen_compare_reg (LT, arc_compare_op0, arc_compare_op1); -}") - -(define_expand "bgtu" - [(set (pc) - (if_then_else (gtu (match_dup 1) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - operands[1] = gen_compare_reg (GTU, arc_compare_op0, arc_compare_op1); -}") - -(define_expand "bleu" - [(set (pc) - (if_then_else (leu (match_dup 1) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - operands[1] = gen_compare_reg (LEU, arc_compare_op0, arc_compare_op1); -}") - -(define_expand "bgeu" - [(set (pc) - (if_then_else (geu (match_dup 1) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - operands[1] = gen_compare_reg (GEU, arc_compare_op0, arc_compare_op1); -}") - -(define_expand "bltu" - [(set (pc) - (if_then_else (ltu (match_dup 1) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] +(define_expand "cbranchsi4" + [(set (match_dup 4) + (match_op_dup 5 + [(match_operand:SI 1 "register_operand" "") + (match_operand:SI 2 "nonmemory_operand" "")])) + (set (pc) + (if_then_else + (match_operator 0 "ordered_comparison_operator" + [(match_dup 4) + (const_int 0)]) + (label_ref (match_operand 3 "" "")) + (pc)))] "" " { - operands[1] = gen_compare_reg (LTU, arc_compare_op0, arc_compare_op1); + operands[4] = gen_compare_reg (GET_CODE (operands[0]), + operands[1], operands[2]); + operands[5] = gen_rtx_fmt_ee (COMPARE, + GET_MODE (operands[4]), + operands[1], operands[2]); }") ;; Now match both normal and inverted jump. diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c index 1d9b4265843..18e009d1368 100644 --- a/gcc/config/arm/arm.c +++ b/gcc/config/arm/arm.c @@ -418,10 +418,6 @@ extern FILE * asm_out_file; /* True if we are currently building a constant table. */ int making_const_table; -/* Define the information needed to generate branch insns. This is - stored from the compare operation. */ -rtx arm_compare_op0, arm_compare_op1; - /* The processor for which instructions should be scheduled. */ enum processor_type arm_tune = arm_none; diff --git a/gcc/config/arm/arm.h b/gcc/config/arm/arm.h index e7bc7a7a2d5..e0430908901 100644 --- a/gcc/config/arm/arm.h +++ b/gcc/config/arm/arm.h @@ -124,10 +124,6 @@ extern arm_cc arm_current_cc; extern int arm_target_label; extern int arm_ccfsm_state; extern GTY(()) rtx arm_target_insn; -/* Define the information needed to generate branch insns. This is - stored from the compare operation. */ -extern GTY(()) rtx arm_compare_op0; -extern GTY(()) rtx arm_compare_op1; /* The label of the current constant pool. */ extern rtx pool_vector_label; /* Set to 1 when a return insn is output, this means that the epilogue diff --git a/gcc/config/arm/arm.md b/gcc/config/arm/arm.md index 801865287b7..b18173e1aff 100644 --- a/gcc/config/arm/arm.md +++ b/gcc/config/arm/arm.md @@ -6386,8 +6386,16 @@ (match_operand:SI 2 "nonmemory_operand" "")]) (label_ref (match_operand 3 "" "")) (pc)))] - "TARGET_THUMB1" + "TARGET_THUMB1 || TARGET_32BIT" " + if (!TARGET_THUMB1) + { + if (!arm_add_operand (operands[2], SImode)) + operands[2] = force_reg (SImode, operands[2]); + emit_jump_insn (gen_cbranch_cc (operands[0], operands[1], operands[2], + operands[3])); + DONE; + } if (thumb1_cmpneg_operand (operands[2], SImode)) { emit_jump_insn (gen_cbranchsi4_scratch (NULL, operands[1], operands[2], @@ -6398,6 +6406,43 @@ operands[2] = force_reg (SImode, operands[2]); ") +(define_expand "cbranchsf4" + [(set (pc) (if_then_else + (match_operator 0 "arm_comparison_operator" + [(match_operand:SF 1 "s_register_operand" "") + (match_operand:SF 2 "arm_float_compare_operand" "")]) + (label_ref (match_operand 3 "" "")) + (pc)))] + "TARGET_32BIT && TARGET_HARD_FLOAT" + "emit_jump_insn (gen_cbranch_cc (operands[0], operands[1], operands[2], + operands[3])); DONE;" +) + +(define_expand "cbranchdf4" + [(set (pc) (if_then_else + (match_operator 0 "arm_comparison_operator" + [(match_operand:DF 1 "s_register_operand" "") + (match_operand:DF 2 "arm_float_compare_operand" "")]) + (label_ref (match_operand 3 "" "")) + (pc)))] + "TARGET_32BIT && TARGET_HARD_FLOAT" + "emit_jump_insn (gen_cbranch_cc (operands[0], operands[1], operands[2], + operands[3])); DONE;" +) + +;; this uses the Cirrus DI compare instruction +(define_expand "cbranchdi4" + [(set (pc) (if_then_else + (match_operator 0 "arm_comparison_operator" + [(match_operand:DI 1 "cirrus_fp_register" "") + (match_operand:DI 2 "cirrus_fp_register" "")]) + (label_ref (match_operand 3 "" "")) + (pc)))] + "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK" + "emit_jump_insn (gen_cbranch_cc (operands[0], operands[1], operands[2], + operands[3])); DONE;" +) + (define_insn "*cbranchsi4_insn" [(set (pc) (if_then_else (match_operator 0 "arm_comparison_operator" @@ -7451,39 +7496,6 @@ ;; Comparison and test insns -(define_expand "cmpsi" - [(match_operand:SI 0 "s_register_operand" "") - (match_operand:SI 1 "arm_add_operand" "")] - "TARGET_32BIT" - "{ - arm_compare_op0 = operands[0]; - arm_compare_op1 = operands[1]; - DONE; - }" -) - -(define_expand "cmpsf" - [(match_operand:SF 0 "s_register_operand" "") - (match_operand:SF 1 "arm_float_compare_operand" "")] - "TARGET_32BIT && TARGET_HARD_FLOAT" - " - arm_compare_op0 = operands[0]; - arm_compare_op1 = operands[1]; - DONE; - " -) - -(define_expand "cmpdf" - [(match_operand:DF 0 "s_register_operand" "") - (match_operand:DF 1 "arm_float_compare_operand" "")] - "TARGET_32BIT && TARGET_HARD_FLOAT" - " - arm_compare_op0 = operands[0]; - arm_compare_op1 = operands[1]; - DONE; - " -) - (define_insn "*arm_cmpsi_insn" [(set (reg:CC CC_REGNUM) (compare:CC (match_operand:SI 0 "s_register_operand" "r,r") @@ -7562,17 +7574,6 @@ (set_attr "cirrus" "compare")] ) -;; Cirrus DI compare instruction -(define_expand "cmpdi" - [(match_operand:DI 0 "cirrus_fp_register" "") - (match_operand:DI 1 "cirrus_fp_register" "")] - "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK" - "{ - arm_compare_op0 = operands[0]; - arm_compare_op1 = operands[1]; - DONE; - }") - (define_insn "*cirrus_cmpdi" [(set (reg:CC CC_REGNUM) (compare:CC (match_operand:DI 0 "cirrus_fp_register" "v") @@ -7600,170 +7601,16 @@ ;; Conditional branch insns -(define_expand "beq" - [(set (pc) - (if_then_else (eq (match_dup 1) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "TARGET_32BIT" - "operands[1] = arm_gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1);" -) - -(define_expand "bne" +(define_expand "cbranch_cc" [(set (pc) - (if_then_else (ne (match_dup 1) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "TARGET_32BIT" - "operands[1] = arm_gen_compare_reg (NE, arm_compare_op0, arm_compare_op1);" -) - -(define_expand "bgt" - [(set (pc) - (if_then_else (gt (match_dup 1) (const_int 0)) - (label_ref (match_operand 0 "" "")) + (if_then_else (match_operator 0 "" [(match_operand 1 "" "") + (match_operand 2 "" "")]) + (label_ref (match_operand 3 "" "")) (pc)))] "TARGET_32BIT" - "operands[1] = arm_gen_compare_reg (GT, arm_compare_op0, arm_compare_op1);" -) - -(define_expand "ble" - [(set (pc) - (if_then_else (le (match_dup 1) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "TARGET_32BIT" - "operands[1] = arm_gen_compare_reg (LE, arm_compare_op0, arm_compare_op1);" -) - -(define_expand "bge" - [(set (pc) - (if_then_else (ge (match_dup 1) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "TARGET_32BIT" - "operands[1] = arm_gen_compare_reg (GE, arm_compare_op0, arm_compare_op1);" -) - -(define_expand "blt" - [(set (pc) - (if_then_else (lt (match_dup 1) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "TARGET_32BIT" - "operands[1] = arm_gen_compare_reg (LT, arm_compare_op0, arm_compare_op1);" -) - -(define_expand "bgtu" - [(set (pc) - (if_then_else (gtu (match_dup 1) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "TARGET_32BIT" - "operands[1] = arm_gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1);" -) - -(define_expand "bleu" - [(set (pc) - (if_then_else (leu (match_dup 1) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "TARGET_32BIT" - "operands[1] = arm_gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1);" -) - -(define_expand "bgeu" - [(set (pc) - (if_then_else (geu (match_dup 1) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "TARGET_32BIT" - "operands[1] = arm_gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1);" -) - -(define_expand "bltu" - [(set (pc) - (if_then_else (ltu (match_dup 1) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "TARGET_32BIT" - "operands[1] = arm_gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1);" -) - -(define_expand "bunordered" - [(set (pc) - (if_then_else (unordered (match_dup 1) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)" - "operands[1] = arm_gen_compare_reg (UNORDERED, arm_compare_op0, - arm_compare_op1);" -) - -(define_expand "bordered" - [(set (pc) - (if_then_else (ordered (match_dup 1) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)" - "operands[1] = arm_gen_compare_reg (ORDERED, arm_compare_op0, - arm_compare_op1);" -) - -(define_expand "bungt" - [(set (pc) - (if_then_else (ungt (match_dup 1) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)" - "operands[1] = arm_gen_compare_reg (UNGT, arm_compare_op0, arm_compare_op1);" -) - -(define_expand "bunlt" - [(set (pc) - (if_then_else (unlt (match_dup 1) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)" - "operands[1] = arm_gen_compare_reg (UNLT, arm_compare_op0, arm_compare_op1);" -) - -(define_expand "bunge" - [(set (pc) - (if_then_else (unge (match_dup 1) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)" - "operands[1] = arm_gen_compare_reg (UNGE, arm_compare_op0, arm_compare_op1);" -) - -(define_expand "bunle" - [(set (pc) - (if_then_else (unle (match_dup 1) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)" - "operands[1] = arm_gen_compare_reg (UNLE, arm_compare_op0, arm_compare_op1);" -) - -;; The following two patterns need two branch instructions, since there is -;; no single instruction that will handle all cases. -(define_expand "buneq" - [(set (pc) - (if_then_else (uneq (match_dup 1) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)" - "operands[1] = arm_gen_compare_reg (UNEQ, arm_compare_op0, arm_compare_op1);" -) - -(define_expand "bltgt" - [(set (pc) - (if_then_else (ltgt (match_dup 1) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)" - "operands[1] = arm_gen_compare_reg (LTGT, arm_compare_op0, arm_compare_op1);" + "operands[1] = arm_gen_compare_reg (GET_CODE (operands[0]), + operands[1], operands[2]); + operands[2] = const0_rtx;" ) ;; @@ -7876,141 +7723,16 @@ ; scc insns -(define_expand "seq" - [(set (match_operand:SI 0 "s_register_operand" "") - (eq:SI (match_dup 1) (const_int 0)))] - "TARGET_32BIT" - "operands[1] = arm_gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1);" -) - -(define_expand "sne" - [(set (match_operand:SI 0 "s_register_operand" "") - (ne:SI (match_dup 1) (const_int 0)))] - "TARGET_32BIT" - "operands[1] = arm_gen_compare_reg (NE, arm_compare_op0, arm_compare_op1);" -) - -(define_expand "sgt" - [(set (match_operand:SI 0 "s_register_operand" "") - (gt:SI (match_dup 1) (const_int 0)))] - "TARGET_32BIT" - "operands[1] = arm_gen_compare_reg (GT, arm_compare_op0, arm_compare_op1);" -) - -(define_expand "sle" - [(set (match_operand:SI 0 "s_register_operand" "") - (le:SI (match_dup 1) (const_int 0)))] - "TARGET_32BIT" - "operands[1] = arm_gen_compare_reg (LE, arm_compare_op0, arm_compare_op1);" -) - -(define_expand "sge" - [(set (match_operand:SI 0 "s_register_operand" "") - (ge:SI (match_dup 1) (const_int 0)))] - "TARGET_32BIT" - "operands[1] = arm_gen_compare_reg (GE, arm_compare_op0, arm_compare_op1);" -) - -(define_expand "slt" - [(set (match_operand:SI 0 "s_register_operand" "") - (lt:SI (match_dup 1) (const_int 0)))] - "TARGET_32BIT" - "operands[1] = arm_gen_compare_reg (LT, arm_compare_op0, arm_compare_op1);" -) - -(define_expand "sgtu" - [(set (match_operand:SI 0 "s_register_operand" "") - (gtu:SI (match_dup 1) (const_int 0)))] - "TARGET_32BIT" - "operands[1] = arm_gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1);" -) - -(define_expand "sleu" - [(set (match_operand:SI 0 "s_register_operand" "") - (leu:SI (match_dup 1) (const_int 0)))] - "TARGET_32BIT" - "operands[1] = arm_gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1);" -) - -(define_expand "sgeu" +(define_expand "cstore_cc" [(set (match_operand:SI 0 "s_register_operand" "") - (geu:SI (match_dup 1) (const_int 0)))] + (match_operator:SI 1 "" [(match_operand 2 "" "") + (match_operand 3 "" "")]))] "TARGET_32BIT" - "operands[1] = arm_gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1);" -) - -(define_expand "sltu" - [(set (match_operand:SI 0 "s_register_operand" "") - (ltu:SI (match_dup 1) (const_int 0)))] - "TARGET_32BIT" - "operands[1] = arm_gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1);" -) - -(define_expand "sunordered" - [(set (match_operand:SI 0 "s_register_operand" "") - (unordered:SI (match_dup 1) (const_int 0)))] - "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)" - "operands[1] = arm_gen_compare_reg (UNORDERED, arm_compare_op0, - arm_compare_op1);" -) - -(define_expand "sordered" - [(set (match_operand:SI 0 "s_register_operand" "") - (ordered:SI (match_dup 1) (const_int 0)))] - "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)" - "operands[1] = arm_gen_compare_reg (ORDERED, arm_compare_op0, - arm_compare_op1);" -) - -(define_expand "sungt" - [(set (match_operand:SI 0 "s_register_operand" "") - (ungt:SI (match_dup 1) (const_int 0)))] - "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)" - "operands[1] = arm_gen_compare_reg (UNGT, arm_compare_op0, - arm_compare_op1);" -) - -(define_expand "sunge" - [(set (match_operand:SI 0 "s_register_operand" "") - (unge:SI (match_dup 1) (const_int 0)))] - "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)" - "operands[1] = arm_gen_compare_reg (UNGE, arm_compare_op0, - arm_compare_op1);" -) - -(define_expand "sunlt" - [(set (match_operand:SI 0 "s_register_operand" "") - (unlt:SI (match_dup 1) (const_int 0)))] - "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)" - "operands[1] = arm_gen_compare_reg (UNLT, arm_compare_op0, - arm_compare_op1);" -) - -(define_expand "sunle" - [(set (match_operand:SI 0 "s_register_operand" "") - (unle:SI (match_dup 1) (const_int 0)))] - "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)" - "operands[1] = arm_gen_compare_reg (UNLE, arm_compare_op0, - arm_compare_op1);" + "operands[2] = arm_gen_compare_reg (GET_CODE (operands[1]), + operands[2], operands[3]); + operands[3] = const0_rtx;" ) -;;; DO NOT add patterns for SUNEQ or SLTGT, these can't be represented with -;;; simple ARM instructions. -; -; (define_expand "suneq" -; [(set (match_operand:SI 0 "s_register_operand" "") -; (uneq:SI (match_dup 1) (const_int 0)))] -; "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)" -; "gcc_unreachable ();" -; ) -; -; (define_expand "sltgt" -; [(set (match_operand:SI 0 "s_register_operand" "") -; (ltgt:SI (match_dup 1) (const_int 0)))] -; "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)" -; "gcc_unreachable ();" -; ) - (define_insn "*mov_scc" [(set (match_operand:SI 0 "s_register_operand" "=r") (match_operator:SI 1 "arm_comparison_operator" @@ -8046,10 +7768,19 @@ (match_operator:SI 1 "arm_comparison_operator" [(match_operand:SI 2 "s_register_operand" "") (match_operand:SI 3 "reg_or_int_operand" "")]))] - "TARGET_THUMB1" + "TARGET_32BIT || TARGET_THUMB1" "{ rtx op3, scratch, scratch2; + if (!TARGET_THUMB1) + { + if (!arm_add_operand (operands[3], SImode)) + operands[3] = force_reg (SImode, operands[3]); + emit_insn (gen_cstore_cc (operands[0], operands[1], + operands[2], operands[3])); + DONE; + } + if (operands[3] == const0_rtx) { switch (GET_CODE (operands[1])) @@ -8170,6 +7901,38 @@ DONE; }") +(define_expand "cstoresf4" + [(set (match_operand:SI 0 "s_register_operand" "") + (match_operator:SI 1 "arm_comparison_operator" + [(match_operand:SF 2 "s_register_operand" "") + (match_operand:SF 3 "arm_float_compare_operand" "")]))] + "TARGET_32BIT && TARGET_HARD_FLOAT" + "emit_insn (gen_cstore_cc (operands[0], operands[1], + operands[2], operands[3])); DONE;" +) + +(define_expand "cstoredf4" + [(set (match_operand:SI 0 "s_register_operand" "") + (match_operator:SI 1 "arm_comparison_operator" + [(match_operand:DF 2 "s_register_operand" "") + (match_operand:DF 3 "arm_float_compare_operand" "")]))] + "TARGET_32BIT && TARGET_HARD_FLOAT" + "emit_insn (gen_cstore_cc (operands[0], operands[1], + operands[2], operands[3])); DONE;" +) + +;; this uses the Cirrus DI compare instruction +(define_expand "cstoredi4" + [(set (match_operand:SI 0 "s_register_operand" "") + (match_operator:SI 1 "arm_comparison_operator" + [(match_operand:DI 2 "cirrus_fp_register" "") + (match_operand:DI 3 "cirrus_fp_register" "")]))] + "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK" + "emit_insn (gen_cstore_cc (operands[0], operands[1], + operands[2], operands[3])); DONE;" +) + + (define_expand "cstoresi_eq0_thumb1" [(parallel [(set (match_operand:SI 0 "s_register_operand" "") @@ -8250,7 +8013,8 @@ if (code == UNEQ || code == LTGT) FAIL; - ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1); + ccreg = arm_gen_compare_reg (code, XEXP (operands[1], 0), + XEXP (operands[1], 1)); operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx); }" ) @@ -8275,7 +8039,8 @@ || (!arm_float_add_operand (operands[3], SFmode))) operands[3] = force_reg (SFmode, operands[3]); - ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1); + ccreg = arm_gen_compare_reg (code, XEXP (operands[1], 0), + XEXP (operands[1], 1)); operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx); }" ) @@ -8294,7 +8059,8 @@ if (code == UNEQ || code == LTGT) FAIL; - ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1); + ccreg = arm_gen_compare_reg (code, XEXP (operands[1], 0), + XEXP (operands[1], 1)); operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx); }" ) diff --git a/gcc/config/arm/predicates.md b/gcc/config/arm/predicates.md index c7d63355d34..b45faf43cbc 100644 --- a/gcc/config/arm/predicates.md +++ b/gcc/config/arm/predicates.md @@ -191,9 +191,13 @@ (define_special_predicate "equality_operator" (match_code "eq,ne")) -;; True for comparisons other than LTGT or UNEQ. +;; True for integer comparisons and, if FP is active, for comparisons +;; other than LTGT or UNEQ. (define_special_predicate "arm_comparison_operator" - (match_code "eq,ne,le,lt,ge,gt,geu,gtu,leu,ltu,unordered,ordered,unlt,unle,unge,ungt")) + (ior (match_code "eq,ne,le,lt,ge,gt,geu,gtu,leu,ltu") + (and (match_test "TARGET_32BIT && TARGET_HARD_FLOAT + && (TARGET_FPA || TARGET_VFP)") + (match_code "unordered,ordered,unlt,unle,unge,ungt")))) (define_special_predicate "minmax_operator" (and (match_code "smin,smax,umin,umax") diff --git a/gcc/config/avr/avr-protos.h b/gcc/config/avr/avr-protos.h index 44246901b32..f4d2119a998 100644 --- a/gcc/config/avr/avr-protos.h +++ b/gcc/config/avr/avr-protos.h @@ -72,8 +72,8 @@ extern const char *out_movhi_mr_r (rtx insn, rtx op[], int *l); extern const char *out_movsi_r_mr (rtx insn, rtx op[], int *l); extern const char *out_movsi_mr_r (rtx insn, rtx op[], int *l); extern const char *output_movsisf (rtx insn, rtx operands[], int *l); -extern const char *out_tstsi (rtx insn, int *l); -extern const char *out_tsthi (rtx insn, int *l); +extern const char *out_tstsi (rtx insn, rtx src, int *l); +extern const char *out_tsthi (rtx insn, rtx src, int *l); extern const char *ret_cond_branch (rtx x, int len, int reverse); extern const char *ashlqi3_out (rtx insn, rtx operands[], int *len); diff --git a/gcc/config/avr/avr.c b/gcc/config/avr/avr.c index 6bcc8e80372..4811b92637f 100644 --- a/gcc/config/avr/avr.c +++ b/gcc/config/avr/avr.c @@ -2915,21 +2915,21 @@ compare_eq_p (rtx insn) /* Output test instruction for HImode. */ const char * -out_tsthi (rtx insn, int *l) +out_tsthi (rtx insn, rtx op, int *l) { if (compare_sign_p (insn)) { if (l) *l = 1; return AS1 (tst,%B0); } - if (reg_unused_after (insn, SET_SRC (PATTERN (insn))) + if (reg_unused_after (insn, op) && compare_eq_p (insn)) { /* Faster than sbiw if we can clobber the operand. */ if (l) *l = 1; return AS2 (or,%A0,%B0); } - if (test_hard_reg_class (ADDW_REGS, SET_SRC (PATTERN (insn)))) + if (test_hard_reg_class (ADDW_REGS, op)) { if (l) *l = 1; return AS2 (sbiw,%0,0); @@ -2943,14 +2943,14 @@ out_tsthi (rtx insn, int *l) /* Output test instruction for SImode. */ const char * -out_tstsi (rtx insn, int *l) +out_tstsi (rtx insn, rtx op, int *l) { if (compare_sign_p (insn)) { if (l) *l = 1; return AS1 (tst,%D0); } - if (test_hard_reg_class (ADDW_REGS, SET_SRC (PATTERN (insn)))) + if (test_hard_reg_class (ADDW_REGS, op)) { if (l) *l = 3; return (AS2 (sbiw,%A0,0) CR_TAB @@ -4367,8 +4367,8 @@ adjust_insn_length (rtx insn, int len) { switch (GET_MODE (op[1])) { - case HImode: out_tsthi (insn,&len); break; - case SImode: out_tstsi (insn,&len); break; + case HImode: out_tsthi (insn, op[1], &len); break; + case SImode: out_tstsi (insn, op[1], &len); break; default: break; } } @@ -5734,6 +5734,21 @@ avr_reorg (void) XEXP (pattern,1) = x; INSN_CODE (next) = -1; } + else if (true_regnum (XEXP (pattern, 0)) >= 0 + && XEXP (pattern, 1) == const0_rtx) + { + /* This is a tst insn, we can reverse it. */ + rtx next = next_real_insn (insn); + rtx pat = PATTERN (next); + rtx src = SET_SRC (pat); + rtx t = XEXP (src,0); + + PUT_CODE (t, swap_condition (GET_CODE (t))); + XEXP (pattern, 1) = XEXP (pattern, 0); + XEXP (pattern, 0) = const0_rtx; + INSN_CODE (next) = -1; + INSN_CODE (insn) = -1; + } else if (true_regnum (XEXP (pattern,0)) >= 0 && GET_CODE (XEXP (pattern,1)) == CONST_INT) { @@ -5753,20 +5768,6 @@ avr_reorg (void) } } } - else if (true_regnum (SET_SRC (pattern)) >= 0) - { - /* This is a tst insn */ - rtx next = next_real_insn (insn); - rtx pat = PATTERN (next); - rtx src = SET_SRC (pat); - rtx t = XEXP (src,0); - - PUT_CODE (t, swap_condition (GET_CODE (t))); - SET_SRC (pattern) = gen_rtx_COMPARE (GET_MODE (SET_SRC (pattern)), const0_rtx, - SET_SRC (pattern)); - INSN_CODE (next) = -1; - INSN_CODE (insn) = -1; - } } } } diff --git a/gcc/config/avr/avr.md b/gcc/config/avr/avr.md index 269e2c5ddb5..86a217dc23c 100644 --- a/gcc/config/avr/avr.md +++ b/gcc/config/avr/avr.md @@ -2202,53 +2202,65 @@ ;;<=><=><=><=><=><=><=><=><=><=><=><=><=><=><=><=><=><=><=><=><=><=><=><=><=> ;; compare -(define_insn "tstqi" +; Optimize negated tests into reverse compare if overflow is undefined. +(define_insn "*negated_tstqi" [(set (cc0) - (match_operand:QI 0 "register_operand" "r"))] - "" - "tst %0" + (compare (neg:QI (match_operand:QI 0 "register_operand" "r")) + (const_int 0)))] + "(!flag_wrapv && !flag_trapv && flag_strict_overflow)" + "cp __zero_reg__,%0" [(set_attr "cc" "compare") (set_attr "length" "1")]) (define_insn "*reversed_tstqi" [(set (cc0) - (compare (const_int 0) + (compare (const_int 0) (match_operand:QI 0 "register_operand" "r")))] "" "cp __zero_reg__,%0" - [(set_attr "cc" "compare") - (set_attr "length" "1")]) +[(set_attr "cc" "compare") + (set_attr "length" "2")]) -(define_insn "tsthi" +(define_insn "*negated_tsthi" [(set (cc0) - (match_operand:HI 0 "register_operand" "!w,r"))] - "" - "* return out_tsthi (insn,NULL);" -[(set_attr "cc" "compare,compare") - (set_attr "length" "1,2")]) + (compare (neg:HI (match_operand:HI 0 "register_operand" "r")) + (const_int 0)))] + "(!flag_wrapv && !flag_trapv && flag_strict_overflow)" + "cp __zero_reg__,%A0 + cpc __zero_reg__,%B0" +[(set_attr "cc" "compare") + (set_attr "length" "2")]) +;; Leave here the clobber used by the cmphi pattern for simplicity, even +;; though it is unused, because this pattern is synthesized by avr_reorg. (define_insn "*reversed_tsthi" [(set (cc0) (compare (const_int 0) - (match_operand:HI 0 "register_operand" "r")))] + (match_operand:HI 0 "register_operand" "r"))) + (clobber (match_scratch:QI 1 "=X"))] "" "cp __zero_reg__,%A0 cpc __zero_reg__,%B0" [(set_attr "cc" "compare") (set_attr "length" "2")]) -(define_insn "tstsi" +(define_insn "*negated_tstsi" [(set (cc0) - (match_operand:SI 0 "register_operand" "r"))] - "" - "* return out_tstsi (insn,NULL);" + (compare (neg:SI (match_operand:SI 0 "register_operand" "r")) + (const_int 0)))] + "(!flag_wrapv && !flag_trapv && flag_strict_overflow)" + "cp __zero_reg__,%A0 + cpc __zero_reg__,%B0 + cpc __zero_reg__,%C0 + cpc __zero_reg__,%D0" [(set_attr "cc" "compare") (set_attr "length" "4")]) (define_insn "*reversed_tstsi" [(set (cc0) - (compare (const_int 0) - (match_operand:SI 0 "register_operand" "r")))] + (compare (const_int 0) + (match_operand:SI 0 "register_operand" "r"))) + (clobber (match_scratch:QI 1 "=X"))] "" "cp __zero_reg__,%A0 cpc __zero_reg__,%B0 @@ -2258,16 +2270,17 @@ (set_attr "length" "4")]) -(define_insn "cmpqi" +(define_insn "*cmpqi" [(set (cc0) - (compare (match_operand:QI 0 "register_operand" "r,d") - (match_operand:QI 1 "nonmemory_operand" "r,i")))] + (compare (match_operand:QI 0 "register_operand" "r,r,d") + (match_operand:QI 1 "nonmemory_operand" "L,r,i")))] "" "@ + tst %0 cp %0,%1 cpi %0,lo8(%1)" - [(set_attr "cc" "compare,compare") - (set_attr "length" "1,1")]) + [(set_attr "cc" "compare,compare,compare") + (set_attr "length" "1,1,1")]) (define_insn "*cmpqi_sign_extend" [(set (cc0) @@ -2279,19 +2292,22 @@ [(set_attr "cc" "compare") (set_attr "length" "1")]) -(define_insn "cmphi" +(define_insn "*cmphi" [(set (cc0) - (compare (match_operand:HI 0 "register_operand" "r,d,d,r,r") - (match_operand:HI 1 "nonmemory_operand" "r,M,i,M,i"))) - (clobber (match_scratch:QI 2 "=X,X,&d,&d,&d"))] + (compare (match_operand:HI 0 "register_operand" "!w,r,r,d,d,r,r") + (match_operand:HI 1 "nonmemory_operand" "L,L,r,M,i,M,i"))) + (clobber (match_scratch:QI 2 "=X,X,X,X,&d,&d,&d"))] "" "*{ switch (which_alternative) { - case 0: + case 0: case 1: + return out_tsthi (insn, operands[0], NULL); + + case 2: return (AS2 (cp,%A0,%A1) CR_TAB AS2 (cpc,%B0,%B1)); - case 1: + case 3: if (reg_unused_after (insn, operands[0]) && INTVAL (operands[1]) >= 0 && INTVAL (operands[1]) <= 63 && test_hard_reg_class (ADDW_REGS, operands[0])) @@ -2299,7 +2315,7 @@ else return (AS2 (cpi,%0,%1) CR_TAB AS2 (cpc,%B0,__zero_reg__)); - case 2: + case 4: if (reg_unused_after (insn, operands[0])) return (AS2 (subi,%0,lo8(%1)) CR_TAB AS2 (sbci,%B0,hi8(%1))); @@ -2307,12 +2323,12 @@ return (AS2 (ldi, %2,hi8(%1)) CR_TAB AS2 (cpi, %A0,lo8(%1)) CR_TAB AS2 (cpc, %B0,%2)); - case 3: + case 5: return (AS2 (ldi, %2,lo8(%1)) CR_TAB AS2 (cp, %A0,%2) CR_TAB AS2 (cpc, %B0,__zero_reg__)); - case 4: + case 6: return (AS2 (ldi, %2,lo8(%1)) CR_TAB AS2 (cp, %A0,%2) CR_TAB AS2 (ldi, %2,hi8(%1)) CR_TAB @@ -2320,25 +2336,28 @@ } return \"bug\"; }" - [(set_attr "cc" "compare,compare,compare,compare,compare") - (set_attr "length" "2,2,3,3,4")]) + [(set_attr "cc" "compare,compare,compare,compare,compare,compare,compare") + (set_attr "length" "1,2,2,2,3,3,4")]) -(define_insn "cmpsi" +(define_insn "*cmpsi" [(set (cc0) - (compare (match_operand:SI 0 "register_operand" "r,d,d,r,r") - (match_operand:SI 1 "nonmemory_operand" "r,M,i,M,i"))) - (clobber (match_scratch:QI 2 "=X,X,&d,&d,&d"))] + (compare (match_operand:SI 0 "register_operand" "r,r,d,d,r,r") + (match_operand:SI 1 "nonmemory_operand" "L,r,M,i,M,i"))) + (clobber (match_scratch:QI 2 "=X,X,X,&d,&d,&d"))] "" "*{ switch (which_alternative) { case 0: + return out_tstsi (insn, operands[0], NULL); + + case 1: return (AS2 (cp,%A0,%A1) CR_TAB AS2 (cpc,%B0,%B1) CR_TAB AS2 (cpc,%C0,%C1) CR_TAB AS2 (cpc,%D0,%D1)); - case 1: + case 2: if (reg_unused_after (insn, operands[0]) && INTVAL (operands[1]) >= 0 && INTVAL (operands[1]) <= 63 && test_hard_reg_class (ADDW_REGS, operands[0])) @@ -2350,7 +2369,7 @@ AS2 (cpc,%B0,__zero_reg__) CR_TAB AS2 (cpc,%C0,__zero_reg__) CR_TAB AS2 (cpc,%D0,__zero_reg__)); - case 2: + case 3: if (reg_unused_after (insn, operands[0])) return (AS2 (subi,%A0,lo8(%1)) CR_TAB AS2 (sbci,%B0,hi8(%1)) CR_TAB @@ -2364,13 +2383,13 @@ AS2 (cpc, %C0,%2) CR_TAB AS2 (ldi, %2,hhi8(%1)) CR_TAB AS2 (cpc, %D0,%2)); - case 3: + case 4: return (AS2 (ldi,%2,lo8(%1)) CR_TAB AS2 (cp,%A0,%2) CR_TAB AS2 (cpc,%B0,__zero_reg__) CR_TAB AS2 (cpc,%C0,__zero_reg__) CR_TAB AS2 (cpc,%D0,__zero_reg__)); - case 4: + case 5: return (AS2 (ldi, %2,lo8(%1)) CR_TAB AS2 (cp, %A0,%2) CR_TAB AS2 (ldi, %2,hi8(%1)) CR_TAB @@ -2382,113 +2401,53 @@ } return \"bug\"; }" - [(set_attr "cc" "compare,compare,compare,compare,compare") - (set_attr "length" "4,4,7,5,8")]) - -; Optimize negated tests into reverse compare if overflow is undefined. -(define_insn_and_split "negated_tst<mode>" - [(set (cc0) - (neg:QISI (match_operand:QISI 0 "register_operand")))] + [(set_attr "cc" "compare,compare,compare,compare,compare,compare") + (set_attr "length" "4,4,4,7,5,8")]) - "(!flag_wrapv && !flag_trapv && flag_strict_overflow)" - "#" - "" - [(set (cc0) - (compare (const_int 0) - (match_dup 0)))] - "") ;; ---------------------------------------------------------------------- ;; JUMP INSTRUCTIONS ;; ---------------------------------------------------------------------- ;; Conditional jump instructions -(define_expand "beq" - [(set (pc) - (if_then_else (eq (cc0) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "") - -(define_expand "bne" - [(set (pc) - (if_then_else (ne (cc0) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "") - -(define_expand "bge" - [(set (pc) - (if_then_else (ge (cc0) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "") - -(define_expand "bgeu" - [(set (pc) - (if_then_else (geu (cc0) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "") - -(define_expand "blt" - [(set (pc) - (if_then_else (lt (cc0) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "") - -(define_expand "bltu" - [(set (pc) - (if_then_else (ltu (cc0) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "") - - - -/**************************************************************** - AVR not have following conditional jumps: LE,LEU,GT,GTU. - Convert them all to proper jumps. -*****************************************************************/ - -(define_expand "ble" - [(set (pc) - (if_then_else (le (cc0) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "") - -(define_expand "bleu" - [(set (pc) - (if_then_else (leu (cc0) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "") +(define_expand "cbranchsi4" + [(parallel [(set (cc0) + (compare (match_operand:SI 1 "register_operand" "") + (match_operand:SI 2 "nonmemory_operand" ""))) + (clobber (match_scratch:QI 4 ""))]) + (set (pc) + (if_then_else + (match_operator 0 "ordered_comparison_operator" [(cc0) + (const_int 0)]) + (label_ref (match_operand 3 "" "")) + (pc)))] + "") + +(define_expand "cbranchhi4" + [(parallel [(set (cc0) + (compare (match_operand:HI 1 "register_operand" "") + (match_operand:HI 2 "nonmemory_operand" ""))) + (clobber (match_scratch:QI 4 ""))]) + (set (pc) + (if_then_else + (match_operator 0 "ordered_comparison_operator" [(cc0) + (const_int 0)]) + (label_ref (match_operand 3 "" "")) + (pc)))] + "") -(define_expand "bgt" - [(set (pc) - (if_then_else (gt (cc0) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "") +(define_expand "cbranchqi4" + [(set (cc0) + (compare (match_operand:QI 1 "register_operand" "") + (match_operand:QI 2 "nonmemory_operand" ""))) + (set (pc) + (if_then_else + (match_operator 0 "ordered_comparison_operator" [(cc0) + (const_int 0)]) + (label_ref (match_operand 3 "" "")) + (pc)))] + "") -(define_expand "bgtu" - [(set (pc) - (if_then_else (gtu (cc0) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "") ;; Test a single bit in a QI/HI/SImode register. (define_insn "*sbrx_branch" @@ -2557,7 +2516,8 @@ ;; Convert sign tests to bit 7/15/31 tests that match the above insns. (define_peephole2 - [(set (cc0) (match_operand:QI 0 "register_operand" "")) + [(set (cc0) (compare (match_operand:QI 0 "register_operand" "") + (const_int 0))) (set (pc) (if_then_else (ge (cc0) (const_int 0)) (label_ref (match_operand 1 "" "")) (pc)))] @@ -2571,7 +2531,8 @@ "") (define_peephole2 - [(set (cc0) (match_operand:QI 0 "register_operand" "")) + [(set (cc0) (compare (match_operand:QI 0 "register_operand" "") + (const_int 0))) (set (pc) (if_then_else (lt (cc0) (const_int 0)) (label_ref (match_operand 1 "" "")) (pc)))] @@ -2585,7 +2546,9 @@ "") (define_peephole2 - [(set (cc0) (match_operand:HI 0 "register_operand" "")) + [(parallel [(set (cc0) (compare (match_operand:HI 0 "register_operand" "") + (const_int 0))) + (clobber (match_operand:HI 2 ""))]) (set (pc) (if_then_else (ge (cc0) (const_int 0)) (label_ref (match_operand 1 "" "")) (pc)))] @@ -2597,7 +2560,9 @@ "") (define_peephole2 - [(set (cc0) (match_operand:HI 0 "register_operand" "")) + [(parallel [(set (cc0) (compare (match_operand:HI 0 "register_operand" "") + (const_int 0))) + (clobber (match_operand:HI 2 ""))]) (set (pc) (if_then_else (lt (cc0) (const_int 0)) (label_ref (match_operand 1 "" "")) (pc)))] @@ -2609,7 +2574,9 @@ "") (define_peephole2 - [(set (cc0) (match_operand:SI 0 "register_operand" "")) + [(parallel [(set (cc0) (compare (match_operand:SI 0 "register_operand" "") + (const_int 0))) + (clobber (match_operand:SI 2 ""))]) (set (pc) (if_then_else (ge (cc0) (const_int 0)) (label_ref (match_operand 1 "" "")) (pc)))] @@ -2621,7 +2588,9 @@ "operands[2] = GEN_INT (-2147483647 - 1);") (define_peephole2 - [(set (cc0) (match_operand:SI 0 "register_operand" "")) + [(parallel [(set (cc0) (compare (match_operand:SI 0 "register_operand" "") + (const_int 0))) + (clobber (match_operand:SI 2 ""))]) (set (pc) (if_then_else (lt (cc0) (const_int 0)) (label_ref (match_operand 1 "" "")) (pc)))] @@ -2650,6 +2619,11 @@ [(set_attr "type" "branch") (set_attr "cc" "clobber")]) +;; **************************************************************** +;; AVR does not have following conditional jumps: LE,LEU,GT,GTU. +;; Convert them all to proper jumps. +;; ****************************************************************/ + (define_insn "difficult_branch" [(set (pc) (if_then_else (match_operator 1 "difficult_comparison_operator" @@ -3150,7 +3124,9 @@ }") (define_peephole - [(set (cc0) (match_operand:QI 0 "register_operand" "")) + [(set (cc0) + (compare (match_operand:QI 0 "register_operand" "") + (const_int 0))) (set (pc) (if_then_else (eq (cc0) (const_int 0)) (label_ref (match_operand 1 "" "")) diff --git a/gcc/config/bfin/bfin.c b/gcc/config/bfin/bfin.c index 077d5c544a7..ac237d73bd2 100644 --- a/gcc/config/bfin/bfin.c +++ b/gcc/config/bfin/bfin.c @@ -67,10 +67,6 @@ struct GTY(()) machine_function int has_loopreg_clobber; }; -/* Test and compare insns in bfin.md store the information needed to - generate branch and scc insns here. */ -rtx bfin_compare_op0, bfin_compare_op1; - /* RTX for condition code flag register and RETS register */ extern GTY(()) rtx bfin_cc_rtx; extern GTY(()) rtx bfin_rets_rtx; @@ -2714,7 +2710,7 @@ rtx bfin_gen_compare (rtx cmp, enum machine_mode mode ATTRIBUTE_UNUSED) { enum rtx_code code1, code2; - rtx op0 = bfin_compare_op0, op1 = bfin_compare_op1; + rtx op0 = XEXP (cmp, 0), op1 = XEXP (cmp, 1); rtx tem = bfin_cc_rtx; enum rtx_code code = GET_CODE (cmp); @@ -2742,7 +2738,7 @@ bfin_gen_compare (rtx cmp, enum machine_mode mode ATTRIBUTE_UNUSED) code2 = EQ; break; } - emit_insn (gen_rtx_SET (BImode, tem, + emit_insn (gen_rtx_SET (VOIDmode, tem, gen_rtx_fmt_ee (code1, BImode, op0, op1))); } @@ -4219,17 +4215,17 @@ bfin_optimize_loop (loop_info loop) { /* If loop->iter_reg is a DREG or PREG, we can split it here without scratch register. */ - rtx insn; + rtx insn, test; emit_insn_before (gen_addsi3 (loop->iter_reg, loop->iter_reg, constm1_rtx), loop->loop_end); - emit_insn_before (gen_cmpsi (loop->iter_reg, const0_rtx), - loop->loop_end); - - insn = emit_jump_insn_before (gen_bne (loop->start_label), + test = gen_rtx_NE (VOIDmode, loop->iter_reg, const0_rtx); + insn = emit_jump_insn_before (gen_cbranchsi4 (test, + loop->iter_reg, const0_rtx, + loop->start_label), loop->loop_end); JUMP_LABEL (insn) = loop->start_label; diff --git a/gcc/config/bfin/bfin.h b/gcc/config/bfin/bfin.h index d97fe8faaf4..352f4b4c208 100644 --- a/gcc/config/bfin/bfin.h +++ b/gcc/config/bfin/bfin.h @@ -1292,7 +1292,6 @@ do { \ #define ASM_OUTPUT_REG_PUSH(FILE, REGNO) fprintf (FILE, "[SP--] = %s;\n", reg_names[REGNO]) #define ASM_OUTPUT_REG_POP(FILE, REGNO) fprintf (FILE, "%s = [SP++];\n", reg_names[REGNO]) -extern struct rtx_def *bfin_compare_op0, *bfin_compare_op1; extern struct rtx_def *bfin_cc_rtx, *bfin_rets_rtx; /* This works for GAS and some other assemblers. */ diff --git a/gcc/config/bfin/bfin.md b/gcc/config/bfin/bfin.md index 4397b7a139a..755a0d3ced6 100644 --- a/gcc/config/bfin/bfin.md +++ b/gcc/config/bfin/bfin.md @@ -2255,29 +2255,6 @@ ;; Conditional branch patterns ;; The Blackfin has only few condition codes: eq, lt, lte, ltu, leu -;; The only outcome of this pattern is that global variables -;; bfin_compare_op[01] are set for use in bcond patterns. - -(define_expand "cmpbi" - [(set (cc0) (compare (match_operand:BI 0 "register_operand" "") - (match_operand:BI 1 "immediate_operand" "")))] - "" -{ - bfin_compare_op0 = operands[0]; - bfin_compare_op1 = operands[1]; - DONE; -}) - -(define_expand "cmpsi" - [(set (cc0) (compare (match_operand:SI 0 "register_operand" "") - (match_operand:SI 1 "reg_or_const_int_operand" "")))] - "" -{ - bfin_compare_op0 = operands[0]; - bfin_compare_op1 = operands[1]; - DONE; -}) - (define_insn "compare_eq" [(set (match_operand:BI 0 "register_operand" "=C,C") (eq:BI (match_operand:SI 1 "register_operand" "d,a") @@ -2326,106 +2303,6 @@ "cc =%1<%2 (iu);" [(set_attr "type" "compare")]) -(define_expand "beq" - [(set (match_dup 1) (match_dup 2)) - (set (pc) - (if_then_else (match_dup 3) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" -{ - rtx op0 = bfin_compare_op0, op1 = bfin_compare_op1; - operands[1] = bfin_cc_rtx; /* hard register: CC */ - operands[2] = gen_rtx_EQ (BImode, op0, op1); - /* If we have a BImode input, then we already have a compare result, and - do not need to emit another comparison. */ - if (GET_MODE (bfin_compare_op0) == BImode) - { - gcc_assert (bfin_compare_op1 == const0_rtx); - emit_insn (gen_cbranchbi4 (operands[2], op0, op1, operands[0])); - DONE; - } - - operands[3] = gen_rtx_NE (BImode, operands[1], const0_rtx); -}) - -(define_expand "bne" - [(set (match_dup 1) (match_dup 2)) - (set (pc) - (if_then_else (match_dup 3) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" -{ - rtx op0 = bfin_compare_op0, op1 = bfin_compare_op1; - /* If we have a BImode input, then we already have a compare result, and - do not need to emit another comparison. */ - if (GET_MODE (bfin_compare_op0) == BImode) - { - rtx cmp = gen_rtx_NE (BImode, op0, op1); - - gcc_assert (bfin_compare_op1 == const0_rtx); - emit_insn (gen_cbranchbi4 (cmp, op0, op1, operands[0])); - DONE; - } - - operands[1] = bfin_cc_rtx; /* hard register: CC */ - operands[2] = gen_rtx_EQ (BImode, op0, op1); - operands[3] = gen_rtx_EQ (BImode, operands[1], const0_rtx); -}) - -(define_expand "bgt" - [(set (match_dup 1) (match_dup 2)) - (set (pc) - (if_then_else (match_dup 3) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" -{ - operands[1] = bfin_cc_rtx; - operands[2] = gen_rtx_LE (BImode, bfin_compare_op0, bfin_compare_op1); - operands[3] = gen_rtx_EQ (BImode, operands[1], const0_rtx); -}) - -(define_expand "bgtu" - [(set (match_dup 1) (match_dup 2)) - (set (pc) - (if_then_else (match_dup 3) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" -{ - operands[1] = bfin_cc_rtx; - operands[2] = gen_rtx_LEU (BImode, bfin_compare_op0, bfin_compare_op1); - operands[3] = gen_rtx_EQ (BImode, operands[1], const0_rtx); -}) - -(define_expand "blt" - [(set (match_dup 1) (match_dup 2)) - (set (pc) - (if_then_else (match_dup 3) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" -{ - operands[1] = bfin_cc_rtx; - operands[2] = gen_rtx_LT (BImode, bfin_compare_op0, bfin_compare_op1); - operands[3] = gen_rtx_NE (BImode, operands[1], const0_rtx); -}) - -(define_expand "bltu" - [(set (match_dup 1) (match_dup 2)) - (set (pc) - (if_then_else (match_dup 3) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" -{ - operands[1] = bfin_cc_rtx; - operands[2] = gen_rtx_LTU (BImode, bfin_compare_op0, bfin_compare_op1); - operands[3] = gen_rtx_NE (BImode, operands[1], const0_rtx); -}) - ;; Same as above, but and CC with the overflow bit generated by the first ;; multiplication. (define_insn "flag_mul_macv2hi_parts_acconly_andcc0" @@ -2490,63 +2367,25 @@ (set_attr "length" "6") (set_attr "seq_insns" "multi")]) -(define_expand "bge" - [(set (match_dup 1) (match_dup 2)) - (set (pc) - (if_then_else (match_dup 3) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" -{ - operands[1] = bfin_cc_rtx; - operands[2] = gen_rtx_LT (BImode, bfin_compare_op0, bfin_compare_op1); - operands[3] = gen_rtx_EQ (BImode, operands[1], const0_rtx); -}) - -(define_expand "bgeu" - [(set (match_dup 1) (match_dup 2)) - (set (pc) - (if_then_else (match_dup 3) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" -{ - operands[1] = bfin_cc_rtx; - operands[2] = gen_rtx_LTU (BImode, bfin_compare_op0, bfin_compare_op1); - operands[3] = gen_rtx_EQ (BImode, operands[1], const0_rtx); -}) - -(define_expand "ble" - [(set (match_dup 1) (match_dup 2)) - (set (pc) - (if_then_else (match_dup 3) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" -{ - operands[1] = bfin_cc_rtx; - operands[2] = gen_rtx_LE (BImode, bfin_compare_op0, bfin_compare_op1); - operands[3] = gen_rtx_NE (BImode, operands[1], const0_rtx); -}) - -(define_expand "bleu" - [(set (match_dup 1) (match_dup 2)) - (set (pc) - (if_then_else (match_dup 3) - (label_ref (match_operand 0 "" "")) - (pc))) - ] +(define_expand "cbranchsi4" + [(set (pc) + (if_then_else (match_operator 0 "ordered_comparison_operator" + [(match_operand:SI 1 "register_operand" "") + (match_operand:SI 2 "reg_or_const_int_operand" "")]) + (label_ref (match_operand 3 "" "")) + (pc)))] "" { - operands[1] = bfin_cc_rtx; - operands[2] = gen_rtx_LEU (BImode, bfin_compare_op0, bfin_compare_op1); - operands[3] = gen_rtx_NE (BImode, operands[1], const0_rtx); + rtx bi_compare = bfin_gen_compare (operands[0], SImode); + emit_jump_insn (gen_cbranchbi4 (bi_compare, bfin_cc_rtx, CONST0_RTX (BImode), + operands[3])); + DONE; }) (define_insn "cbranchbi4" [(set (pc) (if_then_else - (match_operator 0 "bfin_cbranch_operator" + (match_operator 0 "bfin_bimode_comparison_operator" [(match_operand:BI 1 "register_operand" "C") (match_operand:BI 2 "immediate_operand" "P0")]) (label_ref (match_operand 3 "" "")) @@ -2564,7 +2403,7 @@ (define_insn "cbranch_predicted_taken" [(set (pc) (if_then_else - (match_operator 0 "bfin_cbranch_operator" + (match_operator 0 "bfin_bimode_comparison_operator" [(match_operand:BI 1 "register_operand" "C") (match_operand:BI 2 "immediate_operand" "P0")]) (label_ref (match_operand 3 "" "")) @@ -2580,7 +2419,7 @@ (define_insn "cbranch_with_nops" [(set (pc) (if_then_else - (match_operator 0 "bfin_cbranch_operator" + (match_operator 0 "bfin_bimode_comparison_operator" [(match_operand:BI 1 "register_operand" "C") (match_operand:BI 2 "immediate_operand" "P0")]) (label_ref (match_operand 3 "" "")) @@ -2594,60 +2433,49 @@ [(set_attr "type" "brcc") (set_attr "length" "8")]) -;; setcc insns. */ -(define_expand "seq" - [(set (match_dup 1) (eq:BI (match_dup 2) (match_dup 3))) - (set (match_operand:SI 0 "register_operand" "") - (ne:SI (match_dup 1) (const_int 0)))] - "" -{ - operands[2] = bfin_compare_op0; - operands[3] = bfin_compare_op1; - operands[1] = bfin_cc_rtx; -}) +;; setcc insns. -(define_expand "slt" - [(set (match_dup 1) (lt:BI (match_dup 2) (match_dup 3))) +(define_expand "cstorebi4" + [(set (match_dup 4) + (match_operator:BI 1 "bfin_bimode_comparison_operator" + [(match_operand:BI 2 "register_operand" "") + (match_operand:BI 3 "reg_or_const_int_operand" "")])) (set (match_operand:SI 0 "register_operand" "") - (ne:SI (match_dup 1) (const_int 0)))] + (ne:SI (match_dup 4) (const_int 0)))] "" { - operands[2] = bfin_compare_op0; - operands[3] = bfin_compare_op1; - operands[1] = bfin_cc_rtx; -}) + /* It could be expanded as a movbisi instruction, but the portable + alternative produces better code. */ + if (GET_CODE (operands[1]) == NE) + FAIL; -(define_expand "sle" - [(set (match_dup 1) (le:BI (match_dup 2) (match_dup 3))) - (set (match_operand:SI 0 "register_operand" "") - (ne:SI (match_dup 1) (const_int 0)))] - "" -{ - operands[2] = bfin_compare_op0; - operands[3] = bfin_compare_op1; - operands[1] = bfin_cc_rtx; + operands[4] = bfin_cc_rtx; }) -(define_expand "sltu" - [(set (match_dup 1) (ltu:BI (match_dup 2) (match_dup 3))) - (set (match_operand:SI 0 "register_operand" "") - (ne:SI (match_dup 1) (const_int 0)))] +(define_expand "cstoresi4" + [(set (match_operand:SI 0 "register_operand") + (match_operator:SI 1 "ordered_comparison_operator" + [(match_operand:SI 2 "register_operand" "") + (match_operand:SI 3 "reg_or_const_int_operand" "")]))] "" { - operands[2] = bfin_compare_op0; - operands[3] = bfin_compare_op1; - operands[1] = bfin_cc_rtx; -}) + rtx bi_compare, test; -(define_expand "sleu" - [(set (match_dup 1) (leu:BI (match_dup 2) (match_dup 3))) - (set (match_operand:SI 0 "register_operand" "") - (ne:SI (match_dup 1) (const_int 0)))] - "" -{ - operands[2] = bfin_compare_op0; - operands[3] = bfin_compare_op1; - operands[1] = bfin_cc_rtx; + if (!bfin_direct_comparison_operator (operands[1], SImode)) + { + if (!register_operand (operands[3], SImode) + || GET_CODE (operands[1]) == NE) + FAIL; + test = gen_rtx_fmt_ee (swap_condition (GET_CODE (operands[1])), + SImode, operands[3], operands[2]); + } + else + test = operands[1]; + + bi_compare = bfin_gen_compare (test, SImode); + gcc_assert (GET_CODE (bi_compare) == NE); + emit_insn (gen_movbisi (operands[0], bfin_cc_rtx)); + DONE; }) (define_insn "nop" @@ -2676,13 +2504,16 @@ "CC = %1;" [(set_attr "length" "2")]) -(define_insn "movbisi" +(define_insn_and_split "movbisi" [(set (match_operand:SI 0 "register_operand" "=d") (ne:SI (match_operand:BI 1 "register_operand" "C") (const_int 0)))] "" - "%0 = CC;" - [(set_attr "length" "2")]) + "#" + "" + [(set (match_operand:SI 0 "register_operand" "") + (zero_extend:SI (match_operand:BI 1 "register_operand" "")))] + "") (define_insn "notbi" [(set (match_operand:BI 0 "register_operand" "=C") diff --git a/gcc/config/bfin/predicates.md b/gcc/config/bfin/predicates.md index 7aac5b0534c..bce725a7009 100644 --- a/gcc/config/bfin/predicates.md +++ b/gcc/config/bfin/predicates.md @@ -172,10 +172,14 @@ && REGNO (op) <= LAST_VIRTUAL_REGISTER)); }) -;; Test for an operator valid in a conditional branch -(define_predicate "bfin_cbranch_operator" +;; Test for an operator valid in a BImode conditional branch +(define_predicate "bfin_bimode_comparison_operator" (match_code "eq,ne")) +;; Test for an operator whose result is accessible with movbisi. +(define_predicate "bfin_direct_comparison_operator" + (match_code "eq,lt,le,leu,ltu")) + ;; The following two are used to compute the addrtype attribute. They return ;; true if passed a memory address usable for a 16-bit load or store using a ;; P or I register, respectively. If neither matches, we know we have a diff --git a/gcc/config/cris/cris.c b/gcc/config/cris/cris.c index 2112670de6c..bc634ddbf3e 100644 --- a/gcc/config/cris/cris.c +++ b/gcc/config/cris/cris.c @@ -1431,13 +1431,18 @@ cris_normal_notice_update_cc (rtx exp, rtx insn) if (SET_DEST (exp) == cc0_rtx) { CC_STATUS_INIT; - cc_status.value1 = SET_SRC (exp); - /* Handle flags for the special btstq on one bit. */ - if (GET_CODE (SET_SRC (exp)) == ZERO_EXTRACT - && XEXP (SET_SRC (exp), 1) == const1_rtx) + if (GET_CODE (SET_SRC (exp)) == COMPARE + && XEXP (SET_SRC (exp), 1) == const0_rtx) + cc_status.value1 = XEXP (SET_SRC (exp), 0); + else + cc_status.value1 = SET_SRC (exp); + + /* Handle flags for the special btstq on one bit. */ + if (GET_CODE (cc_status.value1) == ZERO_EXTRACT + && XEXP (cc_status.value1, 1) == const1_rtx) { - if (CONST_INT_P (XEXP (SET_SRC (exp), 0))) + if (CONST_INT_P (XEXP (cc_status.value1, 0))) /* Using cmpq. */ cc_status.flags = CC_INVERTED; else @@ -1445,7 +1450,7 @@ cris_normal_notice_update_cc (rtx exp, rtx insn) cc_status.flags = CC_Z_IN_NOT_N; } - if (GET_CODE (SET_SRC (exp)) == COMPARE) + else if (GET_CODE (SET_SRC (exp)) == COMPARE) { if (!REG_P (XEXP (SET_SRC (exp), 0)) && XEXP (SET_SRC (exp), 1) != const0_rtx) @@ -1855,6 +1860,11 @@ cris_rtx_costs (rtx x, int code, int outer_code, int *total, } return false; + case ZERO_EXTRACT: + if (outer_code != COMPARE) + return false; + /* fall through */ + case ZERO_EXTEND: case SIGN_EXTEND: *total = rtx_cost (XEXP (x, 0), outer_code, speed); return true; diff --git a/gcc/config/cris/cris.md b/gcc/config/cris/cris.md index f4b2128ea19..79eb8da3b0d 100644 --- a/gcc/config/cris/cris.md +++ b/gcc/config/cris/cris.md @@ -248,40 +248,16 @@ ;; Test insns. -;; DImode -;; -;; Allow register and offsettable mem operands only; post-increment is -;; not worth the trouble. - -(define_expand "tstdi" - [(set (cc0) (match_operand:DI 0 "nonimmediate_operand"))] - "" -{ - if (TARGET_V32 && MEM_P (operands[0])) - operands[0] = force_reg (DImode, operands[0]); -}) - -(define_insn "*tstdi_non_v32" - [(set (cc0) - (match_operand:DI 0 "nonimmediate_operand" "r,o"))] - "!TARGET_V32" - "test.d %M0\;ax\;test.d %H0") - -(define_insn "*tstdi_v32" - [(set (cc0) - (match_operand:DI 0 "register_operand" "r"))] - "TARGET_V32" - "cmpq 0,%M0\;ax\;cmpq 0,%H0") - ;; No test insns with side-effect on the mem addressing. ;; ;; See note on cmp-insns with side-effects (or lack of them) ;; Normal named test patterns from SI on. -(define_insn "tstsi" +(define_insn "*tstsi" [(set (cc0) - (match_operand:SI 0 "nonimmediate_operand" "r,Q>,m"))] + (compare (match_operand:SI 0 "nonimmediate_operand" "r,Q>,m") + (const_int 0)))] "" { if (which_alternative == 0 && TARGET_V32) @@ -290,15 +266,10 @@ } [(set_attr "slottable" "yes,yes,no")]) -(define_expand "tst<mode>" - [(set (cc0) - (match_operand:BW 0 "nonimmediate_operand"))] - "" - "") - (define_insn "*tst<mode>_cmp" [(set (cc0) - (match_operand:BW 0 "nonimmediate_operand" "r,Q>,m"))] + (compare (match_operand:BW 0 "nonimmediate_operand" "r,Q>,m") + (const_int 0)))] "cris_cc0_user_requires_cmp (insn)" "@ cmp<m> 0,%0 @@ -308,7 +279,8 @@ (define_insn "*tst<mode>_non_cmp" [(set (cc0) - (match_operand:BW 0 "nonimmediate_operand" "r,Q>,m"))] + (compare (match_operand:BW 0 "nonimmediate_operand" "r,Q>,m") + (const_int 0)))] "!cris_cc0_user_requires_cmp (insn)" "@ move<m> %0,%0 @@ -332,24 +304,13 @@ ;; DImode for anything else but a structure/block-mode. Just do the ;; obvious stuff for the straight-forward constraint letters. -(define_expand "cmpdi" - [(set (cc0) - (compare (match_operand:DI 0 "nonimmediate_operand" "") - (match_operand:DI 1 "general_operand" "")))] - "" -{ - if (TARGET_V32 && !REG_P (operands[0])) - operands[0] = force_reg (DImode, operands[0]); - if (TARGET_V32 && MEM_P (operands[1])) - operands[1] = force_reg (DImode, operands[1]); -}) - (define_insn "*cmpdi_non_v32" [(set (cc0) - (compare (match_operand:DI 0 "nonimmediate_operand" "r,r,r,r,r,r,o") - (match_operand:DI 1 "general_operand" "Kc,I,P,n,r,o,r")))] + (compare (match_operand:DI 0 "nonimmediate_operand" "rm,r,r,r,r,r,r,o") + (match_operand:DI 1 "general_operand" "M,Kc,I,P,n,r,o,r")))] "!TARGET_V32" "@ + test.d %M0\;ax\;test.d %H0 cmpq %1,%M0\;ax\;cmpq 0,%H0 cmpq %1,%M0\;ax\;cmpq -1,%H0 cmp%e1.%z1 %1,%M0\;ax\;cmpq %H1,%H0 @@ -415,9 +376,9 @@ (set_attr "cc" "rev")]) ;; The "normal" compare patterns, from SI on. Special-cases with zero -;; should not happen. +;; are covered above. -(define_insn "cmpsi" +(define_insn "*cmpsi" [(set (cc0) (compare (match_operand:SI 0 "nonimmediate_operand" "r,r,r, Q>,r,r,m") @@ -434,7 +395,7 @@ [(set_attr "slottable" "yes,yes,yes,yes,no,no,no") (set_attr "cc" "normal,normal,normal,rev,normal,normal,rev")]) -(define_insn "cmp<mode>" +(define_insn "*cmp<mode>" [(set (cc0) (compare (match_operand:BW 0 "nonimmediate_operand" "r,r, Q>,r,m") (match_operand:BW 1 "general_operand" "r,Q>,r, g,r")))] @@ -457,10 +418,12 @@ ;; extends subregs for lower-size modes. FIXME: Add testcase. (define_insn "*btst" [(set (cc0) - (zero_extract - (match_operand:SI 0 "nonmemory_operand" "r, r,r, r,r, r,Kp") - (match_operand:SI 1 "const_int_operand" "Kc,n,Kc,n,Kc,n,n") - (match_operand:SI 2 "nonmemory_operand" "M, M,Kc,n,r, r,r")))] + (compare + (zero_extract:SI + (match_operand:SI 0 "nonmemory_operand" "r, r,r, r,r, r,Kp") + (match_operand:SI 1 "const_int_operand" "Kc,n,Kc,n,Kc,n,n") + (match_operand:SI 2 "nonmemory_operand" "M, M,Kc,n,r, r,r")) + (const_int 0)))] ;; Either it is a single bit, or consecutive ones starting at 0. ;; The btst ones depend on stuff in NOTICE_UPDATE_CC. "CONST_INT_P (operands[1]) @@ -3550,6 +3513,36 @@ ;; Conditional branches. +(define_expand "cbranch<mode>4" + [(set (cc0) (compare + (match_operand:BWD 1 "nonimmediate_operand") + (match_operand:BWD 2 "general_operand"))) + (set (pc) + (if_then_else (match_operator 0 "ordered_comparison_operator" + [(cc0) (const_int 0)]) + (label_ref (match_operand 3 "" "")) + (pc)))] + "" + "") + +(define_expand "cbranchdi4" + [(set (cc0) + (compare (match_operand:DI 1 "nonimmediate_operand" "") + (match_operand:DI 2 "general_operand" ""))) + (set (pc) + (if_then_else (match_operator 0 "ordered_comparison_operator" + [(cc0) (const_int 0)]) + (label_ref (match_operand 3 "" "")) + (pc)))] + "" +{ + if (TARGET_V32 && !REG_P (operands[1])) + operands[1] = force_reg (DImode, operands[1]); + if (TARGET_V32 && MEM_P (operands[2])) + operands[2] = force_reg (DImode, operands[2]); +}) + + ;; We suffer from the same overflow-bit-gets-in-the-way problem as ;; e.g. m68k, so we have to check if overflow bit is set on all "signed" ;; conditions. @@ -3634,6 +3627,31 @@ ;; Set on condition: sCC. +(define_expand "cstoredi4" + [(set (cc0) (compare + (match_operand:DI 2 "nonimmediate_operand") + (match_operand:DI 3 "general_operand"))) + (set (match_operand:SI 0 "register_operand") + (match_operator:SI 1 "ordered_comparison_operator" + [(cc0) (const_int 0)]))] + "" +{ + if (TARGET_V32 && !REG_P (operands[2])) + operands[2] = force_reg (DImode, operands[2]); + if (TARGET_V32 && MEM_P (operands[3])) + operands[3] = force_reg (DImode, operands[3]); +}) + +(define_expand "cstore<mode>4" + [(set (cc0) (compare + (match_operand:BWD 2 "nonimmediate_operand") + (match_operand:BWD 3 "general_operand"))) + (set (match_operand:SI 0 "register_operand") + (match_operator:SI 1 "ordered_comparison_operator" + [(cc0) (const_int 0)]))] + "" + "") + ;; Like bCC, we have to check the overflow bit for ;; signed conditions. diff --git a/gcc/config/crx/crx-protos.h b/gcc/config/crx/crx-protos.h index 0be641dd89e..386fab9fe43 100644 --- a/gcc/config/crx/crx-protos.h +++ b/gcc/config/crx/crx-protos.h @@ -62,10 +62,6 @@ extern void crx_print_operand (FILE *, rtx, int); extern void crx_print_operand_address (FILE *, rtx); /* Misc functions called from crx.md. */ -extern rtx crx_expand_compare (enum rtx_code, enum machine_mode); -extern void crx_expand_branch (enum rtx_code, rtx); -extern void crx_expand_scond (enum rtx_code, rtx); - extern void crx_expand_movmem_single (rtx, rtx, rtx, rtx, rtx, unsigned HOST_WIDE_INT *); extern int crx_expand_movmem (rtx, rtx, rtx, rtx); #endif /* RTX_CODE */ diff --git a/gcc/config/crx/crx.c b/gcc/config/crx/crx.c index 6f10afd2e5f..cc3248fb5ee 100644 --- a/gcc/config/crx/crx.c +++ b/gcc/config/crx/crx.c @@ -124,10 +124,6 @@ static enum machine_mode output_memory_reference_mode; /* Table of machine attributes. */ const struct attribute_spec crx_attribute_table[]; -/* Test and compare insns use these globals to generate branch insns. */ -rtx crx_compare_op0 = NULL_RTX; -rtx crx_compare_op1 = NULL_RTX; - /*****************************************************************************/ /* TARGETM FUNCTION PROTOTYPES */ /*****************************************************************************/ @@ -1217,43 +1213,6 @@ crx_expand_movmem (rtx dstbase, rtx srcbase, rtx count_exp, rtx align_exp) return 1; } -rtx -crx_expand_compare (enum rtx_code code, enum machine_mode mode) -{ - rtx op0, op1, cc_reg, ret; - - op0 = crx_compare_op0; - op1 = crx_compare_op1; - - /* Emit the compare that writes into CC_REGNUM) */ - cc_reg = gen_rtx_REG (CCmode, CC_REGNUM); - ret = gen_rtx_COMPARE (CCmode, op0, op1); - emit_insn (gen_rtx_SET (VOIDmode, cc_reg, ret)); - /* debug_rtx (get_last_insn ()); */ - - /* Return the rtx for using the result in CC_REGNUM */ - return gen_rtx_fmt_ee (code, mode, cc_reg, const0_rtx); -} - -void -crx_expand_branch (enum rtx_code code, rtx label) -{ - rtx tmp = crx_expand_compare (code, VOIDmode); - tmp = gen_rtx_IF_THEN_ELSE (VOIDmode, tmp, - gen_rtx_LABEL_REF (VOIDmode, label), - pc_rtx); - emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx, tmp)); - /* debug_rtx (get_last_insn ()); */ -} - -void -crx_expand_scond (enum rtx_code code, rtx dest) -{ - rtx tmp = crx_expand_compare (code, GET_MODE (dest)); - emit_move_insn (dest, tmp); - /* debug_rtx (get_last_insn ()); */ -} - static void mpushpop_str (char *stringbuffer, const char *mnemonic, char *mask) { diff --git a/gcc/config/crx/crx.h b/gcc/config/crx/crx.h index 69065f3795b..cac465701bf 100644 --- a/gcc/config/crx/crx.h +++ b/gcc/config/crx/crx.h @@ -520,11 +520,4 @@ struct cumulative_args #define FUNCTION_MODE QImode -/*****************************************************************************/ -/* EXTERNAL DECLARATIONS FOR VARIABLES DEFINED IN CRX.C */ -/*****************************************************************************/ - -extern rtx crx_compare_op0; /* operand 0 for comparisons */ -extern rtx crx_compare_op1; /* operand 1 for comparisons */ - #endif /* ! GCC_CRX_H */ diff --git a/gcc/config/crx/crx.md b/gcc/config/crx/crx.md index b9655544ffc..229e345d32f 100644 --- a/gcc/config/crx/crx.md +++ b/gcc/config/crx/crx.md @@ -63,6 +63,10 @@ (ior (match_code "symbol_ref") (match_operand 0 "register_operand"))) +(define_predicate "cc_reg_operand" + (and (match_code "reg") + (match_test "REGNO (op) == CC_REGNUM"))) + (define_predicate "nosp_reg_operand" (and (match_operand 0 "register_operand") (match_test "REGNO (op) != SP_REGNUM"))) @@ -107,8 +111,6 @@ (define_code_iterator mima_oprnd [smax umax smin umin]) (define_code_attr mimaIsa [(smax "maxs") (umax "maxu") (smin "mins") (umin "minu")]) -(define_code_iterator any_cond [eq ne gt gtu lt ltu ge geu le leu]) - ;; Addition Instructions (define_insn "adddi3" @@ -522,9 +524,21 @@ ;; Compare and Branch Instructions +(define_insn "cbranchcc4" + [(set (pc) + (if_then_else (match_operator 0 "ordered_comparison_operator" + [(match_operand:CC 1 "cc_reg_operand" "r") + (match_operand 2 "cst4_operand" "L")]) + (label_ref (match_operand 3 "")) + (pc)))] + "" + "b%d0\t%l3" + [(set_attr "length" "6")] +) + (define_insn "cbranch<mode>4" [(set (pc) - (if_then_else (match_operator 0 "comparison_operator" + (if_then_else (match_operator 0 "ordered_comparison_operator" [(match_operand:CRXIM 1 "register_operand" "r") (match_operand:CRXIM 2 "reg_or_cst4_operand" "rL")]) (label_ref (match_operand 3 "" "")) @@ -535,18 +549,18 @@ [(set_attr "length" "6")] ) -;; Compare Instructions -(define_expand "cmp<mode>" +;; Scond Instructions + +(define_expand "cstore<mode>4" [(set (reg:CC CC_REGNUM) - (compare:CC (match_operand:CRXIM 0 "register_operand" "") - (match_operand:CRXIM 1 "nonmemory_operand" "")))] + (compare:CC (match_operand:CRXIM 2 "register_operand" "") + (match_operand:CRXIM 3 "nonmemory_operand" ""))) + (set (match_operand:SI 0 "register_operand") + (match_operator:SI 1 "ordered_comparison_operator" + [(reg:CC CC_REGNUM) (const_int 0)]))] + "" "" - { - crx_compare_op0 = operands[0]; - crx_compare_op1 = operands[1]; - DONE; - } ) (define_insn "cmp<mode>_internal" @@ -558,48 +572,9 @@ [(set_attr "length" "2,<lImmArith>")] ) -;; Conditional Branch Instructions - -(define_expand "b<code>" - [(set (pc) - (if_then_else (any_cond (reg:CC CC_REGNUM) - (const_int 0)) - (label_ref (match_operand 0 "")) - (pc)))] - "" - { - crx_expand_branch (<CODE>, operands[0]); - DONE; - } -) - -(define_insn "bCOND_internal" - [(set (pc) - (if_then_else (match_operator 0 "comparison_operator" - [(reg:CC CC_REGNUM) - (const_int 0)]) - (label_ref (match_operand 1 "")) - (pc)))] - "" - "b%d0\t%l1" - [(set_attr "length" "6")] -) - -;; Scond Instructions - -(define_expand "s<code>" - [(set (match_operand:SI 0 "register_operand") - (any_cond:SI (reg:CC CC_REGNUM) (const_int 0)))] - "" - { - crx_expand_scond (<CODE>, operands[0]); - DONE; - } -) - (define_insn "sCOND_internal" [(set (match_operand:SI 0 "register_operand" "=r") - (match_operator:SI 1 "comparison_operator" + (match_operator:SI 1 "ordered_comparison_operator" [(reg:CC CC_REGNUM) (const_int 0)]))] "" "s%d1\t%0" diff --git a/gcc/config/fr30/fr30.c b/gcc/config/fr30/fr30.c index e7f2e3cfd86..5642c548a29 100644 --- a/gcc/config/fr30/fr30.c +++ b/gcc/config/fr30/fr30.c @@ -48,12 +48,6 @@ /*}}}*/ /*{{{ Function Prologues & Epilogues */ -/* Define the information needed to generate branch and scc insns. This is - stored from the compare operation. */ - -struct rtx_def * fr30_compare_op0; -struct rtx_def * fr30_compare_op1; - /* The FR30 stack looks like this: Before call After call diff --git a/gcc/config/fr30/fr30.h b/gcc/config/fr30/fr30.h index c1e8e0a9723..b958a678db4 100644 --- a/gcc/config/fr30/fr30.h +++ b/gcc/config/fr30/fr30.h @@ -1106,16 +1106,6 @@ fprintf (STREAM, "\t.word .L%d\n", VALUE) #endif /*}}}*/ -/*{{{ Exported variables */ - -/* Define the information needed to generate branch and scc insns. This is - stored from the compare operation. Note that we can't use "rtx" here - since it hasn't been defined! */ - -extern struct rtx_def * fr30_compare_op0; -extern struct rtx_def * fr30_compare_op1; - -/*}}}*/ /* Local Variables: */ /* folded-file: t */ diff --git a/gcc/config/fr30/fr30.md b/gcc/config/fr30/fr30.md index a198ea3544d..fa115c4cfa1 100644 --- a/gcc/config/fr30/fr30.md +++ b/gcc/config/fr30/fr30.md @@ -916,23 +916,7 @@ ;;}}} ;;{{{ Comparisons -;; Note, we store the operands in the comparison insns, and use them later -;; when generating the branch or scc operation. - -;; First the routines called by the machine independent part of the compiler -(define_expand "cmpsi" - [(set (reg:CC 16) - (compare:CC (match_operand:SI 0 "register_operand" "") - (match_operand:SI 1 "nonmemory_operand" "")))] - "" - "{ - fr30_compare_op0 = operands[0]; - fr30_compare_op1 = operands[1]; - DONE; - }" -) - -;; Now, the actual comparisons, generated by the branch and/or scc operations +;; The actual comparisons, generated by the cbranch and/or cstore expanders (define_insn "*cmpsi_internal" [(set (reg:CC 16) @@ -951,165 +935,19 @@ ;; Define_expands called by the machine independent part of the compiler ;; to allocate a new comparison register -(define_expand "beq" - [(set (reg:CC 16) - (compare:CC (match_dup 1) - (match_dup 2))) - (set (pc) - (if_then_else (eq:CC (reg:CC 16) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "{ - operands[1] = fr30_compare_op0; - operands[2] = fr30_compare_op1; - }" -) - -(define_expand "bne" - [(set (reg:CC 16) - (compare:CC (match_dup 1) - (match_dup 2))) - (set (pc) - (if_then_else (ne:CC (reg:CC 16) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "{ - operands[1] = fr30_compare_op0; - operands[2] = fr30_compare_op1; - }" -) - -(define_expand "blt" - [(set (reg:CC 16) - (compare:CC (match_dup 1) - (match_dup 2))) - (set (pc) - (if_then_else (lt:CC (reg:CC 16) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "{ - operands[1] = fr30_compare_op0; - operands[2] = fr30_compare_op1; - }" -) - -(define_expand "ble" - [(set (reg:CC 16) - (compare:CC (match_dup 1) - (match_dup 2))) - (set (pc) - (if_then_else (le:CC (reg:CC 16) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "{ - operands[1] = fr30_compare_op0; - operands[2] = fr30_compare_op1; - }" -) - -(define_expand "bgt" +(define_expand "cbranchsi4" [(set (reg:CC 16) - (compare:CC (match_dup 1) - (match_dup 2))) + (compare:CC (match_operand:SI 1 "register_operand" "") + (match_operand:SI 2 "nonmemory_operand" ""))) (set (pc) - (if_then_else (gt:CC (reg:CC 16) - (const_int 0)) - (label_ref (match_operand 0 "" "")) + (if_then_else (match_operator:CC 0 "ordered_comparison_operator" + [(reg:CC 16) (const_int 0)]) + (label_ref (match_operand 3 "" "")) (pc)))] "" - "{ - operands[1] = fr30_compare_op0; - operands[2] = fr30_compare_op1; - }" -) - -(define_expand "bge" - [(set (reg:CC 16) - (compare:CC (match_dup 1) - (match_dup 2))) - (set (pc) - (if_then_else (ge:CC (reg:CC 16) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "{ - operands[1] = fr30_compare_op0; - operands[2] = fr30_compare_op1; - }" -) - -(define_expand "bltu" - [(set (reg:CC 16) - (compare:CC (match_dup 1) - (match_dup 2))) - (set (pc) - (if_then_else (ltu:CC (reg:CC 16) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "{ - operands[1] = fr30_compare_op0; - operands[2] = fr30_compare_op1; - }" -) - -(define_expand "bleu" - [(set (reg:CC 16) - (compare:CC (match_dup 1) - (match_dup 2))) - (set (pc) - (if_then_else (leu:CC (reg:CC 16) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "{ - operands[1] = fr30_compare_op0; - operands[2] = fr30_compare_op1; - }" -) - -(define_expand "bgtu" - [(set (reg:CC 16) - (compare:CC (match_dup 1) - (match_dup 2))) - (set (pc) - (if_then_else (gtu:CC (reg:CC 16) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] "" - "{ - operands[1] = fr30_compare_op0; - operands[2] = fr30_compare_op1; - }" ) -(define_expand "bgeu" - [(set (reg:CC 16) - (compare:CC (match_dup 1) - (match_dup 2))) - (set (pc) - (if_then_else (geu:CC (reg:CC 16) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "{ - operands[1] = fr30_compare_op0; - operands[2] = fr30_compare_op1; - }" -) ;; Actual branches. We must allow for the (label_ref) and the (pc) to be ;; swapped. If they are swapped, it reverses the sense of the branch. diff --git a/gcc/config/frv/frv-protos.h b/gcc/config/frv/frv-protos.h index c34d02cf96f..98ada2286a5 100644 --- a/gcc/config/frv/frv-protos.h +++ b/gcc/config/frv/frv-protos.h @@ -81,8 +81,8 @@ extern const char *output_move_single (rtx *, rtx); extern const char *output_move_double (rtx *, rtx); extern const char *output_condmove_single (rtx *, rtx); -extern int frv_emit_cond_branch (enum rtx_code, rtx); -extern int frv_emit_scc (enum rtx_code, rtx); +extern int frv_emit_cond_branch (rtx *); +extern int frv_emit_scc (rtx *); extern rtx frv_split_scc (rtx, rtx, rtx, rtx, HOST_WIDE_INT); extern int frv_emit_cond_move (rtx, rtx, rtx, rtx); extern rtx frv_split_cond_move (rtx *); diff --git a/gcc/config/frv/frv.c b/gcc/config/frv/frv.c index 4e8c1b24cf8..e5476523f13 100644 --- a/gcc/config/frv/frv.c +++ b/gcc/config/frv/frv.c @@ -193,11 +193,6 @@ typedef struct int base_offset; } frv_frame_accessor_t; -/* Define the information needed to generate branch and scc insns. This is - stored from the compare operation. */ -rtx frv_compare_op0; -rtx frv_compare_op1; - /* Conditional execution support gathered together in one structure. */ typedef struct { @@ -4768,19 +4763,18 @@ frv_emit_comparison (enum rtx_code test, rtx op0, rtx op1) } -/* Emit code for a conditional branch. The comparison operands were previously - stored in frv_compare_op0 and frv_compare_op1. - +/* Emit code for a conditional branch. XXX: I originally wanted to add a clobber of a CCR register to use in conditional execution, but that confuses the rest of the compiler. */ int -frv_emit_cond_branch (enum rtx_code test, rtx label) +frv_emit_cond_branch (rtx operands[]) { rtx test_rtx; rtx label_ref; rtx if_else; - rtx cc_reg = frv_emit_comparison (test, frv_compare_op0, frv_compare_op1); + enum rtx_code test = GET_CODE (operands[0]); + rtx cc_reg = frv_emit_comparison (test, operands[1], operands[2]); enum machine_mode cc_mode = GET_MODE (cc_reg); /* Branches generate: @@ -4788,7 +4782,7 @@ frv_emit_cond_branch (enum rtx_code test, rtx label) (if_then_else (<test>, <cc_reg>, (const_int 0)) (label_ref <branch_label>) (pc))) */ - label_ref = gen_rtx_LABEL_REF (VOIDmode, label); + label_ref = gen_rtx_LABEL_REF (VOIDmode, operands[3]); test_rtx = gen_rtx_fmt_ee (test, cc_mode, cc_reg, const0_rtx); if_else = gen_rtx_IF_THEN_ELSE (cc_mode, test_rtx, label_ref, pc_rtx); emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx, if_else)); @@ -4796,23 +4790,23 @@ frv_emit_cond_branch (enum rtx_code test, rtx label) } -/* Emit code to set a gpr to 1/0 based on a comparison. The comparison - operands were previously stored in frv_compare_op0 and frv_compare_op1. */ +/* Emit code to set a gpr to 1/0 based on a comparison. */ int -frv_emit_scc (enum rtx_code test, rtx target) +frv_emit_scc (rtx operands[]) { rtx set; rtx test_rtx; rtx clobber; rtx cr_reg; - rtx cc_reg = frv_emit_comparison (test, frv_compare_op0, frv_compare_op1); + enum rtx_code test = GET_CODE (operands[1]); + rtx cc_reg = frv_emit_comparison (test, operands[2], operands[3]); /* SCC instructions generate: (parallel [(set <target> (<test>, <cc_reg>, (const_int 0)) (clobber (<ccr_reg>))]) */ test_rtx = gen_rtx_fmt_ee (test, SImode, cc_reg, const0_rtx); - set = gen_rtx_SET (VOIDmode, target, test_rtx); + set = gen_rtx_SET (VOIDmode, operands[0], test_rtx); cr_reg = ((TARGET_ALLOC_CC) ? gen_reg_rtx (CC_CCRmode) @@ -4874,7 +4868,8 @@ frv_emit_cond_move (rtx dest, rtx test_rtx, rtx src1, rtx src2) rtx cr_reg; rtx if_rtx; enum rtx_code test = GET_CODE (test_rtx); - rtx cc_reg = frv_emit_comparison (test, frv_compare_op0, frv_compare_op1); + rtx cc_reg = frv_emit_comparison (test, + XEXP (test_rtx, 0), XEXP (test_rtx, 1)); enum machine_mode cc_mode = GET_MODE (cc_reg); /* Conditional move instructions generate: diff --git a/gcc/config/frv/frv.h b/gcc/config/frv/frv.h index b6fdca4aa0a..e510de08901 100644 --- a/gcc/config/frv/frv.h +++ b/gcc/config/frv/frv.h @@ -2913,9 +2913,6 @@ enum frv_builtins /* Enable prototypes on the call rtl functions. */ #define MD_CALL_PROTOTYPES 1 -extern GTY(()) rtx frv_compare_op0; /* operand save for */ -extern GTY(()) rtx frv_compare_op1; /* comparison generation */ - #define CPU_UNITS_QUERY 1 #ifdef __FRV_FDPIC__ diff --git a/gcc/config/frv/frv.md b/gcc/config/frv/frv.md index aadf02c4fbd..9315f9b623c 100644 --- a/gcc/config/frv/frv.md +++ b/gcc/config/frv/frv.md @@ -3734,59 +3734,7 @@ ;; :: ;; :::::::::::::::::::: -;; Note, we store the operands in the comparison insns, and use them later -;; when generating the branch or scc operation. - -;; First the routines called by the machine independent part of the compiler -(define_expand "cmpsi" - [(set (cc0) - (compare (match_operand:SI 0 "integer_register_operand" "") - (match_operand:SI 1 "gpr_or_int10_operand" "")))] - "" - " -{ - frv_compare_op0 = operands[0]; - frv_compare_op1 = operands[1]; - DONE; -}") - -;(define_expand "cmpdi" -; [(set (cc0) -; (compare (match_operand:DI 0 "register_operand" "") -; (match_operand:DI 1 "nonmemory_operand" "")))] -; "" -; " -;{ -; frv_compare_op0 = operands[0]; -; frv_compare_op1 = operands[1]; -; DONE; -;}") - -(define_expand "cmpsf" - [(set (cc0) - (compare (match_operand:SF 0 "fpr_operand" "") - (match_operand:SF 1 "fpr_operand" "")))] - "TARGET_HARD_FLOAT" - " -{ - frv_compare_op0 = operands[0]; - frv_compare_op1 = operands[1]; - DONE; -}") - -(define_expand "cmpdf" - [(set (cc0) - (compare (match_operand:DF 0 "fpr_operand" "") - (match_operand:DF 1 "fpr_operand" "")))] - "TARGET_HARD_FLOAT && TARGET_DOUBLE" - " -{ - frv_compare_op0 = operands[0]; - frv_compare_op1 = operands[1]; - DONE; -}") - -;; Now, the actual comparisons, generated by the branch and/or scc operations +;; The comparisons are generated by the branch and/or scc operations (define_insn "cmpsi_cc" [(set (match_operand:CC 0 "icc_operand" "=t,t") @@ -3847,137 +3795,31 @@ ;; :::::::::::::::::::: ;; Define_expands called by the machine independent part of the compiler -;; to allocate a new comparison register. Each of these named patterns -;; must be present, and they cannot be amalgamated into one pattern. -;; -;; If a fixed condition code register is being used, (as opposed to, say, -;; using cc0), then the expands should look like this: -;; -;; (define_expand "<name_of_test>" -;; [(set (reg:CC <number_of_CC_register>) -;; (compare:CC (match_dup 1) -;; (match_dup 2))) -;; (set (pc) -;; (if_then_else (eq:CC (reg:CC <number_of_CC_register>) -;; (const_int 0)) -;; (label_ref (match_operand 0 "" "")) -;; (pc)))] -;; "" -;; "{ -;; operands[1] = frv_compare_op0; -;; operands[2] = frv_compare_op1; -;; }" -;; ) - -(define_expand "beq" - [(use (match_operand 0 "" ""))] - "" - " -{ - if (! frv_emit_cond_branch (EQ, operands[0])) - FAIL; - - DONE; -}") - -(define_expand "bne" - [(use (match_operand 0 "" ""))] - "" - " -{ - if (! frv_emit_cond_branch (NE, operands[0])) - FAIL; - - DONE; -}") - -(define_expand "blt" - [(use (match_operand 0 "" ""))] - "" - " -{ - if (! frv_emit_cond_branch (LT, operands[0])) - FAIL; - - DONE; -}") - -(define_expand "ble" - [(use (match_operand 0 "" ""))] - "" - " -{ - if (! frv_emit_cond_branch (LE, operands[0])) - FAIL; - - DONE; -}") - -(define_expand "bgt" - [(use (match_operand 0 "" ""))] - "" - " -{ - if (! frv_emit_cond_branch (GT, operands[0])) - FAIL; - - DONE; -}") - -(define_expand "bge" - [(use (match_operand 0 "" ""))] - "" - " -{ - if (! frv_emit_cond_branch (GE, operands[0])) - FAIL; - - DONE; -}") - -(define_expand "bltu" - [(use (match_operand 0 "" ""))] - "" - " -{ - if (! frv_emit_cond_branch (LTU, operands[0])) - FAIL; - - DONE; -}") - -(define_expand "bleu" - [(use (match_operand 0 "" ""))] - "" - " -{ - if (! frv_emit_cond_branch (LEU, operands[0])) - FAIL; - - DONE; -}") +;; to allocate a new comparison register. -(define_expand "bgtu" - [(use (match_operand 0 "" ""))] - "" - " -{ - if (! frv_emit_cond_branch (GTU, operands[0])) - FAIL; +(define_expand "cbranchdf4" + [(use (match_operator 0 "ordered_comparison_operator" + [(match_operand:DF 1 "fpr_operand" "") + (match_operand:DF 2 "fpr_operand" "")])) + (use (match_operand 3 ""))] + "TARGET_HARD_FLOAT && TARGET_DOUBLE" + { if (frv_emit_cond_branch (operands)) DONE; gcc_unreachable (); }) - DONE; -}") +(define_expand "cbranchsf4" + [(use (match_operator 0 "ordered_comparison_operator" + [(match_operand:SF 1 "fpr_operand" "") + (match_operand:SF 2 "fpr_operand" "")])) + (use (match_operand 3 ""))] + "TARGET_HARD_FLOAT" + { if (frv_emit_cond_branch (operands)) DONE; gcc_unreachable (); }) -(define_expand "bgeu" - [(use (match_operand 0 "" ""))] +(define_expand "cbranchsi4" + [(use (match_operator 0 "ordered_comparison_operator" + [(match_operand:SI 1 "integer_register_operand" "") + (match_operand:SI 2 "gpr_or_int10_operand" "")])) + (use (match_operand 3 ""))] "" - " -{ - if (! frv_emit_cond_branch (GEU, operands[0])) - FAIL; - - DONE; -}") + { if (frv_emit_cond_branch (operands)) DONE; gcc_unreachable (); }) ;; Actual branches. We must allow for the (label_ref) and the (pc) to be ;; swapped. If they are swapped, it reverses the sense of the branch. @@ -4142,115 +3984,29 @@ ;; Define_expands called by the machine independent part of the compiler ;; to allocate a new comparison register -(define_expand "seq" - [(match_operand:SI 0 "integer_register_operand" "")] - "TARGET_SCC" - " -{ - if (! frv_emit_scc (EQ, operands[0])) - FAIL; - - DONE; -}") - -(define_expand "sne" - [(match_operand:SI 0 "integer_register_operand" "")] - "TARGET_SCC" - " -{ - if (! frv_emit_scc (NE, operands[0])) - FAIL; - - DONE; -}") - -(define_expand "slt" - [(match_operand:SI 0 "integer_register_operand" "")] - "TARGET_SCC" - " -{ - if (! frv_emit_scc (LT, operands[0])) - FAIL; - - DONE; -}") - -(define_expand "sle" - [(match_operand:SI 0 "integer_register_operand" "")] - "TARGET_SCC" - " -{ - if (! frv_emit_scc (LE, operands[0])) - FAIL; - - DONE; -}") - -(define_expand "sgt" - [(match_operand:SI 0 "integer_register_operand" "")] - "TARGET_SCC" - " -{ - if (! frv_emit_scc (GT, operands[0])) - FAIL; - - DONE; -}") - -(define_expand "sge" - [(match_operand:SI 0 "integer_register_operand" "")] - "TARGET_SCC" - " -{ - if (! frv_emit_scc (GE, operands[0])) - FAIL; - - DONE; -}") - -(define_expand "sltu" - [(match_operand:SI 0 "integer_register_operand" "")] - "TARGET_SCC" - " -{ - if (! frv_emit_scc (LTU, operands[0])) - FAIL; - - DONE; -}") - -(define_expand "sleu" - [(match_operand:SI 0 "integer_register_operand" "")] - "TARGET_SCC" - " -{ - if (! frv_emit_scc (LEU, operands[0])) - FAIL; - - DONE; -}") - -(define_expand "sgtu" - [(match_operand:SI 0 "integer_register_operand" "")] - "TARGET_SCC" - " -{ - if (! frv_emit_scc (GTU, operands[0])) - FAIL; - - DONE; -}") +(define_expand "cstoredf4" + [(use (match_operator:SI 1 "ordered_comparison_operator" + [(match_operand:DF 2 "fpr_operand") + (match_operand:DF 3 "fpr_operand")])) + (clobber (match_operand:SI 0 "register_operand"))] + "TARGET_HARD_FLOAT && TARGET_DOUBLE" + { if (frv_emit_scc (operands)) DONE; else FAIL; }) -(define_expand "sgeu" - [(match_operand:SI 0 "integer_register_operand" "")] - "TARGET_SCC" - " -{ - if (! frv_emit_scc (GEU, operands[0])) - FAIL; +(define_expand "cstoresf4" + [(use (match_operator:SI 1 "ordered_comparison_operator" + [(match_operand:SF 2 "fpr_operand") + (match_operand:SF 3 "fpr_operand")])) + (clobber (match_operand:SI 0 "register_operand"))] + "TARGET_HARD_FLOAT" + { if (frv_emit_scc (operands)) DONE; else FAIL; }) - DONE; -}") +(define_expand "cstoresi4" + [(use (match_operator:SI 1 "ordered_comparison_operator" + [(match_operand:SI 2 "integer_register_operand") + (match_operand:SI 3 "gpr_or_int10_operand")])) + (clobber (match_operand:SI 0 "register_operand"))] + "" + { if (frv_emit_scc (operands)) DONE; else FAIL; }) (define_insn "*scc_int" [(set (match_operand:SI 0 "integer_register_operand" "=d") diff --git a/gcc/config/h8300/h8300-protos.h b/gcc/config/h8300/h8300-protos.h index 2e7b72fe6c4..4a0b64790a7 100644 --- a/gcc/config/h8300/h8300-protos.h +++ b/gcc/config/h8300/h8300-protos.h @@ -44,7 +44,8 @@ extern const char *output_logical_op (enum machine_mode, rtx *); extern unsigned int compute_logical_op_length (enum machine_mode, rtx *); extern int compute_logical_op_cc (enum machine_mode, rtx *); -extern void h8300_expand_branch (enum rtx_code, rtx); +extern void h8300_expand_branch (rtx[]); +extern void h8300_expand_store (rtx[]); extern bool expand_a_shift (enum machine_mode, int, rtx[]); extern int h8300_shift_needs_scratch_p (int, enum machine_mode); extern int expand_a_rotate (rtx[]); diff --git a/gcc/config/h8300/h8300.c b/gcc/config/h8300/h8300.c index 34d1f82687c..9946d28078f 100644 --- a/gcc/config/h8300/h8300.c +++ b/gcc/config/h8300/h8300.c @@ -1226,6 +1226,11 @@ h8300_rtx_costs (rtx x, int code, int outer_code, int *total, bool speed) *total = 20; return true; + case COMPARE: + if (XEXP (x, 1) == const0_rtx) + *total = 0; + return false; + case AND: if (!h8300_dst_operand (XEXP (x, 0), VOIDmode) || !h8300_src_operand (XEXP (x, 1), VOIDmode)) @@ -3503,16 +3508,42 @@ compute_logical_op_cc (enum machine_mode mode, rtx *operands) /* Expand a conditional branch. */ void -h8300_expand_branch (enum rtx_code code, rtx label) +h8300_expand_branch (rtx operands[]) { + enum rtx_code code = GET_CODE (operands[0]); + rtx op0 = operands[1]; + rtx op1 = operands[2]; + rtx label = operands[3]; rtx tmp; + tmp = gen_rtx_COMPARE (VOIDmode, op0, op1); + emit_insn (gen_rtx_SET (VOIDmode, cc0_rtx, tmp)); + tmp = gen_rtx_fmt_ee (code, VOIDmode, cc0_rtx, const0_rtx); tmp = gen_rtx_IF_THEN_ELSE (VOIDmode, tmp, gen_rtx_LABEL_REF (VOIDmode, label), pc_rtx); emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx, tmp)); } + + +/* Expand a conditional store. */ + +void +h8300_expand_store (rtx operands[]) +{ + rtx dest = operands[0]; + enum rtx_code code = GET_CODE (operands[1]); + rtx op0 = operands[2]; + rtx op1 = operands[3]; + rtx tmp; + + tmp = gen_rtx_COMPARE (VOIDmode, op0, op1); + emit_insn (gen_rtx_SET (VOIDmode, cc0_rtx, tmp)); + + tmp = gen_rtx_fmt_ee (code, GET_MODE (dest), cc0_rtx, const0_rtx); + emit_insn (gen_rtx_SET (VOIDmode, dest, tmp)); +} /* Shifts. diff --git a/gcc/config/h8300/h8300.md b/gcc/config/h8300/h8300.md index 61f876c8399..c05e8c6966f 100644 --- a/gcc/config/h8300/h8300.md +++ b/gcc/config/h8300/h8300.md @@ -961,28 +961,33 @@ ;; ---------------------------------------------------------------------- (define_insn "" - [(set (cc0) (zero_extract:HI (match_operand:QI 0 "bit_memory_operand" "r,U") - (const_int 1) - (match_operand 1 "const_int_operand" "n,n")))] + [(set (cc0) (compare + (zero_extract:QI (match_operand:QI 0 "bit_memory_operand" "r,U") + (const_int 1) + (match_operand 1 "const_int_operand" "n,n")) + (const_int 0)))] "TARGET_H8300" "btst %Z1,%Y0" [(set_attr "length" "2,4") (set_attr "cc" "set_zn,set_zn")]) (define_insn "" - [(set (cc0) (zero_extract:HI (match_operand:HI 0 "register_operand" "r") - (const_int 1) - (match_operand 1 "const_int_operand" "n")))] + [(set (cc0) (compare + (zero_extract:HI (match_operand:HI 0 "register_operand" "r") + (const_int 1) + (match_operand 1 "const_int_operand" "n")) + (const_int 0)))] "TARGET_H8300" "btst %Z1,%Y0" [(set_attr "length" "2") (set_attr "cc" "set_zn")]) (define_insn_and_split "*tst_extzv_1_n" - [(set (cc0) - (zero_extract:SI (match_operand:QI 0 "general_operand_src" "r,U,mn>") - (const_int 1) - (match_operand 1 "const_int_operand" "n,n,n"))) + [(set (cc0) (compare + (zero_extract:SI (match_operand:QI 0 "general_operand_src" "r,U,mn>") + (const_int 1) + (match_operand 1 "const_int_operand" "n,n,n")) + (const_int 0))) (clobber (match_scratch:QI 2 "=X,X,&r"))] "(TARGET_H8300H || TARGET_H8300S)" "@ @@ -993,18 +998,20 @@ && !OK_FOR_U (operands[0])" [(set (match_dup 2) (match_dup 0)) - (parallel [(set (cc0) (zero_extract:SI (match_dup 2) - (const_int 1) - (match_dup 1))) + (parallel [(set (cc0) (compare (zero_extract:SI (match_dup 2) + (const_int 1) + (match_dup 1)) + (const_int 0))) (clobber (scratch:QI))])] "" [(set_attr "length" "2,8,10") (set_attr "cc" "set_zn,set_zn,set_zn")]) (define_insn "" - [(set (cc0) (zero_extract:SI (match_operand:SI 0 "register_operand" "r") - (const_int 1) - (match_operand 1 "const_int_operand" "n")))] + [(set (cc0) (compare (zero_extract:SI (match_operand:SI 0 "register_operand" "r") + (const_int 1) + (match_operand 1 "const_int_operand" "n")) + (const_int 0)))] "(TARGET_H8300H || TARGET_H8300S) && INTVAL (operands[1]) <= 15" "btst %Z1,%Y0" @@ -1012,10 +1019,10 @@ (set_attr "cc" "set_zn")]) (define_insn_and_split "*tstsi_upper_bit" - [(set (cc0) - (zero_extract:SI (match_operand:SI 0 "register_operand" "r") - (const_int 1) - (match_operand 1 "const_int_operand" "n"))) + [(set (cc0) (compare (zero_extract:SI (match_operand:SI 0 "register_operand" "r") + (const_int 1) + (match_operand 1 "const_int_operand" "n")) + (const_int 0))) (clobber (match_scratch:SI 2 "=&r"))] "(TARGET_H8300H || TARGET_H8300S) && INTVAL (operands[1]) >= 16" @@ -1026,18 +1033,18 @@ (const_int -65536)) (lshiftrt:SI (match_dup 0) (const_int 16)))) - (set (cc0) - (zero_extract:SI (match_dup 2) - (const_int 1) - (match_dup 3)))] + (set (cc0) (compare (zero_extract:SI (match_dup 2) + (const_int 1) + (match_dup 3)) + (const_int 0)))] "operands[3] = GEN_INT (INTVAL (operands[1]) - 16);") (define_insn "*tstsi_variable_bit" - [(set (cc0) - (zero_extract:SI (match_operand:SI 0 "register_operand" "r") - (const_int 1) - (and:SI (match_operand:SI 1 "register_operand" "r") - (const_int 7))))] + [(set (cc0) (compare (zero_extract:SI (match_operand:SI 0 "register_operand" "r") + (const_int 1) + (and:SI (match_operand:SI 1 "register_operand" "r") + (const_int 7))) + (const_int 0)))] "TARGET_H8300H || TARGET_H8300S" "btst %w1,%w0" [(set_attr "length" "2") @@ -1045,10 +1052,12 @@ (define_insn_and_split "*tstsi_variable_bit_qi" [(set (cc0) - (zero_extract:SI (zero_extend:SI (match_operand:QI 0 "general_operand_src" "r,U,mn>")) - (const_int 1) - (and:SI (match_operand:SI 1 "register_operand" "r,r,r") - (const_int 7)))) + (compare + (zero_extract:SI (zero_extend:SI (match_operand:QI 0 "general_operand_src" "r,U,mn>")) + (const_int 1) + (and:SI (match_operand:SI 1 "register_operand" "r,r,r") + (const_int 7))) + (const_int 0))) (clobber (match_scratch:QI 2 "=X,X,&r"))] "(TARGET_H8300H || TARGET_H8300S)" "@ @@ -1059,55 +1068,59 @@ && !OK_FOR_U (operands[0])" [(set (match_dup 2) (match_dup 0)) - (parallel [(set (cc0) (zero_extract:SI (zero_extend:SI (match_dup 2)) - (const_int 1) - (and:SI (match_dup 1) - (const_int 7)))) + (parallel [(set (cc0) (compare (zero_extract:SI (zero_extend:SI (match_dup 2)) + (const_int 1) + (and:SI (match_dup 1) + (const_int 7))) + (const_int 0))) (clobber (scratch:QI))])] "" [(set_attr "length" "2,8,10") (set_attr "cc" "set_zn,set_zn,set_zn")]) -(define_insn "tstqi" - [(set (cc0) (match_operand:QI 0 "register_operand" "r"))] +(define_insn "*tstqi" + [(set (cc0) (compare (match_operand:QI 0 "register_operand" "r") + (const_int 0)))] "" "mov.b %X0,%X0" [(set_attr "length" "2") (set_attr "cc" "set_znv")]) -(define_insn "tsthi" - [(set (cc0) (match_operand:HI 0 "register_operand" "r"))] +(define_insn "*tsthi" + [(set (cc0) (compare (match_operand:HI 0 "register_operand" "r") + (const_int 0)))] "" "mov.w %T0,%T0" [(set_attr "length" "2") (set_attr "cc" "set_znv")]) (define_insn "*tsthi_upper" - [(set (cc0) - (and:HI (match_operand:HI 0 "register_operand" "r") - (const_int -256)))] + [(set (cc0) (compare (and:HI (match_operand:HI 0 "register_operand" "r") + (const_int -256)) + (const_int 0)))] "" "mov.b %t0,%t0" [(set_attr "length" "2") (set_attr "cc" "set_znv")]) -(define_insn "tstsi" - [(set (cc0) (match_operand:SI 0 "register_operand" "r"))] +(define_insn "*tstsi" + [(set (cc0) (compare (match_operand:SI 0 "register_operand" "r") + (const_int 0)))] "TARGET_H8300H || TARGET_H8300S" "mov.l %S0,%S0" [(set_attr "length" "2") (set_attr "cc" "set_znv")]) (define_insn "*tstsi_upper" - [(set (cc0) - (and:SI (match_operand:SI 0 "register_operand" "r") - (const_int -65536)))] + [(set (cc0) (compare (and:SI (match_operand:SI 0 "register_operand" "r") + (const_int -65536)) + (const_int 0)))] "" "mov.w %e0,%e0" [(set_attr "length" "2") (set_attr "cc" "set_znv")]) -(define_insn "cmpqi" +(define_insn "*cmpqi" [(set (cc0) (compare (match_operand:QI 0 "h8300_dst_operand" "rQ") (match_operand:QI 1 "h8300_src_operand" "rQi")))] @@ -1116,19 +1129,6 @@ [(set_attr "length_table" "addb") (set_attr "cc" "compare")]) -(define_expand "cmphi" - [(set (cc0) - (compare (match_operand:HI 0 "h8300_dst_operand" "") - (match_operand:HI 1 "h8300_src_operand" "")))] - "" - " -{ - /* Force operand1 into a register if we're compiling - for the H8/300. */ - if (GET_CODE (operands[1]) != REG && TARGET_H8300) - operands[1] = force_reg (HImode, operands[1]); -}") - (define_insn "*cmphi_h8300_znvc" [(set (cc0) (compare (match_operand:HI 0 "register_operand" "r") @@ -2155,55 +2155,37 @@ ;; Conditional jump instructions -(define_expand "ble" - [(match_operand 0 "" "")] - "" - "h8300_expand_branch (LE, operands[0]); DONE;") - -(define_expand "bleu" - [(match_operand 0 "" "")] +(define_expand "cbranchqi4" + [(use (match_operator 0 "ordered_comparison_operator" + [(match_operand:QI 1 "h8300_dst_operand" "") + (match_operand:QI 2 "h8300_src_operand" "")])) + (use (match_operand 3 ""))] "" - "h8300_expand_branch (LEU, operands[0]); DONE;") + "h8300_expand_branch (operands); DONE;") -(define_expand "bge" - [(match_operand 0 "" "")] +(define_expand "cbranchhi4" + [(use (match_operator 0 "ordered_comparison_operator" + [(match_operand:HI 1 "h8300_dst_operand" "") + (match_operand:HI 2 "h8300_src_operand" "")])) + (use (match_operand 3 ""))] "" - "h8300_expand_branch (GE, operands[0]); DONE;") - -(define_expand "bgeu" - [(match_operand 0 "" "")] - "" - "h8300_expand_branch (GEU, operands[0]); DONE;") - -(define_expand "blt" - [(match_operand 0 "" "")] - "" - "h8300_expand_branch (LT, operands[0]); DONE;") - -(define_expand "bltu" - [(match_operand 0 "" "")] - "" - "h8300_expand_branch (LTU, operands[0]); DONE;") - -(define_expand "bgt" - [(match_operand 0 "" "")] - "" - "h8300_expand_branch (GT, operands[0]); DONE;") - -(define_expand "bgtu" - [(match_operand 0 "" "")] - "" - "h8300_expand_branch (GTU, operands[0]); DONE;") - -(define_expand "beq" - [(match_operand 0 "" "")] - "" - "h8300_expand_branch (EQ, operands[0]); DONE;") + " +{ + /* Force operand1 into a register if we're compiling + for the H8/300. */ + if ((GET_CODE (operands[2]) != REG && operands[2] != const0_rtx) + && TARGET_H8300) + operands[2] = force_reg (HImode, operands[2]); + h8300_expand_branch (operands); DONE; +}") -(define_expand "bne" - [(match_operand 0 "" "")] - "" - "h8300_expand_branch (NE, operands[0]); DONE;") +(define_expand "cbranchsi4" + [(use (match_operator 0 "ordered_comparison_operator" + [(match_operand:SI 1 "h8300_dst_operand" "") + (match_operand:SI 2 "h8300_src_operand" "")])) + (use (match_operand 3 ""))] + "TARGET_H8300H || TARGET_H8300S" + "h8300_expand_branch (operands); DONE;") (define_insn "branch_true" [(set (pc) @@ -3019,8 +3001,8 @@ (clobber (match_operand:QI 3 "register_operand" ""))] "epilogue_completed && find_regno_note (insn, REG_DEAD, REGNO (operands[1]))" - [(set (cc0) - (match_dup 1)) + [(set (cc0) (compare (match_dup 1) + (const_int 0))) (set (pc) (if_then_else (le (cc0) (const_int 0)) (label_ref (match_dup 5)) @@ -3032,8 +3014,8 @@ (clobber (scratch:QI))]) (set (match_dup 1) (plus:QI (match_dup 1) (const_int -1))) - (set (cc0) - (match_dup 1)) + (set (cc0) (compare (match_dup 1) + (const_int 0))) (set (pc) (if_then_else (ne (cc0) (const_int 0)) (label_ref (match_dup 4)) @@ -3052,8 +3034,8 @@ && !find_regno_note (insn, REG_DEAD, REGNO (operands[1]))" [(set (match_dup 3) (match_dup 1)) - (set (cc0) - (match_dup 3)) + (set (cc0) (compare (match_dup 3) + (const_int 0))) (set (pc) (if_then_else (le (cc0) (const_int 0)) (label_ref (match_dup 5)) @@ -3065,8 +3047,8 @@ (clobber (scratch:QI))]) (set (match_dup 3) (plus:QI (match_dup 3) (const_int -1))) - (set (cc0) - (match_dup 3)) + (set (cc0) (compare (match_dup 3) + (const_int 0))) (set (pc) (if_then_else (ne (cc0) (const_int 0)) (label_ref (match_dup 4)) @@ -3413,17 +3395,29 @@ [(set_attr "cc" "none_0hit") (set_attr "length_table" "bitfield")]) -(define_expand "seq" - [(set (match_operand:HI 0 "register_operand" "") - (eq:HI (cc0) (const_int 0)))] +(define_expand "cstoreqi4" + [(use (match_operator 1 "eqne_operator" + [(match_operand:QI 2 "h8300_dst_operand" "") + (match_operand:QI 3 "h8300_src_operand" "")])) + (clobber (match_operand:HI 0 "register_operand"))] "TARGET_H8300SX" - "") + "h8300_expand_store (operands); DONE;") -(define_expand "sne" - [(set (match_operand:HI 0 "register_operand" "") - (ne:HI (cc0) (const_int 0)))] +(define_expand "cstorehi4" + [(use (match_operator 1 "eqne_operator" + [(match_operand:HI 2 "h8300_dst_operand" "") + (match_operand:HI 3 "h8300_src_operand" "")])) + (clobber (match_operand:HI 0 "register_operand"))] "TARGET_H8300SX" - "") + "h8300_expand_store (operands); DONE;") + +(define_expand "cstoresi4" + [(use (match_operator 1 "eqne_operator" + [(match_operand:SI 2 "h8300_dst_operand" "") + (match_operand:SI 3 "h8300_src_operand" "")])) + (clobber (match_operand:HI 0 "register_operand"))] + "TARGET_H8300SX" + "h8300_expand_store (operands); DONE;") (define_insn "*bstzhireg" [(set (match_operand:HI 0 "register_operand" "=r") @@ -3451,13 +3445,7 @@ [(set (cc0) (match_dup 5)) (set (zero_extract:QI (match_dup 0) (const_int 1) (match_dup 1)) (match_op_dup:QI 2 [(cc0) (const_int 0)]))] - " -{ - if (operands[4] == const0_rtx && GET_CODE (operands[3]) == REG) - operands[5] = operands[3]; - else - operands[5] = gen_rtx_COMPARE (VOIDmode, operands[3], operands[4]); -}" + "operands[5] = gen_rtx_COMPARE (VOIDmode, operands[3], operands[4]);" [(set_attr "cc" "set_znv,compare")]) (define_insn "*bstz" @@ -3499,13 +3487,7 @@ (if_then_else:QI (match_op_dup 1 [(cc0) (const_int 0)]) (ior:QI (match_dup 4) (match_dup 5)) (match_dup 4)))] - " -{ - if (operands[3] == const0_rtx && GET_CODE (operands[2]) == REG) - operands[6] = operands[2]; - else - operands[6] = gen_rtx_COMPARE (VOIDmode, operands[2], operands[3]); -}" + "operands[6] = gen_rtx_COMPARE (VOIDmode, operands[2], operands[3]);" [(set_attr "cc" "set_znv,compare")]) (define_insn "*condbset" @@ -3541,13 +3523,7 @@ (if_then_else:QI (match_op_dup 1 [(cc0) (const_int 0)]) (and:QI (match_dup 4) (match_dup 5)) (match_dup 4)))] - " -{ - if (operands[3] == const0_rtx && GET_CODE (operands[2]) == REG) - operands[6] = operands[2]; - else - operands[6] = gen_rtx_COMPARE (VOIDmode, operands[2], operands[3]); -}" + "operands[6] = gen_rtx_COMPARE (VOIDmode, operands[2], operands[3]);" [(set_attr "cc" "set_znv,compare")]) (define_insn "*condbclr" @@ -3587,13 +3563,7 @@ (ashift:QI (const_int 1) (match_operand:QI 5 "register_operand" "r,r"))) (match_dup 4)))] - " -{ - if (operands[3] == const0_rtx && GET_CODE (operands[2]) == REG) - operands[6] = operands[2]; - else - operands[6] = gen_rtx_COMPARE (VOIDmode, operands[2], operands[3]); -}" + "operands[6] = gen_rtx_COMPARE (VOIDmode, operands[2], operands[3]);" [(set_attr "cc" "set_znv,compare")]) (define_insn "*condbsetreg" @@ -3634,13 +3604,7 @@ (ashift:QI (const_int 1) (match_operand:QI 5 "register_operand" "r,r"))) (match_dup 4)))] - " -{ - if (operands[3] == const0_rtx && GET_CODE (operands[2]) == REG) - operands[6] = operands[2]; - else - operands[6] = gen_rtx_COMPARE (VOIDmode, operands[2], operands[3]); -}" + "operands[6] = gen_rtx_COMPARE (VOIDmode, operands[2], operands[3]);" [(set_attr "cc" "set_znv,compare")]) (define_insn "*condbclrreg" @@ -3878,10 +3842,10 @@ "(TARGET_H8300H || TARGET_H8300S)" "#" "&& reload_completed" - [(set (cc0) - (zero_extract:SI (match_dup 1) - (const_int 1) - (const_int 0))) + [(set (cc0) (compare (zero_extract:SI (match_dup 1) + (const_int 1) + (const_int 0)) + (const_int 0))) (set (pc) (if_then_else (eq (cc0) (const_int 0)) @@ -3901,10 +3865,10 @@ "(TARGET_H8300H || TARGET_H8300S)" "#" "&& reload_completed" - [(set (cc0) - (zero_extract:SI (match_dup 1) - (const_int 1) - (const_int 0))) + [(set (cc0) (compare (zero_extract:SI (match_dup 1) + (const_int 1) + (const_int 0)) + (const_int 0))) (set (pc) (if_then_else (ne (cc0) (const_int 0)) @@ -4398,8 +4362,8 @@ "" "#" "" - [(set (cc0) - (match_dup 0)) + [(set (cc0) (compare (match_dup 0) + (const_int 0))) (set (pc) (if_then_else (ge (cc0) (const_int 0)) @@ -4418,8 +4382,8 @@ "" "#" "" - [(set (cc0) - (match_dup 0)) + [(set (cc0) (compare (match_dup 0) + (const_int 0))) (set (pc) (if_then_else (lt (cc0) (const_int 0)) @@ -4852,8 +4816,8 @@ [(set (match_operand:HI 0 "register_operand" "") (plus:HI (match_dup 0) (match_operand 1 "incdec_operand" ""))) - (set (cc0) - (match_dup 0)) + (set (cc0) (compare (match_dup 0) + (const_int 0))) (set (pc) (if_then_else (match_operator 3 "eqne_operator" [(cc0) (const_int 0)]) @@ -4864,8 +4828,8 @@ (unspec:HI [(match_dup 0) (match_dup 1)] UNSPEC_INCDEC)) - (set (cc0) - (match_dup 0)) + (set (cc0) (compare (match_dup 0) + (const_int 0))) (set (pc) (if_then_else (match_op_dup 3 [(cc0) (const_int 0)]) (label_ref (match_dup 2)) @@ -4878,8 +4842,8 @@ [(set (match_operand:SI 0 "register_operand" "") (plus:SI (match_dup 0) (match_operand 1 "incdec_operand" ""))) - (set (cc0) - (match_dup 0)) + (set (cc0) (compare (match_dup 0) + (const_int 0))) (set (pc) (if_then_else (match_operator 3 "eqne_operator" [(cc0) (const_int 0)]) @@ -4890,8 +4854,8 @@ (unspec:SI [(match_dup 0) (match_dup 1)] UNSPEC_INCDEC)) - (set (cc0) - (match_dup 0)) + (set (cc0) (compare (match_dup 0) + (const_int 0))) (set (pc) (if_then_else (match_op_dup 3 [(cc0) (const_int 0)]) (label_ref (match_dup 2)) @@ -4900,9 +4864,10 @@ (define_peephole2 [(parallel [(set (cc0) - (zero_extract:SI (match_operand:QI 0 "register_operand" "") - (const_int 1) - (const_int 7))) + (compare (zero_extract:SI (match_operand:QI 0 "register_operand" "") + (const_int 1) + (const_int 7)) + (const_int 0))) (clobber (scratch:QI))]) (set (pc) (if_then_else (match_operator 1 "eqne_operator" @@ -4910,8 +4875,8 @@ (label_ref (match_operand 2 "" "")) (pc)))] "(TARGET_H8300H || TARGET_H8300S)" - [(set (cc0) - (match_dup 0)) + [(set (cc0) (compare (match_dup 0) + (const_int 0))) (set (pc) (if_then_else (match_op_dup 3 [(cc0) (const_int 0)]) (label_ref (match_dup 2)) @@ -5032,6 +4997,45 @@ "operands[3] = gen_lowpart (HImode, operands[0]); operands[4] = gen_lowpart (HImode, operands[1]);") +;; Convert a memory comparison to a move if there is a scratch register. + +(define_peephole2 + [(match_scratch:QI 1 "r") + (set (cc0) + (compare (match_operand:QI 0 "memory_operand" "") + (const_int 0)))] + "" + [(set (match_dup 1) + (match_dup 0)) + (set (cc0) (compare (match_dup 1) + (const_int 0)))] + "") + +(define_peephole2 + [(match_scratch:HI 1 "r") + (set (cc0) + (compare (match_operand:HI 0 "memory_operand" "") + (const_int 0)))] + "(TARGET_H8300H || TARGET_H8300S)" + [(set (match_dup 1) + (match_dup 0)) + (set (cc0) (compare (match_dup 1) + (const_int 0)))] + "") + +(define_peephole2 + [(match_scratch:SI 1 "r") + (set (cc0) + (compare (match_operand:SI 0 "memory_operand" "") + (const_int 0)))] + "(TARGET_H8300H || TARGET_H8300S)" + [(set (match_dup 1) + (match_dup 0)) + (set (cc0) (compare (match_dup 1) + (const_int 0)))] + "") + + ;; (compare (reg:HI) (const_int)) takes 4 bytes, so we try to achieve ;; the equivalent with shorter sequences. Here is the summary. Cases ;; are grouped for each define_peephole2. @@ -5073,13 +5077,14 @@ (label_ref (match_operand 2 "" "")) (pc)))] "(TARGET_H8300H || TARGET_H8300S) + && INTVAL (operands[1]) != 0 && peep2_reg_dead_p (1, operands[0])" [(set (match_dup 0) (unspec:HI [(match_dup 0) (match_dup 4)] UNSPEC_INCDEC)) - (set (cc0) - (match_dup 0)) + (set (cc0) (compare (match_dup 0) + (const_int 0))) (set (pc) (if_then_else (match_op_dup 3 [(cc0) (const_int 0)]) (label_ref (match_dup 2)) @@ -5113,8 +5118,8 @@ (ashiftrt:HI (match_dup 0) (match_dup 4))) (clobber (scratch:QI))]) - (set (cc0) - (match_dup 0)) + (set (cc0) (compare (match_dup 0) + (const_int 0))) (set (pc) (if_then_else (match_dup 2) (label_ref (match_dup 3)) @@ -5148,8 +5153,8 @@ (ashiftrt:HI (match_dup 0) (match_dup 4))) (clobber (scratch:QI))]) - (set (cc0) - (match_dup 0)) + (set (cc0) (compare (match_dup 0) + (const_int 0))) (set (pc) (if_then_else (match_dup 5) (label_ref (match_dup 3)) @@ -5182,9 +5187,9 @@ (label_ref (match_operand 2 "" "")) (pc)))] "TARGET_H8300H || TARGET_H8300S" - [(set (cc0) - (and:HI (match_dup 0) - (const_int -256))) + [(set (cc0) (compare (and:HI (match_dup 0) + (const_int -256)) + (const_int 0))) (set (pc) (if_then_else (match_dup 1) (label_ref (match_dup 2)) @@ -5211,9 +5216,9 @@ (label_ref (match_operand 2 "" "")) (pc)))] "TARGET_H8300H || TARGET_H8300S" - [(set (cc0) - (and:HI (match_dup 0) - (const_int -256))) + [(set (cc0) (compare (and:HI (match_dup 0) + (const_int -256)) + (const_int 0))) (set (pc) (if_then_else (match_dup 3) (label_ref (match_dup 2)) @@ -5307,13 +5312,14 @@ (label_ref (match_operand 2 "" "")) (pc)))] "(TARGET_H8300H || TARGET_H8300S) + && INTVAL (operands[1]) != 0 && peep2_reg_dead_p (1, operands[0])" [(set (match_dup 0) (unspec:SI [(match_dup 0) (match_dup 4)] UNSPEC_INCDEC)) - (set (cc0) - (match_dup 0)) + (set (cc0) (compare (match_dup 0) + (const_int 0))) (set (pc) (if_then_else (match_op_dup 3 [(cc0) (const_int 0)]) (label_ref (match_dup 2)) @@ -5348,8 +5354,8 @@ [(set (match_dup 0) (plus:SI (match_dup 0) (match_dup 4))) - (set (cc0) - (match_dup 0)) + (set (cc0) (compare (match_dup 0) + (const_int 0))) (set (pc) (if_then_else (match_op_dup 3 [(cc0) (const_int 0)]) (label_ref (match_dup 2)) @@ -5381,13 +5387,14 @@ && ((INTVAL (operands[1]) & 0x00ff) == INTVAL (operands[1]) || (INTVAL (operands[1]) & 0xff00) == INTVAL (operands[1]) || INTVAL (operands[1]) == 0x0000ffff) + && INTVAL (operands[1]) != 0 && INTVAL (operands[1]) != 1 && INTVAL (operands[1]) != 2" [(set (match_dup 0) (xor:SI (match_dup 0) (match_dup 1))) - (set (cc0) - (match_dup 0)) + (set (cc0) (compare (match_dup 0) + (const_int 0))) (set (pc) (if_then_else (match_op_dup 3 [(cc0) (const_int 0)]) (label_ref (match_dup 2)) @@ -5425,8 +5432,8 @@ (match_dup 4))) (set (match_dup 0) (not:SI (match_dup 0))) - (set (cc0) - (match_dup 0)) + (set (cc0) (compare (match_dup 0) + (const_int 0))) (set (pc) (if_then_else (match_op_dup 3 [(cc0) (const_int 0)]) (label_ref (match_dup 2)) @@ -5464,8 +5471,8 @@ (unspec:SI [(match_dup 0) (const_int -1)] UNSPEC_INCDEC)) - (set (cc0) - (match_dup 0)) + (set (cc0) (compare (match_dup 0) + (const_int 0))) (set (pc) (if_then_else (match_op_dup 3 [(cc0) (const_int 0)]) (label_ref (match_dup 2)) @@ -5507,8 +5514,8 @@ (ashiftrt:SI (match_dup 4) (match_dup 5))) (clobber (scratch:QI))]) - (set (cc0) - (match_dup 4)) + (set (cc0) (compare (match_dup 4) + (const_int 0))) (set (pc) (if_then_else (match_dup 2) (label_ref (match_dup 3)) @@ -5550,8 +5557,8 @@ (ashiftrt:SI (match_dup 4) (match_dup 5))) (clobber (scratch:QI))]) - (set (cc0) - (match_dup 4)) + (set (cc0) (compare (match_dup 4) + (const_int 0))) (set (pc) (if_then_else (match_dup 6) (label_ref (match_dup 3)) @@ -5591,8 +5598,8 @@ (ashiftrt:SI (match_dup 0) (match_dup 4))) (clobber (scratch:QI))]) - (set (cc0) - (match_dup 0)) + (set (cc0) (compare (match_dup 0) + (const_int 0))) (set (pc) (if_then_else (match_dup 2) (label_ref (match_dup 3)) @@ -5626,8 +5633,8 @@ (ashiftrt:SI (match_dup 0) (match_dup 4))) (clobber (scratch:QI))]) - (set (cc0) - (match_dup 0)) + (set (cc0) (compare (match_dup 0) + (const_int 0))) (set (pc) (if_then_else (match_dup 5) (label_ref (match_dup 3)) @@ -5672,8 +5679,8 @@ [(set (match_dup 0) (and:SI (match_dup 0) (match_dup 4))) - (set (cc0) - (match_dup 0)) + (set (cc0) (compare (match_dup 0) + (const_int 0))) (set (pc) (if_then_else (match_dup 2) (label_ref (match_dup 3)) @@ -5712,8 +5719,8 @@ [(set (match_dup 0) (and:SI (match_dup 0) (match_dup 4))) - (set (cc0) - (match_dup 0)) + (set (cc0) (compare (match_dup 0) + (const_int 0))) (set (pc) (if_then_else (match_dup 5) (label_ref (match_dup 3)) @@ -5746,9 +5753,9 @@ (label_ref (match_operand 2 "" "")) (pc)))] "TARGET_H8300H || TARGET_H8300S" - [(set (cc0) - (and:SI (match_dup 0) - (const_int -65536))) + [(set (cc0) (compare (and:SI (match_dup 0) + (const_int -65536)) + (const_int 0))) (set (pc) (if_then_else (match_dup 1) (label_ref (match_dup 2)) @@ -5775,9 +5782,9 @@ (label_ref (match_operand 2 "" "")) (pc)))] "TARGET_H8300H || TARGET_H8300S" - [(set (cc0) - (and:SI (match_dup 0) - (const_int -65536))) + [(set (cc0) (compare (and:SI (match_dup 0) + (const_int -65536)) + (const_int 0))) (set (pc) (if_then_else (match_dup 3) (label_ref (match_dup 2)) @@ -5814,6 +5821,7 @@ (label_ref (match_operand 2 "" "")) (pc)))] "(TARGET_H8300H || TARGET_H8300S) + && INTVAL (operands[1]) != 0 && !peep2_reg_dead_p (1, operands[0]) && !same_cmp_following_p (insn)" [(set (match_dup 4) @@ -5822,8 +5830,8 @@ (unspec:SI [(match_dup 4) (match_dup 5)] UNSPEC_INCDEC)) - (set (cc0) - (match_dup 4)) + (set (cc0) (compare (match_dup 4) + (const_int 0))) (set (pc) (if_then_else (match_op_dup 3 [(cc0) (const_int 0)]) (label_ref (match_dup 2)) @@ -5836,8 +5844,8 @@ [(set (match_operand:HI 0 "register_operand" "") (and:HI (match_dup 0) (match_operand:HI 1 "const_int_qi_operand" ""))) - (set (cc0) - (match_dup 0)) + (set (cc0) (compare (match_dup 0) + (const_int 0))) (set (pc) (if_then_else (match_operator 3 "eqne_operator" [(cc0) (const_int 0)]) @@ -5847,8 +5855,8 @@ [(set (match_dup 4) (and:QI (match_dup 4) (match_dup 5))) - (set (cc0) - (match_dup 4)) + (set (cc0) (compare (match_dup 4) + (const_int 0))) (set (pc) (if_then_else (match_op_dup 3 [(cc0) (const_int 0)]) (label_ref (match_dup 2)) @@ -5860,8 +5868,8 @@ [(set (match_operand:SI 0 "register_operand" "") (and:SI (match_dup 0) (match_operand:SI 1 "const_int_qi_operand" ""))) - (set (cc0) - (match_dup 0)) + (set (cc0) (compare (match_dup 0) + (const_int 0))) (set (pc) (if_then_else (match_operator 3 "eqne_operator" [(cc0) (const_int 0)]) @@ -5871,8 +5879,8 @@ [(set (match_dup 4) (and:QI (match_dup 4) (match_dup 5))) - (set (cc0) - (match_dup 4)) + (set (cc0) (compare (match_dup 4) + (const_int 0))) (set (pc) (if_then_else (match_op_dup 3 [(cc0) (const_int 0)]) (label_ref (match_dup 2)) @@ -5884,8 +5892,8 @@ [(set (match_operand:SI 0 "register_operand" "") (and:SI (match_dup 0) (match_operand:SI 1 "const_int_hi_operand" ""))) - (set (cc0) - (match_dup 0)) + (set (cc0) (compare (match_dup 0) + (const_int 0))) (set (pc) (if_then_else (match_operator 3 "eqne_operator" [(cc0) (const_int 0)]) @@ -5895,8 +5903,8 @@ [(set (match_dup 4) (and:HI (match_dup 4) (match_dup 5))) - (set (cc0) - (match_dup 4)) + (set (cc0) (compare (match_dup 4) + (const_int 0))) (set (pc) (if_then_else (match_op_dup 3 [(cc0) (const_int 0)]) (label_ref (match_dup 2)) @@ -5911,8 +5919,8 @@ (set (match_dup 0) (xor:SI (match_dup 0) (match_operand:SI 2 "const_int_qi_operand" ""))) - (set (cc0) - (match_dup 0)) + (set (cc0) (compare (match_dup 0) + (const_int 0))) (set (pc) (if_then_else (match_operator 4 "eqne_operator" [(cc0) (const_int 0)]) @@ -5926,8 +5934,8 @@ (set (match_dup 5) (xor:QI (match_dup 5) (match_dup 7))) - (set (cc0) - (match_dup 5)) + (set (cc0) (compare (match_dup 5) + (const_int 0))) (set (pc) (if_then_else (match_op_dup 4 [(cc0) (const_int 0)]) (label_ref (match_dup 3)) @@ -6088,7 +6096,8 @@ (match_operand 2 "h8300_src_operand" "")))] "TARGET_H8300SX && peep2_reg_dead_p (2, operands[0]) - && !reg_overlap_mentioned_p (operands[0], operands[2])" + && !reg_overlap_mentioned_p (operands[0], operands[2]) + && operands[2] != const0_rtx" [(set (cc0) (compare (match_dup 1) (match_dup 2)))]) diff --git a/gcc/config/i386/i386-protos.h b/gcc/config/i386/i386-protos.h index 803a9da7ca3..9452d2a60ec 100644 --- a/gcc/config/i386/i386-protos.h +++ b/gcc/config/i386/i386-protos.h @@ -106,7 +106,7 @@ extern int ix86_match_ccmode (rtx, enum machine_mode); extern rtx ix86_expand_compare (enum rtx_code, rtx *, rtx *); extern int ix86_use_fcomi_compare (enum rtx_code); extern void ix86_expand_branch (enum rtx_code, rtx); -extern int ix86_expand_setcc (enum rtx_code, rtx); +extern void ix86_expand_setcc (enum rtx_code, rtx); extern int ix86_expand_int_movcc (rtx[]); extern int ix86_expand_fp_movcc (rtx[]); extern bool ix86_expand_fp_vcond (rtx[]); diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c index aefb891ff5b..bb013a144f6 100644 --- a/gcc/config/i386/i386.c +++ b/gcc/config/i386/i386.c @@ -14947,15 +14947,12 @@ ix86_split_fp_branch (enum rtx_code code, rtx op1, rtx op2, emit_label (label); } -int +void ix86_expand_setcc (enum rtx_code code, rtx dest) { rtx ret, tmp, tmpreg, equiv; rtx second_test, bypass_test; - if (GET_MODE (ix86_compare_op0) == (TARGET_64BIT ? TImode : DImode)) - return 0; /* FAIL */ - gcc_assert (GET_MODE (dest) == QImode); ret = ix86_expand_compare (code, &second_test, &bypass_test); @@ -14994,8 +14991,6 @@ ix86_expand_setcc (enum rtx_code code, rtx dest) ix86_compare_op0, ix86_compare_op1); set_unique_reg_note (get_last_insn (), REG_EQUAL, equiv); } - - return 1; /* DONE */ } /* Expand comparison setting or clearing carry flag. Return true when @@ -15143,6 +15138,8 @@ ix86_expand_int_movcc (rtx operands[]) bool sign_bit_compare_p = false;; start_sequence (); + ix86_compare_op0 = XEXP (operands[1], 0); + ix86_compare_op1 = XEXP (operands[1], 1); compare_op = ix86_expand_compare (code, &second_test, &bypass_test); compare_seq = get_insns (); end_sequence (); @@ -15860,6 +15857,8 @@ ix86_expand_fp_movcc (rtx operands[]) enum rtx_code code = GET_CODE (operands[1]); rtx tmp, compare_op, second_test, bypass_test; + ix86_compare_op0 = XEXP (operands[1], 0); + ix86_compare_op1 = XEXP (operands[1], 1); if (TARGET_SSE_MATH && SSE_FLOAT_MODE_P (mode)) { enum machine_mode cmode; @@ -16387,6 +16386,8 @@ ix86_expand_int_addcc (rtx operands[]) bool fpcmp = false; enum machine_mode mode = GET_MODE (operands[0]); + ix86_compare_op0 = XEXP (operands[1], 0); + ix86_compare_op1 = XEXP (operands[1], 1); if (operands[3] != const1_rtx && operands[3] != constm1_rtx) return 0; @@ -28870,13 +28871,14 @@ void ix86_emit_i387_log1p (rtx op0, rtx op1) rtx tmp = gen_reg_rtx (XFmode); rtx tmp2 = gen_reg_rtx (XFmode); + rtx test; emit_insn (gen_absxf2 (tmp, op1)); - emit_insn (gen_cmpxf (tmp, + test = gen_rtx_GE (VOIDmode, tmp, CONST_DOUBLE_FROM_REAL_VALUE ( REAL_VALUE_ATOF ("0.29289321881345247561810596348408353", XFmode), - XFmode))); - emit_jump_insn (gen_bge (label1)); + XFmode)); + emit_jump_insn (gen_cbranchxf4 (test, XEXP (test, 0), XEXP (test, 1), label1)); emit_move_insn (tmp2, standard_80387_constant_rtx (4)); /* fldln2 */ emit_insn (gen_fyl2xp1xf3_i387 (op0, op1, tmp2)); diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md index 1bb96fd07db..198b59d2e47 100644 --- a/gcc/config/i386/i386.md +++ b/gcc/config/i386/i386.md @@ -759,77 +759,183 @@ (include "constraints.md") -;; Compare instructions. +;; Compare and branch/compare and store instructions. -;; All compare insns have expanders that save the operands away without -;; actually generating RTL. The bCOND or sCOND (emitted immediately -;; after the cmp) will actually emit the cmpM. +(define_expand "cbranchti4" + [(set (reg:CC FLAGS_REG) + (compare:CC (match_operand:TI 1 "nonimmediate_operand" "") + (match_operand:TI 2 "x86_64_general_operand" ""))) + (set (pc) (if_then_else + (match_operator 0 "comparison_operator" + [(reg:CC FLAGS_REG) + (const_int 0)]) + (label_ref (match_operand 3 "" "")) + (pc)))] + "TARGET_64BIT" +{ + if (MEM_P (operands[1]) && MEM_P (operands[2])) + operands[1] = force_reg (TImode, operands[1]); + ix86_compare_op0 = operands[1]; + ix86_compare_op1 = operands[2]; + ix86_expand_branch (GET_CODE (operands[0]), operands[3]); + DONE; +}) -(define_expand "cmpti" +(define_expand "cbranchdi4" [(set (reg:CC FLAGS_REG) - (compare:CC (match_operand:TI 0 "nonimmediate_operand" "") - (match_operand:TI 1 "x86_64_general_operand" "")))] + (compare:CC (match_operand:DI 1 "nonimmediate_operand" "") + (match_operand:DI 2 "x86_64_general_operand" ""))) + (set (pc) (if_then_else + (match_operator 0 "comparison_operator" + [(reg:CC FLAGS_REG) + (const_int 0)]) + (label_ref (match_operand 3 "" "")) + (pc)))] + "" +{ + if (MEM_P (operands[1]) && MEM_P (operands[2])) + operands[1] = force_reg (DImode, operands[1]); + ix86_compare_op0 = operands[1]; + ix86_compare_op1 = operands[2]; + ix86_expand_branch (GET_CODE (operands[0]), operands[3]); + DONE; +}) + +(define_expand "cstoredi4" + [(set (reg:CC FLAGS_REG) + (compare:CC (match_operand:DI 2 "nonimmediate_operand" "") + (match_operand:DI 3 "x86_64_general_operand" ""))) + (set (match_operand:QI 0 "register_operand" "") + (match_operator 1 "comparison_operator" + [(reg:CC FLAGS_REG) + (const_int 0)]))] "TARGET_64BIT" { - if (MEM_P (operands[0]) && MEM_P (operands[1])) - operands[0] = force_reg (TImode, operands[0]); - ix86_compare_op0 = operands[0]; - ix86_compare_op1 = operands[1]; + if (MEM_P (operands[2]) && MEM_P (operands[3])) + operands[2] = force_reg (DImode, operands[2]); + ix86_compare_op0 = operands[2]; + ix86_compare_op1 = operands[3]; + ix86_expand_setcc (GET_CODE (operands[1]), operands[0]); DONE; }) -(define_expand "cmpdi" +(define_expand "cbranchsi4" [(set (reg:CC FLAGS_REG) - (compare:CC (match_operand:DI 0 "nonimmediate_operand" "") - (match_operand:DI 1 "x86_64_general_operand" "")))] + (compare:CC (match_operand:SI 1 "cmpsi_operand" "") + (match_operand:SI 2 "general_operand" ""))) + (set (pc) (if_then_else + (match_operator 0 "comparison_operator" + [(reg:CC FLAGS_REG) + (const_int 0)]) + (label_ref (match_operand 3 "" "")) + (pc)))] "" { - if (MEM_P (operands[0]) && MEM_P (operands[1])) - operands[0] = force_reg (DImode, operands[0]); - ix86_compare_op0 = operands[0]; - ix86_compare_op1 = operands[1]; + if (MEM_P (operands[1]) && MEM_P (operands[2])) + operands[1] = force_reg (SImode, operands[1]); + ix86_compare_op0 = operands[1]; + ix86_compare_op1 = operands[2]; + ix86_expand_branch (GET_CODE (operands[0]), operands[3]); DONE; }) -(define_expand "cmpsi" +(define_expand "cstoresi4" [(set (reg:CC FLAGS_REG) - (compare:CC (match_operand:SI 0 "cmpsi_operand" "") - (match_operand:SI 1 "general_operand" "")))] + (compare:CC (match_operand:SI 2 "cmpsi_operand" "") + (match_operand:SI 3 "general_operand" ""))) + (set (match_operand:QI 0 "register_operand" "") + (match_operator 1 "comparison_operator" + [(reg:CC FLAGS_REG) + (const_int 0)]))] "" { - if (MEM_P (operands[0]) && MEM_P (operands[1])) - operands[0] = force_reg (SImode, operands[0]); - ix86_compare_op0 = operands[0]; - ix86_compare_op1 = operands[1]; + if (MEM_P (operands[2]) && MEM_P (operands[3])) + operands[2] = force_reg (SImode, operands[2]); + ix86_compare_op0 = operands[2]; + ix86_compare_op1 = operands[3]; + ix86_expand_setcc (GET_CODE (operands[1]), operands[0]); DONE; }) -(define_expand "cmphi" +(define_expand "cbranchhi4" [(set (reg:CC FLAGS_REG) - (compare:CC (match_operand:HI 0 "nonimmediate_operand" "") - (match_operand:HI 1 "general_operand" "")))] + (compare:CC (match_operand:HI 1 "nonimmediate_operand" "") + (match_operand:HI 2 "general_operand" ""))) + (set (pc) (if_then_else + (match_operator 0 "comparison_operator" + [(reg:CC FLAGS_REG) + (const_int 0)]) + (label_ref (match_operand 3 "" "")) + (pc)))] "" { - if (MEM_P (operands[0]) && MEM_P (operands[1])) - operands[0] = force_reg (HImode, operands[0]); - ix86_compare_op0 = operands[0]; - ix86_compare_op1 = operands[1]; + if (MEM_P (operands[1]) && MEM_P (operands[2])) + operands[1] = force_reg (HImode, operands[1]); + ix86_compare_op0 = operands[1]; + ix86_compare_op1 = operands[2]; + ix86_expand_branch (GET_CODE (operands[0]), operands[3]); DONE; }) -(define_expand "cmpqi" +(define_expand "cstorehi4" [(set (reg:CC FLAGS_REG) - (compare:CC (match_operand:QI 0 "nonimmediate_operand" "") - (match_operand:QI 1 "general_operand" "")))] - "TARGET_QIMODE_MATH" + (compare:CC (match_operand:HI 2 "nonimmediate_operand" "") + (match_operand:HI 3 "general_operand" ""))) + (set (match_operand:QI 0 "register_operand" "") + (match_operator 1 "comparison_operator" + [(reg:CC FLAGS_REG) + (const_int 0)]))] + "" { - if (MEM_P (operands[0]) && MEM_P (operands[1])) - operands[0] = force_reg (QImode, operands[0]); - ix86_compare_op0 = operands[0]; - ix86_compare_op1 = operands[1]; + if (MEM_P (operands[2]) && MEM_P (operands[3])) + operands[2] = force_reg (HImode, operands[2]); + ix86_compare_op0 = operands[2]; + ix86_compare_op1 = operands[3]; + ix86_expand_setcc (GET_CODE (operands[1]), operands[0]); + DONE; +}) + + +(define_expand "cbranchqi4" + [(set (reg:CC FLAGS_REG) + (compare:CC (match_operand:QI 1 "nonimmediate_operand" "") + (match_operand:QI 2 "general_operand" ""))) + (set (pc) (if_then_else + (match_operator 0 "comparison_operator" + [(reg:CC FLAGS_REG) + (const_int 0)]) + (label_ref (match_operand 3 "" "")) + (pc)))] + "" +{ + if (MEM_P (operands[1]) && MEM_P (operands[2])) + operands[1] = force_reg (QImode, operands[1]); + ix86_compare_op0 = operands[1]; + ix86_compare_op1 = operands[2]; + ix86_expand_branch (GET_CODE (operands[0]), operands[3]); + DONE; +}) + + +(define_expand "cstoreqi4" + [(set (reg:CC FLAGS_REG) + (compare:CC (match_operand:QI 2 "nonimmediate_operand" "") + (match_operand:QI 3 "general_operand" ""))) + (set (match_operand:QI 0 "register_operand" "") + (match_operator 1 "comparison_operator" + [(reg:CC FLAGS_REG) + (const_int 0)]))] + "" +{ + if (MEM_P (operands[2]) && MEM_P (operands[3])) + operands[2] = force_reg (QImode, operands[2]); + ix86_compare_op0 = operands[2]; + ix86_compare_op1 = operands[3]; + ix86_expand_setcc (GET_CODE (operands[1]), operands[0]); DONE; }) + (define_insn "cmpdi_ccno_1_rex64" [(set (reg FLAGS_REG) (compare (match_operand:DI 0 "nonimmediate_operand" "r,?mr") @@ -1078,39 +1184,103 @@ ;; which would allow mix and match FP modes on the compares. Which is what ;; the old patterns did, but with many more of them. -(define_expand "cmpxf" +(define_expand "cbranchxf4" + [(set (reg:CC FLAGS_REG) + (compare:CC (match_operand:XF 1 "nonmemory_operand" "") + (match_operand:XF 2 "nonmemory_operand" ""))) + (set (pc) (if_then_else + (match_operator 0 "comparison_operator" + [(reg:CC FLAGS_REG) + (const_int 0)]) + (label_ref (match_operand 3 "" "")) + (pc)))] + "TARGET_80387" +{ + ix86_compare_op0 = operands[1]; + ix86_compare_op1 = operands[2]; + ix86_expand_branch (GET_CODE (operands[0]), operands[3]); + DONE; +}) + +(define_expand "cstorexf4" [(set (reg:CC FLAGS_REG) - (compare:CC (match_operand:XF 0 "nonmemory_operand" "") - (match_operand:XF 1 "nonmemory_operand" "")))] + (compare:CC (match_operand:XF 2 "nonmemory_operand" "") + (match_operand:XF 3 "nonmemory_operand" ""))) + (set (match_operand:QI 0 "register_operand" "") + (match_operator 1 "comparison_operator" + [(reg:CC FLAGS_REG) + (const_int 0)]))] "TARGET_80387" { - ix86_compare_op0 = operands[0]; - ix86_compare_op1 = operands[1]; + ix86_compare_op0 = operands[2]; + ix86_compare_op1 = operands[3]; + ix86_expand_setcc (GET_CODE (operands[1]), operands[0]); DONE; }) -(define_expand "cmp<mode>" +(define_expand "cbranch<mode>4" [(set (reg:CC FLAGS_REG) - (compare:CC (match_operand:MODEF 0 "cmp_fp_expander_operand" "") - (match_operand:MODEF 1 "cmp_fp_expander_operand" "")))] + (compare:CC (match_operand:MODEF 1 "cmp_fp_expander_operand" "") + (match_operand:MODEF 2 "cmp_fp_expander_operand" ""))) + (set (pc) (if_then_else + (match_operator 0 "comparison_operator" + [(reg:CC FLAGS_REG) + (const_int 0)]) + (label_ref (match_operand 3 "" "")) + (pc)))] "TARGET_80387 || (SSE_FLOAT_MODE_P (<MODE>mode) && TARGET_SSE_MATH)" { - ix86_compare_op0 = operands[0]; - ix86_compare_op1 = operands[1]; + ix86_compare_op0 = operands[1]; + ix86_compare_op1 = operands[2]; + ix86_expand_branch (GET_CODE (operands[0]), operands[3]); DONE; }) -(define_expand "cmpcc" +(define_expand "cstore<mode>4" [(set (reg:CC FLAGS_REG) - (compare:CC (match_operand 0 "flags_reg_operand" "") - (match_operand 1 "general_operand" "")))] + (compare:CC (match_operand:MODEF 2 "cmp_fp_expander_operand" "") + (match_operand:MODEF 3 "cmp_fp_expander_operand" ""))) + (set (match_operand:QI 0 "register_operand" "") + (match_operator 1 "comparison_operator" + [(reg:CC FLAGS_REG) + (const_int 0)]))] + "TARGET_80387 || (SSE_FLOAT_MODE_P (<MODE>mode) && TARGET_SSE_MATH)" +{ + ix86_compare_op0 = operands[2]; + ix86_compare_op1 = operands[3]; + ix86_expand_setcc (GET_CODE (operands[1]), operands[0]); + DONE; +}) + +(define_expand "cbranchcc4" + [(set (pc) (if_then_else + (match_operator 0 "comparison_operator" + [(match_operand 1 "flags_reg_operand" "") + (match_operand 2 "const0_operand" "")]) + (label_ref (match_operand 3 "" "")) + (pc)))] + "" +{ + ix86_compare_op0 = operands[1]; + ix86_compare_op1 = operands[2]; + ix86_expand_branch (GET_CODE (operands[0]), operands[3]); + DONE; +}) + +(define_expand "cstorecc4" + [(set (match_operand:QI 0 "register_operand" "") + (match_operator 1 "comparison_operator" + [(match_operand 2 "flags_reg_operand" "") + (match_operand 3 "const0_operand" "")]))] "" { - ix86_compare_op0 = operands[0]; - ix86_compare_op1 = operands[1]; + ix86_compare_op0 = operands[2]; + ix86_compare_op1 = operands[3]; + ix86_expand_setcc (GET_CODE (operands[1]), operands[0]); DONE; }) + ;; FP compares, step 1: ;; Set the FP condition codes. ;; @@ -14182,18 +14352,6 @@ ;; to avoid partial register stalls. Otherwise do things the setcc+movzx ;; way, which can later delete the movzx if only QImode is needed. -(define_expand "s<code>" - [(set (match_operand:QI 0 "register_operand" "") - (int_cond:QI (reg:CC FLAGS_REG) (const_int 0)))] - "" - "if (ix86_expand_setcc (<CODE>, operands[0])) DONE; else FAIL;") - -(define_expand "s<code>" - [(set (match_operand:QI 0 "register_operand" "") - (fp_cond:QI (reg:CC FLAGS_REG) (const_int 0)))] - "TARGET_80387 || TARGET_SSE" - "if (ix86_expand_setcc (<CODE>, operands[0])) DONE; else FAIL;") - (define_insn "*setcc_1" [(set (match_operand:QI 0 "nonimmediate_operand" "=qm") (match_operator:QI 1 "ix86_comparison_operator" @@ -14322,27 +14480,6 @@ ;; Basic conditional jump instructions. ;; We ignore the overflow flag for signed branch instructions. -;; For all bCOND expanders, also expand the compare or test insn that -;; generates reg FLAGS_REG. Generate an equality comparison if `beq' or `bne'. - -(define_expand "b<code>" - [(set (pc) - (if_then_else (int_cond:CC (reg:CC FLAGS_REG) - (const_int 0)) - (label_ref (match_operand 0 "")) - (pc)))] - "" - "ix86_expand_branch (<CODE>, operands[0]); DONE;") - -(define_expand "b<code>" - [(set (pc) - (if_then_else (fp_cond:CC (reg:CC FLAGS_REG) - (const_int 0)) - (label_ref (match_operand 0 "")) - (pc)))] - "TARGET_80387 || TARGET_SSE_MATH" - "ix86_expand_branch (<CODE>, operands[0]); DONE;") - (define_insn "*jcc_1" [(set (pc) (if_then_else (match_operator 1 "ix86_comparison_operator" @@ -22004,9 +22141,8 @@ emit_insn (gen_stack_protect_test_si (flags, operands[0], operands[1])); #endif - ix86_compare_op0 = flags; - ix86_compare_op1 = const0_rtx; - emit_jump_insn (gen_beq (operands[2])); + emit_jump_insn (gen_cbranchcc4 (gen_rtx_EQ (VOIDmode, flags, const0_rtx), + flags, const0_rtx, operands[2])); DONE; }) diff --git a/gcc/config/ia64/ia64-protos.h b/gcc/config/ia64/ia64-protos.h index e3b78641eb8..0859c7f53af 100644 --- a/gcc/config/ia64/ia64-protos.h +++ b/gcc/config/ia64/ia64-protos.h @@ -18,13 +18,6 @@ You should have received a copy of the GNU General Public License along with GCC; see the file COPYING3. If not see <http://www.gnu.org/licenses/>. */ -/* Variables defined in ia64.c. */ - -#ifdef RTX_CODE -extern GTY(()) rtx ia64_compare_op0; -extern GTY(()) rtx ia64_compare_op1; -#endif - /* Functions defined in ia64.c */ extern int bundling_p; @@ -43,7 +36,7 @@ extern void ia64_emit_cond_move (rtx, rtx, rtx); extern int ia64_depz_field_mask (rtx, rtx); extern void ia64_split_tmode_move (rtx[]); extern bool ia64_expand_movxf_movrf (enum machine_mode, rtx[]); -extern rtx ia64_expand_compare (enum rtx_code, enum machine_mode); +extern void ia64_expand_compare (rtx *, rtx *, rtx *); extern void ia64_expand_vecint_cmov (rtx[]); extern bool ia64_expand_vecint_minmax (enum rtx_code, enum machine_mode, rtx[]); extern void ia64_expand_widen_sum (rtx[], bool); diff --git a/gcc/config/ia64/ia64.c b/gcc/config/ia64/ia64.c index acf73c52969..1f433a6fb0f 100644 --- a/gcc/config/ia64/ia64.c +++ b/gcc/config/ia64/ia64.c @@ -63,11 +63,6 @@ along with GCC; see the file COPYING3. If not see ASM_OUTPUT_LABELREF. */ int ia64_asm_output_label = 0; -/* Define the information needed to generate branch and scc insns. This is - stored from the compare operation. */ -struct rtx_def * ia64_compare_op0; -struct rtx_def * ia64_compare_op1; - /* Register names for ia64_expand_prologue. */ static const char * const ia64_reg_numbers[96] = { "r32", "r33", "r34", "r35", "r36", "r37", "r38", "r39", @@ -1493,28 +1488,28 @@ ia64_expand_movxf_movrf (enum machine_mode mode, rtx operands[]) return false; } -/* Emit comparison instruction if necessary, returning the expression - that holds the compare result in the proper mode. */ +/* Emit comparison instruction if necessary, replacing *EXPR, *OP0, *OP1 + with the expression that holds the compare result (in VOIDmode). */ static GTY(()) rtx cmptf_libfunc; -rtx -ia64_expand_compare (enum rtx_code code, enum machine_mode mode) +void +ia64_expand_compare (rtx *expr, rtx *op0, rtx *op1) { - rtx op0 = ia64_compare_op0, op1 = ia64_compare_op1; + enum rtx_code code = GET_CODE (*expr); rtx cmp; /* If we have a BImode input, then we already have a compare result, and do not need to emit another comparison. */ - if (GET_MODE (op0) == BImode) + if (GET_MODE (*op0) == BImode) { - gcc_assert ((code == NE || code == EQ) && op1 == const0_rtx); - cmp = op0; + gcc_assert ((code == NE || code == EQ) && *op1 == const0_rtx); + cmp = *op0; } /* HPUX TFmode compare requires a library call to _U_Qfcmp, which takes a magic number as its third argument, that indicates what to do. The return value is an integer to be compared against zero. */ - else if (TARGET_HPUX && GET_MODE (op0) == TFmode) + else if (TARGET_HPUX && GET_MODE (*op0) == TFmode) { enum qfcmp_magic { QCMP_INV = 1, /* Raise FP_INVALID on SNaN as a side effect. */ @@ -1527,7 +1522,7 @@ ia64_expand_compare (enum rtx_code code, enum machine_mode mode) enum rtx_code ncode; rtx ret, insns; - gcc_assert (cmptf_libfunc && GET_MODE (op1) == TFmode); + gcc_assert (cmptf_libfunc && GET_MODE (*op1) == TFmode); switch (code) { /* 1 = equal, 0 = not equal. Equality operators do @@ -1552,7 +1547,7 @@ ia64_expand_compare (enum rtx_code code, enum machine_mode mode) start_sequence (); ret = emit_library_call_value (cmptf_libfunc, 0, LCT_CONST, DImode, 3, - op0, TFmode, op1, TFmode, + *op0, TFmode, *op1, TFmode, GEN_INT (magic), DImode); cmp = gen_reg_rtx (BImode); emit_insn (gen_rtx_SET (VOIDmode, cmp, @@ -1563,18 +1558,20 @@ ia64_expand_compare (enum rtx_code code, enum machine_mode mode) end_sequence (); emit_libcall_block (insns, cmp, cmp, - gen_rtx_fmt_ee (code, BImode, op0, op1)); + gen_rtx_fmt_ee (code, BImode, *op0, *op1)); code = NE; } else { cmp = gen_reg_rtx (BImode); emit_insn (gen_rtx_SET (VOIDmode, cmp, - gen_rtx_fmt_ee (code, BImode, op0, op1))); + gen_rtx_fmt_ee (code, BImode, *op0, *op1))); code = NE; } - return gen_rtx_fmt_ee (code, mode, cmp, const0_rtx); + *expr = gen_rtx_fmt_ee (code, VOIDmode, cmp, const0_rtx); + *op0 = cmp; + *op1 = const0_rtx; } /* Generate an integral vector comparison. Return true if the condition has diff --git a/gcc/config/ia64/ia64.md b/gcc/config/ia64/ia64.md index 26e71f841b5..e5a6d81730c 100644 --- a/gcc/config/ia64/ia64.md +++ b/gcc/config/ia64/ia64.md @@ -409,6 +409,7 @@ (set_attr "speculable2" "no, no, no, no, yes,no,no, no, no, yes,no, no, no, no, no, no, no, no, no")]) (define_mode_iterator MODE [BI QI HI SI DI SF DF XF TI]) +(define_mode_iterator MODE_FOR_CMP [BI SI DI SF DF XF (TF "TARGET_HPUX")]) (define_mode_iterator MODE_FOR_EXTEND [QI HI SI]) (define_mode_attr output_a [ @@ -4759,82 +4760,76 @@ ;; :: ;; :::::::::::::::::::: -(define_expand "cmpbi" - [(set (cc0) - (compare (match_operand:BI 0 "register_operand" "") - (match_operand:BI 1 "const_int_operand" "")))] +(define_expand "cbranchbi4" + [(set (pc) + (if_then_else (match_operator 0 "ia64_cbranch_operator" + [(match_operand:BI 1 "register_operand" "") + (match_operand:BI 2 "const_int_operand" "")]) + (label_ref (match_operand 3 "" "")) + (pc)))] "" -{ - ia64_compare_op0 = operands[0]; - ia64_compare_op1 = operands[1]; - DONE; -}) + "ia64_expand_compare (&operands[0], &operands[1], &operands[2]);") -(define_expand "cmpsi" - [(set (cc0) - (compare (match_operand:SI 0 "gr_register_operand" "") - (match_operand:SI 1 "gr_reg_or_8bit_and_adjusted_operand" "")))] +(define_expand "cbranchsi4" + [(set (pc) + (if_then_else (match_operator 0 "ia64_cbranch_operator" + [(match_operand:SI 1 "gr_register_operand" "") + (match_operand:SI 2 "gr_reg_or_8bit_and_adjusted_operand" "")]) + (label_ref (match_operand 3 "" "")) + (pc)))] "" -{ - ia64_compare_op0 = operands[0]; - ia64_compare_op1 = operands[1]; - DONE; -}) + "ia64_expand_compare (&operands[0], &operands[1], &operands[2]);") -(define_expand "cmpdi" - [(set (cc0) - (compare (match_operand:DI 0 "gr_register_operand" "") - (match_operand:DI 1 "gr_reg_or_8bit_and_adjusted_operand" "")))] +(define_expand "cbranchdi4" + [(set (pc) + (if_then_else (match_operator 0 "ia64_cbranch_operator" + [(match_operand:DI 1 "gr_register_operand" "") + (match_operand:DI 2 "gr_reg_or_8bit_and_adjusted_operand" "")]) + (label_ref (match_operand 3 "" "")) + (pc)))] "" -{ - ia64_compare_op0 = operands[0]; - ia64_compare_op1 = operands[1]; - DONE; -}) + "ia64_expand_compare (&operands[0], &operands[1], &operands[2]);") -(define_expand "cmpsf" - [(set (cc0) - (compare (match_operand:SF 0 "fr_reg_or_fp01_operand" "") - (match_operand:SF 1 "fr_reg_or_fp01_operand" "")))] +(define_expand "cbranchsf4" + [(set (pc) + (if_then_else (match_operator 0 "ia64_cbranch_operator" + [(match_operand:SF 1 "fr_reg_or_fp01_operand" "") + (match_operand:SF 2 "fr_reg_or_fp01_operand" "")]) + (label_ref (match_operand 3 "" "")) + (pc)))] "" -{ - ia64_compare_op0 = operands[0]; - ia64_compare_op1 = operands[1]; - DONE; -}) + "ia64_expand_compare (&operands[0], &operands[1], &operands[2]);") -(define_expand "cmpdf" - [(set (cc0) - (compare (match_operand:DF 0 "fr_reg_or_fp01_operand" "") - (match_operand:DF 1 "fr_reg_or_fp01_operand" "")))] +(define_expand "cbranchdf4" + [(set (pc) + (if_then_else (match_operator 0 "ia64_cbranch_operator" + [(match_operand:DF 1 "fr_reg_or_fp01_operand" "") + (match_operand:DF 2 "fr_reg_or_fp01_operand" "")]) + (label_ref (match_operand 3 "" "")) + (pc)))] "" -{ - ia64_compare_op0 = operands[0]; - ia64_compare_op1 = operands[1]; - DONE; -}) + "ia64_expand_compare (&operands[0], &operands[1], &operands[2]);") -(define_expand "cmpxf" - [(set (cc0) - (compare (match_operand:XF 0 "xfreg_or_fp01_operand" "") - (match_operand:XF 1 "xfreg_or_fp01_operand" "")))] +(define_expand "cbranchxf4" + [(set (pc) + (if_then_else (match_operator 0 "ia64_cbranch_operator" + [(match_operand:XF 1 "xfreg_or_fp01_operand" "") + (match_operand:XF 2 "xfreg_or_fp01_operand" "")]) + (label_ref (match_operand 3 "" "")) + (pc)))] "" -{ - ia64_compare_op0 = operands[0]; - ia64_compare_op1 = operands[1]; - DONE; -}) + "ia64_expand_compare (&operands[0], &operands[1], &operands[2]);") -(define_expand "cmptf" - [(set (cc0) - (compare (match_operand:TF 0 "gr_register_operand" "") - (match_operand:TF 1 "gr_register_operand" "")))] +(define_expand "cbranchtf4" + [(set (pc) + (if_then_else (match_operator 0 "ia64_cbranch_operator" + [(match_operand:TF 1 "gr_register_operand" "") + (match_operand:TF 2 "gr_register_operand" "")]) + (label_ref (match_operand 3 "" "")) + (pc)))] "TARGET_HPUX" -{ - ia64_compare_op0 = operands[0]; - ia64_compare_op1 = operands[1]; - DONE; -}) + "ia64_expand_compare (&operands[0], &operands[1], &operands[2]);") + (define_insn "*cmpsi_normal" [(set (match_operand:BI 0 "register_operand" "=c") @@ -4933,102 +4928,6 @@ ;; :: ;; :::::::::::::::::::: -(define_expand "beq" - [(set (pc) - (if_then_else (match_dup 1) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "operands[1] = ia64_expand_compare (EQ, VOIDmode);") - -(define_expand "bne" - [(set (pc) - (if_then_else (match_dup 1) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "operands[1] = ia64_expand_compare (NE, VOIDmode);") - -(define_expand "blt" - [(set (pc) - (if_then_else (match_dup 1) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "operands[1] = ia64_expand_compare (LT, VOIDmode);") - -(define_expand "ble" - [(set (pc) - (if_then_else (match_dup 1) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "operands[1] = ia64_expand_compare (LE, VOIDmode);") - -(define_expand "bgt" - [(set (pc) - (if_then_else (match_dup 1) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "operands[1] = ia64_expand_compare (GT, VOIDmode);") - -(define_expand "bge" - [(set (pc) - (if_then_else (match_dup 1) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "operands[1] = ia64_expand_compare (GE, VOIDmode);") - -(define_expand "bltu" - [(set (pc) - (if_then_else (match_dup 1) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "operands[1] = ia64_expand_compare (LTU, VOIDmode);") - -(define_expand "bleu" - [(set (pc) - (if_then_else (match_dup 1) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "operands[1] = ia64_expand_compare (LEU, VOIDmode);") - -(define_expand "bgtu" - [(set (pc) - (if_then_else (match_dup 1) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "operands[1] = ia64_expand_compare (GTU, VOIDmode);") - -(define_expand "bgeu" - [(set (pc) - (if_then_else (match_dup 1) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "operands[1] = ia64_expand_compare (GEU, VOIDmode);") - -(define_expand "bunordered" - [(set (pc) - (if_then_else (match_dup 1) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "operands[1] = ia64_expand_compare (UNORDERED, VOIDmode);") - -(define_expand "bordered" - [(set (pc) - (if_then_else (match_dup 1) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "operands[1] = ia64_expand_compare (ORDERED, VOIDmode);") - (define_insn "*br_true" [(set (pc) (if_then_else (match_operator 0 "predicate_operator" @@ -5094,65 +4993,61 @@ ;; :: ;; :::::::::::::::::::: -(define_expand "seq" - [(set (match_operand:DI 0 "gr_register_operand" "") (match_dup 1))] +(define_expand "cstorebi4" + [(set (match_operand:DI 0 "gr_register_operand" "") + (match_operator:DI 1 "ia64_cbranch_operator" + [(match_operand:BI 2 "register_operand" "") + (match_operand:BI 3 "const_int_operand" "")]))] "" - "operands[1] = ia64_expand_compare (EQ, DImode);") + "ia64_expand_compare (&operands[0], &operands[1], &operands[2]);") -(define_expand "sne" - [(set (match_operand:DI 0 "gr_register_operand" "") (match_dup 1))] +(define_expand "cstoresi4" + [(set (match_operand:DI 0 "gr_register_operand" "") + (match_operator:DI 1 "ia64_cbranch_operator" + [(match_operand:SI 2 "gr_register_operand" "") + (match_operand:SI 3 "gr_reg_or_8bit_and_adjusted_operand" "")]))] "" - "operands[1] = ia64_expand_compare (NE, DImode);") + "ia64_expand_compare (&operands[1], &operands[2], &operands[3]);") -(define_expand "slt" - [(set (match_operand:DI 0 "gr_register_operand" "") (match_dup 1))] +(define_expand "cstoredi4" + [(set (match_operand:DI 0 "gr_register_operand" "") + (match_operator:DI 1 "ia64_cbranch_operator" + [(match_operand:DI 2 "gr_register_operand" "") + (match_operand:DI 3 "gr_reg_or_8bit_and_adjusted_operand" "")]))] "" - "operands[1] = ia64_expand_compare (LT, DImode);") + "ia64_expand_compare (&operands[1], &operands[2], &operands[3]);") -(define_expand "sle" - [(set (match_operand:DI 0 "gr_register_operand" "") (match_dup 1))] +(define_expand "cstoresf4" + [(set (match_operand:DI 0 "gr_register_operand" "") + (match_operator:DI 1 "ia64_cbranch_operator" + [(match_operand:SF 2 "fr_reg_or_fp01_operand" "") + (match_operand:SF 3 "fr_reg_or_fp01_operand" "")]))] "" - "operands[1] = ia64_expand_compare (LE, DImode);") + "ia64_expand_compare (&operands[1], &operands[2], &operands[3]);") -(define_expand "sgt" - [(set (match_operand:DI 0 "gr_register_operand" "") (match_dup 1))] +(define_expand "cstoredf4" + [(set (match_operand:DI 0 "gr_register_operand" "") + (match_operator:DI 1 "ia64_cbranch_operator" + [(match_operand:DF 2 "fr_reg_or_fp01_operand" "") + (match_operand:DF 3 "fr_reg_or_fp01_operand" "")]))] "" - "operands[1] = ia64_expand_compare (GT, DImode);") + "ia64_expand_compare (&operands[1], &operands[2], &operands[3]);") -(define_expand "sge" - [(set (match_operand:DI 0 "gr_register_operand" "") (match_dup 1))] +(define_expand "cstorexf4" + [(set (match_operand:DI 0 "gr_register_operand" "") + (match_operator:DI 1 "ia64_cbranch_operator" + [(match_operand:XF 2 "xfreg_or_fp01_operand" "") + (match_operand:XF 3 "xfreg_or_fp01_operand" "")]))] "" - "operands[1] = ia64_expand_compare (GE, DImode);") + "ia64_expand_compare (&operands[1], &operands[2], &operands[3]);") -(define_expand "sltu" - [(set (match_operand:DI 0 "gr_register_operand" "") (match_dup 1))] - "" - "operands[1] = ia64_expand_compare (LTU, DImode);") - -(define_expand "sleu" - [(set (match_operand:DI 0 "gr_register_operand" "") (match_dup 1))] - "" - "operands[1] = ia64_expand_compare (LEU, DImode);") - -(define_expand "sgtu" - [(set (match_operand:DI 0 "gr_register_operand" "") (match_dup 1))] - "" - "operands[1] = ia64_expand_compare (GTU, DImode);") - -(define_expand "sgeu" - [(set (match_operand:DI 0 "gr_register_operand" "") (match_dup 1))] - "" - "operands[1] = ia64_expand_compare (GEU, DImode);") - -(define_expand "sunordered" - [(set (match_operand:DI 0 "gr_register_operand" "") (match_dup 1))] - "" - "operands[1] = ia64_expand_compare (UNORDERED, DImode);") - -(define_expand "sordered" - [(set (match_operand:DI 0 "gr_register_operand" "") (match_dup 1))] - "" - "operands[1] = ia64_expand_compare (ORDERED, DImode);") +(define_expand "cstoretf4" + [(set (match_operand:DI 0 "gr_register_operand" "") + (match_operator:DI 1 "ia64_cbranch_operator" + [(match_operand:TF 2 "gr_register_operand" "") + (match_operand:TF 3 "gr_register_operand" "")]))] + "TARGET_HPUX" + "ia64_expand_compare (&operands[1], &operands[2], &operands[3]);") ;; Don't allow memory as destination here, because cmov/cmov/st is more ;; efficient than mov/mov/cst/cst. @@ -6018,12 +5913,62 @@ "break %0" [(set_attr "itanium_class" "chk_s_i")]) -(define_expand "conditional_trap" - [(trap_if (match_operand 0 "" "") (match_operand 1 "" ""))] +(define_expand "ctrapbi4" + [(trap_if (match_operator 0 "ia64_cbranch_operator" + [(match_operand:BI 1 "register_operand" "") + (match_operand:BI 2 "const_int_operand" "")]) + (match_operand 3 "" ""))] "" -{ - operands[0] = ia64_expand_compare (GET_CODE (operands[0]), VOIDmode); -}) + "ia64_expand_compare (&operands[0], &operands[1], &operands[2]);") + +(define_expand "ctrapsi4" + [(trap_if (match_operator 0 "ia64_cbranch_operator" + [(match_operand:SI 1 "gr_register_operand" "") + (match_operand:SI 2 "gr_reg_or_8bit_and_adjusted_operand" "")]) + (match_operand 3 "" ""))] + "" + "ia64_expand_compare (&operands[0], &operands[1], &operands[2]);") + +(define_expand "ctrapdi4" + [(trap_if (match_operator 0 "ia64_cbranch_operator" + [(match_operand:DI 1 "gr_register_operand" "") + (match_operand:DI 2 "gr_reg_or_8bit_and_adjusted_operand" "")]) + (match_operand 3 "" ""))] + "" + "ia64_expand_compare (&operands[0], &operands[1], &operands[2]);") + +(define_expand "ctrapsf4" + [(trap_if (match_operator 0 "ia64_cbranch_operator" + [(match_operand:SF 1 "fr_reg_or_fp01_operand" "") + (match_operand:SF 2 "fr_reg_or_fp01_operand" "")]) + (match_operand 3 "" ""))] + "" + "ia64_expand_compare (&operands[0], &operands[1], &operands[2]);") + +(define_expand "ctrapdf4" + [(trap_if (match_operator 0 "ia64_cbranch_operator" + [(match_operand:DF 1 "fr_reg_or_fp01_operand" "") + (match_operand:DF 2 "fr_reg_or_fp01_operand" "")]) + (match_operand 3 "" ""))] + "" + "ia64_expand_compare (&operands[0], &operands[1], &operands[2]);") + +(define_expand "ctrapxf4" + [(trap_if (match_operator 0 "ia64_cbranch_operator" + [(match_operand:XF 1 "xfreg_or_fp01_operand" "") + (match_operand:XF 2 "xfreg_or_fp01_operand" "")]) + (match_operand 3 "" ""))] + "" + "ia64_expand_compare (&operands[0], &operands[1], &operands[2]);") + +(define_expand "ctraptf4" + [(trap_if (match_operator 0 "ia64_cbranch_operator" + [(match_operand:TF 1 "gr_register_operand" "") + (match_operand:TF 2 "gr_register_operand" "")]) + (match_operand 3 "" ""))] + "TARGET_HPUX" + "ia64_expand_compare (&operands[0], &operands[1], &operands[2]);") + (define_insn "*conditional_trap" [(trap_if (match_operator 0 "predicate_operator" diff --git a/gcc/config/ia64/predicates.md b/gcc/config/ia64/predicates.md index 5a957490390..1503a0520cb 100644 --- a/gcc/config/ia64/predicates.md +++ b/gcc/config/ia64/predicates.md @@ -536,6 +536,11 @@ (and (match_code "const_double,const_vector") (match_test "op == CONST0_RTX (GET_MODE (op))")))) +;; Return 1 if OP is a valid comparison operator for "cbranch" instructions. +(define_predicate "ia64_cbranch_operator" + (ior (match_operand 0 "ordered_comparison_operator") + (match_code "ordered,unordered"))) + ;; True if this is a comparison operator, which accepts a normal 8-bit ;; signed immediate operand. (define_predicate "normal_comparison_operator" diff --git a/gcc/config/iq2000/iq2000-protos.h b/gcc/config/iq2000/iq2000-protos.h index 094bcbf2f12..a927452d83c 100644 --- a/gcc/config/iq2000/iq2000-protos.h +++ b/gcc/config/iq2000/iq2000-protos.h @@ -41,7 +41,7 @@ extern void print_operand (FILE *, rtx, int); #ifdef RTX_CODE extern rtx gen_int_relational (enum rtx_code, rtx, rtx, rtx, int *); -extern void gen_conditional_branch (rtx *, enum rtx_code); +extern void gen_conditional_branch (rtx *, enum machine_mode); #endif #ifdef TREE_CODE diff --git a/gcc/config/iq2000/iq2000.c b/gcc/config/iq2000/iq2000.c index 3b9e1166b27..28bb7a831fe 100644 --- a/gcc/config/iq2000/iq2000.c +++ b/gcc/config/iq2000/iq2000.c @@ -118,13 +118,6 @@ enum processor_type iq2000_tune; /* Which instruction set architecture to use. */ int iq2000_isa; -/* Cached operands, and operator to compare for use in set/branch/trap - on condition codes. */ -rtx branch_cmp[2]; - -/* What type of branch to use. */ -enum cmp_type branch_type; - /* Local variables. */ /* The next branch instruction is a branch likely, not branch normal. */ @@ -1010,60 +1003,31 @@ gen_int_relational (enum rtx_code test_code, rtx result, rtx cmp0, rtx cmp1, The comparison operands are saved away by cmp{si,di,sf,df}. */ void -gen_conditional_branch (rtx operands[], enum rtx_code test_code) +gen_conditional_branch (rtx operands[], enum machine_mode mode) { - enum cmp_type type = branch_type; - rtx cmp0 = branch_cmp[0]; - rtx cmp1 = branch_cmp[1]; - enum machine_mode mode; + enum rtx_code test_code = GET_CODE (operands[0]); + rtx cmp0 = operands[1]; + rtx cmp1 = operands[2]; rtx reg; int invert; rtx label1, label2; - switch (type) - { - case CMP_SI: - case CMP_DI: - mode = type == CMP_SI ? SImode : DImode; - invert = 0; - reg = gen_int_relational (test_code, NULL_RTX, cmp0, cmp1, &invert); - - if (reg) - { - cmp0 = reg; - cmp1 = const0_rtx; - test_code = NE; - } - else if (GET_CODE (cmp1) == CONST_INT && INTVAL (cmp1) != 0) - /* We don't want to build a comparison against a nonzero - constant. */ - cmp1 = force_reg (mode, cmp1); - - break; - - case CMP_SF: - case CMP_DF: - reg = gen_reg_rtx (CCmode); + invert = 0; + reg = gen_int_relational (test_code, NULL_RTX, cmp0, cmp1, &invert); - /* For cmp0 != cmp1, build cmp0 == cmp1, and test for result == 0. */ - emit_insn (gen_rtx_SET (VOIDmode, reg, - gen_rtx_fmt_ee (test_code == NE ? EQ : test_code, - CCmode, cmp0, cmp1))); - - test_code = test_code == NE ? EQ : NE; - mode = CCmode; + if (reg) + { cmp0 = reg; cmp1 = const0_rtx; - invert = 0; - break; - - default: - abort_with_insn (gen_rtx_fmt_ee (test_code, VOIDmode, cmp0, cmp1), - "bad test"); + test_code = NE; } + else if (GET_CODE (cmp1) == CONST_INT && INTVAL (cmp1) != 0) + /* We don't want to build a comparison against a nonzero + constant. */ + cmp1 = force_reg (mode, cmp1); /* Generate the branch. */ - label1 = gen_rtx_LABEL_REF (VOIDmode, operands[0]); + label1 = gen_rtx_LABEL_REF (VOIDmode, operands[3]); label2 = pc_rtx; if (invert) diff --git a/gcc/config/iq2000/iq2000.h b/gcc/config/iq2000/iq2000.h index 30642b2a13f..0664f511bd3 100644 --- a/gcc/config/iq2000/iq2000.h +++ b/gcc/config/iq2000/iq2000.h @@ -1001,13 +1001,6 @@ extern enum processor_type iq2000_tune; /* Which instruction set architecture to use. */ extern int iq2000_isa; -/* Cached operands, and operator to compare for use in set/branch/trap - on condition codes. */ -extern rtx branch_cmp[2]; - -/* What type of branch to use. */ -extern enum cmp_type branch_type; - enum iq2000_builtins { IQ2000_BUILTIN_ADO16, diff --git a/gcc/config/iq2000/iq2000.md b/gcc/config/iq2000/iq2000.md index 919f6a20231..61275f2c671 100644 --- a/gcc/config/iq2000/iq2000.md +++ b/gcc/config/iq2000/iq2000.md @@ -989,63 +989,25 @@ ;; ;; .................... ;; -;; COMPARISONS +;; CONDITIONAL BRANCHES ;; ;; .................... -;; Flow here is rather complex: -;; -;; 1) The cmp{si,di,sf,df} routine is called. It deposits the -;; arguments into the branch_cmp array, and the type into -;; branch_type. No RTL is generated. -;; -;; 2) The appropriate branch define_expand is called, which then -;; creates the appropriate RTL for the comparison and branch. -;; Different CC modes are used, based on what type of branch is -;; done, so that we can constrain things appropriately. There -;; are assumptions in the rest of GCC that break if we fold the -;; operands into the branches for integer operations, and use cc0 -;; for floating point, so we use the fp status register instead. -;; If needed, an appropriate temporary is created to hold the -;; of the integer compare. - -(define_expand "cmpsi" - [(set (cc0) - (compare:CC (match_operand:SI 0 "register_operand" "") - (match_operand:SI 1 "arith_operand" "")))] +(define_expand "cbranchsi4" + [(set (pc) + (if_then_else + (match_operator:SI 0 "ordered_comparison_operator" + [(match_operand:SI 1 "register_operand") + (match_operand:SI 2 "reg_or_const_operand")]) + (label_ref (match_operand:SI 3 "")) + (pc)))] "" " { - if (operands[0]) /* avoid unused code message */ - { - branch_cmp[0] = operands[0]; - branch_cmp[1] = operands[1]; - branch_type = CMP_SI; - DONE; - } + gen_conditional_branch (operands, SImode); + DONE; }") -(define_expand "tstsi" - [(set (cc0) - (match_operand:SI 0 "register_operand" ""))] - "" - " -{ - if (operands[0]) /* avoid unused code message */ - { - branch_cmp[0] = operands[0]; - branch_cmp[1] = const0_rtx; - branch_type = CMP_SI; - DONE; - } -}") - -;; -;; .................... -;; -;; CONDITIONAL BRANCHES -;; -;; .................... ;; Conditional branches on comparisons with zero. @@ -1135,166 +1097,6 @@ [(set_attr "type" "branch") (set_attr "mode" "none")]) -(define_expand "beq" - [(set (pc) - (if_then_else (eq:CC (cc0) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - if (operands[0]) /* avoid unused code warning */ - { - gen_conditional_branch (operands, EQ); - DONE; - } -}") - -(define_expand "bne" - [(set (pc) - (if_then_else (ne:CC (cc0) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - if (operands[0]) /* avoid unused code warning */ - { - gen_conditional_branch (operands, NE); - DONE; - } -}") - -(define_expand "bgt" - [(set (pc) - (if_then_else (gt:CC (cc0) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - if (operands[0]) /* avoid unused code warning */ - { - gen_conditional_branch (operands, GT); - DONE; - } -}") - -(define_expand "bge" - [(set (pc) - (if_then_else (ge:CC (cc0) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - if (operands[0]) /* avoid unused code warning */ - { - gen_conditional_branch (operands, GE); - DONE; - } -}") - -(define_expand "blt" - [(set (pc) - (if_then_else (lt:CC (cc0) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - if (operands[0]) /* avoid unused code warning */ - { - gen_conditional_branch (operands, LT); - DONE; - } -}") - -(define_expand "ble" - [(set (pc) - (if_then_else (le:CC (cc0) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - if (operands[0]) /* avoid unused code warning */ - { - gen_conditional_branch (operands, LE); - DONE; - } -}") - -(define_expand "bgtu" - [(set (pc) - (if_then_else (gtu:CC (cc0) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - if (operands[0]) /* avoid unused code warning */ - { - gen_conditional_branch (operands, GTU); - DONE; - } -}") - -(define_expand "bgeu" - [(set (pc) - (if_then_else (geu:CC (cc0) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - if (operands[0]) /* avoid unused code warning */ - { - gen_conditional_branch (operands, GEU); - DONE; - } -}") - - -(define_expand "bltu" - [(set (pc) - (if_then_else (ltu:CC (cc0) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - if (operands[0]) /* avoid unused code warning */ - { - gen_conditional_branch (operands, LTU); - DONE; - } -}") - -(define_expand "bleu" - [(set (pc) - (if_then_else (leu:CC (cc0) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - if (operands[0]) /* avoid unused code warning */ - { - gen_conditional_branch (operands, LEU); - DONE; - } -}") ;; Recognize bbi and bbin instructions. These use two unusual template ;; patterns, %Ax and %Px. %Ax outputs an 'i' if operand `x' is a LABEL_REF @@ -1390,25 +1192,19 @@ ;; ;; .................... -(define_expand "seq" +(define_expand "cstoresi4" [(set (match_operand:SI 0 "register_operand" "=d") - (eq:SI (match_dup 1) - (match_dup 2)))] + (match_operator:SI 1 "ordered_comparison_operator" + [(match_operand:SI 2 "register_operand") + (match_operand:SI 3 "reg_or_const_operand")]))] "" " { - if (branch_type != CMP_SI && (branch_type != CMP_DI)) - FAIL; - - /* Set up operands from compare. */ - operands[1] = branch_cmp[0]; - operands[2] = branch_cmp[1]; - - gen_int_relational (EQ, operands[0], operands[1], operands[2], (int *)0); + gen_int_relational (GET_CODE (operands[1]), operands[0], + operands[2], operands[3], (int *)0); DONE; }") - (define_insn "seq_si_zero" [(set (match_operand:SI 0 "register_operand" "=d") (eq:SI (match_operand:SI 1 "register_operand" "d") @@ -1418,24 +1214,6 @@ [(set_attr "type" "arith") (set_attr "mode" "SI")]) -(define_expand "sne" - [(set (match_operand:SI 0 "register_operand" "=d") - (ne:SI (match_dup 1) - (match_dup 2)))] - "" - " -{ - if (branch_type != CMP_SI && (branch_type != CMP_DI)) - FAIL; - - /* Set up operands from compare. */ - operands[1] = branch_cmp[0]; - operands[2] = branch_cmp[1]; - - gen_int_relational (NE, operands[0], operands[1], operands[2], (int *)0); - DONE; -}") - (define_insn "sne_si_zero" [(set (match_operand:SI 0 "register_operand" "=d") (ne:SI (match_operand:SI 1 "register_operand" "d") @@ -1445,24 +1223,6 @@ [(set_attr "type" "arith") (set_attr "mode" "SI")]) -(define_expand "sgt" - [(set (match_operand:SI 0 "register_operand" "=d") - (gt:SI (match_dup 1) - (match_dup 2)))] - "" - " -{ - if (branch_type != CMP_SI && (branch_type != CMP_DI)) - FAIL; - - /* Set up operands from compare. */ - operands[1] = branch_cmp[0]; - operands[2] = branch_cmp[1]; - - gen_int_relational (GT, operands[0], operands[1], operands[2], (int *)0); - DONE; -}") - (define_insn "sgt_si" [(set (match_operand:SI 0 "register_operand" "=d,=d") (gt:SI (match_operand:SI 1 "register_operand" "d,d") @@ -1474,42 +1234,6 @@ [(set_attr "type" "arith,arith") (set_attr "mode" "SI,SI")]) -(define_expand "sge" - [(set (match_operand:SI 0 "register_operand" "=d") - (ge:SI (match_dup 1) - (match_dup 2)))] - "" - " -{ - if (branch_type != CMP_SI && (branch_type != CMP_DI)) - FAIL; - - /* Set up operands from compare. */ - operands[1] = branch_cmp[0]; - operands[2] = branch_cmp[1]; - - gen_int_relational (GE, operands[0], operands[1], operands[2], (int *)0); - DONE; -}") - -(define_expand "slt" - [(set (match_operand:SI 0 "register_operand" "=d") - (lt:SI (match_dup 1) - (match_dup 2)))] - "" - " -{ - if (branch_type != CMP_SI && (branch_type != CMP_DI)) - FAIL; - - /* Set up operands from compare. */ - operands[1] = branch_cmp[0]; - operands[2] = branch_cmp[1]; - - gen_int_relational (LT, operands[0], operands[1], operands[2], (int *)0); - DONE; -}") - (define_insn "slt_si" [(set (match_operand:SI 0 "register_operand" "=d,=d") (lt:SI (match_operand:SI 1 "register_operand" "d,d") @@ -1521,24 +1245,6 @@ [(set_attr "type" "arith,arith") (set_attr "mode" "SI,SI")]) -(define_expand "sle" - [(set (match_operand:SI 0 "register_operand" "=d") - (le:SI (match_dup 1) - (match_dup 2)))] - "" - " -{ - if (branch_type != CMP_SI && (branch_type != CMP_DI)) - FAIL; - - /* Set up operands from compare. */ - operands[1] = branch_cmp[0]; - operands[2] = branch_cmp[1]; - - gen_int_relational (LE, operands[0], operands[1], operands[2], (int *)0); - DONE; -}") - (define_insn "sle_si_const" [(set (match_operand:SI 0 "register_operand" "=d") (le:SI (match_operand:SI 1 "register_operand" "d") @@ -1552,24 +1258,6 @@ [(set_attr "type" "arith") (set_attr "mode" "SI")]) -(define_expand "sgtu" - [(set (match_operand:SI 0 "register_operand" "=d") - (gtu:SI (match_dup 1) - (match_dup 2)))] - "" - " -{ - if (branch_type != CMP_SI && (branch_type != CMP_DI)) - FAIL; - - /* Set up operands from compare. */ - operands[1] = branch_cmp[0]; - operands[2] = branch_cmp[1]; - - gen_int_relational (GTU, operands[0], operands[1], operands[2], (int *)0); - DONE; -}") - (define_insn "sgtu_si" [(set (match_operand:SI 0 "register_operand" "=d") (gtu:SI (match_operand:SI 1 "register_operand" "d") @@ -1588,42 +1276,6 @@ [(set_attr "type" "arith") (set_attr "mode" "SI")]) -(define_expand "sgeu" - [(set (match_operand:SI 0 "register_operand" "=d") - (geu:SI (match_dup 1) - (match_dup 2)))] - "" - " -{ - if (branch_type != CMP_SI && (branch_type != CMP_DI)) - FAIL; - - /* Set up operands from compare. */ - operands[1] = branch_cmp[0]; - operands[2] = branch_cmp[1]; - - gen_int_relational (GEU, operands[0], operands[1], operands[2], (int *)0); - DONE; -}") - -(define_expand "sltu" - [(set (match_operand:SI 0 "register_operand" "=d") - (ltu:SI (match_dup 1) - (match_dup 2)))] - "" - " -{ - if (branch_type != CMP_SI && (branch_type != CMP_DI)) - FAIL; - - /* Set up operands from compare. */ - operands[1] = branch_cmp[0]; - operands[2] = branch_cmp[1]; - - gen_int_relational (LTU, operands[0], operands[1], operands[2], (int *)0); - DONE; -}") - (define_insn "sltu_si" [(set (match_operand:SI 0 "register_operand" "=d,=d") (ltu:SI (match_operand:SI 1 "register_operand" "d,d") @@ -1635,24 +1287,6 @@ [(set_attr "type" "arith,arith") (set_attr "mode" "SI,SI")]) -(define_expand "sleu" - [(set (match_operand:SI 0 "register_operand" "=d") - (leu:SI (match_dup 1) - (match_dup 2)))] - "" - " -{ - if (branch_type != CMP_SI && (branch_type != CMP_DI)) - FAIL; - - /* Set up operands from compare. */ - operands[1] = branch_cmp[0]; - operands[2] = branch_cmp[1]; - - gen_int_relational (LEU, operands[0], operands[1], operands[2], (int *)0); - DONE; -}") - (define_insn "sleu_si_const" [(set (match_operand:SI 0 "register_operand" "=d") (leu:SI (match_operand:SI 1 "register_operand" "d") diff --git a/gcc/config/iq2000/predicates.md b/gcc/config/iq2000/predicates.md index 53471e455ad..f275090309b 100644 --- a/gcc/config/iq2000/predicates.md +++ b/gcc/config/iq2000/predicates.md @@ -41,6 +41,14 @@ return register_operand (op, mode); }) +;; Return 1 if OP is a register or a constant. gen_int_relational +;; takes care of forcing out-of-range constants into a register. + +(define_predicate "reg_or_const_operand" + (ior (match_code "const_int") + (and (match_code "reg,subreg") + (match_operand 0 "register_operand")))) + ;; Return 1 if OP is a integer which fits in 16 bits. (define_predicate "small_int" diff --git a/gcc/config/m32c/cond.md b/gcc/config/m32c/cond.md index 60d83eea6ca..c751070e716 100644 --- a/gcc/config/m32c/cond.md +++ b/gcc/config/m32c/cond.md @@ -58,12 +58,23 @@ [(set (reg:CC FLG_REGNO) (compare (match_dup 1) (match_dup 2))) - (set (pc) (if_then_else (match_dup 4) + (set (pc) (if_then_else (match_op_dup 0 [(reg:CC FLG_REGNO) (const_int 0)]) (label_ref (match_dup 3)) (pc)))] - "operands[4] = m32c_cmp_flg_0 (operands[0]);" + "" ) +(define_insn "bcc_op" + [(set (pc) + (if_then_else (match_operator 0 "ordered_comparison_operator" + [(reg:CC FLG_REGNO) (const_int 0)]) + (label_ref (match_operand 1 "")) + (pc)))] + "" + "j%c0\t%l1" + [(set_attr "flags" "n")] +) + (define_insn "stzx_16" [(set (match_operand:QI 0 "mrai_operand" "=R0w,R0w,R0w") (if_then_else:QI (eq (reg:CC FLG_REGNO) (const_int 0)) @@ -113,34 +124,6 @@ "* return m32c_output_compare(insn, operands); " [(set_attr "flags" "oszc")]) -(define_expand "cmp<mode>" - [(set (reg:CC FLG_REGNO) - (compare (match_operand:QHPSI 0 "mra_operand" "RraSd") - (match_operand:QHPSI 1 "mrai_operand" "RraSdi")))] - "" - "m32c_pend_compare (operands); DONE;") - -(define_insn "b<code>_op" - [(set (pc) - (if_then_else (any_cond (reg:CC FLG_REGNO) - (const_int 0)) - (label_ref (match_operand 0 "")) - (pc)))] - "" - "j<code>\t%l0" - [(set_attr "flags" "n")] -) - -(define_expand "b<code>" - [(set (pc) - (if_then_else (any_cond (reg:CC FLG_REGNO) - (const_int 0)) - (label_ref (match_operand 0 "")) - (pc)))] - "" - "m32c_unpend_compare ();" -) - ;; m32c_conditional_register_usage changes the setcc_gen_code array to ;; point to the _24 variants if needed. @@ -151,51 +134,54 @@ ;; These are the post-split patterns for the conditional sets. -(define_insn "s<code>_op" +(define_insn "scc_op" [(set (match_operand:QI 0 "register_operand" "=Rqi") - (any_cond:QI (reg:CC FLG_REGNO) (const_int 0)))] + (match_operator:QI 1 "ordered_comparison_operator" + [(reg:CC FLG_REGNO) (const_int 0)]))] "TARGET_A16 && reload_completed" - "* return m32c_scc_pattern(operands, <CODE>);") + "* return m32c_scc_pattern(operands, GET_CODE (operands[1]));") -(define_insn "s<code>_24_op" +(define_insn "scc_24_op" [(set (match_operand:HI 0 "mra_operand" "=RhiSd") - (any_cond:HI (reg:CC FLG_REGNO) (const_int 0)))] + (match_operator:HI 1 "ordered_comparison_operator" + [(reg:CC FLG_REGNO) (const_int 0)]))] "TARGET_A24 && reload_completed" - "sc<code>\t%0" + "sc%c1\t%0" [(set_attr "flags" "n")] ) -;; These are the pre-split patterns for the conditional sets. Yes, -;; there are a lot of permutations. +;; These are the pre-split patterns for the conditional sets. -(define_insn_and_split "s<code>_<mode>" +(define_insn_and_split "cstore<mode>4" [(set (match_operand:QI 0 "register_operand" "=Rqi") - (any_cond:QI (match_operand:QHPSI 1 "mra_operand" "RraSd") - (match_operand:QHPSI 2 "mrai_operand" "RraSdi")))] + (match_operator:QI 1 "ordered_comparison_operator" + [(match_operand:QHPSI 2 "mra_operand" "RraSd") + (match_operand:QHPSI 3 "mrai_operand" "RraSdi")]))] "TARGET_A16" "#" "reload_completed" [(set (reg:CC FLG_REGNO) - (compare (match_dup 1) - (match_dup 2))) + (compare (match_dup 2) + (match_dup 3))) (set (match_dup 0) - (any_cond:QI (reg:CC FLG_REGNO) (const_int 0)))] + (match_op_dup 1 [(reg:CC FLG_REGNO) (const_int 0)]))] "" [(set_attr "flags" "x")] ) -(define_insn_and_split "s<code>_<mode>_24" +(define_insn_and_split "cstore<mode>4_24" [(set (match_operand:HI 0 "mra_nopp_operand" "=RhiSd") - (any_cond:HI (match_operand:QHPSI 1 "mra_operand" "RraSd") - (match_operand:QHPSI 2 "mrai_operand" "RraSdi")))] + (match_operator:HI 1 "ordered_comparison_operator" + [(match_operand:QHPSI 2 "mra_operand" "RraSd") + (match_operand:QHPSI 3 "mrai_operand" "RraSdi")]))] "TARGET_A24" "#" "reload_completed" [(set (reg:CC FLG_REGNO) - (compare (match_dup 1) - (match_dup 2))) + (compare (match_dup 2) + (match_dup 3))) (set (match_dup 0) - (any_cond:HI (reg:CC FLG_REGNO) (const_int 0)))] + (match_op_dup 1 [(reg:CC FLG_REGNO) (const_int 0)]))] "" [(set_attr "flags" "x")] ) @@ -240,21 +226,7 @@ [(set_attr "flags" "x")] ) -;; And these are the expanders, which read the pending compare -;; operands to build a combined insn. - -(define_expand "s<code>" - [(set (match_operand:QI 0 "register_operand" "=Rqi") - (any_cond:QI (reg:CC FLG_REGNO) (const_int 0)))] - "TARGET_A16" - "m32c_expand_scc (<CODE>, operands); DONE;") - -(define_expand "s<code>_24" - [(set (match_operand:HI 0 "mra_nopp_operand" "=RhiSd") - (any_cond:HI (reg:CC FLG_REGNO) (const_int 0)))] - "TARGET_A24" - "m32c_expand_scc (<CODE>, operands); DONE;") - +;; And these are the expanders. (define_expand "movqicc" [(set (match_operand:QI 0 "register_operand" "") diff --git a/gcc/config/m32c/m32c-protos.h b/gcc/config/m32c/m32c-protos.h index 650c918b44a..ef857275c9d 100644 --- a/gcc/config/m32c/m32c-protos.h +++ b/gcc/config/m32c/m32c-protos.h @@ -45,7 +45,6 @@ void m32c_register_pragmas (void); int m32c_regno_ok_for_base_p (int); int m32c_trampoline_alignment (void); int m32c_trampoline_size (void); -void m32c_unpend_compare (void); #if defined(RTX_CODE) && defined(TREE_CODE) @@ -58,7 +57,6 @@ rtx m32c_function_value (const_tree, const_tree); int m32c_cannot_change_mode_class (MM, MM, int); int m32c_class_max_nregs (int, MM); -rtx m32c_cmp_flg_0 (rtx); rtx m32c_eh_return_stackadj_rtx (void); void m32c_emit_eh_epilogue (rtx); int m32c_expand_cmpstr (rtx *); @@ -68,7 +66,6 @@ int m32c_expand_movmemhi (rtx *); int m32c_expand_movstr (rtx *); void m32c_expand_neg_mulpsi3 (rtx *); int m32c_expand_setmemhi (rtx *); -void m32c_expand_scc (int, rtx *); int m32c_extra_constraint_p (rtx, char, const char *); int m32c_extra_constraint_p2 (rtx, char, const char *); int m32c_hard_regno_nregs (int, MM); @@ -86,7 +83,6 @@ int m32c_memory_move_cost (MM, int, int); int m32c_modes_tieable_p (MM, MM); bool m32c_mov_ok (rtx *, MM); char * m32c_output_compare (rtx, rtx *); -void m32c_pend_compare (rtx *); int m32c_preferred_output_reload_class (rtx, int); int m32c_preferred_reload_class (rtx, int); int m32c_prepare_move (rtx *, MM); diff --git a/gcc/config/m32c/m32c.c b/gcc/config/m32c/m32c.c index d0980dd63a6..17d5dd32ebc 100644 --- a/gcc/config/m32c/m32c.c +++ b/gcc/config/m32c/m32c.c @@ -1746,22 +1746,15 @@ m32c_initialize_trampoline (rtx tramp, rtx function, rtx chainval) static void m32c_init_libfuncs (void) { + /* We do this because the M32C has an HImode operand, but the + M16C has an 8-bit operand. Since gcc looks at the match data + and not the expanded rtl, we have to reset the optab so that + the right modes are found. */ if (TARGET_A24) { - /* We do this because the M32C has an HImode operand, but the - M16C has an 8-bit operand. Since gcc looks at the match data - and not the expanded rtl, we have to reset the array so that - the right modes are found. */ - setcc_gen_code[EQ] = CODE_FOR_seq_24; - setcc_gen_code[NE] = CODE_FOR_sne_24; - setcc_gen_code[GT] = CODE_FOR_sgt_24; - setcc_gen_code[GE] = CODE_FOR_sge_24; - setcc_gen_code[LT] = CODE_FOR_slt_24; - setcc_gen_code[LE] = CODE_FOR_sle_24; - setcc_gen_code[GTU] = CODE_FOR_sgtu_24; - setcc_gen_code[GEU] = CODE_FOR_sgeu_24; - setcc_gen_code[LTU] = CODE_FOR_sltu_24; - setcc_gen_code[LEU] = CODE_FOR_sleu_24; + optab_handler (cstore_optab, QImode)->insn_code = CODE_FOR_cstoreqi4_24; + optab_handler (cstore_optab, HImode)->insn_code = CODE_FOR_cstorehi4_24; + optab_handler (cstore_optab, PSImode)->insn_code = CODE_FOR_cstorepsi4_24; } } @@ -3691,57 +3684,8 @@ m32c_expand_neg_mulpsi3 (rtx * operands) emit_insn (gen_truncsipsi2 (operands[0], temp2)); } -static rtx compare_op0, compare_op1; - -void -m32c_pend_compare (rtx *operands) -{ - compare_op0 = operands[0]; - compare_op1 = operands[1]; -} - -void -m32c_unpend_compare (void) -{ - switch (GET_MODE (compare_op0)) - { - case QImode: - emit_insn (gen_cmpqi_op (compare_op0, compare_op1)); - case HImode: - emit_insn (gen_cmphi_op (compare_op0, compare_op1)); - case PSImode: - emit_insn (gen_cmppsi_op (compare_op0, compare_op1)); - default: - /* Just to silence the "missing case" warnings. */ ; - } -} - -void -m32c_expand_scc (int code, rtx *operands) -{ - enum machine_mode mode = TARGET_A16 ? QImode : HImode; - - emit_insn (gen_rtx_SET (mode, - operands[0], - gen_rtx_fmt_ee (code, - mode, - compare_op0, - compare_op1))); -} - /* Pattern Output Functions */ -/* Returns a (OP (reg:CC FLG_REGNO) (const_int 0)) from some other - match_operand rtx's OP. */ -rtx -m32c_cmp_flg_0 (rtx cmp) -{ - return gen_rtx_fmt_ee (GET_CODE (cmp), - GET_MODE (cmp), - gen_rtx_REG (CCmode, FLG_REGNO), - GEN_INT (0)); -} - int m32c_expand_movcc (rtx *operands) { @@ -3753,22 +3697,17 @@ m32c_expand_movcc (rtx *operands) if (GET_CODE (operands[2]) != CONST_INT || GET_CODE (operands[3]) != CONST_INT) return 1; - emit_insn (gen_cmpqi(XEXP (rel, 0), XEXP (rel, 1))); if (GET_CODE (rel) == NE) { rtx tmp = operands[2]; operands[2] = operands[3]; operands[3] = tmp; + rel = gen_rtx_EQ (GET_MODE (rel), XEXP (rel, 0), XEXP (rel, 1)); } - cmp = gen_rtx_fmt_ee (GET_CODE (rel), - GET_MODE (rel), - compare_op0, - compare_op1); - emit_move_insn (operands[0], gen_rtx_IF_THEN_ELSE (GET_MODE (operands[0]), - cmp, + rel, operands[2], operands[3])); return 0; diff --git a/gcc/config/m32c/m32c.md b/gcc/config/m32c/m32c.md index 4bc4d05fbf1..da0f8dd23f9 100644 --- a/gcc/config/m32c/m32c.md +++ b/gcc/config/m32c/m32c.md @@ -60,10 +60,7 @@ (define_mode_iterator QHSI [QI HI (SI "TARGET_A24")]) (define_mode_attr bwl [(QI "b") (HI "w") (PSI "l") (SI "l")]) -(define_code_iterator any_cond [eq ne gt ge lt le gtu geu ltu leu]) (define_code_iterator eqne_cond [eq ne]) -(define_code_iterator gl_cond [gt ge lt le gtu geu ltu leu]) - (define_insn "nop" diff --git a/gcc/config/m32r/m32r-protos.h b/gcc/config/m32r/m32r-protos.h index 33a9f9dd01f..04533b9b49e 100644 --- a/gcc/config/m32r/m32r-protos.h +++ b/gcc/config/m32r/m32r-protos.h @@ -38,6 +38,7 @@ extern enum m32r_function_type m32r_compute_function_type (tree); extern int easy_di_const (rtx); extern int easy_df_const (rtx); extern rtx gen_compare (enum rtx_code, rtx, rtx, int); +extern bool gen_cond_store (enum rtx_code, rtx, rtx, rtx); extern rtx gen_split_move_double (rtx *); extern int m32r_address_code (rtx); extern void m32r_initialize_trampoline (rtx, rtx, rtx); diff --git a/gcc/config/m32r/m32r.c b/gcc/config/m32r/m32r.c index 656c0eae1be..0b5ff6bc6fd 100644 --- a/gcc/config/m32r/m32r.c +++ b/gcc/config/m32r/m32r.c @@ -43,10 +43,6 @@ #include "target-def.h" #include "tm-constrs.h" -/* Save the operands last given to a compare for use when we - generate a scc or bcc insn. */ -rtx m32r_compare_op0, m32r_compare_op1; - /* Array of valid operand punctuation characters. */ char m32r_punct_chars[256]; @@ -864,6 +860,151 @@ gen_compare (enum rtx_code code, rtx x, rtx y, int need_compare) return gen_rtx_fmt_ee (branch_code, VOIDmode, cc_reg, CONST0_RTX (CCmode)); } + +bool +gen_cond_store (enum rtx_code code, rtx op0, rtx op1, rtx op2) +{ + enum machine_mode mode = GET_MODE (op0); + + gcc_assert (mode == SImode); + switch (code) + { + case EQ: + if (!register_operand (op1, mode)) + op1 = force_reg (mode, op1); + + if (TARGET_M32RX || TARGET_M32R2) + { + if (!reg_or_zero_operand (op2, mode)) + op2 = force_reg (mode, op2); + + emit_insn (gen_seq_insn_m32rx (op0, op1, op2)); + return true; + } + if (GET_CODE (op2) == CONST_INT && INTVAL (op2) == 0) + { + emit_insn (gen_seq_zero_insn (op0, op1)); + return true; + } + + if (!reg_or_eq_int16_operand (op2, mode)) + op2 = force_reg (mode, op2); + + emit_insn (gen_seq_insn (op0, op1, op2)); + return true; + + case NE: + if (GET_CODE (op2) != CONST_INT + || (INTVAL (op2) != 0 && satisfies_constraint_K (op2))) + { + rtx reg; + + if (reload_completed || reload_in_progress) + return false; + + reg = gen_reg_rtx (SImode); + emit_insn (gen_xorsi3 (reg, op1, op2)); + op1 = reg; + + if (!register_operand (op1, mode)) + op1 = force_reg (mode, op1); + + emit_insn (gen_sne_zero_insn (op0, op1)); + return true; + } + return false; + + case LT: + case GT: + if (code == GT) + { + rtx tmp = op2; + op2 = op1; + op1 = tmp; + code = LT; + } + + if (!register_operand (op1, mode)) + op1 = force_reg (mode, op1); + + if (!reg_or_int16_operand (op2, mode)) + op2 = force_reg (mode, op2); + + emit_insn (gen_slt_insn (op0, op1, op2)); + return true; + + case LTU: + case GTU: + if (code == GTU) + { + rtx tmp = op2; + op2 = op1; + op1 = tmp; + code = LTU; + } + + if (!register_operand (op1, mode)) + op1 = force_reg (mode, op1); + + if (!reg_or_int16_operand (op2, mode)) + op2 = force_reg (mode, op2); + + emit_insn (gen_sltu_insn (op0, op1, op2)); + return true; + + case GE: + case GEU: + if (!register_operand (op1, mode)) + op1 = force_reg (mode, op1); + + if (!reg_or_int16_operand (op2, mode)) + op2 = force_reg (mode, op2); + + if (code == GE) + emit_insn (gen_sge_insn (op0, op1, op2)); + else + emit_insn (gen_sgeu_insn (op0, op1, op2)); + return true; + + case LE: + case LEU: + if (!register_operand (op1, mode)) + op1 = force_reg (mode, op1); + + if (GET_CODE (op2) == CONST_INT) + { + HOST_WIDE_INT value = INTVAL (op2); + if (value >= 2147483647) + { + emit_move_insn (op0, const1_rtx); + return true; + } + + op2 = GEN_INT (value + 1); + if (value < -32768 || value >= 32767) + op2 = force_reg (mode, op2); + + if (code == LEU) + emit_insn (gen_sltu_insn (op0, op1, op2)); + else + emit_insn (gen_slt_insn (op0, op1, op2)); + return true; + } + + if (!register_operand (op2, mode)) + op2 = force_reg (mode, op2); + + if (code == LEU) + emit_insn (gen_sleu_insn (op0, op1, op2)); + else + emit_insn (gen_sle_insn (op0, op1, op2)); + return true; + + default: + gcc_unreachable (); + } +} + /* Split a 2 word move (DI or DF) into component parts. */ @@ -2291,8 +2432,8 @@ m32r_expand_block_move (rtx operands[]) if (bytes > MAX_MOVE_BYTES) { - emit_insn (gen_cmpsi (src_reg, final_src)); - emit_jump_insn (gen_bne (label)); + rtx test = gen_rtx_NE (VOIDmode, src_reg, final_src); + emit_jump_insn (gen_cbranchsi4 (test, src_reg, final_src, label)); } } diff --git a/gcc/config/m32r/m32r.h b/gcc/config/m32r/m32r.h index 9bc0fa98a0a..41dc07abad6 100644 --- a/gcc/config/m32r/m32r.h +++ b/gcc/config/m32r/m32r.h @@ -1495,12 +1495,6 @@ extern char m32r_punct_chars[256]; /* A function address in a call instruction. */ #define FUNCTION_MODE SImode -/* Define the information needed to generate branch and scc insns. This is - stored from the compare operation. Note that we can't use "rtx" here - since it hasn't been defined! */ -extern struct rtx_def * m32r_compare_op0; -extern struct rtx_def * m32r_compare_op1; - /* M32R function types. */ enum m32r_function_type { diff --git a/gcc/config/m32r/m32r.md b/gcc/config/m32r/m32r.md index d117e1e6928..0c76a044ccc 100644 --- a/gcc/config/m32r/m32r.md +++ b/gcc/config/m32r/m32r.md @@ -1180,18 +1180,6 @@ ;; thus merge the compare and branch into one instruction, so they are ;; preferred. -(define_expand "cmpsi" - [(set (reg:CC 17) - (compare:CC (match_operand:SI 0 "register_operand" "") - (match_operand:SI 1 "reg_or_cmp_int16_operand" "")))] - "" - " -{ - m32r_compare_op0 = operands[0]; - m32r_compare_op1 = operands[1]; - DONE; -}") - (define_insn "cmp_eqsi_zero_insn" [(set (reg:CC 17) (eq:CC (match_operand:SI 0 "register_operand" "r,r") @@ -1256,114 +1244,20 @@ ;; These control RTL generation for conditional jump insns. -(define_expand "beq" - [(set (pc) - (if_then_else (match_dup 1) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - operands[1] = gen_compare (EQ, m32r_compare_op0, m32r_compare_op1, FALSE); -}") - -(define_expand "bne" - [(set (pc) - (if_then_else (match_dup 1) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - operands[1] = gen_compare (NE, m32r_compare_op0, m32r_compare_op1, FALSE); -}") - -(define_expand "bgt" - [(set (pc) - (if_then_else (match_dup 1) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - operands[1] = gen_compare (GT, m32r_compare_op0, m32r_compare_op1, FALSE); -}") - -(define_expand "ble" - [(set (pc) - (if_then_else (match_dup 1) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - operands[1] = gen_compare (LE, m32r_compare_op0, m32r_compare_op1, FALSE); -}") - -(define_expand "bge" - [(set (pc) - (if_then_else (match_dup 1) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - operands[1] = gen_compare (GE, m32r_compare_op0, m32r_compare_op1, FALSE); -}") - -(define_expand "blt" - [(set (pc) - (if_then_else (match_dup 1) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - operands[1] = gen_compare (LT, m32r_compare_op0, m32r_compare_op1, FALSE); -}") - -(define_expand "bgtu" - [(set (pc) - (if_then_else (match_dup 1) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - operands[1] = gen_compare (GTU, m32r_compare_op0, m32r_compare_op1, FALSE); -}") - -(define_expand "bleu" - [(set (pc) - (if_then_else (match_dup 1) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - operands[1] = gen_compare (LEU, m32r_compare_op0, m32r_compare_op1, FALSE); -}") - -(define_expand "bgeu" - [(set (pc) - (if_then_else (match_dup 1) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - operands[1] = gen_compare (GEU, m32r_compare_op0, m32r_compare_op1, FALSE); -}") - -(define_expand "bltu" +(define_expand "cbranchsi4" + ; the comparison is emitted by gen_compare if needed. [(set (pc) - (if_then_else (match_dup 1) - (label_ref (match_operand 0 "" "")) + (if_then_else (match_operator 0 "ordered_comparison_operator" + [(match_operand:SI 1 "register_operand" "") + (match_operand:SI 2 "reg_or_cmp_int16_operand" "")]) + (label_ref (match_operand 3 "" "")) (pc)))] "" " { - operands[1] = gen_compare (LTU, m32r_compare_op0, m32r_compare_op1, FALSE); + operands[0] = gen_compare (GET_CODE (operands[0]), operands[1], operands[2], FALSE); + operands[1] = XEXP (operands[0], 0); + operands[2] = XEXP (operands[0], 1); }") ;; Now match both normal and inverted jump. @@ -1597,40 +1491,21 @@ ;; S<cc> operations to set a register to 1/0 based on a comparison -(define_expand "seq" - [(match_operand:SI 0 "register_operand" "")] +(define_expand "cstoresi4" + [(match_operand:SI 0 "register_operand" "") + (match_operator:SI 1 "ordered_comparison_operator" + [(match_operand:SI 2 "register_operand" "") + (match_operand:SI 3 "reg_or_cmp_int16_operand" "")])] "" " { - rtx op0 = operands[0]; - rtx op1 = m32r_compare_op0; - rtx op2 = m32r_compare_op1; - enum machine_mode mode = GET_MODE (op0); - - if (mode != SImode) + if (GET_MODE (operands[0]) != SImode) FAIL; - if (! register_operand (op1, mode)) - op1 = force_reg (mode, op1); - - if (TARGET_M32RX || TARGET_M32R2) - { - if (! reg_or_zero_operand (op2, mode)) - op2 = force_reg (mode, op2); - - emit_insn (gen_seq_insn_m32rx (op0, op1, op2)); - DONE; - } - if (GET_CODE (op2) == CONST_INT && INTVAL (op2) == 0) - { - emit_insn (gen_seq_zero_insn (op0, op1)); - DONE; - } - - if (! reg_or_eq_int16_operand (op2, mode)) - op2 = force_reg (mode, op2); + if (!gen_cond_store (GET_CODE (operands[1]), + operands[0], operands[2], operands[3])) + FAIL; - emit_insn (gen_seq_insn (op0, op1, op2)); DONE; }") @@ -1739,41 +1614,6 @@ end_sequence (); }") -(define_expand "sne" - [(match_operand:SI 0 "register_operand" "")] - "" - " -{ - rtx op0 = operands[0]; - rtx op1 = m32r_compare_op0; - rtx op2 = m32r_compare_op1; - enum machine_mode mode = GET_MODE (op0); - - if (mode != SImode) - FAIL; - - if (GET_CODE (op2) != CONST_INT - || (INTVAL (op2) != 0 && satisfies_constraint_K (op2))) - { - rtx reg; - - if (reload_completed || reload_in_progress) - FAIL; - - reg = gen_reg_rtx (SImode); - emit_insn (gen_xorsi3 (reg, op1, op2)); - op1 = reg; - - if (! register_operand (op1, mode)) - op1 = force_reg (mode, op1); - - emit_insn (gen_sne_zero_insn (op0, op1)); - DONE; - } - else - FAIL; -}") - (define_insn "sne_zero_insn" [(set (match_operand:SI 0 "register_operand" "=r") (ne:SI (match_operand:SI 1 "register_operand" "r") @@ -1801,29 +1641,6 @@ (ne:SI (reg:CC 17) (const_int 0)))] "") -(define_expand "slt" - [(match_operand:SI 0 "register_operand" "")] - "" - " -{ - rtx op0 = operands[0]; - rtx op1 = m32r_compare_op0; - rtx op2 = m32r_compare_op1; - enum machine_mode mode = GET_MODE (op0); - - if (mode != SImode) - FAIL; - - if (! register_operand (op1, mode)) - op1 = force_reg (mode, op1); - - if (! reg_or_int16_operand (op2, mode)) - op2 = force_reg (mode, op2); - - emit_insn (gen_slt_insn (op0, op1, op2)); - DONE; -}") - (define_insn "slt_insn" [(set (match_operand:SI 0 "register_operand" "=r,r") (lt:SI (match_operand:SI 1 "register_operand" "r,r") @@ -1847,46 +1664,6 @@ (ne:SI (reg:CC 17) (const_int 0)))] "") -(define_expand "sle" - [(match_operand:SI 0 "register_operand" "")] - "" - " -{ - rtx op0 = operands[0]; - rtx op1 = m32r_compare_op0; - rtx op2 = m32r_compare_op1; - enum machine_mode mode = GET_MODE (op0); - - if (mode != SImode) - FAIL; - - if (! register_operand (op1, mode)) - op1 = force_reg (mode, op1); - - if (GET_CODE (op2) == CONST_INT) - { - HOST_WIDE_INT value = INTVAL (op2); - if (value >= 2147483647) - { - emit_move_insn (op0, const1_rtx); - DONE; - } - - op2 = GEN_INT (value+1); - if (value < -32768 || value >= 32767) - op2 = force_reg (mode, op2); - - emit_insn (gen_slt_insn (op0, op1, op2)); - DONE; - } - - if (! register_operand (op2, mode)) - op2 = force_reg (mode, op2); - - emit_insn (gen_sle_insn (op0, op1, op2)); - DONE; -}") - (define_insn "sle_insn" [(set (match_operand:SI 0 "register_operand" "=r") (le:SI (match_operand:SI 1 "register_operand" "r") @@ -1933,52 +1710,6 @@ (neg:SI (match_dup 0)))] "") -(define_expand "sgt" - [(match_operand:SI 0 "register_operand" "")] - "" - " -{ - rtx op0 = operands[0]; - rtx op1 = m32r_compare_op0; - rtx op2 = m32r_compare_op1; - enum machine_mode mode = GET_MODE (op0); - - if (mode != SImode) - FAIL; - - if (! register_operand (op1, mode)) - op1 = force_reg (mode, op1); - - if (! register_operand (op2, mode)) - op2 = force_reg (mode, op2); - - emit_insn (gen_slt_insn (op0, op2, op1)); - DONE; -}") - -(define_expand "sge" - [(match_operand:SI 0 "register_operand" "")] - "" - " -{ - rtx op0 = operands[0]; - rtx op1 = m32r_compare_op0; - rtx op2 = m32r_compare_op1; - enum machine_mode mode = GET_MODE (op0); - - if (mode != SImode) - FAIL; - - if (! register_operand (op1, mode)) - op1 = force_reg (mode, op1); - - if (! reg_or_int16_operand (op2, mode)) - op2 = force_reg (mode, op2); - - emit_insn (gen_sge_insn (op0, op1, op2)); - DONE; -}") - (define_insn "sge_insn" [(set (match_operand:SI 0 "register_operand" "=r,r") (ge:SI (match_operand:SI 1 "register_operand" "r,r") @@ -2025,29 +1756,6 @@ (neg:SI (match_dup 0)))] "") -(define_expand "sltu" - [(match_operand:SI 0 "register_operand" "")] - "" - " -{ - rtx op0 = operands[0]; - rtx op1 = m32r_compare_op0; - rtx op2 = m32r_compare_op1; - enum machine_mode mode = GET_MODE (op0); - - if (mode != SImode) - FAIL; - - if (! register_operand (op1, mode)) - op1 = force_reg (mode, op1); - - if (! reg_or_int16_operand (op2, mode)) - op2 = force_reg (mode, op2); - - emit_insn (gen_sltu_insn (op0, op1, op2)); - DONE; -}") - (define_insn "sltu_insn" [(set (match_operand:SI 0 "register_operand" "=r,r") (ltu:SI (match_operand:SI 1 "register_operand" "r,r") @@ -2071,43 +1779,6 @@ (ne:SI (reg:CC 17) (const_int 0)))] "") -(define_expand "sleu" - [(match_operand:SI 0 "register_operand" "")] - "" - " -{ - rtx op0 = operands[0]; - rtx op1 = m32r_compare_op0; - rtx op2 = m32r_compare_op1; - enum machine_mode mode = GET_MODE (op0); - - if (mode != SImode) - FAIL; - - if (GET_CODE (op2) == CONST_INT) - { - HOST_WIDE_INT value = INTVAL (op2); - if (value >= 2147483647) - { - emit_move_insn (op0, const1_rtx); - DONE; - } - - op2 = GEN_INT (value+1); - if (value < 0 || value >= 32767) - op2 = force_reg (mode, op2); - - emit_insn (gen_sltu_insn (op0, op1, op2)); - DONE; - } - - if (! register_operand (op2, mode)) - op2 = force_reg (mode, op2); - - emit_insn (gen_sleu_insn (op0, op1, op2)); - DONE; -}") - (define_insn "sleu_insn" [(set (match_operand:SI 0 "register_operand" "=r") (leu:SI (match_operand:SI 1 "register_operand" "r") @@ -2154,52 +1825,6 @@ (neg:SI (match_dup 0)))] "") -(define_expand "sgtu" - [(match_operand:SI 0 "register_operand" "")] - "" - " -{ - rtx op0 = operands[0]; - rtx op1 = m32r_compare_op0; - rtx op2 = m32r_compare_op1; - enum machine_mode mode = GET_MODE (op0); - - if (mode != SImode) - FAIL; - - if (! register_operand (op1, mode)) - op1 = force_reg (mode, op1); - - if (! register_operand (op2, mode)) - op2 = force_reg (mode, op2); - - emit_insn (gen_sltu_insn (op0, op2, op1)); - DONE; -}") - -(define_expand "sgeu" - [(match_operand:SI 0 "register_operand" "")] - "" - " -{ - rtx op0 = operands[0]; - rtx op1 = m32r_compare_op0; - rtx op2 = m32r_compare_op1; - enum machine_mode mode = GET_MODE (op0); - - if (mode != SImode) - FAIL; - - if (! register_operand (op1, mode)) - op1 = force_reg (mode, op1); - - if (! reg_or_int16_operand (op2, mode)) - op2 = force_reg (mode, op2); - - emit_insn (gen_sgeu_insn (op0, op1, op2)); - DONE; -}") - (define_insn "sgeu_insn" [(set (match_operand:SI 0 "register_operand" "=r,r") (geu:SI (match_operand:SI 1 "register_operand" "r,r") @@ -2546,8 +2171,8 @@ FAIL; /* Generate the comparison that will set the carry flag. */ - operands[1] = gen_compare (GET_CODE (operands[1]), m32r_compare_op0, - m32r_compare_op1, TRUE); + operands[1] = gen_compare (GET_CODE (operands[1]), XEXP (operands[1], 0), + XEXP (operands[1], 1), TRUE); /* See other movsicc pattern below for reason why. */ emit_insn (gen_blockage ()); diff --git a/gcc/config/m68hc11/m68hc11.c b/gcc/config/m68hc11/m68hc11.c index 10bc7a0e66e..024e55de476 100644 --- a/gcc/config/m68hc11/m68hc11.c +++ b/gcc/config/m68hc11/m68hc11.c @@ -141,10 +141,6 @@ int m68hc11_sp_correction; int m68hc11_addr_mode; int m68hc11_mov_addr_mode; - -/* Comparison operands saved by the "tstxx" and "cmpxx" expand patterns. */ -rtx m68hc11_compare_op0; -rtx m68hc11_compare_op1; const struct processor_costs *m68hc11_cost; @@ -3877,7 +3873,11 @@ m68hc11_notice_update_cc (rtx exp, rtx insn ATTRIBUTE_UNUSED) { cc_status.flags = 0; cc_status.value1 = XEXP (exp, 0); - cc_status.value2 = XEXP (exp, 1); + if (GET_CODE (XEXP (exp, 1)) == COMPARE + && XEXP (XEXP (exp, 1), 1) == CONST0_RTX (GET_MODE (XEXP (XEXP (exp, 1), 0)))) + cc_status.value2 = XEXP (XEXP (exp, 1), 0); + else + cc_status.value2 = XEXP (exp, 1); } else { @@ -5355,6 +5355,7 @@ m68hc11_rtx_costs_1 (rtx x, enum rtx_code code, case COMPARE: case ABS: case ZERO_EXTEND: + case ZERO_EXTRACT: total = extra_cost + rtx_cost (XEXP (x, 0), code, !optimize_size); if (mode == QImode) { @@ -5405,6 +5406,10 @@ m68hc11_rtx_costs (rtx x, int code, int outer_code, int *total, *total = 0; return true; + case ZERO_EXTRACT: + if (outer_code != COMPARE) + return false; + case ROTATE: case ROTATERT: case ASHIFT: diff --git a/gcc/config/m68hc11/m68hc11.h b/gcc/config/m68hc11/m68hc11.h index 35176592601..29d998dbf89 100644 --- a/gcc/config/m68hc11/m68hc11.h +++ b/gcc/config/m68hc11/m68hc11.h @@ -1498,8 +1498,6 @@ extern int current_function_interrupt; extern int current_function_trap; extern int current_function_far; -extern GTY(()) rtx m68hc11_compare_op0; -extern GTY(()) rtx m68hc11_compare_op1; extern GTY(()) rtx m68hc11_soft_tmp_reg; extern GTY(()) rtx ix_reg; extern GTY(()) rtx iy_reg; diff --git a/gcc/config/m68hc11/m68hc11.md b/gcc/config/m68hc11/m68hc11.md index 0d40278cebb..f4ff3ebbb4c 100644 --- a/gcc/config/m68hc11/m68hc11.md +++ b/gcc/config/m68hc11/m68hc11.md @@ -162,31 +162,11 @@ ;; An offsetable memory operand should be ok. The 'tst_operand' and ;; 'cmp_operand' predicates take care of this rule. ;; -(define_expand "tstsi" - [(set (cc0) - (match_operand:SI 0 "tst_operand" ""))] - "" - " -{ - m68hc11_compare_op0 = operands[0]; - m68hc11_compare_op1 = const0_rtx; - DONE; -}") - -(define_expand "tsthi" - [(set (cc0) - (match_operand:HI 0 "tst_operand" ""))] - "" - " -{ - m68hc11_compare_op0 = operands[0]; - m68hc11_compare_op1 = const0_rtx; - DONE; -}") (define_insn "tsthi_1" [(set (cc0) - (match_operand:HI 0 "tst_operand" "dx,*y"))] + (compare (match_operand:HI 0 "tst_operand" "dx,*y") + (const_int 0)))] "" "* { @@ -196,34 +176,26 @@ return \"cp%0\\t#0\"; }") -(define_expand "tstqi" - [(set (cc0) - (match_operand:QI 0 "tst_operand" ""))] - "" - " -{ - m68hc11_compare_op0 = operands[0]; - m68hc11_compare_op1 = const0_rtx; - DONE; -}") - ;; ;; Split pattern for (tst:QI) on an address register. ;; (define_split [(set (cc0) - (match_operand:QI 0 "hard_addr_reg_operand" ""))] + (compare (match_operand:QI 0 "hard_addr_reg_operand" "") + (const_int 0)))] "z_replacement_completed == 2 && GET_MODE (operands[0]) == QImode" [(parallel [(set (reg:HI D_REGNUM) (match_dup 1)) (set (match_dup 1) (reg:HI D_REGNUM))]) - (set (cc0) (reg:QI D_REGNUM)) + (set (cc0) (compare (reg:QI D_REGNUM) + (const_int 0))) (parallel [(set (reg:HI D_REGNUM) (match_dup 1)) (set (match_dup 1) (reg:HI D_REGNUM))])] "operands[1] = gen_rtx_REG (HImode, REGNO (operands[0]));") (define_insn "tstqi_1" [(set (cc0) - (match_operand:QI 0 "tst_operand" "m,d,*A,!u"))] + (compare (match_operand:QI 0 "tst_operand" "m,d,*A,!u") + (const_int 0)))] "" "* { @@ -252,8 +224,8 @@ ;; after Z register replacement. ;; (define_insn_and_split "tstqi_z_used" - [(set (cc0) - (match_operand:QI 0 "tst_operand" "m")) + [(set (cc0) (compare (match_operand:QI 0 "tst_operand" "m") + (const_int 0))) (use (match_operand:HI 1 "hard_reg_operand" "dxy")) (use (reg:HI SOFT_Z_REGNUM))] "" @@ -261,7 +233,8 @@ "z_replacement_completed == 2" [(set (mem:HI (pre_dec:HI (reg:HI SP_REGNUM))) (match_dup 1)) (set (match_dup 1) (match_dup 2)) - (set (cc0) (match_dup 0)) + (set (cc0) (compare (match_dup 0) + (const_int 0))) (set (match_dup 1) (mem:HI (post_inc:HI (reg:HI SP_REGNUM))))] "operands[2] = gen_rtx_REG (HImode, SOFT_Z_REGNUM);") @@ -270,21 +243,6 @@ ;;- Compare ;;-------------------------------------------------------------------- -(define_expand "cmpsi" - [(set (cc0) - (compare (match_operand:SI 0 "tst_operand" "") - (match_operand:SI 1 "cmp_operand" "")))] - "" - " -{ - if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM) - operands[0] = force_reg (SImode, operands[0]); - - m68hc11_compare_op0 = operands[0]; - m68hc11_compare_op1 = operands[1]; - DONE; -}") - ;; ;; Comparison of a hard register with another one is provided because ;; it helps GCC to avoid to spill a pseudo hard register. @@ -316,21 +274,6 @@ (compare (match_dup 0) (mem:HI (post_inc:HI (reg:HI SP_REGNUM)))))] "") -(define_expand "cmphi" - [(set (cc0) - (compare (match_operand:HI 0 "tst_operand" "") - (match_operand:HI 1 "cmp_operand" "")))] - "" - " -{ - if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM) - operands[0] = force_reg (HImode, operands[0]); - - m68hc11_compare_op0 = operands[0]; - m68hc11_compare_op1 = operands[1]; - DONE; -}") - (define_insn "cmphi_1_hc12" [(set (cc0) (compare (match_operand:HI 0 "tst_operand" @@ -419,25 +362,11 @@ operands[3] = gen_rtx_REG (HImode, SOFT_TMP_REGNUM); operands[4] = gen_rtx_REG (HImode, REGNO (operands[1]));") -(define_expand "cmpqi" - [(set (cc0) - (compare (match_operand:QI 0 "tst_operand" "") - (match_operand:QI 1 "cmp_operand" "")))] - "" - " -{ - if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM) - operands[0] = force_reg (QImode, operands[0]); - - m68hc11_compare_op0 = operands[0]; - m68hc11_compare_op1 = operands[1]; - DONE; -}") - (define_insn "bitcmpqi" [(set (cc0) - (and:QI (match_operand:QI 0 "tst_operand" "d,d,d,m,!u") - (match_operand:QI 1 "cmp_operand" "im,*B,u,d,d")))] + (compare (and:QI (match_operand:QI 0 "tst_operand" "d,d,d,m,!u") + (match_operand:QI 1 "cmp_operand" "im,*B,u,d,d")) + (const_int 0)))] "" "@ bitb\\t%b1 @@ -448,8 +377,9 @@ (define_split /* "bitcmpqi" */ [(set (cc0) - (and:QI (match_operand:QI 0 "tst_operand" "") - (match_operand:QI 1 "hard_addr_reg_operand" "")))] + (compare (and:QI (match_operand:QI 0 "tst_operand" "") + (match_operand:QI 1 "hard_addr_reg_operand" "")) + (const_int 0)))] "z_replacement_completed == 2" [(set (match_dup 3) (match_dup 2)) (set (cc0) (and:QI (match_dup 0) (match_dup 4)))] @@ -459,8 +389,9 @@ (define_insn_and_split "bitcmpqi_z_used" [(set (cc0) - (and:QI (match_operand:QI 0 "tst_operand" "d,m") - (match_operand:QI 1 "cmp_operand" "m,d"))) + (compare (and:QI (match_operand:QI 0 "tst_operand" "d,m") + (match_operand:QI 1 "cmp_operand" "m,d")) + (const_int 0))) (use (match_operand:HI 2 "hard_reg_operand" "xy,xy")) (use (reg:HI SOFT_Z_REGNUM))] "" @@ -474,8 +405,9 @@ (define_insn "bitcmphi" [(set (cc0) - (and:HI (match_operand:HI 0 "tst_operand" "d") - (match_operand:HI 1 "const_int_operand" "i")))] + (compare (and:HI (match_operand:HI 0 "tst_operand" "d") + (match_operand:HI 1 "const_int_operand" "i")) + (const_int 0)))] "(INTVAL (operands[1]) & 0x0ff) == 0 || (INTVAL (operands[1]) & 0x0ff00) == 0" "* @@ -488,9 +420,10 @@ (define_insn "bitcmpqi_12" [(set (cc0) - (zero_extract (match_operand:HI 0 "tst_operand" "d") - (match_operand:HI 1 "const_int_operand" "i") - (match_operand:HI 2 "const_int_operand" "i")))] + (compare (zero_extract:HI (match_operand:HI 0 "tst_operand" "d") + (match_operand:HI 1 "const_int_operand" "i") + (match_operand:HI 2 "const_int_operand" "i")) + (const_int 0)))] "(unsigned) (INTVAL (operands[2]) + INTVAL (operands[1])) <= 8 || (((unsigned) (INTVAL (operands[2]) + INTVAL (operands[1])) <= 16) && (unsigned) INTVAL (operands[2]) >= 8)" @@ -6134,155 +6067,66 @@ "" "bra\\t%l0") -(define_expand "beq" - [(set (pc) - (if_then_else (eq (cc0) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - m68hc11_expand_compare_and_branch (EQ, m68hc11_compare_op0, - m68hc11_compare_op1, - operands[0]); - DONE; -}") - -(define_expand "bne" - [(set (pc) - (if_then_else (ne (cc0) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - m68hc11_expand_compare_and_branch (NE, m68hc11_compare_op0, - m68hc11_compare_op1, - operands[0]); - DONE; -}") - -(define_expand "bgt" - [(set (pc) - (if_then_else (gt (cc0) - (const_int 0)) - (label_ref (match_operand 0 "" "")) +(define_expand "cbranchsi4" + [(set (cc0) + (compare (match_operand:SI 1 "tst_operand" "") + (match_operand:SI 2 "cmp_operand" ""))) + (set (pc) + (if_then_else (match_operator 0 "ordered_comparison_operator" + [(cc0) (const_int 0)]) + (label_ref (match_operand 3 "" "")) (pc)))] "" " { - m68hc11_expand_compare_and_branch (GT, m68hc11_compare_op0, - m68hc11_compare_op1, - operands[0]); - DONE; -}") + if (GET_CODE (operands[1]) == MEM && GET_CODE (operands[2]) == MEM) + operands[1] = force_reg (SImode, operands[1]); -(define_expand "bgtu" - [(set (pc) - (if_then_else (gtu (cc0) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - m68hc11_expand_compare_and_branch (GTU, m68hc11_compare_op0, - m68hc11_compare_op1, - operands[0]); + m68hc11_expand_compare_and_branch (GET_CODE (operands[0]), operands[1], + operands[2], operands[3]); DONE; }") -(define_expand "blt" - [(set (pc) - (if_then_else (lt (cc0) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - m68hc11_expand_compare_and_branch (LT, m68hc11_compare_op0, - m68hc11_compare_op1, - operands[0]); - DONE; -}") - -(define_expand "bltu" - [(set (pc) - (if_then_else (ltu (cc0) - (const_int 0)) - (label_ref (match_operand 0 "" "")) +(define_expand "cbranchhi4" + [(set (cc0) + (compare (match_operand:HI 1 "tst_operand" "") + (match_operand:HI 2 "cmp_operand" ""))) + (set (pc) + (if_then_else (match_operator 0 "ordered_comparison_operator" + [(cc0) (const_int 0)]) + (label_ref (match_operand 3 "" "")) (pc)))] "" " { - m68hc11_expand_compare_and_branch (LTU, m68hc11_compare_op0, - m68hc11_compare_op1, - operands[0]); - DONE; -}") + if (GET_CODE (operands[1]) == MEM && GET_CODE (operands[2]) == MEM) + operands[1] = force_reg (HImode, operands[1]); -(define_expand "bge" - [(set (pc) - (if_then_else (ge (cc0) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - m68hc11_expand_compare_and_branch (GE, m68hc11_compare_op0, - m68hc11_compare_op1, - operands[0]); + m68hc11_expand_compare_and_branch (GET_CODE (operands[0]), operands[1], + operands[2], operands[3]); DONE; }") -(define_expand "bgeu" - [(set (pc) - (if_then_else (geu (cc0) - (const_int 0)) - (label_ref (match_operand 0 "" "")) +(define_expand "cbranchqi4" + [(set (cc0) + (compare (match_operand:QI 1 "tst_operand" "") + (match_operand:QI 2 "cmp_operand" ""))) + (set (pc) + (if_then_else (match_operator 0 "ordered_comparison_operator" + [(cc0) (const_int 0)]) + (label_ref (match_operand 3 "" "")) (pc)))] "" " { - m68hc11_expand_compare_and_branch (GEU, m68hc11_compare_op0, - m68hc11_compare_op1, - operands[0]); - DONE; -}") + if (GET_CODE (operands[1]) == MEM && GET_CODE (operands[2]) == MEM) + operands[1] = force_reg (QImode, operands[1]); -(define_expand "ble" - [(set (pc) - (if_then_else (le (cc0) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - m68hc11_expand_compare_and_branch (LE, m68hc11_compare_op0, - m68hc11_compare_op1, - operands[0]); + m68hc11_expand_compare_and_branch (GET_CODE (operands[0]), operands[1], + operands[2], operands[3]); DONE; }") -(define_expand "bleu" - [(set (pc) - (if_then_else (leu (cc0) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - m68hc11_expand_compare_and_branch (LEU, m68hc11_compare_op0, - m68hc11_compare_op1, - operands[0]); - DONE; -}") ;; ;; Test and branch instructions for 68HC12 for EQ and NE. @@ -7091,11 +6935,14 @@ (plus:HI (match_dup 0) (match_operand:HI 1 "const_int_operand" ""))) (set (cc0) - (match_operand:QI 2 "memory_operand" ""))] + (compare (match_operand:QI 2 "memory_operand" "") + (const_int 0)))] "TARGET_AUTO_INC_DEC && (INTVAL (operands[1]) == -1 || INTVAL (operands[1]) == 1) && reg_mentioned_p (operands[0], operands[2])" - [(set (cc0) (match_dup 3))] + [(set (cc0) + (compare (match_dup 3) + (const_int 0)))] "if (INTVAL (operands[1]) == 1) operands[3] = gen_rtx_MEM (QImode, gen_rtx_PRE_INC (HImode, operands[0])); @@ -7326,7 +7173,8 @@ (match_operand:HI 1 "hard_reg_operand" "")) (set (match_dup 1) (plus:HI (match_dup 1) (match_operand:HI 2 "const_int_operand" ""))) - (set (cc0) (match_dup 0))] + (set (cc0) (compare (match_dup 0) + (const_int 0)))] "peep2_reg_dead_p (3, operands[0]) && !Z_REG_P (operands[1])" [(set (match_dup 1) (plus:HI (match_dup 1) (match_dup 2))) (set (cc0) (compare (match_dup 1) (match_dup 2)))] @@ -7339,7 +7187,8 @@ (plus:HI (match_dup 2) (match_operand:HI 3 "const_int_operand" ""))) (set (match_operand:HI 4 "memory_operand" "") (match_dup 2)) - (set (cc0) (match_operand:HI 5 "hard_reg_operand" ""))] + (set (cc0) (compare (match_operand:HI 5 "hard_reg_operand" "") + (const_int 0)))] "peep2_reg_dead_p (4, operands[5]) && !Z_REG_P (operands[2]) && !reg_mentioned_p (operands[2], operands[4]) diff --git a/gcc/config/m68k/constraints.md b/gcc/config/m68k/constraints.md index 592112a155b..8be423788d6 100644 --- a/gcc/config/m68k/constraints.md +++ b/gcc/config/m68k/constraints.md @@ -78,6 +78,11 @@ (and (match_code "const_double") (match_test "!(TARGET_68881 && standard_68881_constant_p (op))"))) +(define_constraint "H" + "Defines a real zero constant." + (and (match_code "const_double") + (match_test "op == CONST0_RTX (GET_MODE (op))"))) + (define_constraint "S" "Used for operands that satisfy 'm' when -mpcrel is in effect." (and (match_code "mem") diff --git a/gcc/config/m68k/m68k.c b/gcc/config/m68k/m68k.c index d3734efd9cf..1b5c83bb414 100644 --- a/gcc/config/m68k/m68k.c +++ b/gcc/config/m68k/m68k.c @@ -152,11 +152,6 @@ static bool m68k_return_in_memory (const_tree, const_tree); /* Specify the identification number of the library being built */ const char *m68k_library_id_string = "_current_shared_library_a5_offset_"; - -/* Nonzero if the last compare/test insn had FP operands. The - sCC expanders peek at this to determine what to do for the - 68060, which has no fsCC instructions. */ -int m68k_last_compare_had_fp_operands; /* Initialize the GCC target structure. */ @@ -1024,10 +1019,10 @@ m68k_expand_prologue (void) emit_move_insn (gen_rtx_REG (Pmode, D0_REG), limit); limit = gen_rtx_REG (Pmode, D0_REG); } - emit_insn (gen_cmpsi (stack_pointer_rtx, limit)); - emit_insn (gen_conditional_trap (gen_rtx_LTU (VOIDmode, - cc0_rtx, const0_rtx), - const1_rtx)); + emit_insn (gen_ctrapsi4 (gen_rtx_LTU (VOIDmode, + stack_pointer_rtx, limit), + stack_pointer_rtx, limit, + const1_rtx)); } fsize_with_regs = current_frame.size; @@ -1110,12 +1105,11 @@ m68k_expand_prologue (void) if (crtl->limit_stack) { if (REG_P (stack_limit_rtx)) - { - emit_insn (gen_cmpsi (stack_pointer_rtx, stack_limit_rtx)); - emit_insn (gen_conditional_trap (gen_rtx_LTU (VOIDmode, - cc0_rtx, const0_rtx), - const1_rtx)); - } + emit_insn (gen_ctrapsi4 (gen_rtx_LTU (VOIDmode, stack_pointer_rtx, + stack_limit_rtx), + stack_pointer_rtx, stack_limit_rtx, + const1_rtx)); + else if (GET_CODE (stack_limit_rtx) != SYMBOL_REF) warning (0, "stack limit expression is not supported"); } @@ -2418,6 +2412,11 @@ m68k_rtx_costs (rtx x, int code, int outer_code, int *total, *total = COSTS_N_INSNS (43); /* div.l */ return true; + case ZERO_EXTRACT: + if (outer_code == COMPARE) + *total = 0; + return false; + default: return false; } diff --git a/gcc/config/m68k/m68k.h b/gcc/config/m68k/m68k.h index 875667dc428..ec0b35bdc1b 100644 --- a/gcc/config/m68k/m68k.h +++ b/gcc/config/m68k/m68k.h @@ -1060,7 +1060,6 @@ enum m68k_function_kind /* Variables in m68k.c; see there for details. */ extern const char *m68k_library_id_string; -extern int m68k_last_compare_had_fp_operands; extern enum target_device m68k_cpu; extern enum uarch_type m68k_tune; extern enum fpu_type m68k_fpu; diff --git a/gcc/config/m68k/m68k.md b/gcc/config/m68k/m68k.md index 68442fd5746..33058fa08b8 100644 --- a/gcc/config/m68k/m68k.md +++ b/gcc/config/m68k/m68k.md @@ -300,17 +300,10 @@ ;; (set (cc0) (const_int foo)) has no mode information. Such insns will ;; be folded while optimizing anyway. -(define_expand "tstdi" - [(parallel [(set (cc0) - (match_operand:DI 0 "nonimmediate_operand" "")) - (clobber (match_scratch:SI 1 "")) - (clobber (match_scratch:DI 2 ""))])] - "" - "m68k_last_compare_had_fp_operands = 0;") - -(define_insn "" +(define_insn "tstdi" [(set (cc0) - (match_operand:DI 0 "nonimmediate_operand" "am,d")) + (compare (match_operand:DI 0 "nonimmediate_operand" "am,d") + (const_int 0))) (clobber (match_scratch:SI 1 "=X,d")) (clobber (match_scratch:DI 2 "=d,X"))] "" @@ -339,17 +332,12 @@ return "sub%.l %1,%1\;tst%.l %R0\;subx%.l %1,%0"; }) -(define_expand "tstsi" - [(set (cc0) - (match_operand:SI 0 "nonimmediate_operand" ""))] - "" - "m68k_last_compare_had_fp_operands = 0;") - ;; If you think that the 68020 does not support tstl a0, ;; reread page B-167 of the 68020 manual more carefully. (define_insn "*tstsi_internal_68020_cf" [(set (cc0) - (match_operand:SI 0 "nonimmediate_operand" "rm"))] + (compare (match_operand:SI 0 "nonimmediate_operand" "rm") + (const_int 0)))] "TARGET_68020 || TARGET_COLDFIRE" "tst%.l %0" [(set_attr "type" "tst_l")]) @@ -357,7 +345,8 @@ ;; On an address reg, cmpw may replace cmpl. (define_insn "*tstsi_internal" [(set (cc0) - (match_operand:SI 0 "nonimmediate_operand" "dm,r"))] + (compare (match_operand:SI 0 "nonimmediate_operand" "dm,r") + (const_int 0)))] "!(TARGET_68020 || TARGET_COLDFIRE)" "@ tst%.l %0 @@ -366,43 +355,26 @@ ;; This can't use an address register, because comparisons ;; with address registers as second operand always test the whole word. -(define_expand "tsthi" - [(set (cc0) - (match_operand:HI 0 "nonimmediate_operand" ""))] - "" - "m68k_last_compare_had_fp_operands = 0;") - (define_insn "*tsthi_internal" [(set (cc0) - (match_operand:HI 0 "nonimmediate_operand" "dm"))] + (compare (match_operand:HI 0 "nonimmediate_operand" "dm") + (const_int 0)))] "" "tst%.w %0" [(set_attr "type" "tst")]) -(define_expand "tstqi" - [(set (cc0) - (match_operand:QI 0 "nonimmediate_operand" ""))] - "" - "m68k_last_compare_had_fp_operands = 0;") - (define_insn "*tstqi_internal" [(set (cc0) - (match_operand:QI 0 "nonimmediate_operand" "dm"))] + (compare (match_operand:QI 0 "nonimmediate_operand" "dm") + (const_int 0)))] "" "tst%.b %0" [(set_attr "type" "tst")]) -(define_expand "tst<mode>" - [(set (cc0) - (match_operand:FP 0 "general_operand" ""))] - "TARGET_HARD_FLOAT" -{ - m68k_last_compare_had_fp_operands = 1; -}) - (define_insn "tst<mode>_68881" [(set (cc0) - (match_operand:FP 0 "general_operand" "f<FP:dreg>m"))] + (compare (match_operand:FP 0 "general_operand" "f<FP:dreg>m") + (match_operand:FP 1 "const0_operand" "H")))] "TARGET_68881" { cc_status.flags = CC_IN_68881; @@ -414,7 +386,8 @@ (define_insn "tst<mode>_cf" [(set (cc0) - (match_operand:FP 0 "general_operand" "f<FP:dreg><Q>U"))] + (compare (match_operand:FP 0 "general_operand" "f<FP:dreg><Q>U") + (match_operand:FP 1 "const0_operand" "H")))] "TARGET_COLDFIRE_FPU" { cc_status.flags = CC_IN_68881; @@ -427,20 +400,11 @@ ;; compare instructions. -(define_expand "cmpdi" - [(parallel - [(set (cc0) - (compare (match_operand:DI 0 "nonimmediate_operand" "") - (match_operand:DI 1 "general_operand" ""))) - (clobber (match_scratch:DI 2 ""))])] - "" - "m68k_last_compare_had_fp_operands = 0;") - -(define_insn "" - [(set (cc0) - (compare (match_operand:DI 1 "nonimmediate_operand" "0,d") - (match_operand:DI 2 "general_operand" "d,0"))) - (clobber (match_scratch:DI 0 "=d,d"))] +(define_insn "*cmpdi_internal" + [(set (cc0) + (compare (match_operand:DI 1 "nonimmediate_operand" "0,d") + (match_operand:DI 2 "general_operand" "d,0"))) + (clobber (match_scratch:DI 0 "=d,d"))] "" { if (rtx_equal_p (operands[0], operands[1])) @@ -452,15 +416,71 @@ } }) -(define_expand "cmpsi" - [(set (cc0) - (compare (match_operand:SI 0 "nonimmediate_operand" "") - (match_operand:SI 1 "general_operand" "")))] +(define_insn "cmpdi" + [(set (cc0) + (compare (match_operand:DI 0 "nonimmediate_operand") + (match_operand:DI 1 "general_operand"))) + (clobber (match_scratch:DI 2))] + "" + "") + + +(define_expand "cbranchdi4" + [(set (pc) + (if_then_else (match_operator 0 "ordered_comparison_operator" + [(match_operand:DI 1 "nonimmediate_operand") + (match_operand:DI 2 "general_operand")]) + (label_ref (match_operand 3 "")) + (pc)))] "" { - m68k_last_compare_had_fp_operands = 0; + if (operands[2] == const0_rtx) + emit_insn (gen_tstdi (operands[1])); + else + emit_insn (gen_cmpdi (operands[1], operands[2])); + operands[1] = cc0_rtx; + operands[2] = const0_rtx; +}) + +(define_expand "cstoredi4" + [(set (match_operand:QI 0 "register_operand") + (match_operator:QI 1 "ordered_comparison_operator" + [(match_operand:DI 2 "nonimmediate_operand") + (match_operand:DI 3 "general_operand")]))] + "" +{ + if (operands[3] == const0_rtx) + emit_insn (gen_tstdi (operands[2])); + else + emit_insn (gen_cmpdi (operands[2], operands[3])); + operands[2] = cc0_rtx; + operands[3] = const0_rtx; }) + +(define_expand "cbranchsi4" + [(set (cc0) + (compare (match_operand:SI 1 "nonimmediate_operand" "") + (match_operand:SI 2 "general_operand" ""))) + (set (pc) + (if_then_else (match_operator 0 "ordered_comparison_operator" + [(cc0) (const_int 0)]) + (label_ref (match_operand 3 "")) + (pc)))] + "" + "") + +(define_expand "cstoresi4" + [(set (cc0) + (compare (match_operand:SI 2 "nonimmediate_operand" "") + (match_operand:SI 3 "general_operand" ""))) + (set (match_operand:QI 0 "register_operand") + (match_operator:QI 1 "ordered_comparison_operator" + [(cc0) (const_int 0)]))] + "" + "") + + ;; A composite of the cmp, cmpa, cmpi & cmpm m68000 op codes. (define_insn "" [(set (cc0) @@ -500,12 +520,27 @@ } [(set_attr "type" "cmp_l")]) -(define_expand "cmphi" +(define_expand "cbranchhi4" [(set (cc0) - (compare (match_operand:HI 0 "nonimmediate_src_operand" "") - (match_operand:HI 1 "general_src_operand" "")))] - "!TARGET_COLDFIRE" - "m68k_last_compare_had_fp_operands = 0;") + (compare (match_operand:HI 1 "nonimmediate_src_operand" "") + (match_operand:HI 2 "m68k_subword_comparison_operand" ""))) + (set (pc) + (if_then_else (match_operator 0 "ordered_comparison_operator" + [(cc0) (const_int 0)]) + (label_ref (match_operand 3 "")) + (pc)))] + "" + "") + +(define_expand "cstorehi4" + [(set (cc0) + (compare (match_operand:HI 2 "nonimmediate_operand" "") + (match_operand:HI 3 "m68k_subword_comparison_operand" ""))) + (set (match_operand:QI 0 "register_operand") + (match_operator:QI 1 "ordered_comparison_operator" + [(cc0) (const_int 0)]))] + "" + "") (define_insn "" [(set (cc0) @@ -524,12 +559,27 @@ return "cmp%.w %d1,%d0"; }) -(define_expand "cmpqi" +(define_expand "cbranchqi4" [(set (cc0) - (compare (match_operand:QI 0 "nonimmediate_src_operand" "") - (match_operand:QI 1 "general_src_operand" "")))] - "!TARGET_COLDFIRE" - "m68k_last_compare_had_fp_operands = 0;") + (compare (match_operand:QI 1 "nonimmediate_src_operand" "") + (match_operand:QI 2 "m68k_subword_comparison_operand" ""))) + (set (pc) + (if_then_else (match_operator 0 "ordered_comparison_operator" + [(cc0) (const_int 0)]) + (label_ref (match_operand 3 "")) + (pc)))] + "" + "") + +(define_expand "cstoreqi4" + [(set (cc0) + (compare (match_operand:QI 2 "nonimmediate_src_operand" "") + (match_operand:QI 3 "m68k_subword_comparison_operand" ""))) + (set (match_operand:QI 0 "register_operand") + (match_operator:QI 1 "ordered_comparison_operator" + [(cc0) (const_int 0)]))] + "" + "") (define_insn "" [(set (cc0) @@ -548,12 +598,28 @@ return "cmp%.b %d1,%d0"; }) -(define_expand "cmp<mode>" +(define_expand "cbranch<mode>4" [(set (cc0) - (compare (match_operand:FP 0 "register_operand" "") - (match_operand:FP 1 "fp_src_operand" "")))] + (compare (match_operand:FP 1 "register_operand" "") + (match_operand:FP 2 "fp_src_operand" ""))) + (set (pc) + (if_then_else (match_operator 0 "comparison_operator" + [(cc0) (const_int 0)]) + (label_ref (match_operand 3 "")) + (pc)))] "TARGET_HARD_FLOAT" - "m68k_last_compare_had_fp_operands = 1;") + "") + +(define_expand "cstore<mode>4" + [(set (cc0) + (compare (match_operand:FP 2 "register_operand" "") + (match_operand:FP 3 "fp_src_operand" ""))) + (set (match_operand:QI 0 "register_operand") + (match_operator:QI 1 "m68k_cstore_comparison_operator" + [(cc0) (const_int 0)]))] + "TARGET_HARD_FLOAT && !(TUNE_68060 || TARGET_COLDFIRE_FPU)" + "if (TARGET_COLDFIRE && operands[2] != const0_rtx) + FAIL;") (define_insn "*cmp<mode>_68881" [(set (cc0) @@ -588,10 +654,13 @@ ;; from a MEM at a constant bit position if we can't use this as a constraint. (define_insn "" - [(set (cc0) (zero_extract (match_operand:QI 0 "memory_src_operand" "oS") - (const_int 1) - (minus:SI (const_int 7) - (match_operand:SI 1 "general_operand" "di"))))] + [(set + (cc0) + (compare (zero_extract:SI (match_operand:QI 0 "memory_src_operand" "oS") + (const_int 1) + (minus:SI (const_int 7) + (match_operand:SI 1 "general_operand" "di"))) + (const_int 0)))] "!TARGET_COLDFIRE" { return output_btst (operands, operands[1], operands[0], insn, 7); @@ -601,20 +670,26 @@ ;; has been deleted. (define_insn "" - [(set (cc0) (zero_extract (match_operand:QI 0 "memory_operand" "o") - (const_int 1) - (minus:SI (const_int 7) - (match_operand:SI 1 "general_operand" "d"))))] + [(set + (cc0) + (compare (zero_extract:SI (match_operand:QI 0 "memory_operand" "o") + (const_int 1) + (minus:SI (const_int 7) + (match_operand:SI 1 "general_operand" "d"))) + (const_int 0)))] "TARGET_COLDFIRE" { return output_btst (operands, operands[1], operands[0], insn, 7); }) (define_insn "" - [(set (cc0) (zero_extract (match_operand:SI 0 "register_operand" "d") - (const_int 1) - (minus:SI (const_int 31) - (match_operand:SI 1 "general_operand" "di"))))] + [(set + (cc0) + (compare (zero_extract:SI (match_operand:SI 0 "register_operand" "d") + (const_int 1) + (minus:SI (const_int 31) + (match_operand:SI 1 "general_operand" "di"))) + (const_int 0)))] "" { return output_btst (operands, operands[1], operands[0], insn, 31); @@ -625,24 +700,30 @@ ;; are automatically masked to 3 or 5 bits. (define_insn "" - [(set (cc0) (zero_extract (match_operand:QI 0 "memory_operand" "o") - (const_int 1) - (minus:SI (const_int 7) - (and:SI - (match_operand:SI 1 "register_operand" "d") - (const_int 7)))))] + [(set + (cc0) + (compare (zero_extract:SI (match_operand:QI 0 "memory_operand" "o") + (const_int 1) + (minus:SI (const_int 7) + (and:SI + (match_operand:SI 1 "register_operand" "d") + (const_int 7)))) + (const_int 0)))] "" { return output_btst (operands, operands[1], operands[0], insn, 7); }) (define_insn "" - [(set (cc0) (zero_extract (match_operand:SI 0 "register_operand" "d") - (const_int 1) - (minus:SI (const_int 31) - (and:SI - (match_operand:SI 1 "register_operand" "d") - (const_int 31)))))] + [(set + (cc0) + (compare (zero_extract:SI (match_operand:SI 0 "register_operand" "d") + (const_int 1) + (minus:SI (const_int 31) + (and:SI + (match_operand:SI 1 "register_operand" "d") + (const_int 31)))) + (const_int 0)))] "" { return output_btst (operands, operands[1], operands[0], insn, 31); @@ -651,9 +732,12 @@ ;; Nonoffsettable mem refs are ok in this one pattern ;; since we don't try to adjust them. (define_insn "" - [(set (cc0) (zero_extract (match_operand:QI 0 "memory_operand" "m") - (const_int 1) - (match_operand:SI 1 "const_int_operand" "n")))] + [(set + (cc0) + (compare (zero_extract:SI (match_operand:QI 0 "memory_operand" "m") + (const_int 1) + (match_operand:SI 1 "const_int_operand" "n")) + (const_int 0)))] "(unsigned) INTVAL (operands[1]) < 8 && !TARGET_COLDFIRE" { operands[1] = GEN_INT (7 - INTVAL (operands[1])); @@ -661,9 +745,12 @@ }) (define_insn "" - [(set (cc0) (zero_extract (match_operand:SI 0 "register_operand" "do") - (const_int 1) - (match_operand:SI 1 "const_int_operand" "n")))] + [(set + (cc0) + (compare (zero_extract:SI (match_operand:SI 0 "register_operand" "do") + (const_int 1) + (match_operand:SI 1 "const_int_operand" "n")) + (const_int 0)))] "!TARGET_COLDFIRE" { if (GET_CODE (operands[0]) == MEM) @@ -681,9 +768,12 @@ ;; The 'o' has been replaced with 'Q'. (define_insn "" - [(set (cc0) (zero_extract (match_operand:SI 0 "register_operand" "dQ") - (const_int 1) - (match_operand:SI 1 "const_int_operand" "n")))] + [(set + (cc0) + (compare (zero_extract:SI (match_operand:SI 0 "register_operand" "dQ") + (const_int 1) + (match_operand:SI 1 "const_int_operand" "n")) + (const_int 0)))] "TARGET_COLDFIRE" { if (GET_CODE (operands[0]) == MEM) @@ -5751,9 +5841,10 @@ (define_insn "" [(set (cc0) - (zero_extract:SI (match_operand:QI 0 "memory_operand" "o") - (match_operand:SI 1 "const_int_operand" "n") - (match_operand:SI 2 "general_operand" "dn")))] + (compare (zero_extract:SI (match_operand:QI 0 "memory_operand" "o") + (match_operand:SI 1 "const_int_operand" "n") + (match_operand:SI 2 "general_operand" "dn")) + (const_int 0)))] "TARGET_68020 && TARGET_BITFIELD" { if (operands[1] == const1_rtx @@ -5776,9 +5867,10 @@ ;;; now handle the register cases (define_insn "" [(set (cc0) - (zero_extract:SI (match_operand:SI 0 "register_operand" "d") - (match_operand:SI 1 "const_int_operand" "n") - (match_operand:SI 2 "general_operand" "dn")))] + (compare (zero_extract:SI (match_operand:SI 0 "register_operand" "d") + (match_operand:SI 1 "const_int_operand" "n") + (match_operand:SI 2 "general_operand" "dn")) + (const_int 0)))] "TARGET_68020 && TARGET_BITFIELD" { if (operands[1] == const1_rtx @@ -5798,7 +5890,7 @@ (define_insn "scc0_di" [(set (match_operand:QI 0 "nonimmediate_operand" "=dm") - (match_operator 1 "valid_dbcc_comparison_p" + (match_operator 1 "ordered_comparison_operator" [(match_operand:DI 2 "general_operand" "ro") (const_int 0)]))] "! TARGET_COLDFIRE" { @@ -5807,7 +5899,7 @@ (define_insn "scc0_di_5200" [(set (match_operand:QI 0 "nonimmediate_operand" "=d") - (match_operator 1 "valid_dbcc_comparison_p" + (match_operator 1 "ordered_comparison_operator" [(match_operand:DI 2 "general_operand" "ro") (const_int 0)]))] "TARGET_COLDFIRE" { @@ -5816,7 +5908,7 @@ (define_insn "scc_di" [(set (match_operand:QI 0 "nonimmediate_operand" "=dm,dm") - (match_operator 1 "valid_dbcc_comparison_p" + (match_operator 1 "ordered_comparison_operator" [(match_operand:DI 2 "general_operand" "ro,r") (match_operand:DI 3 "general_operand" "r,ro")]))] "! TARGET_COLDFIRE" @@ -5826,7 +5918,7 @@ (define_insn "scc_di_5200" [(set (match_operand:QI 0 "nonimmediate_operand" "=d,d") - (match_operator 1 "valid_dbcc_comparison_p" + (match_operator 1 "ordered_comparison_operator" [(match_operand:DI 2 "general_operand" "ro,r") (match_operand:DI 3 "general_operand" "r,ro")]))] "TARGET_COLDFIRE" @@ -5838,19 +5930,6 @@ ;; memory, but we cannot allow it to be in memory in case the address ;; needs to be reloaded. -(define_expand "seq" - [(set (match_operand:QI 0 "register_operand" "") - (eq:QI (cc0) (const_int 0)))] - "" -{ - if ((TUNE_68060 || TARGET_COLDFIRE_FPU) - && m68k_last_compare_had_fp_operands) - { - m68k_last_compare_had_fp_operands = 0; - FAIL; - } -}) - (define_insn "" [(set (match_operand:QI 0 "register_operand" "=d") (eq:QI (cc0) (const_int 0)))] @@ -5860,19 +5939,6 @@ OUTPUT_JUMP ("seq %0", "fseq %0", "seq %0"); }) -(define_expand "sne" - [(set (match_operand:QI 0 "register_operand" "") - (ne:QI (cc0) (const_int 0)))] - "" -{ - if ((TUNE_68060 || TARGET_COLDFIRE_FPU) - && m68k_last_compare_had_fp_operands) - { - m68k_last_compare_had_fp_operands = 0; - FAIL; - } -}) - (define_insn "" [(set (match_operand:QI 0 "register_operand" "=d") (ne:QI (cc0) (const_int 0)))] @@ -5882,19 +5948,6 @@ OUTPUT_JUMP ("sne %0", "fsne %0", "sne %0"); }) -(define_expand "sgt" - [(set (match_operand:QI 0 "register_operand" "") - (gt:QI (cc0) (const_int 0)))] - "" -{ - if ((TUNE_68060 || TARGET_COLDFIRE_FPU) - && m68k_last_compare_had_fp_operands) - { - m68k_last_compare_had_fp_operands = 0; - FAIL; - } -}) - (define_insn "" [(set (match_operand:QI 0 "register_operand" "=d") (gt:QI (cc0) (const_int 0)))] @@ -5904,12 +5957,6 @@ OUTPUT_JUMP ("sgt %0", "fsgt %0", 0); }) -(define_expand "sgtu" - [(set (match_operand:QI 0 "register_operand" "") - (gtu:QI (cc0) (const_int 0)))] - "" - "") - (define_insn "" [(set (match_operand:QI 0 "register_operand" "=d") (gtu:QI (cc0) (const_int 0)))] @@ -5919,19 +5966,6 @@ return "shi %0"; }) -(define_expand "slt" - [(set (match_operand:QI 0 "register_operand" "") - (lt:QI (cc0) (const_int 0)))] - "" -{ - if ((TUNE_68060 || TARGET_COLDFIRE_FPU) - && m68k_last_compare_had_fp_operands) - { - m68k_last_compare_had_fp_operands = 0; - FAIL; - } -}) - (define_insn "" [(set (match_operand:QI 0 "register_operand" "=d") (lt:QI (cc0) (const_int 0)))] @@ -5941,12 +5975,6 @@ OUTPUT_JUMP ("slt %0", "fslt %0", "smi %0"); }) -(define_expand "sltu" - [(set (match_operand:QI 0 "register_operand" "") - (ltu:QI (cc0) (const_int 0)))] - "" - "") - (define_insn "" [(set (match_operand:QI 0 "register_operand" "=d") (ltu:QI (cc0) (const_int 0)))] @@ -5956,19 +5984,6 @@ return "scs %0"; }) -(define_expand "sge" - [(set (match_operand:QI 0 "register_operand" "") - (ge:QI (cc0) (const_int 0)))] - "" -{ - if ((TUNE_68060 || TARGET_COLDFIRE_FPU) - && m68k_last_compare_had_fp_operands) - { - m68k_last_compare_had_fp_operands = 0; - FAIL; - } -}) - (define_insn "" [(set (match_operand:QI 0 "register_operand" "=d") (ge:QI (cc0) (const_int 0)))] @@ -5978,12 +5993,6 @@ OUTPUT_JUMP ("sge %0", "fsge %0", "spl %0"); }) -(define_expand "sgeu" - [(set (match_operand:QI 0 "register_operand" "") - (geu:QI (cc0) (const_int 0)))] - "" - "") - (define_insn "*scc" [(set (match_operand:QI 0 "register_operand" "=d") (geu:QI (cc0) (const_int 0)))] @@ -5994,19 +6003,6 @@ } [(set_attr "type" "scc")]) -(define_expand "sle" - [(set (match_operand:QI 0 "register_operand" "") - (le:QI (cc0) (const_int 0)))] - "" -{ - if ((TUNE_68060 || TARGET_COLDFIRE_FPU) - && m68k_last_compare_had_fp_operands) - { - m68k_last_compare_had_fp_operands = 0; - FAIL; - } -}) - (define_insn "" [(set (match_operand:QI 0 "register_operand" "=d") (le:QI (cc0) (const_int 0)))] @@ -6016,12 +6012,6 @@ OUTPUT_JUMP ("sle %0", "fsle %0", 0); }) -(define_expand "sleu" - [(set (match_operand:QI 0 "register_operand" "") - (leu:QI (cc0) (const_int 0)))] - "" - "") - (define_insn "*sls" [(set (match_operand:QI 0 "register_operand" "=d") (leu:QI (cc0) (const_int 0)))] @@ -6032,15 +6022,6 @@ } [(set_attr "type" "scc")]) -(define_expand "sordered" - [(set (match_operand:QI 0 "register_operand" "") - (ordered:QI (cc0) (const_int 0)))] - "TARGET_68881 && !TUNE_68060" -{ - gcc_assert (m68k_last_compare_had_fp_operands); - m68k_last_compare_had_fp_operands = 0; -}) - (define_insn "*sordered_1" [(set (match_operand:QI 0 "register_operand" "=d") (ordered:QI (cc0) (const_int 0)))] @@ -6050,15 +6031,6 @@ return "fsor %0"; }) -(define_expand "sunordered" - [(set (match_operand:QI 0 "register_operand" "") - (unordered:QI (cc0) (const_int 0)))] - "TARGET_68881 && !TUNE_68060" -{ - gcc_assert (m68k_last_compare_had_fp_operands); - m68k_last_compare_had_fp_operands = 0; -}) - (define_insn "*sunordered_1" [(set (match_operand:QI 0 "register_operand" "=d") (unordered:QI (cc0) (const_int 0)))] @@ -6068,15 +6040,6 @@ return "fsun %0"; }) -(define_expand "suneq" - [(set (match_operand:QI 0 "register_operand" "") - (uneq:QI (cc0) (const_int 0)))] - "TARGET_68881 && !TUNE_68060" -{ - gcc_assert (m68k_last_compare_had_fp_operands); - m68k_last_compare_had_fp_operands = 0; -}) - (define_insn "*suneq_1" [(set (match_operand:QI 0 "register_operand" "=d") (uneq:QI (cc0) (const_int 0)))] @@ -6086,15 +6049,6 @@ return "fsueq %0"; }) -(define_expand "sunge" - [(set (match_operand:QI 0 "register_operand" "") - (unge:QI (cc0) (const_int 0)))] - "TARGET_68881 && !TUNE_68060" -{ - gcc_assert (m68k_last_compare_had_fp_operands); - m68k_last_compare_had_fp_operands = 0; -}) - (define_insn "*sunge_1" [(set (match_operand:QI 0 "register_operand" "=d") (unge:QI (cc0) (const_int 0)))] @@ -6104,15 +6058,6 @@ return "fsuge %0"; }) -(define_expand "sungt" - [(set (match_operand:QI 0 "register_operand" "") - (ungt:QI (cc0) (const_int 0)))] - "TARGET_68881 && !TUNE_68060" -{ - gcc_assert (m68k_last_compare_had_fp_operands); - m68k_last_compare_had_fp_operands = 0; -}) - (define_insn "*sungt_1" [(set (match_operand:QI 0 "register_operand" "=d") (ungt:QI (cc0) (const_int 0)))] @@ -6122,15 +6067,6 @@ return "fsugt %0"; }) -(define_expand "sunle" - [(set (match_operand:QI 0 "register_operand" "") - (unle:QI (cc0) (const_int 0)))] - "TARGET_68881 && !TUNE_68060" -{ - gcc_assert (m68k_last_compare_had_fp_operands); - m68k_last_compare_had_fp_operands = 0; -}) - (define_insn "*sunle_1" [(set (match_operand:QI 0 "register_operand" "=d") (unle:QI (cc0) (const_int 0)))] @@ -6140,15 +6076,6 @@ return "fsule %0"; }) -(define_expand "sunlt" - [(set (match_operand:QI 0 "register_operand" "") - (unlt:QI (cc0) (const_int 0)))] - "TARGET_68881 && !TUNE_68060" -{ - gcc_assert (m68k_last_compare_had_fp_operands); - m68k_last_compare_had_fp_operands = 0; -}) - (define_insn "*sunlt_1" [(set (match_operand:QI 0 "register_operand" "=d") (unlt:QI (cc0) (const_int 0)))] @@ -6158,15 +6085,6 @@ return "fsult %0"; }) -(define_expand "sltgt" - [(set (match_operand:QI 0 "register_operand" "") - (ltgt:QI (cc0) (const_int 0)))] - "TARGET_68881 && !TUNE_68060" -{ - gcc_assert (m68k_last_compare_had_fp_operands); - m68k_last_compare_had_fp_operands = 0; -}) - (define_insn "*sltgt_1" [(set (match_operand:QI 0 "register_operand" "=d") (ltgt:QI (cc0) (const_int 0)))] @@ -7758,23 +7676,54 @@ "trap #7" [(set_attr "type" "trap")]) -(define_expand "conditional_trap" - [(trap_if (match_operator 0 "valid_dbcc_comparison_p" +(define_expand "ctrapdi4" + [(trap_if (match_operator 0 "ordered_comparison_operator" [(cc0) (const_int 0)]) - (match_operand:SI 1 "const_int_operand" "I"))] + (match_operand:SI 3 "const1_operand" ""))] "TARGET_68020" { - if (m68k_last_compare_had_fp_operands) - { - m68k_last_compare_had_fp_operands = 0; - FAIL; - } + if (operands[2] == const0_rtx) + emit_insn (gen_tstdi (operands[1])); + else + emit_insn (gen_cmpdi (operands[1], operands[2])); + operands[1] = cc0_rtx; + operands[2] = const0_rtx; }) +(define_expand "ctrapsi4" + [(set (cc0) + (compare (match_operand:SI 1 "nonimmediate_operand" "") + (match_operand:SI 2 "general_operand" ""))) + (trap_if (match_operator 0 "ordered_comparison_operator" + [(cc0) (const_int 0)]) + (match_operand:SI 3 "const1_operand" ""))] + "TARGET_68020" + "") + +(define_expand "ctraphi4" + [(set (cc0) + (compare (match_operand:HI 1 "nonimmediate_src_operand" "") + (match_operand:HI 2 "general_src_operand" ""))) + (trap_if (match_operator 0 "ordered_comparison_operator" + [(cc0) (const_int 0)]) + (match_operand:SI 3 "const1_operand" ""))] + "TARGET_68020" + "") + +(define_expand "ctrapqi4" + [(set (cc0) + (compare (match_operand:QI 1 "nonimmediate_src_operand" "") + (match_operand:QI 2 "general_src_operand" ""))) + (trap_if (match_operator 0 "ordered_comparison_operator" + [(cc0) (const_int 0)]) + (match_operand:SI 3 "const1_operand" ""))] + "TARGET_68020" + "") + (define_insn "*conditional_trap" - [(trap_if (match_operator 0 "valid_dbcc_comparison_p" + [(trap_if (match_operator 0 "ordered_comparison_operator" [(cc0) (const_int 0)]) - (match_operand:SI 1 "const_int_operand" "I"))] + (match_operand:SI 1 "const1_operand" "I"))] "TARGET_68020 && ! flags_in_68881 ()" { switch (GET_CODE (operands[0])) diff --git a/gcc/config/m68k/predicates.md b/gcc/config/m68k/predicates.md index b43e55b8972..417989f6d6c 100644 --- a/gcc/config/m68k/predicates.md +++ b/gcc/config/m68k/predicates.md @@ -124,6 +124,11 @@ (and (match_code "eq,ne,gtu,ltu,geu,leu,gt,lt,ge,le") (match_test "valid_dbcc_comparison_p_2 (op, mode)"))) +(define_predicate "m68k_cstore_comparison_operator" + (if_then_else (match_test "TARGET_68881") + (match_operand 0 "comparison_operator") + (match_operand 0 "ordered_comparison_operator"))) + ;; Check for sign_extend or zero_extend. Used for bit-count operands. (define_predicate "extend_operator" @@ -193,6 +198,24 @@ (and (match_code "mem") (match_test "GET_CODE (XEXP (op, 0)) == PRE_DEC"))) +;; A zero constant. +(define_predicate "const0_operand" + (and (match_code "const_int,const_double,const_vector") + (match_test "op == CONST0_RTX (mode)"))) + +;; A one constant (operand for conditional_trap). +(define_predicate "const1_operand" + (and (match_code "const_int") + (match_test "op == const1_rtx"))) + +;; A valid operand for a HImode or QImode conditional operation. +;; ColdFire has tst patterns, but not cmp patterns. +(define_predicate "m68k_subword_comparison_operand" + (if_then_else (match_test "TARGET_COLDFIRE") + (and (match_code "const_int") + (match_test "op == const0_rtx")) + (match_operand 0 "general_src_operand"))) + ;; An operand for movsi_const0 pattern. (define_predicate "movsi_const0_operand" (and (match_operand 0 "nonimmediate_operand") diff --git a/gcc/config/mcore/mcore-protos.h b/gcc/config/mcore/mcore-protos.h index 93c7c11e766..331cf7191d7 100644 --- a/gcc/config/mcore/mcore-protos.h +++ b/gcc/config/mcore/mcore-protos.h @@ -46,21 +46,17 @@ extern rtx mcore_function_value (const_tree, const_tree); #ifdef RTX_CODE -extern GTY(()) rtx arch_compare_op0; -extern GTY(()) rtx arch_compare_op1; - extern const char * mcore_output_bclri (rtx, int); extern const char * mcore_output_bseti (rtx, int); extern const char * mcore_output_cmov (rtx *, int, const char *); extern char * mcore_output_call (rtx *, int); extern int mcore_is_dead (rtx, rtx); extern int mcore_expand_insv (rtx *); -extern int mcore_modify_comparison (RTX_CODE); extern bool mcore_expand_block_move (rtx *); extern const char * mcore_output_andn (rtx, rtx *); extern void mcore_print_operand_address (FILE *, rtx); extern void mcore_print_operand (FILE *, rtx, int); -extern rtx mcore_gen_compare_reg (RTX_CODE); +extern bool mcore_gen_compare (RTX_CODE, rtx, rtx); extern int mcore_symbolic_address_p (rtx); extern bool mcore_r15_operand_p (rtx); extern enum reg_class mcore_secondary_reload_class (enum reg_class, enum machine_mode, rtx); diff --git a/gcc/config/mcore/mcore.c b/gcc/config/mcore/mcore.c index 24cc9406ed7..472bb75562a 100644 --- a/gcc/config/mcore/mcore.c +++ b/gcc/config/mcore/mcore.c @@ -57,11 +57,6 @@ long mcore_current_compilation_timestamp = 0; /* Global variables for machine-dependent things. */ -/* Saved operands from the last compare to use when we generate an scc - or bcc insn. */ -rtx arch_compare_op0; -rtx arch_compare_op1; - /* Provides the class number of the smallest class containing reg number. */ const int regno_reg_class[FIRST_PSEUDO_REGISTER] = @@ -519,26 +514,36 @@ mcore_rtx_costs (rtx x, int code, int outer_code, int * total, } } -/* Check to see if a comparison against a constant can be made more efficient - by incrementing/decrementing the constant to get one that is more efficient - to load. */ +/* Prepare the operands for a comparison. Return whether the branch/setcc + should reverse the operands. */ -int -mcore_modify_comparison (enum rtx_code code) +bool +mcore_gen_compare (enum rtx_code code, rtx op0, rtx op1) { - rtx op1 = arch_compare_op1; - + rtx cc_reg = gen_rtx_REG (CCmode, CC_REG); + bool invert; + if (GET_CODE (op1) == CONST_INT) { HOST_WIDE_INT val = INTVAL (op1); switch (code) { + case GTU: + /* Unsigned > 0 is the same as != 0; everything else is converted + below to LEU (reversed cmphs). */ + if (val == 0) + code = NE; + break; + + /* Check whether (LE A imm) can become (LT A imm + 1), + or (GT A imm) can become (GE A imm + 1). */ + case GT: case LE: if (CONST_OK_FOR_J (val + 1)) { - arch_compare_op1 = GEN_INT (val + 1); - return 1; + op1 = GEN_INT (val + 1); + code = code == LE ? LT : GE; } break; @@ -546,28 +551,18 @@ mcore_modify_comparison (enum rtx_code code) break; } } - - return 0; -} - -/* Prepare the operands for a comparison. */ - -rtx -mcore_gen_compare_reg (enum rtx_code code) -{ - rtx op0 = arch_compare_op0; - rtx op1 = arch_compare_op1; - rtx cc_reg = gen_rtx_REG (CCmode, CC_REG); - + if (CONSTANT_P (op1) && GET_CODE (op1) != CONST_INT) op1 = force_reg (SImode, op1); /* cmpnei: 0-31 (K immediate) cmplti: 1-32 (J immediate, 0 using btsti x,31). */ + invert = false; switch (code) { case EQ: /* Use inverted condition, cmpne. */ code = NE; + invert = true; /* Drop through. */ case NE: /* Use normal condition, cmpne. */ @@ -577,6 +572,7 @@ mcore_gen_compare_reg (enum rtx_code code) case LE: /* Use inverted condition, reversed cmplt. */ code = GT; + invert = true; /* Drop through. */ case GT: /* Use normal condition, reversed cmplt. */ @@ -586,6 +582,7 @@ mcore_gen_compare_reg (enum rtx_code code) case GE: /* Use inverted condition, cmplt. */ code = LT; + invert = true; /* Drop through. */ case LT: /* Use normal condition, cmplt. */ @@ -597,13 +594,10 @@ mcore_gen_compare_reg (enum rtx_code code) break; case GTU: /* Use inverted condition, cmple. */ - /* Unsigned > 0 is the same as != 0, but we need to invert the - condition, so we want to set code = EQ. This cannot be done - however, as the mcore does not support such a test. Instead - we cope with this case in the "bgtu" pattern itself so we - should never reach this point. */ + /* We coped with unsigned > 0 above. */ gcc_assert (GET_CODE (op1) != CONST_INT || INTVAL (op1) != 0); code = LEU; + invert = true; /* Drop through. */ case LEU: /* Use normal condition, reversed cmphs. */ @@ -613,6 +607,7 @@ mcore_gen_compare_reg (enum rtx_code code) case LTU: /* Use inverted condition, cmphs. */ code = GEU; + invert = true; /* Drop through. */ case GEU: /* Use normal condition, cmphs. */ @@ -624,9 +619,10 @@ mcore_gen_compare_reg (enum rtx_code code) break; } - emit_insn (gen_rtx_SET (VOIDmode, cc_reg, gen_rtx_fmt_ee (code, CCmode, op0, op1))); - - return cc_reg; + emit_insn (gen_rtx_SET (VOIDmode, + cc_reg, + gen_rtx_fmt_ee (code, CCmode, op0, op1))); + return invert; } int diff --git a/gcc/config/mcore/mcore.md b/gcc/config/mcore/mcore.md index 74906993e20..65b91588fc2 100644 --- a/gcc/config/mcore/mcore.md +++ b/gcc/config/mcore/mcore.md @@ -303,22 +303,6 @@ "" "cmphs %1,%0") -;; We save the compare operands in the cmpxx patterns and use them when -;; we generate the branch. - -;; We accept constants here, in case we can modify them to ones which -;; are more efficient to load. E.g. change 'x <= 62' to 'x < 63'. - -(define_expand "cmpsi" - [(set (reg:CC 17) (compare:CC (match_operand:SI 0 "mcore_compare_operand" "") - (match_operand:SI 1 "nonmemory_operand" "")))] - "" - " -{ arch_compare_op0 = operands[0]; - arch_compare_op1 = operands[1]; - DONE; -}") - ;; ------------------------------------------------------------------------- ;; Logical operations ;; ------------------------------------------------------------------------- @@ -1479,6 +1463,10 @@ ;; Define the real conditional branch instructions. ;; ------------------------------------------------------------------------ +;; At top-level, condition test are eq/ne, because we +;; are comparing against the condition register (which +;; has the result of the true relational test + (define_insn "branch_true" [(set (pc) (if_then_else (ne (reg:CC 17) (const_int 0)) (label_ref (match_operand 0 "" "")) @@ -1513,189 +1501,28 @@ ;; Conditional branch insns -;; At top-level, condition test are eq/ne, because we -;; are comparing against the condition register (which -;; has the result of the true relational test - -; There is no beq compare, so we reverse the branch arms. - -(define_expand "beq" - [(set (pc) (if_then_else (ne (match_dup 1) (const_int 0)) - (pc) - (label_ref (match_operand 0 "" ""))))] - "" - " -{ - operands[1] = mcore_gen_compare_reg (EQ); -}") - -(define_expand "bne" - [(set (pc) (if_then_else (ne (match_dup 1) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - operands[1] = mcore_gen_compare_reg (NE); -}") - -; check whether (GT A imm) can become (LE A imm) with the branch reversed. -; if so, emit a (LT A imm + 1) in place of the (LE A imm). BRC - -(define_expand "bgt" - [(set (pc) (if_then_else (ne (match_dup 1) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - if (mcore_modify_comparison (LE)) - { - emit_jump_insn (gen_reverse_blt (operands[0])); - DONE; - } - operands[1] = mcore_gen_compare_reg (GT); -}") - -; There is no ble compare, so we reverse the branch arms. -; reversed the condition and branch arms for ble -- the check_dbra_loop() -; transformation assumes that ble uses a branch-true with the label as -; as the target. BRC - -; check whether (LE A imm) can become (LT A imm + 1). - -(define_expand "ble" - [(set (pc) (if_then_else (eq (match_dup 1) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - if (mcore_modify_comparison (LE)) - { - emit_jump_insn (gen_blt (operands[0])); - DONE; - } - operands[1] = mcore_gen_compare_reg (LE); -}") - -; make generating a reversed blt simple -(define_expand "reverse_blt" - [(set (pc) (if_then_else (ne (match_dup 1) (const_int 0)) - (pc) - (label_ref (match_operand 0 "" ""))))] - "" - " -{ - operands[1] = mcore_gen_compare_reg (LT); -}") - -(define_expand "blt" - [(set (pc) (if_then_else (ne (match_dup 1) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - operands[1] = mcore_gen_compare_reg (LT); -}") - -; There is no bge compare, so we reverse the branch arms. - -(define_expand "bge" - [(set (pc) (if_then_else (ne (match_dup 1) (const_int 0)) - (pc) - (label_ref (match_operand 0 "" ""))))] - "" - " -{ - operands[1] = mcore_gen_compare_reg (GE); -}") - -; There is no gtu compare, so we reverse the branch arms - -;(define_expand "bgtu" -; [(set (pc) (if_then_else (ne (match_dup 1) (const_int 0)) -; (pc) -; (label_ref (match_operand 0 "" ""))))] -; "" -; " -;{ -; if (GET_CODE (arch_compare_op1) == CONST_INT -; && INTVAL (arch_compare_op1) == 0) -; operands[1] = mcore_gen_compare_reg (NE); -; else -; { if (mcore_modify_comparison (GTU)) -; { -; emit_jump_insn (gen_bgeu (operands[0])); -; DONE; -; } -; operands[1] = mcore_gen_compare_reg (LEU); -; } -;}") - -(define_expand "bgtu" - [(set (pc) (if_then_else (ne (match_dup 1) (const_int 0)) - (pc) - (label_ref (match_operand 0 "" ""))))] - "" - " -{ - if (GET_CODE (arch_compare_op1) == CONST_INT - && INTVAL (arch_compare_op1) == 0) - { - /* The inverse of '> 0' for an unsigned test is - '== 0' but we do not have such an instruction available. - Instead we must reverse the branch (back to the normal - ordering) and test '!= 0'. */ - - operands[1] = mcore_gen_compare_reg (NE); - - emit_jump_insn (gen_rtx_SET (VOIDmode, - pc_rtx, - gen_rtx_IF_THEN_ELSE (VOIDmode, - gen_rtx_NE (VOIDmode, - operands[1], - const0_rtx), - gen_rtx_LABEL_REF (VOIDmode,operands[0]), - pc_rtx))); - DONE; - } - operands[1] = mcore_gen_compare_reg (GTU); -}") - - -(define_expand "bleu" - [(set (pc) (if_then_else (ne (match_dup 1) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] +(define_expand "cbranchsi4" + [(set (pc) + (if_then_else (match_operator:SI 0 "ordered_comparison_operator" + [(match_operand:SI 1 "mcore_compare_operand") + (match_operand:SI 2 "nonmemory_operand")]) + (label_ref (match_operand 3 "")) + (pc)))] "" " { - operands[1] = mcore_gen_compare_reg (LEU); -}") + bool invert; + invert = mcore_gen_compare (GET_CODE (operands[0]), + operands[1], operands[2]); -; There is no bltu compare, so we reverse the branch arms -(define_expand "bltu" - [(set (pc) (if_then_else (ne (match_dup 1) (const_int 0)) - (pc) - (label_ref (match_operand 0 "" ""))))] - "" - " -{ - operands[1] = mcore_gen_compare_reg (LTU); + if (invert) + emit_jump_insn (gen_branch_false (operands[3])); + else + emit_jump_insn (gen_branch_true (operands[3])); + DONE; }") -(define_expand "bgeu" - [(set (pc) (if_then_else (ne (match_dup 1) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - operands[1] = mcore_gen_compare_reg (GEU); -}") ;; ------------------------------------------------------------------------ ;; Jump and linkage insns @@ -1853,118 +1680,23 @@ (set (match_dup 0) (eq:SI (reg:CC 17) (const_int 0)))]) -(define_expand "seq" - [(set (match_operand:SI 0 "mcore_arith_reg_operand" "") - (eq:SI (match_dup 1) (const_int 0)))] - "" - " -{ - operands[1] = mcore_gen_compare_reg (NE); -}") - -(define_expand "sne" - [(set (match_operand:SI 0 "mcore_arith_reg_operand" "") - (ne:SI (match_dup 1) (const_int 0)))] - "" - " -{ - operands[1] = mcore_gen_compare_reg (NE); -}") - -(define_expand "slt" - [(set (match_operand:SI 0 "mcore_arith_reg_operand" "") - (ne:SI (match_dup 1) (const_int 0)))] - "" - " -{ - operands[1] = mcore_gen_compare_reg (LT); -}") - -; make generating a LT with the comparison reversed easy. BRC -(define_expand "reverse_slt" - [(set (match_operand:SI 0 "mcore_arith_reg_operand" "") - (eq:SI (match_dup 1) (const_int 0)))] - "" - " -{ - operands[1] = mcore_gen_compare_reg (LT); -}") - -(define_expand "sge" - [(set (match_operand:SI 0 "mcore_arith_reg_operand" "") - (eq:SI (match_dup 1) (const_int 0)))] - "" - " -{ - operands[1] = mcore_gen_compare_reg (LT); -}") - -; check whether (GT A imm) can become (LE A imm) with the comparison -; reversed. if so, emit a (LT A imm + 1) in place of the (LE A imm). BRC - -(define_expand "sgt" - [(set (match_operand:SI 0 "mcore_arith_reg_operand" "") - (ne:SI (match_dup 1) (const_int 0)))] - "" - " -{ - if (mcore_modify_comparison (LE)) - { - emit_insn (gen_reverse_slt (operands[0])); - DONE; - } - - operands[1] = mcore_gen_compare_reg (GT); -}") - -(define_expand "sle" - [(set (match_operand:SI 0 "mcore_arith_reg_operand" "") - (eq:SI (match_dup 1) (const_int 0)))] - "" - " -{ - if (mcore_modify_comparison (LE)) - { - emit_insn (gen_slt (operands[0])); - DONE; - } - operands[1] = mcore_gen_compare_reg (GT); -}") - -(define_expand "sltu" - [(set (match_operand:SI 0 "mcore_arith_reg_operand" "") - (eq:SI (match_dup 1) (const_int 0)))] - "" - " -{ - operands[1] = mcore_gen_compare_reg (GEU); -}") - -(define_expand "sgeu" - [(set (match_operand:SI 0 "mcore_arith_reg_operand" "") - (ne:SI (match_dup 1) (const_int 0)))] - "" - " -{ - operands[1] = mcore_gen_compare_reg (GEU); -}") - -(define_expand "sgtu" +(define_expand "cstoresi4" [(set (match_operand:SI 0 "mcore_arith_reg_operand" "") - (eq:SI (match_dup 1) (const_int 0)))] + (match_operator:SI 1 "ordered_comparison_operator" + [(match_operand:SI 2 "mcore_compare_operand" "") + (match_operand:SI 3 "nonmemory_operand" "")]))] "" " { - operands[1] = mcore_gen_compare_reg (LEU); -}") + bool invert; + invert = mcore_gen_compare (GET_CODE (operands[1]), + operands[2], operands[3]); -(define_expand "sleu" - [(set (match_operand:SI 0 "mcore_arith_reg_operand" "") - (ne:SI (match_dup 1) (const_int 0)))] - "" - " -{ - operands[1] = mcore_gen_compare_reg (LEU); + if (invert) + emit_insn (gen_mvcv (operands[0])); + else + emit_insn (gen_mvc (operands[0])); + DONE; }") (define_insn "incscc" @@ -3308,7 +3040,7 @@ rtx loop_label = gen_label_rtx (); rtx step = gen_reg_rtx (Pmode); rtx tmp = gen_reg_rtx (Pmode); - rtx memref; + rtx test, memref; #if 1 emit_insn (gen_movsi (tmp, operands[1])); @@ -3317,8 +3049,8 @@ if (GET_CODE (operands[1]) != CONST_INT) { out_label = gen_label_rtx (); - emit_insn (gen_cmpsi (step, tmp)); /* quick out */ - emit_jump_insn (gen_bgeu (out_label)); + test = gen_rtx_GEU (VOIDmode, step, tmp); /* quick out */ + emit_jump_insn (gen_cbranchsi4 (test, step, tmp, out_label)); } /* Run a loop that steps it incrementally. */ @@ -3332,8 +3064,8 @@ emit_insn(gen_subsi3(tmp, tmp, step)); /* Loop condition -- going back up. */ - emit_insn (gen_cmpsi (step, tmp)); - emit_jump_insn (gen_bltu (loop_label)); + test = gen_rtx_LTU (VOIDmode, step, tmp); + emit_jump_insn (gen_cbranchsi4 (test, step, tmp, loop_label)); if (out_label) emit_label (out_label); diff --git a/gcc/config/mips/mips-protos.h b/gcc/config/mips/mips-protos.h index b95461a4c4f..f2c67b84908 100644 --- a/gcc/config/mips/mips-protos.h +++ b/gcc/config/mips/mips-protos.h @@ -222,11 +222,11 @@ extern void mips_split_doubleword_move (rtx, rtx); extern const char *mips_output_move (rtx, rtx); extern void mips_restore_gp (rtx); #ifdef RTX_CODE -extern bool mips_expand_scc (enum rtx_code, rtx); -extern void mips_expand_conditional_branch (rtx *, enum rtx_code); +extern void mips_expand_scc (rtx *); +extern void mips_expand_conditional_branch (rtx *); extern void mips_expand_vcondv2sf (rtx, rtx, rtx, enum rtx_code, rtx, rtx); extern void mips_expand_conditional_move (rtx *); -extern void mips_expand_conditional_trap (enum rtx_code); +extern void mips_expand_conditional_trap (rtx); #endif extern bool mips_use_pic_fn_addr_reg_p (const_rtx); extern rtx mips_expand_call (enum mips_call_type, rtx, rtx, rtx, rtx, bool); diff --git a/gcc/config/mips/mips-ps-3d.md b/gcc/config/mips/mips-ps-3d.md index d4efe4cbf79..98932d85b11 100644 --- a/gcc/config/mips/mips-ps-3d.md +++ b/gcc/config/mips/mips-ps-3d.md @@ -58,7 +58,7 @@ MOVZ.PS. MOVT.PS and MOVF.PS depend on two CC values and move each item independently. */ - if (GET_MODE_CLASS (GET_MODE (cmp_operands[0])) != MODE_INT) + if (GET_MODE_CLASS (GET_MODE (XEXP (operands[1], 0))) != MODE_INT) FAIL; mips_expand_conditional_move (operands); diff --git a/gcc/config/mips/mips.c b/gcc/config/mips/mips.c index 32c898bcf83..9d712d2f096 100644 --- a/gcc/config/mips/mips.c +++ b/gcc/config/mips/mips.c @@ -448,9 +448,6 @@ static int set_noat; normal branch. */ static bool mips_branch_likely; -/* The operands passed to the last cmpMM expander. */ -rtx cmp_operands[2]; - /* The current instruction-set architecture. */ enum processor_type mips_arch; const struct mips_cpu_info *mips_arch_info; @@ -4221,8 +4218,8 @@ mips_reversed_fp_cond (enum rtx_code *code) } /* Convert a comparison into something that can be used in a branch or - conditional move. cmp_operands[0] and cmp_operands[1] are the values - being compared and *CODE is the code used to compare them. + conditional move. On entry, *OP0 and *OP1 are the values being + compared and *CODE is the code used to compare them. Update *CODE, *OP0 and *OP1 so that they describe the final comparison. If NEED_EQ_NE_P, then only EQ or NE comparisons against zero are possible, @@ -4235,42 +4232,38 @@ mips_reversed_fp_cond (enum rtx_code *code) static void mips_emit_compare (enum rtx_code *code, rtx *op0, rtx *op1, bool need_eq_ne_p) { - if (GET_MODE_CLASS (GET_MODE (cmp_operands[0])) == MODE_INT) + rtx cmp_op0 = *op0; + rtx cmp_op1 = *op1; + + if (GET_MODE_CLASS (GET_MODE (*op0)) == MODE_INT) { - if (!need_eq_ne_p && cmp_operands[1] == const0_rtx) - { - *op0 = cmp_operands[0]; - *op1 = cmp_operands[1]; - } + if (!need_eq_ne_p && *op1 == const0_rtx) + ; else if (*code == EQ || *code == NE) { if (need_eq_ne_p) { - *op0 = mips_zero_if_equal (cmp_operands[0], cmp_operands[1]); + *op0 = mips_zero_if_equal (cmp_op0, cmp_op1); *op1 = const0_rtx; } else - { - *op0 = cmp_operands[0]; - *op1 = force_reg (GET_MODE (*op0), cmp_operands[1]); - } + *op1 = force_reg (GET_MODE (cmp_op0), cmp_op1); } else { /* The comparison needs a separate scc instruction. Store the result of the scc in *OP0 and compare it against zero. */ bool invert = false; - *op0 = gen_reg_rtx (GET_MODE (cmp_operands[0])); - mips_emit_int_order_test (*code, &invert, *op0, - cmp_operands[0], cmp_operands[1]); + *op0 = gen_reg_rtx (GET_MODE (cmp_op0)); + mips_emit_int_order_test (*code, &invert, *op0, cmp_op0, cmp_op1); *code = (invert ? EQ : NE); *op1 = const0_rtx; } } - else if (ALL_FIXED_POINT_MODE_P (GET_MODE (cmp_operands[0]))) + else if (ALL_FIXED_POINT_MODE_P (GET_MODE (cmp_op0))) { *op0 = gen_rtx_REG (CCDSPmode, CCDSP_CC_REGNUM); - mips_emit_binary (*code, *op0, cmp_operands[0], cmp_operands[1]); + mips_emit_binary (*code, *op0, cmp_op0, cmp_op1); *code = NE; *op1 = const0_rtx; } @@ -4290,49 +4283,55 @@ mips_emit_compare (enum rtx_code *code, rtx *op0, rtx *op1, bool need_eq_ne_p) ? gen_reg_rtx (CCmode) : gen_rtx_REG (CCmode, FPSW_REGNUM)); *op1 = const0_rtx; - mips_emit_binary (cmp_code, *op0, cmp_operands[0], cmp_operands[1]); + mips_emit_binary (cmp_code, *op0, cmp_op0, cmp_op1); } } -/* Try comparing cmp_operands[0] and cmp_operands[1] using rtl code CODE. - Store the result in TARGET and return true if successful. +/* Try performing the comparison in OPERANDS[1], whose arms are OPERANDS[2] + and OPERAND[3]. Store the result in OPERANDS[0]. - On 64-bit targets, TARGET may be narrower than cmp_operands[0]. */ + On 64-bit targets, the mode of the comparison and target will always be + SImode, thus possibly narrower than that of the comparison's operands. */ -bool -mips_expand_scc (enum rtx_code code, rtx target) +void +mips_expand_scc (rtx operands[]) { - if (GET_MODE_CLASS (GET_MODE (cmp_operands[0])) != MODE_INT) - return false; + rtx target = operands[0]; + enum rtx_code code = GET_CODE (operands[1]); + rtx op0 = operands[2]; + rtx op1 = operands[3]; + + gcc_assert (GET_MODE_CLASS (GET_MODE (op0)) == MODE_INT); if (code == EQ || code == NE) { if (ISA_HAS_SEQ_SNE - && reg_imm10_operand (cmp_operands[1], GET_MODE (cmp_operands[1]))) - mips_emit_binary (code, target, cmp_operands[0], cmp_operands[1]); + && reg_imm10_operand (op1, GET_MODE (op1))) + mips_emit_binary (code, target, op0, op1); else { - rtx zie = mips_zero_if_equal (cmp_operands[0], cmp_operands[1]); + rtx zie = mips_zero_if_equal (op0, op1); mips_emit_binary (code, target, zie, const0_rtx); } } else - mips_emit_int_order_test (code, 0, target, - cmp_operands[0], cmp_operands[1]); - return true; + mips_emit_int_order_test (code, 0, target, op0, op1); } -/* Compare cmp_operands[0] with cmp_operands[1] using comparison code - CODE and jump to OPERANDS[0] if the condition holds. */ +/* Compare OPERANDS[1] with OPERANDS[2] using comparison code + CODE and jump to OPERANDS[3] if the condition holds. */ void -mips_expand_conditional_branch (rtx *operands, enum rtx_code code) +mips_expand_conditional_branch (rtx *operands) { - rtx op0, op1, condition; + enum rtx_code code = GET_CODE (operands[0]); + rtx op0 = operands[1]; + rtx op1 = operands[2]; + rtx condition; mips_emit_compare (&code, &op0, &op1, TARGET_MIPS16); condition = gen_rtx_fmt_ee (code, VOIDmode, op0, op1); - emit_jump_insn (gen_condjump (condition, operands[0])); + emit_jump_insn (gen_condjump (condition, operands[3])); } /* Implement: @@ -4359,35 +4358,36 @@ mips_expand_vcondv2sf (rtx dest, rtx true_src, rtx false_src, cmp_result)); } -/* Compare cmp_operands[0] with cmp_operands[1] using the code of - OPERANDS[1]. Move OPERANDS[2] into OPERANDS[0] if the condition - holds, otherwise move OPERANDS[3] into OPERANDS[0]. */ +/* Perform the comparison in OPERANDS[1]. Move OPERANDS[2] into OPERANDS[0] + if the condition holds, otherwise move OPERANDS[3] into OPERANDS[0]. */ void mips_expand_conditional_move (rtx *operands) { - enum rtx_code code; - rtx cond, op0, op1; + rtx cond; + enum rtx_code code = GET_CODE (operands[1]); + rtx op0 = XEXP (operands[1], 0); + rtx op1 = XEXP (operands[1], 1); - code = GET_CODE (operands[1]); mips_emit_compare (&code, &op0, &op1, true); - cond = gen_rtx_fmt_ee (code, GET_MODE (op0), op0, op1), + cond = gen_rtx_fmt_ee (code, GET_MODE (op0), op0, op1); emit_insn (gen_rtx_SET (VOIDmode, operands[0], gen_rtx_IF_THEN_ELSE (GET_MODE (operands[0]), cond, operands[2], operands[3]))); } -/* Compare cmp_operands[0] with cmp_operands[1] using rtl code CODE, - then trap if the condition holds. */ +/* Perform the comparison in COMPARISON, then trap if the condition holds. */ void -mips_expand_conditional_trap (enum rtx_code code) +mips_expand_conditional_trap (rtx comparison) { rtx op0, op1; enum machine_mode mode; + enum rtx_code code; /* MIPS conditional trap instructions don't have GT or LE flavors, so we must swap the operands and convert to LT and GE respectively. */ + code = GET_CODE (comparison); switch (code) { case GT: @@ -4395,17 +4395,17 @@ mips_expand_conditional_trap (enum rtx_code code) case GTU: case LEU: code = swap_condition (code); - op0 = cmp_operands[1]; - op1 = cmp_operands[0]; + op0 = XEXP (comparison, 1); + op1 = XEXP (comparison, 0); break; default: - op0 = cmp_operands[0]; - op1 = cmp_operands[1]; + op0 = XEXP (comparison, 0); + op1 = XEXP (comparison, 1); break; } - mode = GET_MODE (cmp_operands[0]); + mode = GET_MODE (XEXP (comparison, 0)); op0 = force_reg (mode, op0); if (!arith_operand (op1, mode)) op1 = force_reg (mode, op1); @@ -6396,7 +6396,7 @@ static void mips_block_move_loop (rtx dest, rtx src, HOST_WIDE_INT length, HOST_WIDE_INT bytes_per_iter) { - rtx label, src_reg, dest_reg, final_src; + rtx label, src_reg, dest_reg, final_src, test; HOST_WIDE_INT leftover; leftover = length % bytes_per_iter; @@ -6423,11 +6423,11 @@ mips_block_move_loop (rtx dest, rtx src, HOST_WIDE_INT length, mips_emit_move (dest_reg, plus_constant (dest_reg, bytes_per_iter)); /* Emit the loop condition. */ + test = gen_rtx_NE (VOIDmode, src_reg, final_src); if (Pmode == DImode) - emit_insn (gen_cmpdi (src_reg, final_src)); + emit_jump_insn (gen_cbranchdi4 (test, src_reg, final_src, label)); else - emit_insn (gen_cmpsi (src_reg, final_src)); - emit_jump_insn (gen_bne (label)); + emit_jump_insn (gen_cbranchsi4 (test, src_reg, final_src, label)); /* Mop up any left-over bytes. */ if (leftover) diff --git a/gcc/config/mips/mips.h b/gcc/config/mips/mips.h index 5c68688ccce..301a26ec1ad 100644 --- a/gcc/config/mips/mips.h +++ b/gcc/config/mips/mips.h @@ -3432,7 +3432,6 @@ extern int mips_dbx_regno[]; extern int mips_dwarf_regno[]; extern bool mips_split_p[]; extern bool mips_split_hi_p[]; -extern GTY(()) rtx cmp_operands[2]; extern enum processor_type mips_arch; /* which cpu to codegen for */ extern enum processor_type mips_tune; /* which cpu to schedule for */ extern int mips_isa; /* architectural level */ diff --git a/gcc/config/mips/mips.md b/gcc/config/mips/mips.md index 95ba6ba2620..713bd834730 100644 --- a/gcc/config/mips/mips.md +++ b/gcc/config/mips/mips.md @@ -791,11 +791,6 @@ (DF "ISA_HAS_FP4 && TARGET_FLOAT64") (V2SF "TARGET_SB1")]) -;; This code iterator allows all branch instructions to be generated from -;; a single define_expand template. -(define_code_iterator any_cond [unordered ordered unlt unge uneq ltgt unle ungt - eq ne gt ge lt le gtu geu ltu leu]) - ;; This code iterator allows signed and unsigned widening multiplications ;; to use the same template. (define_code_iterator any_extend [sign_extend zero_extend]) @@ -994,19 +989,15 @@ } [(set_attr "type" "trap")]) -(define_expand "conditional_trap" +(define_expand "ctrap<mode>4" [(trap_if (match_operator 0 "comparison_operator" - [(match_dup 2) (match_dup 3)]) - (match_operand 1 "const_int_operand"))] + [(match_operand:GPR 1 "reg_or_0_operand") + (match_operand:GPR 2 "arith_operand")]) + (match_operand 3 "const_0_operand"))] "ISA_HAS_COND_TRAP" { - if (GET_MODE_CLASS (GET_MODE (cmp_operands[0])) == MODE_INT - && operands[1] == const0_rtx) - { - mips_expand_conditional_trap (GET_CODE (operands[0])); - DONE; - } - FAIL; + mips_expand_conditional_trap (operands[0]); + DONE; }) (define_insn "*conditional_trap<mode>" @@ -3243,6 +3234,7 @@ rtx reg3 = gen_reg_rtx (SImode); rtx label1 = gen_label_rtx (); rtx label2 = gen_label_rtx (); + rtx test; REAL_VALUE_TYPE offset; real_2expN (&offset, 31, DFmode); @@ -3252,8 +3244,8 @@ mips_emit_move (reg1, CONST_DOUBLE_FROM_REAL_VALUE (offset, DFmode)); do_pending_stack_adjust (); - emit_insn (gen_cmpdf (operands[1], reg1)); - emit_jump_insn (gen_bge (label1)); + test = gen_rtx_GE (VOIDmode, operands[1], reg1); + emit_jump_insn (gen_cbranchdf4 (test, operands[1], reg1, label1)); emit_insn (gen_fix_truncdfsi2 (operands[0], operands[1])); emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx, @@ -3288,6 +3280,7 @@ rtx reg3 = gen_reg_rtx (DImode); rtx label1 = gen_label_rtx (); rtx label2 = gen_label_rtx (); + rtx test; REAL_VALUE_TYPE offset; real_2expN (&offset, 63, DFmode); @@ -3295,8 +3288,8 @@ mips_emit_move (reg1, CONST_DOUBLE_FROM_REAL_VALUE (offset, DFmode)); do_pending_stack_adjust (); - emit_insn (gen_cmpdf (operands[1], reg1)); - emit_jump_insn (gen_bge (label1)); + test = gen_rtx_GE (VOIDmode, operands[1], reg1); + emit_jump_insn (gen_cbranchdf4 (test, operands[1], reg1, label1)); emit_insn (gen_fix_truncdfdi2 (operands[0], operands[1])); emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx, @@ -3330,6 +3323,7 @@ rtx reg3 = gen_reg_rtx (SImode); rtx label1 = gen_label_rtx (); rtx label2 = gen_label_rtx (); + rtx test; REAL_VALUE_TYPE offset; real_2expN (&offset, 31, SFmode); @@ -3337,8 +3331,8 @@ mips_emit_move (reg1, CONST_DOUBLE_FROM_REAL_VALUE (offset, SFmode)); do_pending_stack_adjust (); - emit_insn (gen_cmpsf (operands[1], reg1)); - emit_jump_insn (gen_bge (label1)); + test = gen_rtx_GE (VOIDmode, operands[1], reg1); + emit_jump_insn (gen_cbranchsf4 (test, operands[1], reg1, label1)); emit_insn (gen_fix_truncsfsi2 (operands[0], operands[1])); emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx, @@ -3372,6 +3366,7 @@ rtx reg3 = gen_reg_rtx (DImode); rtx label1 = gen_label_rtx (); rtx label2 = gen_label_rtx (); + rtx test; REAL_VALUE_TYPE offset; real_2expN (&offset, 63, SFmode); @@ -3379,8 +3374,8 @@ mips_emit_move (reg1, CONST_DOUBLE_FROM_REAL_VALUE (offset, SFmode)); do_pending_stack_adjust (); - emit_insn (gen_cmpsf (operands[1], reg1)); - emit_jump_insn (gen_bge (label1)); + test = gen_rtx_GE (VOIDmode, operands[1], reg1); + emit_jump_insn (gen_cbranchsf4 (test, operands[1], reg1, label1)); emit_insn (gen_fix_truncsfdi2 (operands[0], operands[1])); emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx, @@ -5011,50 +5006,6 @@ ;; ;; .................... ;; -;; COMPARISONS -;; -;; .................... - -;; Flow here is rather complex: -;; -;; 1) The cmp{si,di,sf,df} routine is called. It deposits the arguments -;; into cmp_operands[] but generates no RTL. -;; -;; 2) The appropriate branch define_expand is called, which then -;; creates the appropriate RTL for the comparison and branch. -;; Different CC modes are used, based on what type of branch is -;; done, so that we can constrain things appropriately. There -;; are assumptions in the rest of GCC that break if we fold the -;; operands into the branches for integer operations, and use cc0 -;; for floating point, so we use the fp status register instead. -;; If needed, an appropriate temporary is created to hold the -;; of the integer compare. - -(define_expand "cmp<mode>" - [(set (cc0) - (compare:CC (match_operand:GPR 0 "register_operand") - (match_operand:GPR 1 "nonmemory_operand")))] - "" -{ - cmp_operands[0] = operands[0]; - cmp_operands[1] = operands[1]; - DONE; -}) - -(define_expand "cmp<mode>" - [(set (cc0) - (compare:CC (match_operand:SCALARF 0 "register_operand") - (match_operand:SCALARF 1 "register_operand")))] - "" -{ - cmp_operands[0] = operands[0]; - cmp_operands[1] = operands[1]; - DONE; -}) - -;; -;; .................... -;; ;; CONDITIONAL BRANCHES ;; ;; .................... @@ -5189,15 +5140,29 @@ [(set_attr "type" "branch") (set_attr "mode" "none")]) -(define_expand "b<code>" +(define_expand "cbranch<mode>4" [(set (pc) - (if_then_else (any_cond:CC (cc0) - (const_int 0)) - (label_ref (match_operand 0 "")) + (if_then_else (match_operator 0 "comparison_operator" + [(match_operand:GPR 1 "register_operand") + (match_operand:GPR 2 "nonmemory_operand")]) + (label_ref (match_operand 3 "")) (pc)))] "" { - mips_expand_conditional_branch (operands, <CODE>); + mips_expand_conditional_branch (operands); + DONE; +}) + +(define_expand "cbranch<mode>4" + [(set (pc) + (if_then_else (match_operator 0 "comparison_operator" + [(match_operand:SCALARF 1 "register_operand") + (match_operand:SCALARF 2 "register_operand")]) + (label_ref (match_operand 3 "")) + (pc)))] + "" +{ + mips_expand_conditional_branch (operands); DONE; }) @@ -5261,12 +5226,16 @@ ;; Destination is always set in SI mode. -(define_expand "seq" +(define_expand "cstore<mode>4" [(set (match_operand:SI 0 "register_operand") - (eq:SI (match_dup 1) - (match_dup 2)))] + (match_operator:SI 1 "mips_cstore_operator" + [(match_operand:GPR 2 "register_operand") + (match_operand:GPR 3 "nonmemory_operand")]))] "" - { if (mips_expand_scc (EQ, operands[0])) DONE; else FAIL; }) +{ + mips_expand_scc (operands); + DONE; +}) (define_insn "*seq_zero_<GPR:mode><GPR2:mode>" [(set (match_operand:GPR2 0 "register_operand" "=d") @@ -5299,16 +5268,6 @@ [(set_attr "type" "slt") (set_attr "mode" "<GPR:MODE>")]) -;; "sne" uses sltu instructions in which the first operand is $0. -;; This isn't possible in mips16 code. - -(define_expand "sne" - [(set (match_operand:SI 0 "register_operand") - (ne:SI (match_dup 1) - (match_dup 2)))] - "!TARGET_MIPS16" - { if (mips_expand_scc (NE, operands[0])) DONE; else FAIL; }) - (define_insn "*sne_zero_<GPR:mode><GPR2:mode>" [(set (match_operand:GPR2 0 "register_operand" "=d") (ne:GPR2 (match_operand:GPR 1 "register_operand" "d") @@ -5331,13 +5290,6 @@ [(set_attr "type" "slt") (set_attr "mode" "<GPR:MODE>")]) -(define_expand "sgt<u>" - [(set (match_operand:SI 0 "register_operand") - (any_gt:SI (match_dup 1) - (match_dup 2)))] - "" - { if (mips_expand_scc (<CODE>, operands[0])) DONE; else FAIL; }) - (define_insn "*sgt<u>_<GPR:mode><GPR2:mode>" [(set (match_operand:GPR2 0 "register_operand" "=d") (any_gt:GPR2 (match_operand:GPR 1 "register_operand" "d") @@ -5356,13 +5308,6 @@ [(set_attr "type" "slt") (set_attr "mode" "<GPR:MODE>")]) -(define_expand "sge<u>" - [(set (match_operand:SI 0 "register_operand") - (any_ge:SI (match_dup 1) - (match_dup 2)))] - "" - { if (mips_expand_scc (<CODE>, operands[0])) DONE; else FAIL; }) - (define_insn "*sge<u>_<GPR:mode><GPR2:mode>" [(set (match_operand:GPR2 0 "register_operand" "=d") (any_ge:GPR2 (match_operand:GPR 1 "register_operand" "d") @@ -5372,13 +5317,6 @@ [(set_attr "type" "slt") (set_attr "mode" "<GPR:MODE>")]) -(define_expand "slt<u>" - [(set (match_operand:SI 0 "register_operand") - (any_lt:SI (match_dup 1) - (match_dup 2)))] - "" - { if (mips_expand_scc (<CODE>, operands[0])) DONE; else FAIL; }) - (define_insn "*slt<u>_<GPR:mode><GPR2:mode>" [(set (match_operand:GPR2 0 "register_operand" "=d") (any_lt:GPR2 (match_operand:GPR 1 "register_operand" "d") @@ -5402,13 +5340,6 @@ (const_int 4) (const_int 8))])]) -(define_expand "sle<u>" - [(set (match_operand:SI 0 "register_operand") - (any_le:SI (match_dup 1) - (match_dup 2)))] - "" - { if (mips_expand_scc (<CODE>, operands[0])) DONE; else FAIL; }) - (define_insn "*sle<u>_<GPR:mode><GPR2:mode>" [(set (match_operand:GPR2 0 "register_operand" "=d") (any_le:GPR2 (match_operand:GPR 1 "register_operand" "d") diff --git a/gcc/config/mips/predicates.md b/gcc/config/mips/predicates.md index aaebdded674..d32eaf13f8e 100644 --- a/gcc/config/mips/predicates.md +++ b/gcc/config/mips/predicates.md @@ -285,6 +285,12 @@ (define_predicate "order_operator" (match_code "lt,ltu,le,leu,ge,geu,gt,gtu")) +;; For NE, cstore uses sltu instructions in which the first operand is $0. +;; This isn't possible in mips16 code. + +(define_predicate "mips_cstore_operator" + (ior (match_code "eq,gt,gtu,ge,geu,lt,ltu,le,leu") + (and (match_code "ne") (match_test "!TARGET_MIPS16")))) (define_predicate "small_data_pattern" (and (match_code "set,parallel,unspec,unspec_volatile,prefetch") diff --git a/gcc/config/mmix/mmix-protos.h b/gcc/config/mmix/mmix-protos.h index d71064aa6d7..d294d8ff0ed 100644 --- a/gcc/config/mmix/mmix-protos.h +++ b/gcc/config/mmix/mmix-protos.h @@ -96,7 +96,6 @@ extern void mmix_setup_frame_addresses (void); /* Needs to be ifdef:d for sake of enum rtx_code. */ extern enum machine_mode mmix_select_cc_mode (enum rtx_code, rtx, rtx); extern void mmix_canonicalize_comparison (enum rtx_code *, rtx *, rtx *); -extern int mmix_valid_comparison (enum rtx_code, enum machine_mode, rtx); extern rtx mmix_gen_compare_reg (enum rtx_code, rtx, rtx); #endif diff --git a/gcc/config/mmix/mmix.c b/gcc/config/mmix/mmix.c index ceed8dbb6db..6ced05c04dc 100644 --- a/gcc/config/mmix/mmix.c +++ b/gcc/config/mmix/mmix.c @@ -2359,70 +2359,14 @@ mmix_shiftable_wyde_value (unsigned HOST_WIDEST_INT value) return 1; } -/* Returns zero if code and mode is not a valid condition from a - compare-type insn. Nonzero if it is. The parameter op, if non-NULL, - is the comparison of mode is CC-somethingmode. */ - -int -mmix_valid_comparison (RTX_CODE code, enum machine_mode mode, rtx op) -{ - if (mode == VOIDmode && op != NULL_RTX) - mode = GET_MODE (op); - - /* We don't care to look at these, they should always be valid. */ - if (mode == CCmode || mode == CC_UNSmode || mode == DImode) - return 1; - - if ((mode == CC_FPmode || mode == DFmode) - && (code == GT || code == LT)) - return 1; - - if ((mode == CC_FPEQmode || mode == DFmode) - && (code == EQ || code == NE)) - return 1; - - if ((mode == CC_FUNmode || mode == DFmode) - && (code == ORDERED || code == UNORDERED)) - return 1; - - return 0; -} - -/* X and Y are two things to compare using CODE. Emit a compare insn if - possible and return the rtx for the cc-reg in the proper mode, or - NULL_RTX if this is not a valid comparison. */ +/* X and Y are two things to compare using CODE. Return the rtx for + the cc-reg in the proper mode. */ rtx mmix_gen_compare_reg (RTX_CODE code, rtx x, rtx y) { enum machine_mode ccmode = SELECT_CC_MODE (code, x, y); - rtx cc_reg; - - /* FIXME: Do we get constants here? Of double mode? */ - enum machine_mode mode - = GET_MODE (x) == VOIDmode - ? GET_MODE (y) - : GET_MODE_CLASS (GET_MODE (x)) == MODE_FLOAT ? DFmode : DImode; - - if (! mmix_valid_comparison (code, mode, x)) - return NULL_RTX; - - cc_reg = gen_reg_rtx (ccmode); - - /* FIXME: Can we avoid emitting a compare insn here? */ - if (! REG_P (x) && ! REG_P (y)) - x = force_reg (mode, x); - - /* If it's not quite right yet, put y in a register. */ - if (! REG_P (y) - && (GET_CODE (y) != CONST_INT - || ! CONST_OK_FOR_LETTER_P (INTVAL (y), 'I'))) - y = force_reg (mode, y); - - emit_insn (gen_rtx_SET (VOIDmode, cc_reg, - gen_rtx_COMPARE (ccmode, x, y))); - - return cc_reg; + return gen_reg_rtx (ccmode); } /* Local (static) helper functions. */ diff --git a/gcc/config/mmix/mmix.h b/gcc/config/mmix/mmix.h index a7fb6e5884e..5a0582df26b 100644 --- a/gcc/config/mmix/mmix.h +++ b/gcc/config/mmix/mmix.h @@ -81,11 +81,6 @@ along with GCC; see the file COPYING3. If not see #define MMIX_FUNCTION_ARG_SIZE(MODE, TYPE) \ ((MODE) != BLKmode ? GET_MODE_SIZE (MODE) : int_size_in_bytes (TYPE)) -/* Declarations for helper variables that are not tied to a particular - target macro. */ -extern GTY(()) rtx mmix_compare_op0; -extern GTY(()) rtx mmix_compare_op1; - /* Per-function machine data. This is normally an opaque type just defined and used in the tm.c file, but we need to see the definition in mmix.md too. */ diff --git a/gcc/config/mmix/mmix.md b/gcc/config/mmix/mmix.md index aa878af0f82..44263e47f64 100644 --- a/gcc/config/mmix/mmix.md +++ b/gcc/config/mmix/mmix.md @@ -440,30 +440,6 @@ DIVU %1,%1,%2\;GET %0,:rR\;NEGU %2,0,%0\;CSNN %0,$255,%2") "" "NOR %0,%1,0") -;; Since we don't have cc0, we do what is recommended in the manual; -;; store away the operands for use in the branch, scc or movcc insn. -(define_expand "cmpdi" - [(match_operand:DI 0 "register_operand" "") - (match_operand:DI 1 "mmix_reg_or_8bit_operand" "")] - "" - " -{ - mmix_compare_op0 = operands[0]; - mmix_compare_op1 = operands[1]; - DONE; -}") - -(define_expand "cmpdf" - [(match_operand:DF 0 "register_operand" "") - (match_operand:DF 1 "register_operand" "")] - "" - " -{ - mmix_compare_op0 = operands[0]; - mmix_compare_op1 = operands[1]; - DONE; -}") - ;; When the user-patterns expand, the resulting insns will match the ;; patterns below. @@ -474,7 +450,7 @@ DIVU %1,%1,%2\;GET %0,:rR\;NEGU %2,0,%0\;CSNN %0,$255,%2") ;; unsigned, so that has to be done another way. ;; FIXME: Perhaps a peep2 changing CCcode to a new code, that ;; gets folded here. -(define_insn "*cmpcc_folded" +(define_insn "*cmpdi_folded" [(set (match_operand:CC 0 "register_operand" "=r") (compare:CC (match_operand:DI 1 "register_operand" "r") @@ -485,7 +461,7 @@ DIVU %1,%1,%2\;GET %0,:rR\;NEGU %2,0,%0\;CSNN %0,$255,%2") && REGNO (operands[1]) == REGNO (operands[0])" "%% folded: cmp %0,%1,0") -(define_insn "*cmpcc" +(define_insn "*cmps" [(set (match_operand:CC 0 "register_operand" "=r") (compare:CC (match_operand:DI 1 "register_operand" "r") @@ -724,7 +700,8 @@ DIVU %1,%1,%2\;GET %0,:rR\;NEGU %2,0,%0\;CSNN %0,$255,%2") ;; 0 to use in movdfcc. (define_expand "movdfcc" - [(set (match_operand:DF 0 "register_operand" "") + [(set (match_dup 4) (match_dup 5)) + (set (match_operand:DF 0 "register_operand" "") (if_then_else:DF (match_operand 1 "comparison_operator" "") (match_operand:DF 2 "mmix_reg_or_0_operand" "") @@ -733,15 +710,20 @@ DIVU %1,%1,%2\;GET %0,:rR\;NEGU %2,0,%0\;CSNN %0,$255,%2") " { enum rtx_code code = GET_CODE (operands[1]); - rtx cc_reg = mmix_gen_compare_reg (code, mmix_compare_op0, - mmix_compare_op1); - if (cc_reg == NULL_RTX) + if (code == LE || code == GE) FAIL; - operands[1] = gen_rtx_fmt_ee (code, VOIDmode, cc_reg, const0_rtx); + + operands[4] = mmix_gen_compare_reg (code, XEXP (operands[1], 0), + XEXP (operands[1], 1)); + operands[5] = gen_rtx_COMPARE (GET_MODE (operands[4]), + XEXP (operands[1], 0), + XEXP (operands[1], 1)); + operands[1] = gen_rtx_fmt_ee (code, VOIDmode, operands[4], const0_rtx); }") (define_expand "movdicc" - [(set (match_operand:DI 0 "register_operand" "") + [(set (match_dup 4) (match_dup 5)) + (set (match_operand:DI 0 "register_operand" "") (if_then_else:DI (match_operand 1 "comparison_operator" "") (match_operand:DI 2 "mmix_reg_or_8bit_operand" "") @@ -750,11 +732,15 @@ DIVU %1,%1,%2\;GET %0,:rR\;NEGU %2,0,%0\;CSNN %0,$255,%2") " { enum rtx_code code = GET_CODE (operands[1]); - rtx cc_reg = mmix_gen_compare_reg (code, mmix_compare_op0, - mmix_compare_op1); - if (cc_reg == NULL_RTX) + if (code == LE || code == GE) FAIL; - operands[1] = gen_rtx_fmt_ee (code, VOIDmode, cc_reg, const0_rtx); + + operands[4] = mmix_gen_compare_reg (code, XEXP (operands[1], 0), + XEXP (operands[1], 1)); + operands[5] = gen_rtx_COMPARE (GET_MODE (operands[4]), + XEXP (operands[1], 0), + XEXP (operands[1], 1)); + operands[1] = gen_rtx_fmt_ee (code, VOIDmode, operands[4], const0_rtx); }") ;; FIXME: Is this the right way to do "folding" of CCmode -> DImode? @@ -854,175 +840,65 @@ DIVU %1,%1,%2\;GET %0,:rR\;NEGU %2,0,%0\;CSNN %0,$255,%2") CS%d2 %0,%3,%1 ZS%d2 %0,%3,%1") -;; FIXME: scc patterns will probably help, I just skip them +;; FIXME: scc insns will probably help, I just skip them ;; right now. Revisit. -(define_expand "beq" - [(set (pc) - (if_then_else (eq (match_dup 1) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - operands[1] - = mmix_gen_compare_reg (EQ, mmix_compare_op0, mmix_compare_op1); -}") - -(define_expand "bne" - [(set (pc) - (if_then_else (ne (match_dup 1) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] +(define_expand "cbranchdi4" + [(set (match_dup 4) + (match_op_dup 5 + [(match_operand:DI 1 "register_operand" "") + (match_operand:DI 2 "mmix_reg_or_8bit_operand" "")])) + (set (pc) + (if_then_else + (match_operator 0 "ordered_comparison_operator" + [(match_dup 4) + (const_int 0)]) + (label_ref (match_operand 3 "" "")) + (pc)))] "" " { - operands[1] - = mmix_gen_compare_reg (NE, mmix_compare_op0, mmix_compare_op1); + operands[4] = mmix_gen_compare_reg (GET_CODE (operands[0]), + operands[1], operands[2]); + operands[5] = gen_rtx_fmt_ee (COMPARE, + GET_MODE (operands[4]), + operands[1], operands[2]); }") -(define_expand "bgt" - [(set (pc) - (if_then_else (gt (match_dup 1) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] +(define_expand "cbranchdf4" + [(set (match_dup 4) + (match_op_dup 5 + [(match_operand:DF 1 "register_operand" "") + (match_operand:DF 2 "register_operand" "")])) + (set (pc) + (if_then_else + (match_operator 0 "float_comparison_operator" + [(match_dup 4) + (const_int 0)]) + (label_ref (match_operand 3 "" "")) + (pc)))] "" " { - operands[1] - = mmix_gen_compare_reg (GT, mmix_compare_op0, mmix_compare_op1); -}") - -(define_expand "ble" - [(set (pc) - (if_then_else (le (match_dup 1) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - operands[1] - = mmix_gen_compare_reg (LE, mmix_compare_op0, mmix_compare_op1); - /* The head comment of optabs.c:can_compare_p says we're required to implement this, so we have to clean up the mess here. */ - if (operands[1] == NULL_RTX) + if (GET_CODE (operands[0]) == LE || GET_CODE (operands[0]) == GE) { - /* FIXME: Watch out for sharing/unsharing of rtx:es. */ - emit_jump_insn ((*bcc_gen_fctn[(int) LT]) (operands[0])); - emit_jump_insn ((*bcc_gen_fctn[(int) EQ]) (operands[0])); + enum rtx_code ltgt_code = GET_CODE (operands[0]) == LE ? LT : GT; + emit_cmp_and_jump_insns (operands[1], operands[2], ltgt_code, NULL_RTX, + DFmode, 0, operands[3]); + emit_cmp_and_jump_insns (operands[1], operands[2], EQ, NULL_RTX, + DFmode, 0, operands[3]); DONE; } -}") - -(define_expand "bge" - [(set (pc) - (if_then_else (ge (match_dup 1) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - operands[1] - = mmix_gen_compare_reg (GE, mmix_compare_op0, mmix_compare_op1); - /* The head comment of optabs.c:can_compare_p says we're required to - implement this, so we have to clean up the mess here. */ - if (operands[1] == NULL_RTX) - { - /* FIXME: Watch out for sharing/unsharing of rtx:es. */ - emit_jump_insn ((*bcc_gen_fctn[(int) GT]) (operands[0])); - emit_jump_insn ((*bcc_gen_fctn[(int) EQ]) (operands[0])); - DONE; - } + operands[4] = mmix_gen_compare_reg (GET_CODE (operands[0]), + operands[1], operands[2]); + operands[5] = gen_rtx_fmt_ee (COMPARE, + GET_MODE (operands[4]), + operands[1], operands[2]); }") -(define_expand "blt" - [(set (pc) - (if_then_else (lt (match_dup 1) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - operands[1] - = mmix_gen_compare_reg (LT, mmix_compare_op0, mmix_compare_op1); -}") - -(define_expand "bgtu" - [(set (pc) - (if_then_else (gtu (match_dup 1) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - operands[1] - = mmix_gen_compare_reg (GTU, mmix_compare_op0, mmix_compare_op1); -}") - -(define_expand "bleu" - [(set (pc) - (if_then_else (leu (match_dup 1) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - operands[1] - = mmix_gen_compare_reg (LEU, mmix_compare_op0, mmix_compare_op1); -}") - -(define_expand "bgeu" - [(set (pc) - (if_then_else (geu (match_dup 1) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - operands[1] - = mmix_gen_compare_reg (GEU, mmix_compare_op0, mmix_compare_op1); -}") - -(define_expand "bltu" - [(set (pc) - (if_then_else (ltu (match_dup 1) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - operands[1] - = mmix_gen_compare_reg (LTU, mmix_compare_op0, mmix_compare_op1); -}") - -(define_expand "bunordered" - [(set (pc) - (if_then_else (unordered (match_dup 1) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - operands[1] - = mmix_gen_compare_reg (UNORDERED, mmix_compare_op0, mmix_compare_op1); - - if (operands[1] == NULL_RTX) - FAIL; -}") - -(define_expand "bordered" - [(set (pc) - (if_then_else (ordered (match_dup 1) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - operands[1] - = mmix_gen_compare_reg (ORDERED, mmix_compare_op0, mmix_compare_op1); -}") ;; FIXME: we can emit an unordered-or-*not*-equal compare in one insn, but ;; there's no RTL code for it. Maybe revisit in future. diff --git a/gcc/config/mmix/predicates.md b/gcc/config/mmix/predicates.md index 5c5792e1f6b..b5773b87aee 100644 --- a/gcc/config/mmix/predicates.md +++ b/gcc/config/mmix/predicates.md @@ -17,6 +17,11 @@ ;; along with GCC; see the file COPYING3. If not see ;; <http://www.gnu.org/licenses/>. +;; Return 1 if OP is a valid comparison operator for "cbranch" instructions. +;; LE and GE are further lowered by the cbranchdf4 pattern. +(define_predicate "float_comparison_operator" + (match_code "ne, eq, le, ge, lt, gt, ordered, unordered")) + ;; True if this is a foldable comparison operator ;; - one where a the result of (compare:CC (reg) (const_int 0)) can be ;; replaced by (reg). */ diff --git a/gcc/config/mn10300/mn10300.c b/gcc/config/mn10300/mn10300.c index ceb77e862c2..47fd5cbf933 100644 --- a/gcc/config/mn10300/mn10300.c +++ b/gcc/config/mn10300/mn10300.c @@ -2030,7 +2030,7 @@ mn10300_rtx_costs (rtx x, int code, int outer_code, int *total, bool speed ATTRI { case CONST_INT: /* Zeros are extremely cheap. */ - if (INTVAL (x) == 0 && outer_code == SET) + if (INTVAL (x) == 0 && (outer_code == SET || outer_code == COMPARE)) *total = 0; /* If it fits in 8 bits, then it's still relatively cheap. */ else if (INT_8_BITS (INTVAL (x))) @@ -2059,6 +2059,12 @@ mn10300_rtx_costs (rtx x, int code, int outer_code, int *total, bool speed ATTRI *total = 8; return true; + case ZERO_EXTRACT: + /* This is cheap, we can use btst. */ + if (outer_code == COMPARE) + *total = 0; + return false; + /* ??? This probably needs more work. */ case MOD: case DIV: diff --git a/gcc/config/mn10300/mn10300.md b/gcc/config/mn10300/mn10300.md index 35b0e589cb5..a2b6296912f 100644 --- a/gcc/config/mn10300/mn10300.md +++ b/gcc/config/mn10300/mn10300.md @@ -826,34 +826,34 @@ ;; TEST INSTRUCTIONS ;; ---------------------------------------------------------------------- -;; Go ahead and define tstsi so we can eliminate redundant tst insns -;; when we start trying to optimize this port. -(define_insn "tstsi" - [(set (cc0) (match_operand:SI 0 "register_operand" "dax"))] - "" - "* return output_tst (operands[0], insn);" - [(set_attr "cc" "set_znv")]) - -(define_insn "" - [(set (cc0) (zero_extend:SI (match_operand:QI 0 "memory_operand" "dx,!a")))] +(define_insn "*tst_extqisi_am33" + [(set (cc0) (compare + (zero_extend:SI (match_operand:QI 0 "memory_operand" "dx,!a")) + (const_int 0)))] "TARGET_AM33" "* return output_tst (operands[0], insn);" [(set_attr "cc" "set_znv")]) -(define_insn "" - [(set (cc0) (zero_extend:SI (match_operand:QI 0 "memory_operand" "dx")))] +(define_insn "*tst_extqisi" + [(set (cc0) (compare + (zero_extend:SI (match_operand:QI 0 "memory_operand" "dx")) + (const_int 0)))] "" "* return output_tst (operands[0], insn);" [(set_attr "cc" "set_znv")]) -(define_insn "" - [(set (cc0) (zero_extend:SI (match_operand:HI 0 "memory_operand" "dx,!a")))] +(define_insn "*tst_exthisi_am33" + [(set (cc0) (compare + (zero_extend:SI (match_operand:HI 0 "memory_operand" "dx,!a")) + (const_int 0)))] "TARGET_AM33" "* return output_tst (operands[0], insn);" [(set_attr "cc" "set_znv")]) -(define_insn "" - [(set (cc0) (zero_extend:SI (match_operand:HI 0 "memory_operand" "dx")))] +(define_insn "*tst_exthisi" + [(set (cc0) (compare + (zero_extend:SI (match_operand:HI 0 "memory_operand" "dx")) + (const_int 0)))] "" "* return output_tst (operands[0], insn);" [(set_attr "cc" "set_znv")]) @@ -874,17 +874,22 @@ ;; possibly satisfied, so just mark the alternative with a `!', so ;; that it is not considered by reload. -(define_insn "cmpsi" +(define_insn "*cmpsi" [(set (cc0) - (compare (match_operand:SI 0 "register_operand" "!*d*a*x,dax") - (match_operand:SI 1 "nonmemory_operand" "*0,daxi")))] + (compare (match_operand:SI 0 "register_operand" "!*d*a*x,dax,dax") + (match_operand:SI 1 "nonmemory_operand" "*0,I,daxi")))] "" - "@ - btst 0,d0 - cmp %1,%0" - [(set_attr "cc" "compare,compare")]) + "* +{ + if (which_alternative == 0) + return \"btst 0,d0\"; + if (which_alternative == 1) + return output_tst (operands[0], insn); + return \"cmp %1,%0\"; +}" + [(set_attr "cc" "compare,set_znv,compare")]) -(define_insn "cmpsf" +(define_insn "*cmpsf" [(set (cc0) (compare (match_operand:SF 0 "register_operand" "f,f") (match_operand:SF 1 "nonmemory_operand" "f,F")))] @@ -1510,9 +1515,10 @@ (define_insn "" [(set (cc0) - (zero_extract:SI (match_operand:SI 0 "register_operand" "dx") - (match_operand 1 "const_int_operand" "") - (match_operand 2 "const_int_operand" "")))] + (compare (zero_extract:SI (match_operand:SI 0 "register_operand" "dx") + (match_operand 1 "const_int_operand" "") + (match_operand 2 "const_int_operand" "")) + (const_int 0)))] "" "* { @@ -1537,9 +1543,10 @@ (define_insn "" [(set (cc0) - (zero_extract:SI (match_operand:QI 0 "general_operand" "R,dx") - (match_operand 1 "const_int_operand" "") - (match_operand 2 "const_int_operand" "")))] + (compare (zero_extract:SI (match_operand:QI 0 "general_operand" "R,dx") + (match_operand 1 "const_int_operand" "") + (match_operand 2 "const_int_operand" "")) + (const_int 0)))] "mask_ok_for_mem_btst (INTVAL (operands[1]), INTVAL (operands[2]))" "* { @@ -1581,17 +1588,19 @@ [(set_attr "cc" "clobber")]) (define_insn "" - [(set (cc0) (and:SI (match_operand:SI 0 "register_operand" "dx") - (match_operand:SI 1 "const_int_operand" "")))] + [(set (cc0) (compare (and:SI (match_operand:SI 0 "register_operand" "dx") + (match_operand:SI 1 "const_int_operand" "")) + (const_int 0)))] "" "btst %1,%0" [(set_attr "cc" "clobber")]) (define_insn "" [(set (cc0) - (and:SI - (subreg:SI (match_operand:QI 0 "general_operand" "R,dx") 0) - (match_operand:SI 1 "const_8bit_operand" "")))] + (compare (and:SI + (subreg:SI (match_operand:QI 0 "general_operand" "R,dx") 0) + (match_operand:SI 1 "const_8bit_operand" "")) + (const_int 0)))] "" "@ btst %U1,%A0 @@ -1603,97 +1612,34 @@ ;; JUMP INSTRUCTIONS ;; ---------------------------------------------------------------------- -;; Conditional jump instructions - -(define_expand "ble" - [(set (pc) - (if_then_else (le (cc0) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "") - -(define_expand "bleu" - [(set (pc) - (if_then_else (leu (cc0) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "") - -(define_expand "bge" - [(set (pc) - (if_then_else (ge (cc0) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "") - -(define_expand "bgeu" - [(set (pc) - (if_then_else (geu (cc0) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "") - -(define_expand "blt" - [(set (pc) - (if_then_else (lt (cc0) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "") - -(define_expand "bltu" - [(set (pc) - (if_then_else (ltu (cc0) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "") - -(define_expand "bgt" - [(set (pc) - (if_then_else (gt (cc0) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] +(define_expand "cbranchsi4" + [(set (cc0) + (compare (match_operand:SI 1 "register_operand" "") + (match_operand:SI 2 "nonmemory_operand" ""))) + (set (pc) + (if_then_else + (match_operator 0 "ordered_comparison_operator" [(cc0) + (const_int 0)]) + (label_ref (match_operand 3 "" "")) + (pc)))] "" "") -(define_expand "bgtu" - [(set (pc) - (if_then_else (gtu (cc0) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" +(define_expand "cbranchsf4" + [(set (cc0) + (compare (match_operand:SF 1 "register_operand" "") + (match_operand:SF 2 "nonmemory_operand" ""))) + (set (pc) + (if_then_else + (match_operator 0 "ordered_comparison_operator" [(cc0) + (const_int 0)]) + (label_ref (match_operand 3 "" "")) + (pc)))] + "TARGET_AM33_2" "") -(define_expand "beq" - [(set (pc) - (if_then_else (eq (cc0) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "") -(define_expand "bne" - [(set (pc) - (if_then_else (ne (cc0) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "") +;; Conditional jump instructions (define_insn "" [(set (pc) @@ -1774,11 +1720,13 @@ rtx table = gen_reg_rtx (SImode); rtx index = gen_reg_rtx (SImode); rtx addr = gen_reg_rtx (Pmode); + rtx test; emit_move_insn (table, gen_rtx_LABEL_REF (VOIDmode, operands[3])); emit_move_insn (index, plus_constant (operands[0], - INTVAL (operands[1]))); - emit_insn (gen_cmpsi (index, operands[2])); - emit_jump_insn (gen_bgtu (operands[4])); + test = gen_rtx_fmt_ee (GTU, VOIDmode, index, operands[2]); + emit_jump_insn (gen_cbranchsi4 (test, index, operands[2], operands[4])); + emit_move_insn (index, gen_rtx_ASHIFT (SImode, index, const2_rtx)); emit_move_insn (addr, gen_rtx_MEM (SImode, gen_rtx_PLUS (SImode, table, index))); @@ -2518,7 +2466,8 @@ ;; This will work on the mn10200 because we can check the ZX flag ;; if the comparison is in HImode. (define_peephole - [(set (cc0) (match_operand:SI 0 "register_operand" "dx")) + [(set (cc0) (compare (match_operand:SI 0 "register_operand" "dx") + (const_int 0))) (set (pc) (if_then_else (ge (cc0) (const_int 0)) (match_operand 1 "" "") (pc)))] @@ -2527,7 +2476,8 @@ [(set_attr "cc" "clobber")]) (define_peephole - [(set (cc0) (match_operand:SI 0 "register_operand" "dx")) + [(set (cc0) (compare (match_operand:SI 0 "register_operand" "dx") + (const_int 0))) (set (pc) (if_then_else (lt (cc0) (const_int 0)) (match_operand 1 "" "") (pc)))] @@ -2536,7 +2486,8 @@ [(set_attr "cc" "clobber")]) (define_peephole - [(set (cc0) (match_operand:SI 0 "register_operand" "dx")) + [(set (cc0) (compare (match_operand:SI 0 "register_operand" "dx") + (const_int 0))) (set (pc) (if_then_else (ge (cc0) (const_int 0)) (pc) (match_operand 1 "" "")))] @@ -2545,7 +2496,8 @@ [(set_attr "cc" "clobber")]) (define_peephole - [(set (cc0) (match_operand:SI 0 "register_operand" "dx")) + [(set (cc0) (compare (match_operand:SI 0 "register_operand" "dx") + (const_int 0))) (set (pc) (if_then_else (lt (cc0) (const_int 0)) (pc) (match_operand 1 "" "")))] diff --git a/gcc/config/pa/pa-protos.h b/gcc/config/pa/pa-protos.h index 3cd1f8580bc..526081acd52 100644 --- a/gcc/config/pa/pa-protos.h +++ b/gcc/config/pa/pa-protos.h @@ -56,7 +56,6 @@ extern void output_arg_descriptor (rtx); extern void output_global_address (FILE *, rtx, int); extern void print_operand (FILE *, rtx, int); extern rtx legitimize_pic_address (rtx, enum machine_mode, rtx); -extern struct rtx_def *gen_cmp_fp (enum rtx_code, rtx, rtx); extern void hppa_encode_label (rtx); extern int arith11_operand (rtx, enum machine_mode); extern int adddi3_operand (rtx, enum machine_mode); @@ -96,7 +95,7 @@ extern int fmpyaddoperands (rtx *); extern int fmpysuboperands (rtx *); extern int call_operand_address (rtx, enum machine_mode); extern int ior_operand (rtx, enum machine_mode); -extern void emit_bcond_fp (enum rtx_code, rtx); +extern void emit_bcond_fp (rtx[]); extern int emit_move_sequence (rtx *, enum machine_mode, rtx); extern int emit_hpdiv_const (rtx *, int); extern int is_function_label_plus_const (rtx); diff --git a/gcc/config/pa/pa.c b/gcc/config/pa/pa.c index 80f5fe90bc2..882fac1aad4 100644 --- a/gcc/config/pa/pa.c +++ b/gcc/config/pa/pa.c @@ -165,11 +165,6 @@ static GTY(()) section *som_readonly_data_section; static GTY(()) section *som_one_only_readonly_data_section; static GTY(()) section *som_one_only_data_section; -/* Save the operands last given to a compare for use when we - generate a scc or bcc insn. */ -rtx hppa_compare_op0, hppa_compare_op1; -enum cmp_type hppa_branch_type; - /* Which cpu we are scheduling for. */ enum processor_type pa_cpu = TARGET_SCHED_DEFAULT; @@ -4383,6 +4378,19 @@ return_addr_rtx (int count, rtx frameaddr) rtx saved_rp; rtx ins; + /* Instruction stream at the normal return address for the export stub: + + 0x4bc23fd1 | stub+8: ldw -18(sr0,sp),rp + 0x004010a1 | stub+12: ldsid (sr0,rp),r1 + 0x00011820 | stub+16: mtsp r1,sr0 + 0xe0400002 | stub+20: be,n 0(sr0,rp) + + 0xe0400002 must be specified as -532676606 so that it won't be + rejected as an invalid immediate operand on 64-bit hosts. */ + + HOST_WIDE_INT insns[4] = {0x4bc23fd1, 0x004010a1, 0x00011820, -532676606}; + int i; + if (count != 0) return NULL_RTX; @@ -4391,6 +4399,9 @@ return_addr_rtx (int count, rtx frameaddr) if (TARGET_64BIT || TARGET_NO_SPACE_REGS) return rp; + /* If there is no export stub then just use the value saved from + the return pointer register. */ + saved_rp = gen_reg_rtx (Pmode); emit_move_insn (saved_rp, rp); @@ -4402,37 +4413,15 @@ return_addr_rtx (int count, rtx frameaddr) label = gen_label_rtx (); /* Check the instruction stream at the normal return address for the - export stub: - - 0x4bc23fd1 | stub+8: ldw -18(sr0,sp),rp - 0x004010a1 | stub+12: ldsid (sr0,rp),r1 - 0x00011820 | stub+16: mtsp r1,sr0 - 0xe0400002 | stub+20: be,n 0(sr0,rp) + export stub. If it is an export stub, than our return address is + really in -24[frameaddr]. */ - If it is an export stub, than our return address is really in - -24[frameaddr]. */ - - emit_cmp_insn (gen_rtx_MEM (SImode, ins), GEN_INT (0x4bc23fd1), NE, - NULL_RTX, SImode, 1); - emit_jump_insn (gen_bne (label)); - - emit_cmp_insn (gen_rtx_MEM (SImode, plus_constant (ins, 4)), - GEN_INT (0x004010a1), NE, NULL_RTX, SImode, 1); - emit_jump_insn (gen_bne (label)); - - emit_cmp_insn (gen_rtx_MEM (SImode, plus_constant (ins, 8)), - GEN_INT (0x00011820), NE, NULL_RTX, SImode, 1); - emit_jump_insn (gen_bne (label)); - - /* 0xe0400002 must be specified as -532676606 so that it won't be - rejected as an invalid immediate operand on 64-bit hosts. */ - emit_cmp_insn (gen_rtx_MEM (SImode, plus_constant (ins, 12)), - GEN_INT (-532676606), NE, NULL_RTX, SImode, 1); - - /* If there is no export stub then just use the value saved from - the return pointer register. */ - - emit_jump_insn (gen_bne (label)); + for (i = 0; i < 3; i++) + { + rtx op0 = gen_rtx_MEM (SImode, plus_constant (ins, i * 4)); + rtx op1 = GEN_INT (insns[i]); + emit_cmp_and_jump_insns (op0, op1, NE, NULL, SImode, 0, label); + } /* Here we know that our return address points to an export stub. We don't want to return the address of the export stub, @@ -4446,30 +4435,32 @@ return_addr_rtx (int count, rtx frameaddr) -24)))); emit_label (label); + return saved_rp; } void -emit_bcond_fp (enum rtx_code code, rtx operand0) +emit_bcond_fp (rtx operands[]) { + enum rtx_code code = GET_CODE (operands[0]); + rtx operand0 = operands[1]; + rtx operand1 = operands[2]; + rtx label = operands[3]; + + emit_insn (gen_rtx_SET (VOIDmode, gen_rtx_REG (CCFPmode, 0), + gen_rtx_fmt_ee (code, CCFPmode, operand0, operand1))); + emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx, gen_rtx_IF_THEN_ELSE (VOIDmode, - gen_rtx_fmt_ee (code, + gen_rtx_fmt_ee (NE, VOIDmode, gen_rtx_REG (CCFPmode, 0), const0_rtx), - gen_rtx_LABEL_REF (VOIDmode, operand0), + gen_rtx_LABEL_REF (VOIDmode, label), pc_rtx))); } -rtx -gen_cmp_fp (enum rtx_code code, rtx operand0, rtx operand1) -{ - return gen_rtx_SET (VOIDmode, gen_rtx_REG (CCFPmode, 0), - gen_rtx_fmt_ee (code, CCFPmode, operand0, operand1)); -} - /* Adjust the cost of a scheduling dependency. Return the new cost of a dependency LINK or INSN on DEP_INSN. COST is the current cost. */ diff --git a/gcc/config/pa/pa.h b/gcc/config/pa/pa.h index 303bdd341df..576916f5b7b 100644 --- a/gcc/config/pa/pa.h +++ b/gcc/config/pa/pa.h @@ -21,14 +21,6 @@ You should have received a copy of the GNU General Public License along with GCC; see the file COPYING3. If not see <http://www.gnu.org/licenses/>. */ -enum cmp_type /* comparison type */ -{ - CMP_SI, /* compare integers */ - CMP_SF, /* compare single precision floats */ - CMP_DF, /* compare double precision floats */ - CMP_MAX /* max comparison type */ -}; - /* For long call handling. */ extern unsigned long total_code_bytes; @@ -755,10 +747,6 @@ struct hppa_args {int words, nargs_prototype, incoming, indirect; }; ? PARM_BOUNDARY : MAX_PARM_BOUNDARY) -extern GTY(()) rtx hppa_compare_op0; -extern GTY(()) rtx hppa_compare_op1; -extern enum cmp_type hppa_branch_type; - /* On HPPA, we emit profiling code as rtl via PROFILE_HOOK rather than as assembly via FUNCTION_PROFILER. Just output a local label. We can't use the function label because the GAS SOM target can't diff --git a/gcc/config/pa/pa.md b/gcc/config/pa/pa.md index b845182d592..1f5a69b9352 100644 --- a/gcc/config/pa/pa.md +++ b/gcc/config/pa/pa.md @@ -653,64 +653,6 @@ ;; Compare instructions. ;; This controls RTL generation and register allocation. -;; We generate RTL for comparisons and branches by having the cmpxx -;; patterns store away the operands. Then, the scc and bcc patterns -;; emit RTL for both the compare and the branch. -;; - -(define_expand "cmpdi" - [(set (reg:CC 0) - (compare:CC (match_operand:DI 0 "reg_or_0_operand" "") - (match_operand:DI 1 "register_operand" "")))] - "TARGET_64BIT" - - " -{ - hppa_compare_op0 = operands[0]; - hppa_compare_op1 = operands[1]; - hppa_branch_type = CMP_SI; - DONE; -}") - -(define_expand "cmpsi" - [(set (reg:CC 0) - (compare:CC (match_operand:SI 0 "reg_or_0_operand" "") - (match_operand:SI 1 "arith5_operand" "")))] - "" - " -{ - hppa_compare_op0 = operands[0]; - hppa_compare_op1 = operands[1]; - hppa_branch_type = CMP_SI; - DONE; -}") - -(define_expand "cmpsf" - [(set (reg:CCFP 0) - (compare:CCFP (match_operand:SF 0 "reg_or_0_operand" "") - (match_operand:SF 1 "reg_or_0_operand" "")))] - "! TARGET_SOFT_FLOAT" - " -{ - hppa_compare_op0 = operands[0]; - hppa_compare_op1 = operands[1]; - hppa_branch_type = CMP_SF; - DONE; -}") - -(define_expand "cmpdf" - [(set (reg:CCFP 0) - (compare:CCFP (match_operand:DF 0 "reg_or_0_operand" "") - (match_operand:DF 1 "reg_or_0_operand" "")))] - "! TARGET_SOFT_FLOAT" - " -{ - hppa_compare_op0 = operands[0]; - hppa_compare_op1 = operands[1]; - hppa_branch_type = CMP_DF; - DONE; -}") - (define_insn "" [(set (reg:CCFP 0) (match_operator:CCFP 2 "comparison_operator" @@ -767,143 +709,13 @@ ;; scc insns. -(define_expand "seq" - [(set (match_operand:SI 0 "register_operand" "") - (eq:SI (match_dup 1) - (match_dup 2)))] - "!TARGET_64BIT" - " -{ - /* fp scc patterns rarely match, and are not a win on the PA. */ - if (hppa_branch_type != CMP_SI) - FAIL; - /* set up operands from compare. */ - operands[1] = hppa_compare_op0; - operands[2] = hppa_compare_op1; - /* fall through and generate default code */ -}") - -(define_expand "sne" - [(set (match_operand:SI 0 "register_operand" "") - (ne:SI (match_dup 1) - (match_dup 2)))] - "!TARGET_64BIT" - " -{ - /* fp scc patterns rarely match, and are not a win on the PA. */ - if (hppa_branch_type != CMP_SI) - FAIL; - operands[1] = hppa_compare_op0; - operands[2] = hppa_compare_op1; -}") - -(define_expand "slt" - [(set (match_operand:SI 0 "register_operand" "") - (lt:SI (match_dup 1) - (match_dup 2)))] - "!TARGET_64BIT" - " -{ - /* fp scc patterns rarely match, and are not a win on the PA. */ - if (hppa_branch_type != CMP_SI) - FAIL; - operands[1] = hppa_compare_op0; - operands[2] = hppa_compare_op1; -}") - -(define_expand "sgt" - [(set (match_operand:SI 0 "register_operand" "") - (gt:SI (match_dup 1) - (match_dup 2)))] - "!TARGET_64BIT" - " -{ - /* fp scc patterns rarely match, and are not a win on the PA. */ - if (hppa_branch_type != CMP_SI) - FAIL; - operands[1] = hppa_compare_op0; - operands[2] = hppa_compare_op1; -}") - -(define_expand "sle" - [(set (match_operand:SI 0 "register_operand" "") - (le:SI (match_dup 1) - (match_dup 2)))] - "!TARGET_64BIT" - " -{ - /* fp scc patterns rarely match, and are not a win on the PA. */ - if (hppa_branch_type != CMP_SI) - FAIL; - operands[1] = hppa_compare_op0; - operands[2] = hppa_compare_op1; -}") - -(define_expand "sge" - [(set (match_operand:SI 0 "register_operand" "") - (ge:SI (match_dup 1) - (match_dup 2)))] - "!TARGET_64BIT" - " -{ - /* fp scc patterns rarely match, and are not a win on the PA. */ - if (hppa_branch_type != CMP_SI) - FAIL; - operands[1] = hppa_compare_op0; - operands[2] = hppa_compare_op1; -}") - -(define_expand "sltu" - [(set (match_operand:SI 0 "register_operand" "") - (ltu:SI (match_dup 1) - (match_dup 2)))] +(define_expand "cstoresi4" + [(set (match_operand:SI 0 "register_operand") + (match_operator:SI 1 "ordered_comparison_operator" + [(match_operand:SI 2 "reg_or_0_operand" "") + (match_operand:SI 3 "arith5_operand" "")]))] "!TARGET_64BIT" - " -{ - if (hppa_branch_type != CMP_SI) - FAIL; - operands[1] = hppa_compare_op0; - operands[2] = hppa_compare_op1; -}") - -(define_expand "sgtu" - [(set (match_operand:SI 0 "register_operand" "") - (gtu:SI (match_dup 1) - (match_dup 2)))] - "!TARGET_64BIT" - " -{ - if (hppa_branch_type != CMP_SI) - FAIL; - operands[1] = hppa_compare_op0; - operands[2] = hppa_compare_op1; -}") - -(define_expand "sleu" - [(set (match_operand:SI 0 "register_operand" "") - (leu:SI (match_dup 1) - (match_dup 2)))] - "!TARGET_64BIT" - " -{ - if (hppa_branch_type != CMP_SI) - FAIL; - operands[1] = hppa_compare_op0; - operands[2] = hppa_compare_op1; -}") - -(define_expand "sgeu" - [(set (match_operand:SI 0 "register_operand" "") - (geu:SI (match_dup 1) - (match_dup 2)))] - "!TARGET_64BIT" - " -{ - if (hppa_branch_type != CMP_SI) - FAIL; - operands[1] = hppa_compare_op0; - operands[2] = hppa_compare_op1; -}") + "") ;; Instruction canonicalization puts immediate operands second, which ;; is the reverse of what we want. @@ -1346,28 +1158,15 @@ (define_expand "movsicc" [(set (match_operand:SI 0 "register_operand" "") (if_then_else:SI - (match_operator 1 "comparison_operator" - [(match_dup 4) - (match_dup 5)]) + (match_operand 1 "comparison_operator" "") (match_operand:SI 2 "reg_or_cint_move_operand" "") (match_operand:SI 3 "reg_or_cint_move_operand" "")))] "" " { - enum rtx_code code = GET_CODE (operands[1]); - - if (hppa_branch_type != CMP_SI) + if (GET_MODE (XEXP (operands[1], 0)) != SImode + || GET_MODE (XEXP (operands[1], 0)) != GET_MODE (XEXP (operands[1], 1))) FAIL; - - if (GET_MODE (hppa_compare_op0) != GET_MODE (hppa_compare_op1) - || GET_MODE (hppa_compare_op0) != GET_MODE (operands[0])) - FAIL; - - /* operands[1] is currently the result of compare_from_rtx. We want to - emit a compare of the original operands. */ - operands[1] = gen_rtx_fmt_ee (code, SImode, hppa_compare_op0, hppa_compare_op1); - operands[4] = hppa_compare_op0; - operands[5] = hppa_compare_op1; }") ;; We used to accept any register for op1. @@ -1419,28 +1218,15 @@ (define_expand "movdicc" [(set (match_operand:DI 0 "register_operand" "") (if_then_else:DI - (match_operator 1 "comparison_operator" - [(match_dup 4) - (match_dup 5)]) + (match_operand 1 "comparison_operator" "") (match_operand:DI 2 "reg_or_cint_move_operand" "") (match_operand:DI 3 "reg_or_cint_move_operand" "")))] "TARGET_64BIT" " { - enum rtx_code code = GET_CODE (operands[1]); - - if (hppa_branch_type != CMP_SI) + if (GET_MODE (XEXP (operands[1], 0)) != DImode + || GET_MODE (XEXP (operands[1], 0)) != GET_MODE (XEXP (operands[1], 1))) FAIL; - - if (GET_MODE (hppa_compare_op0) != GET_MODE (hppa_compare_op1) - || GET_MODE (hppa_compare_op0) != GET_MODE (operands[0])) - FAIL; - - /* operands[1] is currently the result of compare_from_rtx. We want to - emit a compare of the original operands. */ - operands[1] = gen_rtx_fmt_ee (code, DImode, hppa_compare_op0, hppa_compare_op1); - operands[4] = hppa_compare_op0; - operands[5] = hppa_compare_op1; }") ; We need the first constraint alternative in order to avoid @@ -1486,289 +1272,52 @@ ;; Conditional Branches -(define_expand "beq" - [(set (pc) - (if_then_else (eq (match_dup 1) (match_dup 2)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - if (hppa_branch_type != CMP_SI) - { - emit_insn (gen_cmp_fp (EQ, hppa_compare_op0, hppa_compare_op1)); - emit_bcond_fp (NE, operands[0]); - DONE; - } - /* set up operands from compare. */ - operands[1] = hppa_compare_op0; - operands[2] = hppa_compare_op1; - /* fall through and generate default code */ -}") - -(define_expand "bne" - [(set (pc) - (if_then_else (ne (match_dup 1) (match_dup 2)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - if (hppa_branch_type != CMP_SI) - { - emit_insn (gen_cmp_fp (NE, hppa_compare_op0, hppa_compare_op1)); - emit_bcond_fp (NE, operands[0]); - DONE; - } - operands[1] = hppa_compare_op0; - operands[2] = hppa_compare_op1; -}") - -(define_expand "bgt" +(define_expand "cbranchdi4" [(set (pc) - (if_then_else (gt (match_dup 1) (match_dup 2)) - (label_ref (match_operand 0 "" "")) + (if_then_else (match_operator 0 "ordered_comparison_operator" + [(match_operand:DI 1 "reg_or_0_operand" "") + (match_operand:DI 2 "register_operand" "")]) + (label_ref (match_operand 3 "" "")) (pc)))] - "" - " -{ - if (hppa_branch_type != CMP_SI) - { - emit_insn (gen_cmp_fp (GT, hppa_compare_op0, hppa_compare_op1)); - emit_bcond_fp (NE, operands[0]); - DONE; - } - operands[1] = hppa_compare_op0; - operands[2] = hppa_compare_op1; -}") - -(define_expand "blt" - [(set (pc) - (if_then_else (lt (match_dup 1) (match_dup 2)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - if (hppa_branch_type != CMP_SI) - { - emit_insn (gen_cmp_fp (LT, hppa_compare_op0, hppa_compare_op1)); - emit_bcond_fp (NE, operands[0]); - DONE; - } - operands[1] = hppa_compare_op0; - operands[2] = hppa_compare_op1; -}") - -(define_expand "bge" - [(set (pc) - (if_then_else (ge (match_dup 1) (match_dup 2)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - if (hppa_branch_type != CMP_SI) - { - emit_insn (gen_cmp_fp (GE, hppa_compare_op0, hppa_compare_op1)); - emit_bcond_fp (NE, operands[0]); - DONE; - } - operands[1] = hppa_compare_op0; - operands[2] = hppa_compare_op1; -}") - -(define_expand "ble" - [(set (pc) - (if_then_else (le (match_dup 1) (match_dup 2)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - if (hppa_branch_type != CMP_SI) - { - emit_insn (gen_cmp_fp (LE, hppa_compare_op0, hppa_compare_op1)); - emit_bcond_fp (NE, operands[0]); - DONE; - } - operands[1] = hppa_compare_op0; - operands[2] = hppa_compare_op1; -}") - -(define_expand "bgtu" - [(set (pc) - (if_then_else (gtu (match_dup 1) (match_dup 2)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - if (hppa_branch_type != CMP_SI) - FAIL; - operands[1] = hppa_compare_op0; - operands[2] = hppa_compare_op1; -}") - -(define_expand "bltu" - [(set (pc) - (if_then_else (ltu (match_dup 1) (match_dup 2)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - if (hppa_branch_type != CMP_SI) - FAIL; - operands[1] = hppa_compare_op0; - operands[2] = hppa_compare_op1; -}") - -(define_expand "bgeu" - [(set (pc) - (if_then_else (geu (match_dup 1) (match_dup 2)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - if (hppa_branch_type != CMP_SI) - FAIL; - operands[1] = hppa_compare_op0; - operands[2] = hppa_compare_op1; -}") - -(define_expand "bleu" - [(set (pc) - (if_then_else (leu (match_dup 1) (match_dup 2)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - if (hppa_branch_type != CMP_SI) - FAIL; - operands[1] = hppa_compare_op0; - operands[2] = hppa_compare_op1; -}") - -(define_expand "bltgt" - [(set (pc) - (if_then_else (ltgt (match_dup 1) (match_dup 2)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - if (hppa_branch_type == CMP_SI) - FAIL; - emit_insn (gen_cmp_fp (LTGT, hppa_compare_op0, hppa_compare_op1)); - emit_bcond_fp (NE, operands[0]); - DONE; -}") - -(define_expand "bunle" - [(set (pc) - (if_then_else (unle (match_dup 1) (match_dup 2)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - if (hppa_branch_type == CMP_SI) - FAIL; - emit_insn (gen_cmp_fp (UNLE, hppa_compare_op0, hppa_compare_op1)); - emit_bcond_fp (NE, operands[0]); - DONE; -}") - -(define_expand "bunlt" - [(set (pc) - (if_then_else (unlt (match_dup 1) (match_dup 2)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - if (hppa_branch_type == CMP_SI) - FAIL; - emit_insn (gen_cmp_fp (UNLT, hppa_compare_op0, hppa_compare_op1)); - emit_bcond_fp (NE, operands[0]); - DONE; -}") - -(define_expand "bunge" - [(set (pc) - (if_then_else (unge (match_dup 1) (match_dup 2)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - if (hppa_branch_type == CMP_SI) - FAIL; - emit_insn (gen_cmp_fp (UNGE, hppa_compare_op0, hppa_compare_op1)); - emit_bcond_fp (NE, operands[0]); - DONE; -}") + "TARGET_64BIT" + "") -(define_expand "bungt" +(define_expand "cbranchsi4" [(set (pc) - (if_then_else (ungt (match_dup 1) (match_dup 2)) - (label_ref (match_operand 0 "" "")) + (if_then_else (match_operator 0 "ordered_comparison_operator" + [(match_operand:SI 1 "reg_or_0_operand" "") + (match_operand:SI 2 "arith5_operand" "")]) + (label_ref (match_operand 3 "" "")) (pc)))] "" - " -{ - if (hppa_branch_type == CMP_SI) - FAIL; - emit_insn (gen_cmp_fp (UNGT, hppa_compare_op0, hppa_compare_op1)); - emit_bcond_fp (NE, operands[0]); - DONE; -}") + "") -(define_expand "buneq" +(define_expand "cbranchsf4" [(set (pc) - (if_then_else (uneq (match_dup 1) (match_dup 2)) - (label_ref (match_operand 0 "" "")) + (if_then_else (match_operator 0 "comparison_operator" + [(match_operand:SF 1 "reg_or_0_operand" "") + (match_operand:SF 2 "reg_or_0_operand" "")]) + (label_ref (match_operand 3 "" "")) (pc)))] "" " { - if (hppa_branch_type == CMP_SI) - FAIL; - emit_insn (gen_cmp_fp (UNEQ, hppa_compare_op0, hppa_compare_op1)); - emit_bcond_fp (NE, operands[0]); + emit_bcond_fp (operands); DONE; }") -(define_expand "bunordered" - [(set (pc) - (if_then_else (unordered (match_dup 1) (match_dup 2)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - if (hppa_branch_type == CMP_SI) - FAIL; - emit_insn (gen_cmp_fp (UNORDERED, hppa_compare_op0, hppa_compare_op1)); - emit_bcond_fp (NE, operands[0]); - DONE; -}") -(define_expand "bordered" +(define_expand "cbranchdf4" [(set (pc) - (if_then_else (ordered (match_dup 1) (match_dup 2)) - (label_ref (match_operand 0 "" "")) + (if_then_else (match_operator 0 "comparison_operator" + [(match_operand:DF 1 "reg_or_0_operand" "") + (match_operand:DF 2 "reg_or_0_operand" "")]) + (label_ref (match_operand 3 "" "")) (pc)))] "" " { - if (hppa_branch_type == CMP_SI) - FAIL; - emit_insn (gen_cmp_fp (ORDERED, hppa_compare_op0, hppa_compare_op1)); - emit_bcond_fp (NE, operands[0]); + emit_bcond_fp (operands); DONE; }") @@ -7527,8 +7076,10 @@ then be worthwhile to split the casesi patterns to improve scheduling. However, it's not clear that all this extra complexity is worth the effort. */ - emit_insn (gen_cmpsi (operands[0], operands[2])); - emit_jump_insn (gen_bgtu (operands[4])); + { + rtx test = gen_rtx_GTU (VOIDmode, operands[0], operands[2]); + emit_jump_insn (gen_cbranchsi4 (test, operands[0], operands[2], operands[4])); + } if (TARGET_BIG_SWITCH) { diff --git a/gcc/config/pdp11/pdp11-protos.h b/gcc/config/pdp11/pdp11-protos.h index f493fbc8ab1..1ed272e5081 100644 --- a/gcc/config/pdp11/pdp11-protos.h +++ b/gcc/config/pdp11/pdp11-protos.h @@ -33,9 +33,9 @@ extern void output_addr_const_pdp11 (FILE *, rtx); extern const char *output_move_double (rtx *); extern const char *output_move_quad (rtx *); extern const char *output_block_move (rtx *); +extern const char *output_jump (enum rtx_code, int, int); extern void print_operand_address (FILE *, rtx); extern int register_move_cost (enum reg_class, enum reg_class); #endif /* RTX_CODE */ extern void output_ascii (FILE *, const char *, int); -extern const char *output_jump (const char *, const char *, int); diff --git a/gcc/config/pdp11/pdp11.c b/gcc/config/pdp11/pdp11.c index 6e8941d75e9..8f2d78fe555 100644 --- a/gcc/config/pdp11/pdp11.c +++ b/gcc/config/pdp11/pdp11.c @@ -1170,11 +1170,27 @@ pdp11_rtx_costs (rtx x, int code, int outer_code ATTRIBUTE_UNUSED, int *total, } const char * -output_jump (const char *pos, const char *neg, int length) +output_jump (enum rtx_code code, int inv, int length) { static int x = 0; static char buf[1000]; + const char *pos, *neg; + + switch (code) + { + case EQ: pos = "beq", neg = "bne"; break; + case NE: pos = "bne", neg = "beq"; break; + case GT: pos = "bgt", neg = "ble"; break; + case GTU: pos = "bhi", neg = "blos"; break; + case LT: pos = "blt", neg = "bge"; break; + case LTU: pos = "blo", neg = "bhis"; break; + case GE: pos = "bge", neg = "blt"; break; + case GEU: pos = "bhis", neg = "blo"; break; + case LE: pos = "ble", neg = "bgt"; break; + case LEU: pos = "blos", neg = "bhi"; break; + default: gcc_unreachable (); + } #if 0 /* currently we don't need this, because the tstdf and cmpdf @@ -1190,14 +1206,13 @@ output_jump (const char *pos, const char *neg, int length) { case 1: - strcpy(buf, pos); - strcat(buf, " %l0"); + sprintf(buf, "%s %%l1", inv ? neg : pos); return buf; case 3: - sprintf(buf, "%s JMP_%d\n\tjmp %%l0\nJMP_%d:", neg, x, x); + sprintf(buf, "%s JMP_%d\n\tjmp %%l1\nJMP_%d:", inv ? pos : neg, x, x); x++; diff --git a/gcc/config/pdp11/pdp11.h b/gcc/config/pdp11/pdp11.h index 9dbb41eb7c1..437e2b81e2e 100644 --- a/gcc/config/pdp11/pdp11.h +++ b/gcc/config/pdp11/pdp11.h @@ -1031,6 +1031,9 @@ JMP FUNCTION 0x0058 0x0000 <- FUNCTION #define OPTIMIZATION_OPTIONS(LEVEL,SIZE) \ { \ + flag_finite_math_only = 0; \ + flag_trapping_math = 0; \ + flag_signaling_nans = 0; \ if (LEVEL >= 3) \ { \ flag_omit_frame_pointer = 1; \ diff --git a/gcc/config/pdp11/pdp11.md b/gcc/config/pdp11/pdp11.md index d5d4396b1c6..64d57e056b3 100644 --- a/gcc/config/pdp11/pdp11.md +++ b/gcc/config/pdp11/pdp11.md @@ -19,6 +19,11 @@ ;; along with GCC; see the file COPYING3. If not see ;; <http://www.gnu.org/licenses/>. +;; Match CONST_DOUBLE zero for tstd/tstf. +(define_predicate "register_or_const0_operand" + (ior (match_operand 0 "register_operand") + (match_test "op == CONST0_RTX (GET_MODE (op))"))) + ;; HI is 16 bit ;; QI is 8 bit @@ -81,141 +86,50 @@ ;(define_function_unit "fpu" 1 1 (eq_attr "type" "fp") 0 0) ;; compare -(define_insn "cmpdf" +(define_insn "*cmpdf" [(set (cc0) - (compare (match_operand:DF 0 "general_operand" "fR,Q,F") - (match_operand:DF 1 "register_operand" "a,a,a")))] + (compare (match_operand:DF 0 "general_operand" "fR,fR,Q,Q,F") + (match_operand:DF 1 "register_or_const0_operand" "G,a,G,a,a")))] "TARGET_FPU" "* { cc_status.flags = CC_IN_FPU; - return \"{cmpd|cmpf} %0, %1\;cfcc\"; -}" - [(set_attr "length" "2,3,6")]) - -;; a bit of brain damage, maybe inline later - -;; problem is - gcc seems to NEED SImode because -;; of the cmp weirdness - maybe change gcc to handle this? - -(define_expand "cmpsi" - [(set (reg:SI 0) - (match_operand:SI 0 "general_operand" "g")) - (set (reg:SI 2) - (match_operand:SI 1 "general_operand" "g")) - (parallel [(set (cc0) - (compare (reg:SI 0) - (reg:SI 2))) - (clobber (reg:SI 0))])] - "0" ;; disable for test - "") - -;; check for next insn for branch code - does this still -;; work in gcc 2.* ? - -(define_insn "" - [(set (cc0) - (compare (reg:SI 0) - (reg:SI 2))) - (clobber (reg:SI 0))] - "" - "* -{ - rtx br_insn = NEXT_INSN (insn); - RTX_CODE br_code; - - gcc_assert (GET_CODE (br_insn) == JUMP_INSN); - br_code = GET_CODE (XEXP (XEXP (PATTERN (br_insn), 1), 0)); - - switch(br_code) - { - case GEU: - case LTU: - case GTU: - case LEU: - - return \"jsr pc, ___ucmpsi\;cmp $1,r0\"; - - case GE: - case LT: - case GT: - case LE: - case EQ: - case NE: - - return \"jsr pc, ___cmpsi\;tst r0\"; - - default: - - gcc_unreachable (); - } + if (which_alternative == 0 || which_alternative == 2) + return \"{tstd|tstf} %0, %1\;cfcc\"; + else + return \"{cmpd|cmpf} %0, %1\;cfcc\"; }" - [(set_attr "length" "4")]) + [(set_attr "length" "2,2,3,3,6")]) - -(define_insn "cmphi" +(define_insn "*cmphi" [(set (cc0) - (compare (match_operand:HI 0 "general_operand" "rR,rR,Qi,Qi") - (match_operand:HI 1 "general_operand" "rR,Qi,rR,Qi")))] + (compare (match_operand:HI 0 "general_operand" "rR,rR,rR,Q,Qi,Qi") + (match_operand:HI 1 "general_operand" "N,rR,Qi,N,rR,Qi")))] "" - "cmp %0,%1" - [(set_attr "length" "1,2,2,3")]) - -(define_insn "cmpqi" + "@ + tst %0 + cmp %0,%1 + cmp %0,%1 + tst %0 + cmp %0,%1 + cmp %0,%1" + [(set_attr "length" "1,1,2,2,2,3")]) + +(define_insn "*cmpqi" [(set (cc0) - (compare (match_operand:QI 0 "general_operand" "rR,rR,Qi,Qi") - (match_operand:QI 1 "general_operand" "rR,Qi,rR,Qi")))] + (compare (match_operand:QI 0 "general_operand" "rR,rR,rR,Q,Qi,Qi") + (match_operand:QI 1 "general_operand" "N,rR,Qi,N,rR,Qi")))] "" - "cmpb %0,%1" - [(set_attr "length" "1,2,2,3")]) + "@ + tstb %0 + cmpb %0,%1 + cmpb %0,%1 + tstb %0 + cmpb %0,%1 + cmpb %0,%1" + [(set_attr "length" "1,1,2,2,2,3")]) -;; We have to have this because cse can optimize the previous pattern -;; into this one. - -(define_insn "tstdf" - [(set (cc0) - (match_operand:DF 0 "general_operand" "fR,Q"))] - "TARGET_FPU" - "* -{ - cc_status.flags = CC_IN_FPU; - return \"{tstd|tstf} %0\;cfcc\"; -}" - [(set_attr "length" "2,3")]) - - -(define_expand "tstsi" - [(set (reg:SI 0) - (match_operand:SI 0 "general_operand" "g")) - (parallel [(set (cc0) - (reg:SI 0)) - (clobber (reg:SI 0))])] - "0" ;; disable for test - "") - -(define_insn "" - [(set (cc0) - (reg:SI 0)) - (clobber (reg:SI 0))] - "" - "jsr pc, ___tstsi\;tst r0" - [(set_attr "length" "3")]) - - -(define_insn "tsthi" - [(set (cc0) - (match_operand:HI 0 "general_operand" "rR,Q"))] - "" - "tst %0" - [(set_attr "length" "1,2")]) - -(define_insn "tstqi" - [(set (cc0) - (match_operand:QI 0 "general_operand" "rR,Q"))] - "" - "tstb %0" - [(set_attr "length" "1,2")]) - ;; sob instruction - we need an assembler which can make this instruction ;; valid under _all_ circumstances! @@ -264,353 +178,81 @@ ;; These control RTL generation for conditional jump insns ;; and match them for register allocation. -;; problem with too short jump distance! we need an assembler which can -;; make this valid for all jump distances! -;; e.g. gas! - -;; these must be changed to check for CC_IN_FCCR if float is to be -;; enabled - -(define_insn "beq" - [(set (pc) - (if_then_else (eq (cc0) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "* return output_jump(\"beq\", \"bne\", get_attr_length(insn));" - [(set (attr "length") (if_then_else (ior (le (minus (match_dup 0) - (pc)) - (const_int -128)) - (ge (minus (match_dup 0) - (pc)) - (const_int 128))) - (const_int 3) - (const_int 1)))]) - - -(define_insn "bne" - [(set (pc) - (if_then_else (ne (cc0) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "* return output_jump(\"bne\", \"beq\", get_attr_length(insn));" - [(set (attr "length") (if_then_else (ior (le (minus (match_dup 0) - (pc)) - (const_int -128)) - (ge (minus (match_dup 0) - (pc)) - (const_int 128))) - (const_int 3) - (const_int 1)))]) - -(define_insn "bgt" - [(set (pc) - (if_then_else (gt (cc0) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "* return output_jump(\"bgt\", \"ble\", get_attr_length(insn));" - [(set (attr "length") (if_then_else (ior (le (minus (match_dup 0) - (pc)) - (const_int -128)) - (ge (minus (match_dup 0) - (pc)) - (const_int 128))) - (const_int 3) - (const_int 1)))]) - -(define_insn "bgtu" - [(set (pc) - (if_then_else (gtu (cc0) - (const_int 0)) - (label_ref (match_operand 0 "" "")) +(define_expand "cbranchdf4" + [(set (cc0) + (compare (match_operand:DF 1 "general_operand") + (match_operand:DF 2 "general_operand"))) + (set (pc) + (if_then_else (match_operator 0 "ordered_comparison_operator" + [(cc0) (const_int 0)]) + (label_ref (match_operand 3 "" "")) (pc)))] "" - "* return output_jump(\"bhi\", \"blos\", get_attr_length(insn));" - [(set (attr "length") (if_then_else (ior (le (minus (match_dup 0) - (pc)) - (const_int -128)) - (ge (minus (match_dup 0) - (pc)) - (const_int 128))) - (const_int 3) - (const_int 1)))]) + "") -(define_insn "blt" - [(set (pc) - (if_then_else (lt (cc0) - (const_int 0)) - (label_ref (match_operand 0 "" "")) +(define_expand "cbranchhi4" + [(set (cc0) + (compare (match_operand:HI 1 "general_operand") + (match_operand:HI 2 "general_operand"))) + (set (pc) + (if_then_else (match_operator 0 "ordered_comparison_operator" + [(cc0) (const_int 0)]) + (label_ref (match_operand 3 "" "")) (pc)))] "" - "* return output_jump(\"blt\", \"bge\", get_attr_length(insn));" - [(set (attr "length") (if_then_else (ior (le (minus (match_dup 0) - (pc)) - (const_int -128)) - (ge (minus (match_dup 0) - (pc)) - (const_int 128))) - (const_int 3) - (const_int 1)))]) - + "") -(define_insn "bltu" - [(set (pc) - (if_then_else (ltu (cc0) - (const_int 0)) - (label_ref (match_operand 0 "" "")) +(define_expand "cbranchqi4" + [(set (cc0) + (compare (match_operand:QI 1 "general_operand") + (match_operand:QI 2 "general_operand"))) + (set (pc) + (if_then_else (match_operator 0 "ordered_comparison_operator" + [(cc0) (const_int 0)]) + (label_ref (match_operand 3 "" "")) (pc)))] "" - "* return output_jump(\"blo\", \"bhis\", get_attr_length(insn));" - [(set (attr "length") (if_then_else (ior (le (minus (match_dup 0) - (pc)) - (const_int -128)) - (ge (minus (match_dup 0) - (pc)) - (const_int 128))) - (const_int 3) - (const_int 1)))]) + "") -(define_insn "bge" - [(set (pc) - (if_then_else (ge (cc0) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "* return output_jump(\"bge\", \"blt\", get_attr_length(insn));" - [(set (attr "length") (if_then_else (ior (le (minus (match_dup 0) - (pc)) - (const_int -128)) - (ge (minus (match_dup 0) - (pc)) - (const_int 128))) - (const_int 3) - (const_int 1)))]) +;; problem with too short jump distance! we need an assembler which can +;; make this valid for all jump distances! +;; e.g. gas! -(define_insn "bgeu" - [(set (pc) - (if_then_else (geu (cc0) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "* return output_jump(\"bhis\", \"blo\", get_attr_length(insn));" - [(set (attr "length") (if_then_else (ior (le (minus (match_dup 0) - (pc)) - (const_int -128)) - (ge (minus (match_dup 0) - (pc)) - (const_int 128))) - (const_int 3) - (const_int 1)))]) +;; these must be changed to check for CC_IN_FCCR if float is to be +;; enabled -(define_insn "ble" +(define_insn "*branch" [(set (pc) - (if_then_else (le (cc0) - (const_int 0)) - (label_ref (match_operand 0 "" "")) + (if_then_else (match_operator 0 "ordered_comparison_operator" + [(cc0) (const_int 0)]) + (label_ref (match_operand 1 "" "")) (pc)))] "" - "* return output_jump(\"ble\", \"bgt\", get_attr_length(insn));" - [(set (attr "length") (if_then_else (ior (le (minus (match_dup 0) + "* return output_jump(GET_CODE (operands[0]), 0, get_attr_length(insn));" + [(set (attr "length") (if_then_else (ior (le (minus (match_dup 1) (pc)) (const_int -128)) - (ge (minus (match_dup 0) + (ge (minus (match_dup 1) (pc)) (const_int 128))) (const_int 3) (const_int 1)))]) -(define_insn "bleu" - [(set (pc) - (if_then_else (leu (cc0) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "* return output_jump(\"blos\", \"bhi\", get_attr_length(insn));" - [(set (attr "length") (if_then_else (ior (le (minus (match_dup 0) - (pc)) - (const_int -128)) - (ge (minus (match_dup 0) - (pc)) - (const_int 128))) - (const_int 3) - (const_int 1)))]) - ;; These match inverted jump insns for register allocation. -(define_insn "" +(define_insn "*branch_inverted" [(set (pc) - (if_then_else (eq (cc0) - (const_int 0)) + (if_then_else (match_operator 0 "ordered_comparison_operator" + [(cc0) (const_int 0)]) (pc) - (label_ref (match_operand 0 "" ""))))] + (label_ref (match_operand 1 "" ""))))] "" - "* return output_jump(\"bne\", \"beq\", get_attr_length(insn));" - [(set (attr "length") (if_then_else (ior (le (minus (match_dup 0) + "* return output_jump(GET_CODE (operands[0]), 1, get_attr_length(insn));" + [(set (attr "length") (if_then_else (ior (le (minus (match_dup 1) (pc)) (const_int -128)) - (ge (minus (match_dup 0) - (pc)) - (const_int 128))) - (const_int 3) - (const_int 1)))]) - -(define_insn "" - [(set (pc) - (if_then_else (ne (cc0) - (const_int 0)) - (pc) - (label_ref (match_operand 0 "" ""))))] - "" - "* return output_jump(\"beq\", \"bne\", get_attr_length(insn));" - [(set (attr "length") (if_then_else (ior (le (minus (match_dup 0) - (pc)) - (const_int -128)) - (ge (minus (match_dup 0) - (pc)) - (const_int 128))) - (const_int 3) - (const_int 1)))]) - -(define_insn "" - [(set (pc) - (if_then_else (gt (cc0) - (const_int 0)) - (pc) - (label_ref (match_operand 0 "" ""))))] - "" - "* return output_jump(\"ble\", \"bgt\", get_attr_length(insn));" - [(set (attr "length") (if_then_else (ior (le (minus (match_dup 0) - (pc)) - (const_int -128)) - (ge (minus (match_dup 0) - (pc)) - (const_int 128))) - (const_int 3) - (const_int 1)))]) - -(define_insn "" - [(set (pc) - (if_then_else (gtu (cc0) - (const_int 0)) - (pc) - (label_ref (match_operand 0 "" ""))))] - "" - "* return output_jump(\"blos\", \"bhi\", get_attr_length(insn));" - [(set (attr "length") (if_then_else (ior (le (minus (match_dup 0) - (pc)) - (const_int -128)) - (ge (minus (match_dup 0) - (pc)) - (const_int 128))) - (const_int 3) - (const_int 1)))]) - -(define_insn "" - [(set (pc) - (if_then_else (lt (cc0) - (const_int 0)) - (pc) - (label_ref (match_operand 0 "" ""))))] - "" - "* return output_jump(\"bge\", \"blt\", get_attr_length(insn));" - [(set (attr "length") (if_then_else (ior (le (minus (match_dup 0) - (pc)) - (const_int -128)) - (ge (minus (match_dup 0) - (pc)) - (const_int 128))) - (const_int 3) - (const_int 1)))]) - -(define_insn "" - [(set (pc) - (if_then_else (ltu (cc0) - (const_int 0)) - (pc) - (label_ref (match_operand 0 "" ""))))] - "" - "* return output_jump(\"bhis\", \"blo\", get_attr_length(insn));" - [(set (attr "length") (if_then_else (ior (le (minus (match_dup 0) - (pc)) - (const_int -128)) - (ge (minus (match_dup 0) - (pc)) - (const_int 128))) - (const_int 3) - (const_int 1)))]) - -(define_insn "" - [(set (pc) - (if_then_else (ge (cc0) - (const_int 0)) - (pc) - (label_ref (match_operand 0 "" ""))))] - "" - "* return output_jump(\"blt\", \"bge\", get_attr_length(insn));" - [(set (attr "length") (if_then_else (ior (le (minus (match_dup 0) - (pc)) - (const_int -128)) - (ge (minus (match_dup 0) - (pc)) - (const_int 128))) - (const_int 3) - (const_int 1)))]) - -(define_insn "" - [(set (pc) - (if_then_else (geu (cc0) - (const_int 0)) - (pc) - (label_ref (match_operand 0 "" ""))))] - "" - "* return output_jump(\"blo\", \"bhis\", get_attr_length(insn));" - [(set (attr "length") (if_then_else (ior (le (minus (match_dup 0) - (pc)) - (const_int -128)) - (ge (minus (match_dup 0) - (pc)) - (const_int 128))) - (const_int 3) - (const_int 1)))]) - -(define_insn "" - [(set (pc) - (if_then_else (le (cc0) - (const_int 0)) - (pc) - (label_ref (match_operand 0 "" ""))))] - "" - "* return output_jump(\"bgt\", \"ble\", get_attr_length(insn));" - [(set (attr "length") (if_then_else (ior (le (minus (match_dup 0) - (pc)) - (const_int -128)) - (ge (minus (match_dup 0) - (pc)) - (const_int 128))) - (const_int 3) - (const_int 1)))]) - -(define_insn "" - [(set (pc) - (if_then_else (leu (cc0) - (const_int 0)) - (pc) - (label_ref (match_operand 0 "" ""))))] - "" - "* return output_jump(\"bhi\", \"blos\", get_attr_length(insn));" - [(set (attr "length") (if_then_else (ior (le (minus (match_dup 0) - (pc)) - (const_int -128)) - (ge (minus (match_dup 0) + (ge (minus (match_dup 1) (pc)) (const_int 128))) (const_int 3) diff --git a/gcc/config/picochip/picochip.md b/gcc/config/picochip/picochip.md index 657629c96fa..02f0f14850d 100644 --- a/gcc/config/picochip/picochip.md +++ b/gcc/config/picochip/picochip.md @@ -551,7 +551,7 @@ (define_insn_and_split "cbranchhi4" [(set (pc) (if_then_else - (match_operator:CC 0 "comparison_operator" + (match_operator:CC 0 "ordered_comparison_operator" [(match_operand:HI 1 "register_operand" "r") (match_operand:HI 2 "picochip_comparison_operand" "ri")]) (label_ref (match_operand 3 "" "")) @@ -2524,117 +2524,6 @@ (set_attr "type" "picoAlu,picoAlu") (set_attr "longConstant" "false,true")]) -;; cmphi - This needs to be defined, to ensure that the conditional -;; move works properly (because the if-cvt code uses this pattern to -;; build the conditional move, even though normally we use cbranch to -;; directly generate the instructions). - -(define_expand "cmphi" - [(match_operand:HI 0 "general_operand" "g") - (match_operand:HI 1 "general_operand" "g")] - "" - "DONE;") - -;;============================================================================ -;; Branch patterns - needed for conditional moves. This is because -;; they result in the bcc_gen_fctn array being initialised with the -;; code to define_expand the following, and this in turn means that -;; when noce_emit_cmove is called, the correct pattern can be -;; generated, based upon the assumed presence of the following. The -;; following are never actually used, because the earlier cbranch -;; patterns take precendence. -;;============================================================================ - -(define_expand "bne" - [(set (pc) - (if_then_else - (ne (reg:CC CC_REGNUM) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "gcc_unreachable();") - -(define_expand "beq" - [(set (pc) - (if_then_else - (eq (reg:CC CC_REGNUM) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "gcc_unreachable();") - -(define_expand "blt" - [(set (pc) - (if_then_else - (lt (reg:CC CC_REGNUM) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "gcc_unreachable();") - -(define_expand "bge" - [(set (pc) - (if_then_else - (ge (reg:CC CC_REGNUM) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "gcc_unreachable();") - -(define_expand "bgeu" - [(set (pc) - (if_then_else - (geu (reg:CC CC_REGNUM) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "gcc_unreachable();") - -(define_expand "bltu" - [(set (pc) - (if_then_else - (ltu (reg:CC CC_REGNUM) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "gcc_unreachable();") - -(define_expand "ble" - [(set (pc) - (if_then_else - (le (reg:CC CC_REGNUM) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "gcc_unreachable();") - -(define_expand "bgt" - [(set (pc) - (if_then_else - (gt (reg:CC CC_REGNUM) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "gcc_unreachable();") - -(define_expand "bleu" - [(set (pc) - (if_then_else - (leu (reg:CC CC_REGNUM) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "gcc_unreachable();") - -(define_expand "bgtu" - [(set (pc) - (if_then_else - (gtu (reg:CC CC_REGNUM) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "gcc_unreachable();") - ;;============================================================================ ;; Scheduling, including delay slot scheduling. ;;============================================================================ diff --git a/gcc/config/rs6000/predicates.md b/gcc/config/rs6000/predicates.md index af80ef46b6f..dbf78734b17 100644 --- a/gcc/config/rs6000/predicates.md +++ b/gcc/config/rs6000/predicates.md @@ -830,6 +830,11 @@ GET_MODE (XEXP (op, 0))), 1")))) +(define_predicate "rs6000_cbranch_operator" + (if_then_else (match_test "TARGET_HARD_FLOAT && !TARGET_FPRS") + (match_operand 0 "ordered_comparison_operator") + (match_operand 0 "comparison_operator"))) + ;; Return 1 if OP is a comparison operation that is valid for an SCC insn -- ;; it must be a positive comparison. (define_predicate "scc_comparison_operator" @@ -842,11 +847,6 @@ (and (match_operand 0 "branch_comparison_operator") (match_code "eq,lt,gt,ltu,gtu,unordered"))) -;; Return 1 is OP is a comparison operation that is valid for a trap insn. -(define_predicate "trap_comparison_operator" - (and (match_operand 0 "comparison_operator") - (match_code "eq,ne,le,lt,ge,gt,leu,ltu,geu,gtu"))) - ;; Return 1 if OP is a load multiple operation, known to be a PARALLEL. (define_predicate "load_multiple_operation" (match_code "parallel") diff --git a/gcc/config/rs6000/rs6000-protos.h b/gcc/config/rs6000/rs6000-protos.h index 4b8f5220a51..f40adabd00a 100644 --- a/gcc/config/rs6000/rs6000-protos.h +++ b/gcc/config/rs6000/rs6000-protos.h @@ -81,8 +81,8 @@ extern void print_operand_address (FILE *, rtx); extern bool rs6000_output_addr_const_extra (FILE *, rtx); extern enum rtx_code rs6000_reverse_condition (enum machine_mode, enum rtx_code); -extern void rs6000_emit_sCOND (enum rtx_code, rtx); -extern void rs6000_emit_cbranch (enum rtx_code, rtx); +extern void rs6000_emit_sCOND (enum machine_mode, rtx[]); +extern void rs6000_emit_cbranch (enum machine_mode, rtx[]); extern char * output_cbranch (rtx, const char *, int, rtx); extern char * output_e500_flip_gt_bit (rtx, rtx); extern rtx rs6000_emit_set_const (rtx, enum machine_mode, rtx, int); diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c index 8e24769816d..2d34b14f63f 100644 --- a/gcc/config/rs6000/rs6000.c +++ b/gcc/config/rs6000/rs6000.c @@ -190,11 +190,6 @@ int rs6000_darwin64_abi; /* Set to nonzero once AIX common-mode calls have been defined. */ static GTY(()) int common_mode_defined; -/* Save information from a "cmpxx" operation until the branch or scc is - emitted. */ -rtx rs6000_compare_op0, rs6000_compare_op1; -int rs6000_compare_fp_p; - /* Label number of label created for -mrelocatable, to call to so we can get the address of the GOT section */ int rs6000_pic_labelno; @@ -752,7 +747,7 @@ struct processor_costs power6_cost = { static bool rs6000_function_ok_for_sibcall (tree, tree); static const char *rs6000_invalid_within_doloop (const_rtx); -static rtx rs6000_generate_compare (enum rtx_code); +static rtx rs6000_generate_compare (rtx, enum machine_mode); static void rs6000_emit_stack_tie (void); static void rs6000_frame_related (rtx, rtx, HOST_WIDE_INT, rtx, rtx); static bool spe_func_has_64bit_regs_p (void); @@ -12788,21 +12783,24 @@ rs6000_reverse_condition (enum machine_mode mode, enum rtx_code code) represents the result of the compare. */ static rtx -rs6000_generate_compare (enum rtx_code code) +rs6000_generate_compare (rtx cmp, enum machine_mode mode) { enum machine_mode comp_mode; rtx compare_result; + enum rtx_code code = GET_CODE (cmp); + rtx op0 = XEXP (cmp, 0); + rtx op1 = XEXP (cmp, 1); - if (rs6000_compare_fp_p) + if (FLOAT_MODE_P (mode)) comp_mode = CCFPmode; else if (code == GTU || code == LTU || code == GEU || code == LEU) comp_mode = CCUNSmode; else if ((code == EQ || code == NE) - && GET_CODE (rs6000_compare_op0) == SUBREG - && GET_CODE (rs6000_compare_op1) == SUBREG - && SUBREG_PROMOTED_UNSIGNED_P (rs6000_compare_op0) - && SUBREG_PROMOTED_UNSIGNED_P (rs6000_compare_op1)) + && GET_CODE (op0) == SUBREG + && GET_CODE (op1) == SUBREG + && SUBREG_PROMOTED_UNSIGNED_P (op0) + && SUBREG_PROMOTED_UNSIGNED_P (op1)) /* These are unsigned values, perhaps there will be a later ordering compare that can be shared with this one. Unfortunately we cannot detect the signedness of the operands @@ -12816,13 +12814,13 @@ rs6000_generate_compare (enum rtx_code code) /* E500 FP compare instructions on the GPRs. Yuck! */ if ((!TARGET_FPRS && TARGET_HARD_FLOAT) - && rs6000_compare_fp_p) + && FLOAT_MODE_P (mode)) { rtx cmp, or_result, compare_result2; - enum machine_mode op_mode = GET_MODE (rs6000_compare_op0); + enum machine_mode op_mode = GET_MODE (op0); if (op_mode == VOIDmode) - op_mode = GET_MODE (rs6000_compare_op1); + op_mode = GET_MODE (op1); /* The E500 FP compare instructions toggle the GT bit (CR bit 1) only. This explains the following mess. */ @@ -12834,26 +12832,20 @@ rs6000_generate_compare (enum rtx_code code) { case SFmode: cmp = (flag_finite_math_only && !flag_trapping_math) - ? gen_tstsfeq_gpr (compare_result, rs6000_compare_op0, - rs6000_compare_op1) - : gen_cmpsfeq_gpr (compare_result, rs6000_compare_op0, - rs6000_compare_op1); + ? gen_tstsfeq_gpr (compare_result, op0, op1) + : gen_cmpsfeq_gpr (compare_result, op0, op1); break; case DFmode: cmp = (flag_finite_math_only && !flag_trapping_math) - ? gen_tstdfeq_gpr (compare_result, rs6000_compare_op0, - rs6000_compare_op1) - : gen_cmpdfeq_gpr (compare_result, rs6000_compare_op0, - rs6000_compare_op1); + ? gen_tstdfeq_gpr (compare_result, op0, op1) + : gen_cmpdfeq_gpr (compare_result, op0, op1); break; case TFmode: cmp = (flag_finite_math_only && !flag_trapping_math) - ? gen_tsttfeq_gpr (compare_result, rs6000_compare_op0, - rs6000_compare_op1) - : gen_cmptfeq_gpr (compare_result, rs6000_compare_op0, - rs6000_compare_op1); + ? gen_tsttfeq_gpr (compare_result, op0, op1) + : gen_cmptfeq_gpr (compare_result, op0, op1); break; default: @@ -12866,26 +12858,20 @@ rs6000_generate_compare (enum rtx_code code) { case SFmode: cmp = (flag_finite_math_only && !flag_trapping_math) - ? gen_tstsfgt_gpr (compare_result, rs6000_compare_op0, - rs6000_compare_op1) - : gen_cmpsfgt_gpr (compare_result, rs6000_compare_op0, - rs6000_compare_op1); + ? gen_tstsfgt_gpr (compare_result, op0, op1) + : gen_cmpsfgt_gpr (compare_result, op0, op1); break; case DFmode: cmp = (flag_finite_math_only && !flag_trapping_math) - ? gen_tstdfgt_gpr (compare_result, rs6000_compare_op0, - rs6000_compare_op1) - : gen_cmpdfgt_gpr (compare_result, rs6000_compare_op0, - rs6000_compare_op1); + ? gen_tstdfgt_gpr (compare_result, op0, op1) + : gen_cmpdfgt_gpr (compare_result, op0, op1); break; case TFmode: cmp = (flag_finite_math_only && !flag_trapping_math) - ? gen_tsttfgt_gpr (compare_result, rs6000_compare_op0, - rs6000_compare_op1) - : gen_cmptfgt_gpr (compare_result, rs6000_compare_op0, - rs6000_compare_op1); + ? gen_tsttfgt_gpr (compare_result, op0, op1) + : gen_cmptfgt_gpr (compare_result, op0, op1); break; default: @@ -12898,26 +12884,20 @@ rs6000_generate_compare (enum rtx_code code) { case SFmode: cmp = (flag_finite_math_only && !flag_trapping_math) - ? gen_tstsflt_gpr (compare_result, rs6000_compare_op0, - rs6000_compare_op1) - : gen_cmpsflt_gpr (compare_result, rs6000_compare_op0, - rs6000_compare_op1); + ? gen_tstsflt_gpr (compare_result, op0, op1) + : gen_cmpsflt_gpr (compare_result, op0, op1); break; case DFmode: cmp = (flag_finite_math_only && !flag_trapping_math) - ? gen_tstdflt_gpr (compare_result, rs6000_compare_op0, - rs6000_compare_op1) - : gen_cmpdflt_gpr (compare_result, rs6000_compare_op0, - rs6000_compare_op1); + ? gen_tstdflt_gpr (compare_result, op0, op1) + : gen_cmpdflt_gpr (compare_result, op0, op1); break; case TFmode: cmp = (flag_finite_math_only && !flag_trapping_math) - ? gen_tsttflt_gpr (compare_result, rs6000_compare_op0, - rs6000_compare_op1) - : gen_cmptflt_gpr (compare_result, rs6000_compare_op0, - rs6000_compare_op1); + ? gen_tsttflt_gpr (compare_result, op0, op1) + : gen_cmptflt_gpr (compare_result, op0, op1); break; default: @@ -12949,26 +12929,20 @@ rs6000_generate_compare (enum rtx_code code) { case SFmode: cmp = (flag_finite_math_only && !flag_trapping_math) - ? gen_tstsfeq_gpr (compare_result2, rs6000_compare_op0, - rs6000_compare_op1) - : gen_cmpsfeq_gpr (compare_result2, rs6000_compare_op0, - rs6000_compare_op1); + ? gen_tstsfeq_gpr (compare_result2, op0, op1) + : gen_cmpsfeq_gpr (compare_result2, op0, op1); break; case DFmode: cmp = (flag_finite_math_only && !flag_trapping_math) - ? gen_tstdfeq_gpr (compare_result2, rs6000_compare_op0, - rs6000_compare_op1) - : gen_cmpdfeq_gpr (compare_result2, rs6000_compare_op0, - rs6000_compare_op1); + ? gen_tstdfeq_gpr (compare_result2, op0, op1) + : gen_cmpdfeq_gpr (compare_result2, op0, op1); break; case TFmode: cmp = (flag_finite_math_only && !flag_trapping_math) - ? gen_tsttfeq_gpr (compare_result2, rs6000_compare_op0, - rs6000_compare_op1) - : gen_cmptfeq_gpr (compare_result2, rs6000_compare_op0, - rs6000_compare_op1); + ? gen_tsttfeq_gpr (compare_result2, op0, op1) + : gen_cmptfeq_gpr (compare_result2, op0, op1); break; default: @@ -12998,16 +12972,14 @@ rs6000_generate_compare (enum rtx_code code) /* Generate XLC-compatible TFmode compare as PARALLEL with extra CLOBBERs to match cmptf_internal2 pattern. */ if (comp_mode == CCFPmode && TARGET_XL_COMPAT - && GET_MODE (rs6000_compare_op0) == TFmode + && GET_MODE (op0) == TFmode && !TARGET_IEEEQUAD && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_LONG_DOUBLE_128) emit_insn (gen_rtx_PARALLEL (VOIDmode, gen_rtvec (9, gen_rtx_SET (VOIDmode, compare_result, - gen_rtx_COMPARE (comp_mode, - rs6000_compare_op0, - rs6000_compare_op1)), + gen_rtx_COMPARE (comp_mode, op0, op1)), gen_rtx_CLOBBER (VOIDmode, gen_rtx_SCRATCH (DFmode)), gen_rtx_CLOBBER (VOIDmode, gen_rtx_SCRATCH (DFmode)), gen_rtx_CLOBBER (VOIDmode, gen_rtx_SCRATCH (DFmode)), @@ -13016,29 +12988,25 @@ rs6000_generate_compare (enum rtx_code code) gen_rtx_CLOBBER (VOIDmode, gen_rtx_SCRATCH (DFmode)), gen_rtx_CLOBBER (VOIDmode, gen_rtx_SCRATCH (DFmode)), gen_rtx_CLOBBER (VOIDmode, gen_rtx_SCRATCH (DFmode))))); - else if (GET_CODE (rs6000_compare_op1) == UNSPEC - && XINT (rs6000_compare_op1, 1) == UNSPEC_SP_TEST) + else if (GET_CODE (op1) == UNSPEC + && XINT (op1, 1) == UNSPEC_SP_TEST) { - rtx op1 = XVECEXP (rs6000_compare_op1, 0, 0); + rtx op1 = XVECEXP (op1, 0, 0); comp_mode = CCEQmode; compare_result = gen_reg_rtx (CCEQmode); if (TARGET_64BIT) - emit_insn (gen_stack_protect_testdi (compare_result, - rs6000_compare_op0, op1)); + emit_insn (gen_stack_protect_testdi (compare_result, op0, op1)); else - emit_insn (gen_stack_protect_testsi (compare_result, - rs6000_compare_op0, op1)); + emit_insn (gen_stack_protect_testsi (compare_result, op0, op1)); } else emit_insn (gen_rtx_SET (VOIDmode, compare_result, - gen_rtx_COMPARE (comp_mode, - rs6000_compare_op0, - rs6000_compare_op1))); + gen_rtx_COMPARE (comp_mode, op0, op1))); } /* Some kinds of FP comparisons need an OR operation; under flag_finite_math_only we don't bother. */ - if (rs6000_compare_fp_p + if (FLOAT_MODE_P (mode) && !flag_finite_math_only && !(TARGET_HARD_FLOAT && !TARGET_FPRS) && (code == LE || code == GE @@ -13081,16 +13049,17 @@ rs6000_generate_compare (enum rtx_code code) /* Emit the RTL for an sCOND pattern. */ void -rs6000_emit_sCOND (enum rtx_code code, rtx result) +rs6000_emit_sCOND (enum machine_mode mode, rtx operands[]) { rtx condition_rtx; enum machine_mode op_mode; enum rtx_code cond_code; + rtx result = operands[0]; - condition_rtx = rs6000_generate_compare (code); + condition_rtx = rs6000_generate_compare (operands[1], mode); cond_code = GET_CODE (condition_rtx); - if (rs6000_compare_fp_p + if (FLOAT_MODE_P (mode) && !TARGET_FPRS && TARGET_HARD_FLOAT) { rtx t; @@ -13125,11 +13094,11 @@ rs6000_emit_sCOND (enum rtx_code code, rtx result) condition_rtx = gen_rtx_EQ (VOIDmode, not_result, const0_rtx); } - op_mode = GET_MODE (rs6000_compare_op0); + op_mode = GET_MODE (XEXP (operands[1], 0)); if (op_mode == VOIDmode) - op_mode = GET_MODE (rs6000_compare_op1); + op_mode = GET_MODE (XEXP (operands[1], 1)); - if (TARGET_POWERPC64 && (op_mode == DImode || rs6000_compare_fp_p)) + if (TARGET_POWERPC64 && (op_mode == DImode || FLOAT_MODE_P (mode))) { PUT_MODE (condition_rtx, DImode); convert_move (result, condition_rtx, 0); @@ -13144,12 +13113,12 @@ rs6000_emit_sCOND (enum rtx_code code, rtx result) /* Emit a branch of kind CODE to location LOC. */ void -rs6000_emit_cbranch (enum rtx_code code, rtx loc) +rs6000_emit_cbranch (enum machine_mode mode, rtx operands[]) { rtx condition_rtx, loc_ref; - condition_rtx = rs6000_generate_compare (code); - loc_ref = gen_rtx_LABEL_REF (VOIDmode, loc); + condition_rtx = rs6000_generate_compare (operands[0], mode); + loc_ref = gen_rtx_LABEL_REF (VOIDmode, operands[3]); emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx, gen_rtx_IF_THEN_ELSE (VOIDmode, condition_rtx, loc_ref, pc_rtx))); @@ -13595,8 +13564,8 @@ int rs6000_emit_cmove (rtx dest, rtx op, rtx true_cond, rtx false_cond) { enum rtx_code code = GET_CODE (op); - rtx op0 = rs6000_compare_op0; - rtx op1 = rs6000_compare_op1; + rtx op0 = XEXP (op, 0); + rtx op1 = XEXP (op, 1); REAL_VALUE_TYPE c1; enum machine_mode compare_mode = GET_MODE (op0); enum machine_mode result_mode = GET_MODE (dest); @@ -13616,7 +13585,7 @@ rs6000_emit_cmove (rtx dest, rtx op, rtx true_cond, rtx false_cond) /* First, work out if the hardware can do this at all, or if it's too slow.... */ - if (! rs6000_compare_fp_p) + if (!FLOAT_MODE_P (compare_mode)) { if (TARGET_ISEL) return rs6000_emit_int_cmove (dest, op, true_cond, false_cond); @@ -13781,13 +13750,13 @@ rs6000_emit_int_cmove (rtx dest, rtx op, rtx true_cond, rtx false_cond) rtx condition_rtx, cr; /* All isel implementations thus far are 32-bits. */ - if (GET_MODE (rs6000_compare_op0) != SImode) + if (GET_MODE (XEXP (op, 0)) != SImode) return 0; /* We still have to do the compare, because isel doesn't do a compare, it just looks at the CRx bits set by a previous compare instruction. */ - condition_rtx = rs6000_generate_compare (GET_CODE (op)); + condition_rtx = rs6000_generate_compare (op, SImode); cr = XEXP (condition_rtx, 0); if (GET_MODE (cr) == CCmode) diff --git a/gcc/config/rs6000/rs6000.h b/gcc/config/rs6000/rs6000.h index f11ea1fe249..e65bf5d95df 100644 --- a/gcc/config/rs6000/rs6000.h +++ b/gcc/config/rs6000/rs6000.h @@ -1986,12 +1986,6 @@ do { \ /* Given a condition code and a mode, return the inverse condition. */ #define REVERSE_CONDITION(CODE, MODE) rs6000_reverse_condition (MODE, CODE) -/* Define the information needed to generate branch and scc insns. This is - stored from the compare operation. */ - -extern GTY(()) rtx rs6000_compare_op0; -extern GTY(()) rtx rs6000_compare_op1; -extern int rs6000_compare_fp_p; /* Control the assembler format that we output. */ diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md index cc37d911dbb..9d4a96051b7 100644 --- a/gcc/config/rs6000/rs6000.md +++ b/gcc/config/rs6000/rs6000.md @@ -11897,262 +11897,90 @@ ;; signed & unsigned, and one type of branch. ;; ;; Start with the DEFINE_EXPANDs to generate the rtl for compares, scc -;; insns, and branches. We store the operands of compares until we see -;; how it is used. -(define_expand "cmp<mode>" - [(set (cc0) - (compare (match_operand:GPR 0 "gpc_reg_operand" "") - (match_operand:GPR 1 "reg_or_short_operand" "")))] +;; insns, and branches. + +(define_expand "cbranch<mode>4" + [(use (match_operator 0 "rs6000_cbranch_operator" + [(match_operand:GPR 1 "gpc_reg_operand" "") + (match_operand:GPR 2 "reg_or_short_operand" "")])) + (use (match_operand 3 ""))] "" " { - /* Take care of the possibility that operands[1] might be negative but + /* Take care of the possibility that operands[2] might be negative but this might be a logical operation. That insn doesn't exist. */ - if (GET_CODE (operands[1]) == CONST_INT - && INTVAL (operands[1]) < 0) - operands[1] = force_reg (<MODE>mode, operands[1]); - - rs6000_compare_op0 = operands[0]; - rs6000_compare_op1 = operands[1]; - rs6000_compare_fp_p = 0; - DONE; -}") + if (GET_CODE (operands[2]) == CONST_INT + && INTVAL (operands[2]) < 0) + { + operands[2] = force_reg (<MODE>mode, operands[2]); + operands[0] = gen_rtx_fmt_ee (GET_CODE (operands[0]), + GET_MODE (operands[0]), + operands[1], operands[2]); + } -(define_expand "cmp<mode>" - [(set (cc0) (compare (match_operand:FP 0 "gpc_reg_operand" "") - (match_operand:FP 1 "gpc_reg_operand" "")))] - "" - " -{ - rs6000_compare_op0 = operands[0]; - rs6000_compare_op1 = operands[1]; - rs6000_compare_fp_p = 1; + rs6000_emit_cbranch (<MODE>mode, operands); DONE; }") -(define_expand "beq" - [(use (match_operand 0 "" ""))] - "" - "{ rs6000_emit_cbranch (EQ, operands[0]); DONE; }") - -(define_expand "bne" - [(use (match_operand 0 "" ""))] - "" - "{ rs6000_emit_cbranch (NE, operands[0]); DONE; }") - -(define_expand "bge" - [(use (match_operand 0 "" ""))] - "" - "{ rs6000_emit_cbranch (GE, operands[0]); DONE; }") - -(define_expand "bgt" - [(use (match_operand 0 "" ""))] - "" - "{ rs6000_emit_cbranch (GT, operands[0]); DONE; }") - -(define_expand "ble" - [(use (match_operand 0 "" ""))] - "" - "{ rs6000_emit_cbranch (LE, operands[0]); DONE; }") - -(define_expand "blt" - [(use (match_operand 0 "" ""))] - "" - "{ rs6000_emit_cbranch (LT, operands[0]); DONE; }") - -(define_expand "bgeu" - [(use (match_operand 0 "" ""))] - "" - "{ rs6000_emit_cbranch (GEU, operands[0]); DONE; }") - -(define_expand "bgtu" - [(use (match_operand 0 "" ""))] - "" - "{ rs6000_emit_cbranch (GTU, operands[0]); DONE; }") - -(define_expand "bleu" - [(use (match_operand 0 "" ""))] - "" - "{ rs6000_emit_cbranch (LEU, operands[0]); DONE; }") - -(define_expand "bltu" - [(use (match_operand 0 "" ""))] - "" - "{ rs6000_emit_cbranch (LTU, operands[0]); DONE; }") - -(define_expand "bunordered" - [(use (match_operand 0 "" ""))] - "! (TARGET_HARD_FLOAT && !TARGET_FPRS)" - "{ rs6000_emit_cbranch (UNORDERED, operands[0]); DONE; }") - -(define_expand "bordered" - [(use (match_operand 0 "" ""))] - "! (TARGET_HARD_FLOAT && !TARGET_FPRS)" - "{ rs6000_emit_cbranch (ORDERED, operands[0]); DONE; }") - -(define_expand "buneq" - [(use (match_operand 0 "" ""))] - "! (TARGET_HARD_FLOAT && !TARGET_FPRS)" - "{ rs6000_emit_cbranch (UNEQ, operands[0]); DONE; }") - -(define_expand "bunge" - [(use (match_operand 0 "" ""))] - "! (TARGET_HARD_FLOAT && !TARGET_FPRS)" - "{ rs6000_emit_cbranch (UNGE, operands[0]); DONE; }") - -(define_expand "bungt" - [(use (match_operand 0 "" ""))] - "! (TARGET_HARD_FLOAT && !TARGET_FPRS)" - "{ rs6000_emit_cbranch (UNGT, operands[0]); DONE; }") - -(define_expand "bunle" - [(use (match_operand 0 "" ""))] - "! (TARGET_HARD_FLOAT && !TARGET_FPRS)" - "{ rs6000_emit_cbranch (UNLE, operands[0]); DONE; }") - -(define_expand "bunlt" - [(use (match_operand 0 "" ""))] - "! (TARGET_HARD_FLOAT && !TARGET_FPRS)" - "{ rs6000_emit_cbranch (UNLT, operands[0]); DONE; }") - -(define_expand "bltgt" - [(use (match_operand 0 "" ""))] - "! (TARGET_HARD_FLOAT && !TARGET_FPRS)" - "{ rs6000_emit_cbranch (LTGT, operands[0]); DONE; }") - -;; For SNE, we would prefer that the xor/abs sequence be used for integers. -;; For SEQ, likewise, except that comparisons with zero should be done -;; with an scc insns. However, due to the order that combine see the -;; resulting insns, we must, in fact, allow SEQ for integers. Fail in -;; the cases we don't want to handle. -(define_expand "seq" - [(clobber (match_operand:SI 0 "gpc_reg_operand" ""))] - "" - "{ rs6000_emit_sCOND (EQ, operands[0]); DONE; }") - -(define_expand "sne" - [(clobber (match_operand:SI 0 "gpc_reg_operand" ""))] +(define_expand "cbranch<mode>4" + [(use (match_operator 0 "rs6000_cbranch_operator" + [(match_operand:FP 1 "gpc_reg_operand" "") + (match_operand:FP 2 "gpc_reg_operand" "")])) + (use (match_operand 3 ""))] "" " { - if (! rs6000_compare_fp_p) - FAIL; - - rs6000_emit_sCOND (NE, operands[0]); + rs6000_emit_cbranch (<MODE>mode, operands); DONE; }") -;; A >= 0 is best done the portable way for A an integer. -(define_expand "sge" - [(clobber (match_operand:SI 0 "gpc_reg_operand" ""))] +(define_expand "cstore<mode>4" + [(use (match_operator 1 "rs6000_cbranch_operator" + [(match_operand:GPR 2 "gpc_reg_operand" "") + (match_operand:GPR 3 "reg_or_short_operand" "")])) + (clobber (match_operand:SI 0 "register_operand"))] "" " { - if (! rs6000_compare_fp_p && rs6000_compare_op1 == const0_rtx) - FAIL; - - rs6000_emit_sCOND (GE, operands[0]); - DONE; -}") + /* Take care of the possibility that operands[3] might be negative but + this might be a logical operation. That insn doesn't exist. */ + if (GET_CODE (operands[3]) == CONST_INT + && INTVAL (operands[3]) < 0) + { + operands[3] = force_reg (<MODE>mode, operands[3]); + operands[1] = gen_rtx_fmt_ee (GET_CODE (operands[1]), + GET_MODE (operands[1]), + operands[2], operands[3]); + } -;; A > 0 is best done using the portable sequence, so fail in that case. -(define_expand "sgt" - [(clobber (match_operand:SI 0 "gpc_reg_operand" ""))] - "" - " -{ - if (! rs6000_compare_fp_p && rs6000_compare_op1 == const0_rtx) + /* For SNE, we would prefer that the xor/abs sequence be used for integers. + For SEQ, likewise, except that comparisons with zero should be done + with an scc insns. However, due to the order that combine see the + resulting insns, we must, in fact, allow SEQ for integers. Fail in + the cases we don't want to handle or are best handled by portable + code. */ + if (GET_CODE (operands[1]) == NE) FAIL; - - rs6000_emit_sCOND (GT, operands[0]); - DONE; -}") - -;; A <= 0 is best done the portable way for A an integer. -(define_expand "sle" - [(clobber (match_operand:SI 0 "gpc_reg_operand" ""))] - "" - " -{ - if (! rs6000_compare_fp_p && rs6000_compare_op1 == const0_rtx) + if ((GET_CODE (operands[1]) == LT || GET_CODE (operands[1]) == LE + || GET_CODE (operands[1]) == GT || GET_CODE (operands[1]) == GE) + && operands[3] == const0_rtx) FAIL; - - rs6000_emit_sCOND (LE, operands[0]); + rs6000_emit_sCOND (<MODE>mode, operands); DONE; }") -;; A < 0 is best done in the portable way for A an integer. -(define_expand "slt" - [(clobber (match_operand:SI 0 "gpc_reg_operand" ""))] +(define_expand "cstore<mode>4" + [(use (match_operator 1 "rs6000_cbranch_operator" + [(match_operand:FP 2 "gpc_reg_operand" "") + (match_operand:FP 3 "gpc_reg_operand" "")])) + (clobber (match_operand:SI 0 "register_operand"))] "" " { - if (! rs6000_compare_fp_p && rs6000_compare_op1 == const0_rtx) - FAIL; - - rs6000_emit_sCOND (LT, operands[0]); + rs6000_emit_sCOND (<MODE>mode, operands); DONE; }") -(define_expand "sgeu" - [(clobber (match_operand:SI 0 "gpc_reg_operand" ""))] - "" - "{ rs6000_emit_sCOND (GEU, operands[0]); DONE; }") - -(define_expand "sgtu" - [(clobber (match_operand:SI 0 "gpc_reg_operand" ""))] - "" - "{ rs6000_emit_sCOND (GTU, operands[0]); DONE; }") - -(define_expand "sleu" - [(clobber (match_operand:SI 0 "gpc_reg_operand" ""))] - "" - "{ rs6000_emit_sCOND (LEU, operands[0]); DONE; }") - -(define_expand "sltu" - [(clobber (match_operand:SI 0 "gpc_reg_operand" ""))] - "" - "{ rs6000_emit_sCOND (LTU, operands[0]); DONE; }") - -(define_expand "sunordered" - [(clobber (match_operand:SI 0 "gpc_reg_operand" ""))] - "! (TARGET_HARD_FLOAT && !TARGET_FPRS)" - "{ rs6000_emit_sCOND (UNORDERED, operands[0]); DONE; }") - -(define_expand "sordered" - [(clobber (match_operand:SI 0 "gpc_reg_operand" ""))] - "! (TARGET_HARD_FLOAT && !TARGET_FPRS)" - "{ rs6000_emit_sCOND (ORDERED, operands[0]); DONE; }") - -(define_expand "suneq" - [(clobber (match_operand:SI 0 "gpc_reg_operand" ""))] - "! (TARGET_HARD_FLOAT && !TARGET_FPRS)" - "{ rs6000_emit_sCOND (UNEQ, operands[0]); DONE; }") - -(define_expand "sunge" - [(clobber (match_operand:SI 0 "gpc_reg_operand" ""))] - "! (TARGET_HARD_FLOAT && !TARGET_FPRS)" - "{ rs6000_emit_sCOND (UNGE, operands[0]); DONE; }") - -(define_expand "sungt" - [(clobber (match_operand:SI 0 "gpc_reg_operand" ""))] - "! (TARGET_HARD_FLOAT && !TARGET_FPRS)" - "{ rs6000_emit_sCOND (UNGT, operands[0]); DONE; }") - -(define_expand "sunle" - [(clobber (match_operand:SI 0 "gpc_reg_operand" ""))] - "! (TARGET_HARD_FLOAT && !TARGET_FPRS)" - "{ rs6000_emit_sCOND (UNLE, operands[0]); DONE; }") - -(define_expand "sunlt" - [(clobber (match_operand:SI 0 "gpc_reg_operand" ""))] - "! (TARGET_HARD_FLOAT && !TARGET_FPRS)" - "{ rs6000_emit_sCOND (UNLT, operands[0]); DONE; }") - -(define_expand "sltgt" - [(clobber (match_operand:SI 0 "gpc_reg_operand" ""))] - "! (TARGET_HARD_FLOAT && !TARGET_FPRS)" - "{ rs6000_emit_sCOND (LTGT, operands[0]); DONE; }") (define_expand "stack_protect_set" [(match_operand 0 "memory_operand" "") @@ -12195,16 +12023,16 @@ (match_operand 2 "" "")] "" { + rtx test, op0, op1; #ifdef TARGET_THREAD_SSP_OFFSET rtx tlsreg = gen_rtx_REG (Pmode, TARGET_64BIT ? 13 : 2); rtx addr = gen_rtx_PLUS (Pmode, tlsreg, GEN_INT (TARGET_THREAD_SSP_OFFSET)); operands[1] = gen_rtx_MEM (Pmode, addr); #endif - rs6000_compare_op0 = operands[0]; - rs6000_compare_op1 = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, operands[1]), - UNSPEC_SP_TEST); - rs6000_compare_fp_p = 0; - emit_jump_insn (gen_beq (operands[2])); + op0 = operands[0]; + op1 = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, operands[1]), UNSPEC_SP_TEST); + test = gen_rtx_EQ (VOIDmode, op0, op1); + emit_jump_insn (gen_cbranchsi4 (test, op0, op1, operands[2])); DONE; }) @@ -14775,17 +14603,16 @@ "{t 31,0,0|trap}" [(set_attr "type" "trap")]) -(define_expand "conditional_trap" - [(trap_if (match_operator 0 "trap_comparison_operator" - [(match_dup 2) (match_dup 3)]) - (match_operand 1 "const_int_operand" ""))] +(define_expand "ctrap<mode>4" + [(trap_if (match_operator 0 "ordered_comparison_operator" + [(match_operand:GPR 1 "register_operand") + (match_operand:GPR 2 "reg_or_short_operand")]) + (match_operand 3 "zero_constant" ""))] "" - "if (rs6000_compare_fp_p || operands[1] != const0_rtx) FAIL; - operands[2] = rs6000_compare_op0; - operands[3] = rs6000_compare_op1;") + "") (define_insn "" - [(trap_if (match_operator 0 "trap_comparison_operator" + [(trap_if (match_operator 0 "ordered_comparison_operator" [(match_operand:GPR 1 "register_operand" "r") (match_operand:GPR 2 "reg_or_short_operand" "rI")]) (const_int 0))] diff --git a/gcc/config/s390/predicates.md b/gcc/config/s390/predicates.md index bb8fdf261d5..d09c9b3e161 100644 --- a/gcc/config/s390/predicates.md +++ b/gcc/config/s390/predicates.md @@ -189,6 +189,14 @@ return (s390_compare_and_branch_condition_mask (op) >= 0); }) +;; Return nonzero if OP is a valid comparison operator for the +;; cstore expanders -- respectively cstorecc4 and integer cstore. +(define_predicate "s390_eqne_operator" + (match_code "eq, ne")) + +(define_predicate "s390_scond_operator" + (match_code "ltu, gtu, leu, geu")) + ;; Return nonzero if OP is a valid comparison operator ;; for an ALC condition. diff --git a/gcc/config/s390/s390.c b/gcc/config/s390/s390.c index e2ed4a0d407..17891c6492f 100644 --- a/gcc/config/s390/s390.c +++ b/gcc/config/s390/s390.c @@ -223,11 +223,6 @@ struct processor_costs z10_cost = extern int reload_completed; -/* Save information from a "cmpxx" operation until the branch or scc is - emitted. A pair of a MODE_CC register and a const0_rtx if a compare - has been emitted already. */ -rtx s390_compare_op0, s390_compare_op1; - /* Structure used to hold the components of a S/390 memory address. A legitimate address on S/390 is of the general form @@ -7747,15 +7742,11 @@ s390_emit_prologue (void) rtx t = gen_rtx_AND (Pmode, stack_pointer_rtx, GEN_INT (stack_check_mask)); if (TARGET_64BIT) - gen_cmpdi (t, const0_rtx); + emit_insn (gen_ctrapdi4 (gen_rtx_EQ (VOIDmode, t, const0_rtx), + t, const0_rtx, const0_rtx)); else - gen_cmpsi (t, const0_rtx); - - emit_insn (gen_conditional_trap (gen_rtx_EQ (CCmode, - gen_rtx_REG (CCmode, - CC_REGNUM), - const0_rtx), - const0_rtx)); + emit_insn (gen_ctrapsi4 (gen_rtx_EQ (VOIDmode, t, const0_rtx), + t, const0_rtx, const0_rtx)); } } diff --git a/gcc/config/s390/s390.h b/gcc/config/s390/s390.h index 2b4d7ce72ca..b2541857170 100644 --- a/gcc/config/s390/s390.h +++ b/gcc/config/s390/s390.h @@ -803,12 +803,6 @@ do { \ #define CANONICALIZE_COMPARISON(CODE, OP0, OP1) \ s390_canonicalize_comparison (&(CODE), &(OP0), &(OP1)) -/* Define the information needed to generate branch and scc insns. This is - stored from the compare operation. Note that we can't use "rtx" here - since it hasn't been defined! */ -extern struct rtx_def *s390_compare_op0, *s390_compare_op1; - - /* Relative costs of operations. */ /* On s390, copy between fprs and gprs is expensive. */ diff --git a/gcc/config/s390/s390.md b/gcc/config/s390/s390.md index c3d181f0aac..7c9a2b28100 100644 --- a/gcc/config/s390/s390.md +++ b/gcc/config/s390/s390.md @@ -354,13 +354,6 @@ (define_mode_iterator INT [(DI "TARGET_64BIT") SI HI QI]) (define_mode_iterator INTALL [TI DI SI HI QI]) -;; This iterator allows to unify all 'bCOND' expander patterns. -(define_code_iterator COMPARE [eq ne gt gtu lt ltu ge geu le leu unordered - ordered uneq unlt ungt unle unge ltgt]) - -;; This iterator allows to unify all 'sCOND' patterns. -(define_code_iterator SCOND [ltu gtu leu geu]) - ;; This iterator allows some 'ashift' and 'lshiftrt' pattern to be defined from ;; the same template. (define_code_iterator SHIFT [ashift lshiftrt]) @@ -493,39 +486,6 @@ ;;- Compare instructions. ;; -(define_expand "cmp<mode>" - [(set (reg:CC CC_REGNUM) - (compare:CC (match_operand:GPR 0 "register_operand" "") - (match_operand:GPR 1 "general_operand" "")))] - "" -{ - s390_compare_op0 = operands[0]; - s390_compare_op1 = operands[1]; - DONE; -}) - -(define_expand "cmp<mode>" - [(set (reg:CC CC_REGNUM) - (compare:CC (match_operand:FP 0 "register_operand" "") - (match_operand:FP 1 "general_operand" "")))] - "TARGET_HARD_FLOAT" -{ - s390_compare_op0 = operands[0]; - s390_compare_op1 = operands[1]; - DONE; -}) - -(define_expand "cmpcc" - [(set (reg:CC CC_REGNUM) - (compare:CC (match_operand 0 "cc_reg_operand" "") - (match_operand 1 "general_operand" "")))] - "" -{ - s390_compare_op0 = operands[0]; - s390_compare_op1 = operands[1]; - DONE; -}) - ; Test-under-Mask instructions (define_insn "*tmqi_mem" @@ -3812,9 +3772,9 @@ TD -> DI convert afterwards. */ emit_insn (gen_extendddtd2 (temp, operands[1])); temp = force_reg (TDmode, temp); - emit_insn (gen_cmptd (temp, - CONST_DOUBLE_FROM_REAL_VALUE (cmp, TDmode))); - emit_jump_insn (gen_blt (label1)); + emit_cmp_and_jump_insns (temp, + CONST_DOUBLE_FROM_REAL_VALUE (cmp, TDmode), + LT, NULL_RTX, VOIDmode, 0, label1); emit_insn (gen_subtd3 (temp, temp, CONST_DOUBLE_FROM_REAL_VALUE (sub, TDmode))); emit_insn (gen_fix_trunctddi2_dfp (operands[0], temp, GEN_INT (11))); @@ -3840,9 +3800,9 @@ decimal_real_from_string (&cmp, "9223372036854775808.0"); /* 2^63 */ decimal_real_from_string (&sub, "18446744073709551616.0"); /* 2^64 */ - emit_insn (gen_cmptd (operands[1], - CONST_DOUBLE_FROM_REAL_VALUE (cmp, TDmode))); - emit_jump_insn (gen_blt (label1)); + emit_cmp_and_jump_insns (operands[1], + CONST_DOUBLE_FROM_REAL_VALUE (cmp, TDmode), + LT, NULL_RTX, VOIDmode, 0, label1); emit_insn (gen_subtd3 (temp, operands[1], CONST_DOUBLE_FROM_REAL_VALUE (sub, TDmode))); emit_insn (gen_fix_trunctddi2_dfp (operands[0], temp, GEN_INT (11))); @@ -3873,9 +3833,9 @@ real_2expN (&cmp, GET_MODE_BITSIZE(<GPR:MODE>mode) - 1, <BFP:MODE>mode); real_2expN (&sub, GET_MODE_BITSIZE(<GPR:MODE>mode), <BFP:MODE>mode); - emit_insn (gen_cmp<BFP:mode> (operands[1], - CONST_DOUBLE_FROM_REAL_VALUE (cmp, <BFP:MODE>mode))); - emit_jump_insn (gen_blt (label1)); + emit_cmp_and_jump_insns (operands[1], + CONST_DOUBLE_FROM_REAL_VALUE (cmp, <BFP:MODE>mode), + LT, NULL_RTX, VOIDmode, 0, label1); emit_insn (gen_sub<BFP:mode>3 (temp, operands[1], CONST_DOUBLE_FROM_REAL_VALUE (sub, <BFP:MODE>mode))); emit_insn (gen_fix_trunc<BFP:mode><GPR:mode>2_bfp (operands[0], temp, @@ -5074,7 +5034,7 @@ (match_operand:GPR 3 "const_int_operand" "")] "TARGET_CPU_ZARCH" "if (!s390_expand_addcc (GET_CODE (operands[1]), - s390_compare_op0, s390_compare_op1, + XEXP (operands[1], 0), XEXP (operands[1], 1), operands[0], operands[2], operands[3])) FAIL; DONE;") @@ -5114,31 +5074,29 @@ "") -(define_expand "s<code>" +(define_expand "cstore<mode>4" [(set (match_operand:SI 0 "register_operand" "") - (SCOND (match_dup 0) - (match_dup 0)))] + (match_operator:SI 1 "s390_scond_operator" + [(match_operand:GPR 2 "register_operand" "") + (match_operand:GPR 3 "general_operand" "")]))] "TARGET_CPU_ZARCH" - "if (!s390_expand_addcc (<CODE>, s390_compare_op0, s390_compare_op1, + "if (!s390_expand_addcc (GET_CODE (operands[1]), operands[2], operands[3], operands[0], const0_rtx, const1_rtx)) FAIL; DONE;") -(define_expand "seq" +(define_expand "cstorecc4" [(parallel - [(set (match_operand:SI 0 "register_operand" "=d") - (match_dup 1)) - (clobber (reg:CC CC_REGNUM))]) - (parallel - [(set (match_dup 0) (xor:SI (match_dup 0) (const_int 1))) + [(set (match_operand:SI 0 "register_operand" "") + (match_operator:SI 1 "s390_eqne_operator" + [(match_operand:CCZ1 2 "register_operand") + (match_operand 3 "const0_operand")])) (clobber (reg:CC CC_REGNUM))])] "" -{ - if (GET_MODE (s390_compare_op0) != CCZ1mode) - FAIL; - operands[1] = s390_emit_compare (NE, s390_compare_op0, s390_compare_op1); - PUT_MODE (operands[1], SImode); -}) + "emit_insn (gen_sne (operands[0], operands[2])); + if (GET_CODE (operands[1]) == EQ) + emit_insn (gen_xorsi3 (operands[0], operands[0], const1_rtx)); + DONE;") -(define_insn_and_split "*sne" +(define_insn_and_split "sne" [(set (match_operand:SI 0 "register_operand" "=d") (ne:SI (match_operand:CCZ1 1 "register_operand" "0") (const_int 0))) @@ -5566,8 +5524,8 @@ operands[1] = make_safe_from (operands[1], operands[0]); emit_move_insn (operands[0], const0_rtx); - emit_insn (gen_cmpsi (operands[1], operands[2])); - emit_jump_insn (gen_bltu (label1)); + emit_cmp_and_jump_insns (operands[1], operands[2], LT, NULL_RTX, + SImode, 1, label1); emit_move_insn (operands[0], const1_rtx); emit_label (label1); } @@ -5598,12 +5556,12 @@ operands[2] = make_safe_from (operands[2], operands[0]); emit_move_insn (operands[0], const0_rtx); - emit_insn (gen_cmpsi (operands[2], operands[1])); - emit_jump_insn (gen_bgtu (label3)); - emit_insn (gen_cmpsi (operands[2], const0_rtx)); - emit_jump_insn (gen_blt (label2)); - emit_insn (gen_cmpsi (operands[2], const1_rtx)); - emit_jump_insn (gen_beq (label1)); + emit_cmp_and_jump_insns (operands[2], operands[1], GT, NULL_RTX, + SImode, 1, label3); + emit_cmp_and_jump_insns (operands[2], const0_rtx, LT, NULL_RTX, + SImode, 0, label2); + emit_cmp_and_jump_insns (operands[2], const1_rtx, EQ, NULL_RTX, + SImode, 0, label1); emit_insn (gen_zero_extendsidi2 (operands[3], operands[1])); insn = emit_insn (gen_divmoddisi3 (operands[3], operands[3], operands[2])); @@ -5652,8 +5610,8 @@ operands[1] = make_safe_from (operands[1], operands[0]); emit_move_insn (operands[0], operands[1]); - emit_insn (gen_cmpsi (operands[0], operands[2])); - emit_jump_insn (gen_bltu (label1)); + emit_cmp_and_jump_insns (operands[0], operands[2], LT, NULL_RTX, + SImode, 1, label1); emit_insn (gen_abssi2 (operands[0], operands[2])); emit_insn (gen_addsi3 (operands[0], operands[0], operands[1])); emit_label (label1); @@ -5685,12 +5643,12 @@ operands[2] = make_safe_from (operands[2], operands[0]); emit_move_insn(operands[0], operands[1]); - emit_insn (gen_cmpsi (operands[2], operands[1])); - emit_jump_insn (gen_bgtu (label3)); - emit_insn (gen_cmpsi (operands[2], const0_rtx)); - emit_jump_insn (gen_blt (label2)); - emit_insn (gen_cmpsi (operands[2], const1_rtx)); - emit_jump_insn (gen_beq (label1)); + emit_cmp_and_jump_insns (operands[2], operands[1], GT, NULL_RTX, + SImode, 1, label3); + emit_cmp_and_jump_insns (operands[2], const0_rtx, LT, NULL_RTX, + SImode, 0, label2); + emit_cmp_and_jump_insns (operands[2], const1_rtx, EQ, NULL_RTX, + SImode, 0, label1); emit_insn (gen_zero_extendsidi2 (operands[3], operands[1])); insn = emit_insn (gen_divmoddisi3 (operands[3], operands[3], operands[2])); @@ -7359,15 +7317,42 @@ ;; Branch instruction patterns. ;; -(define_expand "b<code>" +(define_expand "cbranch<mode>4" [(set (pc) - (if_then_else (COMPARE (match_operand 0 "" "") - (const_int 0)) - (match_dup 0) + (if_then_else (match_operator 0 "comparison_operator" + [(match_operand:GPR 1 "register_operand" "") + (match_operand:GPR 2 "general_operand" "")]) + (label_ref (match_operand 3 "" "")) (pc)))] "" - "s390_emit_jump (operands[0], - s390_emit_compare (<CODE>, s390_compare_op0, s390_compare_op1)); DONE;") + "s390_emit_jump (operands[3], + s390_emit_compare (GET_CODE (operands[0]), operands[1], operands[2])); + DONE;") + +(define_expand "cbranch<mode>4" + [(set (pc) + (if_then_else (match_operator 0 "comparison_operator" + [(match_operand:FP 1 "register_operand" "") + (match_operand:FP 2 "general_operand" "")]) + (label_ref (match_operand 3 "" "")) + (pc)))] + "TARGET_HARD_FLOAT" + "s390_emit_jump (operands[3], + s390_emit_compare (GET_CODE (operands[0]), operands[1], operands[2])); + DONE;") + +(define_expand "cbranchcc4" + [(set (pc) + (if_then_else (match_operator 0 "s390_eqne_operator" + [(match_operand 1 "cc_reg_operand" "") + (match_operand 2 "const0_operand" "")]) + (label_ref (match_operand 3 "" "")) + (pc)))] + "TARGET_HARD_FLOAT" + "s390_emit_jump (operands[3], + s390_emit_compare (GET_CODE (operands[0]), operands[1], operands[2])); + DONE;") + ;; @@ -7506,18 +7491,36 @@ [(set_attr "op_type" "RI") (set_attr "type" "branch")]) -(define_expand "conditional_trap" - [(trap_if (match_operand 0 "comparison_operator" "") - (match_operand 1 "general_operand" ""))] +(define_expand "ctrap<mode>4" + [(trap_if (match_operator 0 "comparison_operator" + [(match_operand:GPR 1 "register_operand" "") + (match_operand:GPR 2 "general_operand" "")]) + (match_operand 3 "const0_operand" ""))] "" -{ - if (operands[1] != const0_rtx) FAIL; - operands[0] = s390_emit_compare (GET_CODE (operands[0]), - s390_compare_op0, s390_compare_op1); -}) + { + rtx cond = s390_emit_compare (GET_CODE (operands[0]), + operands[1], operands[2]); + emit_insn (gen_condtrap (cond, XEXP (cond, 0))); + DONE; + }) + +(define_expand "ctrap<mode>4" + [(trap_if (match_operator 0 "comparison_operator" + [(match_operand:FP 1 "register_operand" "") + (match_operand:FP 2 "general_operand" "")]) + (match_operand 3 "const0_operand" ""))] + "" + { + rtx cond = s390_emit_compare (GET_CODE (operands[0]), + operands[1], operands[2]); + emit_insn (gen_condtrap (cond, XEXP (cond, 0))); + DONE; + }) -(define_insn "*trap" - [(trap_if (match_operator 0 "s390_comparison" [(reg CC_REGNUM) (const_int 0)]) +(define_insn "condtrap" + [(trap_if (match_operator 0 "s390_comparison" + [(match_operand 1 "cc_reg_operand" "c") + (const_int 0)]) (const_int 0))] "" "j%C0\t.+2"; @@ -8665,6 +8668,7 @@ (match_operand 2 "" "")] "" { + rtx cc_reg, test; #ifdef TARGET_THREAD_SSP_OFFSET operands[1] = gen_rtx_MEM (Pmode, gen_rtx_PLUS (Pmode, s390_get_thread_pointer (), @@ -8675,9 +8679,9 @@ else emit_insn (gen_stack_protect_testsi (operands[0], operands[1])); - s390_compare_op0 = gen_rtx_REG (CCZmode, CC_REGNUM); - s390_compare_op1 = const0_rtx; - emit_jump_insn (gen_beq (operands[2])); + cc_reg = gen_rtx_REG (CCZmode, CC_REGNUM); + test = gen_rtx_EQ (VOIDmode, cc_reg, const0_rtx); + emit_jump_insn (gen_cbranchcc4 (test, cc_reg, const0_rtx, operands[2])); DONE; }) diff --git a/gcc/config/score/score-conv.h b/gcc/config/score/score-conv.h index 67855da895e..e042dc1b7d3 100644 --- a/gcc/config/score/score-conv.h +++ b/gcc/config/score/score-conv.h @@ -22,11 +22,6 @@ extern int target_flags; -/* Define the information needed to generate branch insns. This is - stored from the compare operation. */ -extern GTY(()) rtx cmp_op0; -extern GTY(()) rtx cmp_op1; - #define GP_REG_FIRST 0U #define GP_REG_LAST 31U #define GP_REG_NUM (GP_REG_LAST - GP_REG_FIRST + 1U) diff --git a/gcc/config/score/score-protos.h b/gcc/config/score/score-protos.h index d6739b8cf4c..204dc1876a4 100644 --- a/gcc/config/score/score-protos.h +++ b/gcc/config/score/score-protos.h @@ -25,7 +25,6 @@ enum score_mem_unit {SCORE_BYTE = 0, SCORE_HWORD = 1, SCORE_WORD = 2}; #define SCORE_ALIGN_UNIT(V, UNIT) !(V & ((1 << UNIT) - 1)) -extern void score_gen_cmp (enum machine_mode mode); extern void score_prologue (void); extern void score_epilogue (int sibcall_p); extern void score_call (rtx *ops, bool sib); diff --git a/gcc/config/score/score.c b/gcc/config/score/score.c index 2ac3021bf5e..e517eeb6608 100644 --- a/gcc/config/score/score.c +++ b/gcc/config/score/score.c @@ -117,7 +117,6 @@ #define TARGET_ADDRESS_COST score_address_cost struct extern_list *extern_head = 0; -rtx cmp_op0, cmp_op1; /* default 0 = NO_REGS */ enum reg_class score_char_to_class[256]; @@ -698,17 +697,6 @@ score_epilogue (int sibcall_p) gcc_unreachable (); } -void -score_gen_cmp (enum machine_mode mode) -{ - if (TARGET_SCORE5 || TARGET_SCORE5U || TARGET_SCORE7 || TARGET_SCORE7D) - return score7_gen_cmp (mode); - else if (TARGET_SCORE3) - return score3_gen_cmp (mode); - - gcc_unreachable (); -} - /* Call and sibcall pattern all need call this function. */ void score_call (rtx *ops, bool sib) @@ -1118,7 +1106,7 @@ score_block_move_loop (rtx dst, rtx src, HOST_WIDE_INT length) HOST_WIDE_INT loop_mov_bytes; HOST_WIDE_INT iteration = 0; HOST_WIDE_INT head_length = 0, leftover; - rtx label, src_reg, dst_reg, final_dst; + rtx label, src_reg, dst_reg, final_dst, test; bool gen_loop_head = (src_align < BITS_PER_WORD || dst_align < BITS_PER_WORD); @@ -1158,8 +1146,8 @@ score_block_move_loop (rtx dst, rtx src, HOST_WIDE_INT length) score_block_move_loop_body (dst_reg, dst_align, src_reg, src_align, loop_mov_bytes); - emit_insn (gen_cmpsi (dst_reg, final_dst)); - emit_jump_insn (gen_bne (label)); + test = gen_rtx_NE (VOIDmode, dst_reg, final_dst); + emit_jump_insn (gen_cbranchsi4 (test, dst_reg, final_dst, label)); score_block_move_loop_foot (dst_reg, dst_align, src_reg, src_align, leftover); diff --git a/gcc/config/score/score.md b/gcc/config/score/score.md index e616c57aa7e..b426e14e0ac 100644 --- a/gcc/config/score/score.md +++ b/gcc/config/score/score.md @@ -2175,6 +2175,20 @@ (set_attr "length" "4,4") (set_attr "mode" "SI")]) +(define_expand "cbranchsi4" + [(set (reg:CC CC_REGNUM) + (compare:CC (match_operand:SI 1 "score_register_operand" "") + (match_operand:SI 2 "arith_operand" ""))) + (set (pc) + (if_then_else + (match_operator 0 "ordered_comparison_operator" + [(reg:CC CC_REGNUM) + (const_int 0)]) + (label_ref (match_operand 3 "" "")) + (pc)))] + "" + "") + (define_insn "cbrancheqz" [(set (pc) (if_then_else (eq (match_operand:SI 0 "score_register_operand" "d") @@ -2259,16 +2273,6 @@ (const_int 4) (const_int 6)))]) -(define_expand "cmpsi" - [(match_operand:SI 0 "score_register_operand") - (match_operand:SI 1 "arith_operand")] - "" -{ - cmp_op0 = operands[0]; - cmp_op1 = operands[1]; - DONE; -}) - (define_insn "cmpsi_nz_score7" [(set (reg:CC_NZ CC_REGNUM) (compare:CC_NZ (match_operand:SI 0 "register_operand" "d,e,d") @@ -2375,106 +2379,6 @@ (set_attr "up_c" "yes") (set_attr "mode" "SI")]) -(define_expand "beq" - [(set (pc) - (if_then_else (eq (reg:CC CC_REGNUM) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" -{ - score_gen_cmp (CCmode); -}) - -(define_expand "bne" - [(set (pc) - (if_then_else (ne (reg:CC CC_REGNUM) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" -{ - score_gen_cmp (CCmode); -}) - -(define_expand "bgt" - [(set (pc) - (if_then_else (gt (reg:CC CC_REGNUM) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" -{ - score_gen_cmp (CCmode); -}) - -(define_expand "ble" - [(set (pc) - (if_then_else (le (reg:CC CC_REGNUM) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" -{ - score_gen_cmp (CCmode); -}) - -(define_expand "bge" - [(set (pc) - (if_then_else (ge (reg:CC CC_REGNUM) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" -{ - score_gen_cmp (CCmode); -}) - -(define_expand "blt" - [(set (pc) - (if_then_else (lt (reg:CC CC_REGNUM) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" -{ - score_gen_cmp (CCmode); -}) - -(define_expand "bgtu" - [(set (pc) - (if_then_else (gtu (reg:CC CC_REGNUM) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" -{ - score_gen_cmp (CCmode); -}) - -(define_expand "bleu" - [(set (pc) - (if_then_else (leu (reg:CC CC_REGNUM) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" -{ - score_gen_cmp (CCmode); -}) - -(define_expand "bgeu" - [(set (pc) - (if_then_else (geu (reg:CC CC_REGNUM) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" -{ - score_gen_cmp (CCmode); -}) - -(define_expand "bltu" - [(set (pc) - (if_then_else (ltu (reg:CC CC_REGNUM) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" -{ - score_gen_cmp (CCmode); -}) - (define_insn "*branch_n_score7" [(set (pc) (if_then_else diff --git a/gcc/config/score/score3.c b/gcc/config/score/score3.c index 9e41452c03d..3ddc3b8c798 100644 --- a/gcc/config/score/score3.c +++ b/gcc/config/score/score3.c @@ -54,9 +54,6 @@ #define BITSET_P(VALUE, BIT) (((VALUE) & (1L << (BIT))) != 0) #define INS_BUF_SZ 128 -/* Define the information needed to generate branch insns. This is - stored from the compare operation. */ -extern rtx cmp_op0, cmp_op1; extern enum reg_class score_char_to_class[256]; static int score3_sdata_max; @@ -1647,13 +1644,6 @@ score3_epilogue (int sibcall_p) emit_jump_insn (gen_return_internal_score3 (gen_rtx_REG (Pmode, RA_REGNUM))); } -void -score3_gen_cmp (enum machine_mode mode) -{ - emit_insn (gen_rtx_SET (VOIDmode, gen_rtx_REG (mode, CC_REGNUM), - gen_rtx_COMPARE (mode, cmp_op0, cmp_op1))); -} - /* Return true if X is a symbolic constant that can be calculated in the same way as a bare symbol. If it is, store the type of the symbol in *SYMBOL_TYPE. */ @@ -1692,7 +1682,8 @@ score3_movsicc (rtx *ops) mode = score3_select_cc_mode (GET_CODE (ops[1]), ops[2], ops[3]); emit_insn (gen_rtx_SET (VOIDmode, gen_rtx_REG (mode, CC_REGNUM), - gen_rtx_COMPARE (mode, cmp_op0, cmp_op1))); + gen_rtx_COMPARE (mode, XEXP (ops[1], 0), + XEXP (ops[1], 1)))); } /* Call and sibcall pattern all need call this function. */ diff --git a/gcc/config/score/score3.h b/gcc/config/score/score3.h index c46a8e694d9..d718d12e8d9 100644 --- a/gcc/config/score/score3.h +++ b/gcc/config/score/score3.h @@ -138,7 +138,6 @@ extern enum machine_mode score3_select_cc_mode (enum rtx_code op, rtx x, rtx y); extern void score3_prologue (void); extern void score3_epilogue (int sibcall_p); -extern void score3_gen_cmp (enum machine_mode mode); extern void score3_call (rtx *ops, bool sib); extern void score3_call_value (rtx *ops, bool sib); extern void score3_movsicc (rtx *ops); diff --git a/gcc/config/score/score7.c b/gcc/config/score/score7.c index dc532764edd..661cae73bd3 100644 --- a/gcc/config/score/score7.c +++ b/gcc/config/score/score7.c @@ -54,9 +54,6 @@ #define BITSET_P(VALUE, BIT) (((VALUE) & (1L << (BIT))) != 0) #define INS_BUF_SZ 128 -/* Define the information needed to generate branch insns. This is - stored from the compare operation. */ -extern rtx cmp_op0, cmp_op1; extern enum reg_class score_char_to_class[256]; static int score7_sdata_max; @@ -1531,13 +1528,6 @@ score7_epilogue (int sibcall_p) emit_jump_insn (gen_return_internal_score7 (gen_rtx_REG (Pmode, RA_REGNUM))); } -void -score7_gen_cmp (enum machine_mode mode) -{ - emit_insn (gen_rtx_SET (VOIDmode, gen_rtx_REG (mode, CC_REGNUM), - gen_rtx_COMPARE (mode, cmp_op0, cmp_op1))); -} - /* Return true if X is a symbolic constant that can be calculated in the same way as a bare symbol. If it is, store the type of the symbol in *SYMBOL_TYPE. */ @@ -1576,7 +1566,8 @@ score7_movsicc (rtx *ops) mode = score7_select_cc_mode (GET_CODE (ops[1]), ops[2], ops[3]); emit_insn (gen_rtx_SET (VOIDmode, gen_rtx_REG (mode, CC_REGNUM), - gen_rtx_COMPARE (mode, cmp_op0, cmp_op1))); + gen_rtx_COMPARE (mode, XEXP (ops[1], 0), + XEXP (ops[1], 1)))); } /* Call and sibcall pattern all need call this function. */ diff --git a/gcc/config/score/score7.h b/gcc/config/score/score7.h index e2033c74498..0c0a3b20f8e 100644 --- a/gcc/config/score/score7.h +++ b/gcc/config/score/score7.h @@ -139,7 +139,6 @@ extern enum machine_mode score7_select_cc_mode (enum rtx_code op, rtx y); extern void score7_prologue (void); extern void score7_epilogue (int sibcall_p); -extern void score7_gen_cmp (enum machine_mode mode); extern void score7_call (rtx *ops, bool sib); extern void score7_call_value (rtx *ops, bool sib); extern void score7_movsicc (rtx *ops); diff --git a/gcc/config/sh/predicates.md b/gcc/config/sh/predicates.md index da9962c9984..ea924d830f5 100644 --- a/gcc/config/sh/predicates.md +++ b/gcc/config/sh/predicates.md @@ -552,6 +552,17 @@ (and (match_code "minus,div") (match_test "GET_MODE (op) == mode"))) +;; UNORDERED is only supported on SHMEDIA. + +(define_predicate "sh_float_comparison_operator" + (ior (match_operand 0 "ordered_comparison_operator") + (and (match_test "TARGET_SHMEDIA") + (match_code "unordered")))) + +(define_predicate "shmedia_cbranch_comparison_operator" + (ior (match_operand 0 "equality_comparison_operator") + (match_operand 0 "greater_comparison_operator"))) + ;; TODO: Add a comment here. (define_predicate "sh_const_vec" diff --git a/gcc/config/sh/sh-protos.h b/gcc/config/sh/sh-protos.h index a484b9c5d05..0c89f17b15d 100644 --- a/gcc/config/sh/sh-protos.h +++ b/gcc/config/sh/sh-protos.h @@ -41,7 +41,6 @@ enum sh_function_kind { extern rtx sh_fsca_sf2int (void); extern rtx sh_fsca_df2int (void); extern rtx sh_fsca_int2sf (void); -extern struct rtx_def *prepare_scc_operands (enum rtx_code); /* Declare functions defined in sh.c and used in templates. */ @@ -72,7 +71,10 @@ extern enum rtx_code prepare_cbranch_operands (rtx *, enum machine_mode mode, enum rtx_code comparison); extern void expand_cbranchsi4 (rtx *operands, enum rtx_code comparison, int); extern bool expand_cbranchdi4 (rtx *operands, enum rtx_code comparison); -extern void from_compare (rtx *, int); +extern void sh_emit_scc_to_t (enum rtx_code, rtx, rtx); +extern rtx sh_emit_cheap_store_flag (enum machine_mode, enum rtx_code, rtx, rtx); +extern void sh_emit_compare_and_branch (rtx *, enum machine_mode); +extern void sh_emit_compare_and_set (rtx *, enum machine_mode); extern int shift_insns_rtx (rtx); extern void gen_ashift (int, int, rtx); extern void gen_ashift_hi (int, int, rtx); @@ -117,7 +119,7 @@ extern int sh_insn_length_adjustment (rtx); extern int sh_can_redirect_branch (rtx, rtx); extern void sh_expand_unop_v2sf (enum rtx_code, rtx, rtx); extern void sh_expand_binop_v2sf (enum rtx_code, rtx, rtx, rtx); -extern int sh_expand_t_scc (enum rtx_code code, rtx target); +extern int 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); #endif /* RTX_CODE */ diff --git a/gcc/config/sh/sh.c b/gcc/config/sh/sh.c index d23a45a2289..e25cd42e871 100644 --- a/gcc/config/sh/sh.c +++ b/gcc/config/sh/sh.c @@ -105,12 +105,6 @@ static int skip_cycles = 0; and returned from sh_reorder2. */ static short cached_can_issue_more; -/* Saved operands from the last compare to use when we generate an scc - or bcc insn. */ - -rtx sh_compare_op0; -rtx sh_compare_op1; - /* Provides the class number of the smallest class containing reg number. */ @@ -1677,10 +1671,26 @@ expand_cbranchdi4 (rtx *operands, enum rtx_code comparison) return true; } +/* Emit INSN, possibly in a PARALLEL with an USE of fpscr for SH4. */ + +static void +sh_emit_set_t_insn (rtx insn, enum machine_mode mode) +{ + if ((TARGET_SH4 || TARGET_SH2A) && GET_MODE_CLASS (mode) == MODE_FLOAT) + { + insn = gen_rtx_PARALLEL (VOIDmode, + gen_rtvec (2, insn, + gen_rtx_USE (VOIDmode, get_fpscr_rtx ()))); + (mode == SFmode ? emit_sf_insn : emit_df_insn) (insn); + } + else + emit_insn (insn); +} + /* Prepare the operands for an scc instruction; make sure that the - compare has been done. */ -rtx -prepare_scc_operands (enum rtx_code code) + compare has been done and the result is in T_REG. */ +void +sh_emit_scc_to_t (enum rtx_code code, rtx op0, rtx op1) { rtx t_reg = gen_rtx_REG (SImode, T_REG); enum rtx_code oldcode = code; @@ -1709,77 +1719,222 @@ prepare_scc_operands (enum rtx_code code) } if (code != oldcode) { - rtx tmp = sh_compare_op0; - sh_compare_op0 = sh_compare_op1; - sh_compare_op1 = tmp; + rtx tmp = op0; + op0 = op1; + op1 = tmp; } - mode = GET_MODE (sh_compare_op0); + mode = GET_MODE (op0); if (mode == VOIDmode) - mode = GET_MODE (sh_compare_op1); + mode = GET_MODE (op1); - sh_compare_op0 = force_reg (mode, sh_compare_op0); + op0 = force_reg (mode, op0); if ((code != EQ && code != NE - && (sh_compare_op1 != const0_rtx + && (op1 != const0_rtx || code == GTU || code == GEU || code == LTU || code == LEU)) - || (mode == DImode && sh_compare_op1 != const0_rtx) + || (mode == DImode && op1 != const0_rtx) || (TARGET_SH2E && GET_MODE_CLASS (mode) == MODE_FLOAT)) - sh_compare_op1 = force_reg (mode, sh_compare_op1); + op1 = force_reg (mode, op1); - if ((TARGET_SH4 || TARGET_SH2A) && GET_MODE_CLASS (mode) == MODE_FLOAT) - (mode == SFmode ? emit_sf_insn : emit_df_insn) - (gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, - gen_rtx_SET (VOIDmode, t_reg, - gen_rtx_fmt_ee (code, SImode, - sh_compare_op0, sh_compare_op1)), - gen_rtx_USE (VOIDmode, get_fpscr_rtx ())))); - else - emit_insn (gen_rtx_SET (VOIDmode, t_reg, - gen_rtx_fmt_ee (code, SImode, - sh_compare_op0, sh_compare_op1))); + sh_emit_set_t_insn (gen_rtx_SET (VOIDmode, t_reg, + gen_rtx_fmt_ee (code, SImode, op0, op1)), + mode); +} - return t_reg; +rtx +sh_emit_cheap_store_flag (enum machine_mode mode, enum rtx_code code, + rtx op0, rtx op1) +{ + rtx target = gen_reg_rtx (SImode); + rtx tmp; + + gcc_assert (TARGET_SHMEDIA); + switch (code) + { + case EQ: + case GT: + case LT: + case UNORDERED: + case GTU: + case LTU: + tmp = gen_rtx_fmt_ee (code, SImode, op0, op1); + emit_insn (gen_cstore4_media (target, tmp, op0, op1)); + code = NE; + break; + + case NE: + case GE: + case LE: + case ORDERED: + case GEU: + case LEU: + tmp = gen_rtx_fmt_ee (reverse_condition (code), mode, op0, op1); + emit_insn (gen_cstore4_media (target, tmp, op0, op1)); + code = EQ; + break; + + case UNEQ: + case UNGE: + case UNGT: + case UNLE: + case UNLT: + case LTGT: + return NULL_RTX; + + default: + gcc_unreachable (); + } + + if (mode == DImode) + { + rtx t2 = gen_reg_rtx (DImode); + emit_insn (gen_extendsidi2 (t2, target)); + target = t2; + } + + return gen_rtx_fmt_ee (code, VOIDmode, target, const0_rtx); } /* Called from the md file, set up the operands of a compare instruction. */ void -from_compare (rtx *operands, int code) +sh_emit_compare_and_branch (rtx *operands, enum machine_mode mode) { - enum machine_mode mode = GET_MODE (sh_compare_op0); - rtx insn; - if (mode == VOIDmode) - mode = GET_MODE (sh_compare_op1); - if (code != EQ - || mode == DImode - || (TARGET_SH2E && GET_MODE_CLASS (mode) == MODE_FLOAT)) + enum rtx_code code = GET_CODE (operands[0]); + enum rtx_code branch_code; + rtx op0 = operands[1]; + rtx op1 = operands[2]; + rtx insn, tem; + bool need_ccmpeq = false; + + if (TARGET_SH2E && GET_MODE_CLASS (mode) == MODE_FLOAT) { - /* Force args into regs, since we can't use constants here. */ - sh_compare_op0 = force_reg (mode, sh_compare_op0); - if (sh_compare_op1 != const0_rtx - || code == GTU || code == GEU - || (TARGET_SH2E && GET_MODE_CLASS (mode) == MODE_FLOAT)) - sh_compare_op1 = force_reg (mode, sh_compare_op1); + op0 = force_reg (mode, op0); + op1 = force_reg (mode, op1); } - if (TARGET_SH2E && GET_MODE_CLASS (mode) == MODE_FLOAT && code == GE) + else { - from_compare (operands, GT); - insn = gen_ieee_ccmpeqsf_t (sh_compare_op0, sh_compare_op1); + if (code != EQ || mode == DImode) + { + /* Force args into regs, since we can't use constants here. */ + op0 = force_reg (mode, op0); + if (op1 != const0_rtx || code == GTU || code == GEU) + op1 = force_reg (mode, op1); + } } + + if (GET_MODE_CLASS (mode) == MODE_FLOAT) + { + if (code == LT + || (code == LE && TARGET_IEEE && TARGET_SH2E) + || (code == GE && !(TARGET_IEEE && TARGET_SH2E))) + { + tem = op0, op0 = op1, op1 = tem; + code = swap_condition (code); + } + + /* GE becomes fcmp/gt+fcmp/eq, for SH2E and TARGET_IEEE only. */ + if (code == GE) + { + gcc_assert (TARGET_IEEE && TARGET_SH2E); + need_ccmpeq = true; + code = GT; + } + + /* Now we can have EQ, NE, GT, LE. NE and LE are then transformed + to EQ/GT respectively. */ + gcc_assert (code == EQ || code == GT || code == NE || code == LE); + } + + switch (code) + { + case EQ: + case GT: + case GE: + case GTU: + case GEU: + branch_code = code; + break; + case NE: + case LT: + case LE: + case LTU: + case LEU: + branch_code = reverse_condition (code); + break; + default: + gcc_unreachable (); + } + + insn = gen_rtx_SET (VOIDmode, + gen_rtx_REG (SImode, T_REG), + gen_rtx_fmt_ee (branch_code, SImode, op0, op1)); + + sh_emit_set_t_insn (insn, mode); + if (need_ccmpeq) + sh_emit_set_t_insn (gen_ieee_ccmpeqsf_t (op0, op1), mode); + + if (branch_code == code) + emit_jump_insn (gen_branch_true (operands[3])); else - insn = gen_rtx_SET (VOIDmode, - gen_rtx_REG (SImode, T_REG), - gen_rtx_fmt_ee ((enum rtx_code) code, SImode, - sh_compare_op0, sh_compare_op1)); - if ((TARGET_SH4 || TARGET_SH2A) && GET_MODE_CLASS (mode) == MODE_FLOAT) + emit_jump_insn (gen_branch_false (operands[3])); +} + +void +sh_emit_compare_and_set (rtx *operands, enum machine_mode mode) +{ + enum rtx_code code = GET_CODE (operands[1]); + rtx op0 = operands[2]; + rtx op1 = operands[3]; + rtx lab = NULL_RTX; + bool invert = false; + rtx tem; + + op0 = force_reg (mode, op0); + if ((code != EQ && code != NE + && (op1 != const0_rtx + || code == GTU || code == GEU || code == LTU || code == LEU)) + || (mode == DImode && op1 != const0_rtx) + || (TARGET_SH2E && GET_MODE_CLASS (mode) == MODE_FLOAT)) + op1 = force_reg (mode, op1); + + if (GET_MODE_CLASS (mode) == MODE_FLOAT) { - insn = gen_rtx_PARALLEL (VOIDmode, - gen_rtvec (2, insn, - gen_rtx_USE (VOIDmode, get_fpscr_rtx ()))); - (mode == SFmode ? emit_sf_insn : emit_df_insn) (insn); + if (code == LT || code == LE) + { + code = swap_condition (code); + tem = op0, op0 = op1, op1 = tem; + } + if (code == GE) + { + if (TARGET_IEEE) + { + lab = gen_label_rtx (); + sh_emit_scc_to_t (EQ, op0, op1); + emit_jump_insn (gen_branch_true (lab)); + code = GT; + } + else + { + code = LT; + invert = true; + } + } } + + if (code == NE) + { + code = EQ; + invert = true; + } + + sh_emit_scc_to_t (code, op0, op1); + if (lab) + emit_label (lab); + if (invert) + emit_insn (gen_movnegt (operands[0])); else - emit_insn (insn); + emit_move_insn (operands[0], gen_rtx_REG (SImode, T_REG)); } /* Functions to output assembly code. */ @@ -10782,17 +10937,21 @@ sh_get_pr_initial_val (void) } int -sh_expand_t_scc (enum rtx_code code, rtx target) +sh_expand_t_scc (rtx operands[]) { + enum rtx_code code = GET_CODE (operands[1]); + rtx target = operands[0]; + rtx op0 = operands[2]; + rtx op1 = operands[3]; rtx result = target; HOST_WIDE_INT val; - if (GET_CODE (sh_compare_op0) != REG || REGNO (sh_compare_op0) != T_REG - || GET_CODE (sh_compare_op1) != CONST_INT) + if (GET_CODE (op0) != REG || REGNO (op0) != T_REG + || GET_CODE (op1) != CONST_INT) return 0; if (GET_CODE (result) != REG) result = gen_reg_rtx (SImode); - val = INTVAL (sh_compare_op1); + val = INTVAL (op1); if ((code == EQ && val == 1) || (code == NE && val == 0)) emit_insn (gen_movt (result)); else if (TARGET_SH2A && ((code == EQ && val == 0) diff --git a/gcc/config/sh/sh.md b/gcc/config/sh/sh.md index dc6a7ab6b82..ffd0db08225 100644 --- a/gcc/config/sh/sh.md +++ b/gcc/config/sh/sh.md @@ -646,8 +646,15 @@ (label_ref (match_operand 3 "" "")) (pc))) (clobber (reg:SI T_REG))] - "TARGET_CBRANCHDI4" - "expand_cbranchsi4 (operands, LAST_AND_UNUSED_RTX_CODE, -1); DONE;") + "" + "if (TARGET_SHMEDIA) + emit_jump_insn (gen_cbranchint4_media (operands[0], operands[1], + operands[2], operands[3])); + else if (TARGET_CBRANCHDI4) + expand_cbranchsi4 (operands, LAST_AND_UNUSED_RTX_CODE, -1); + else + sh_emit_compare_and_branch (operands, SImode); + DONE;") ;; ------------------------------------------------------------------------- ;; SImode unsigned integer comparisons @@ -676,23 +683,6 @@ "cmp/hi %1,%0" [(set_attr "type" "mt_group")]) -;; We save the compare operands in the cmpxx patterns and use them when -;; we generate the branch. - -(define_expand "cmpsi" - [(set (reg:SI T_REG) - (compare (match_operand:SI 0 "cmpsi_operand" "") - (match_operand:SI 1 "arith_operand" "")))] - "TARGET_SH1 || TARGET_SHMEDIA" - " -{ - if (GET_CODE (operands[0]) == REG && REGNO (operands[0]) == T_REG - && GET_CODE (operands[1]) != CONST_INT) - operands[0] = copy_to_mode_reg (SImode, operands[0]); - sh_compare_op0 = operands[0]; - sh_compare_op1 = operands[1]; - DONE; -}") ;; ------------------------------------------------------------------------- ;; DImode compare and branch @@ -713,29 +703,45 @@ (pc))) (clobber (match_dup 4)) (clobber (reg:SI T_REG))] - "TARGET_CBRANCHDI4" + "TARGET_CBRANCHDI4 || TARGET_SH2 || TARGET_SHMEDIA" " { enum rtx_code comparison; - if (TARGET_EXPAND_CBRANCHDI4) + if (TARGET_SHMEDIA) + { + emit_jump_insn (gen_cbranchint4_media (operands[0], operands[1], + operands[2], operands[3])); + DONE; + } + + else if (!TARGET_CBRANCHDI4) + { + sh_emit_compare_and_branch (operands, DImode); + DONE; + } + + else { - if (expand_cbranchdi4 (operands, LAST_AND_UNUSED_RTX_CODE)) - DONE; + if (TARGET_EXPAND_CBRANCHDI4) + { + if (expand_cbranchdi4 (operands, LAST_AND_UNUSED_RTX_CODE)) + DONE; + } + comparison = prepare_cbranch_operands (operands, DImode, + LAST_AND_UNUSED_RTX_CODE); + if (comparison != GET_CODE (operands[0])) + operands[0] + = gen_rtx_fmt_ee (comparison, VOIDmode, operands[1], operands[2]); + operands[4] = gen_rtx_SCRATCH (SImode); } - comparison = prepare_cbranch_operands (operands, DImode, - LAST_AND_UNUSED_RTX_CODE); - if (comparison != GET_CODE (operands[0])) - operands[0] - = gen_rtx_fmt_ee (comparison, VOIDmode, operands[1], operands[2]); - operands[4] = gen_rtx_SCRATCH (SImode); }") (define_insn_and_split "cbranchdi4_i" [(set (pc) (if_then_else (match_operator 0 "comparison_operator" [(match_operand:DI 1 "arith_operand" "r,r") - (match_operand:DI 2 "arith_operand" "rN,i")]) + (match_operand:DI 2 "arith_operand" "rN,I08")]) (label_ref (match_operand 3 "" "")) (pc))) (clobber (match_scratch:SI 4 "=X,&r")) @@ -907,20 +913,6 @@ "cmpgtu %1,r63,%0" [(set_attr "type" "cmp_media")]) -;; We save the compare operands in the cmpxx patterns and use them when -;; we generate the branch. - -(define_expand "cmpdi" - [(set (reg:SI T_REG) - (compare (match_operand:DI 0 "arith_operand" "") - (match_operand:DI 1 "arith_operand" "")))] - "TARGET_SH2 || TARGET_SHMEDIA" - " -{ - sh_compare_op0 = operands[0]; - sh_compare_op1 = operands[1]; - DONE; -}") ;; ------------------------------------------------------------------------- ;; Conditional move instructions ;; ------------------------------------------------------------------------- @@ -988,92 +980,20 @@ " { if ((GET_CODE (operands[1]) == EQ || GET_CODE (operands[1]) == NE) - && GET_MODE (sh_compare_op0) == DImode - && sh_compare_op1 == const0_rtx) - operands[1] = gen_rtx_fmt_ee (GET_CODE (operands[1]), VOIDmode, - sh_compare_op0, sh_compare_op1); + && GET_MODE (XEXP (operands[1], 0)) == DImode + && XEXP (operands[1], 1) == const0_rtx) + ; else { - rtx tmp; - if (!can_create_pseudo_p ()) FAIL; - tmp = gen_reg_rtx (DImode); - - switch (GET_CODE (operands[1])) - { - case EQ: - emit_insn (gen_seq (tmp)); - operands[1] = gen_rtx_NE (VOIDmode, tmp, const0_rtx); - break; - - case NE: - emit_insn (gen_seq (tmp)); - operands[1] = gen_rtx_EQ (VOIDmode, tmp, const0_rtx); - break; - - case GT: - emit_insn (gen_sgt (tmp)); - operands[1] = gen_rtx_NE (VOIDmode, tmp, const0_rtx); - break; - - case LT: - emit_insn (gen_slt (tmp)); - operands[1] = gen_rtx_NE (VOIDmode, tmp, const0_rtx); - break; - - case GE: - emit_insn (gen_slt (tmp)); - operands[1] = gen_rtx_EQ (VOIDmode, tmp, const0_rtx); - break; - - case LE: - emit_insn (gen_sgt (tmp)); - operands[1] = gen_rtx_EQ (VOIDmode, tmp, const0_rtx); - break; - - case GTU: - emit_insn (gen_sgtu (tmp)); - operands[1] = gen_rtx_NE (VOIDmode, tmp, const0_rtx); - break; - - case LTU: - emit_insn (gen_sltu (tmp)); - operands[1] = gen_rtx_NE (VOIDmode, tmp, const0_rtx); - break; - - case GEU: - emit_insn (gen_sltu (tmp)); - operands[1] = gen_rtx_EQ (VOIDmode, tmp, const0_rtx); - break; - - case LEU: - emit_insn (gen_sgtu (tmp)); - operands[1] = gen_rtx_EQ (VOIDmode, tmp, const0_rtx); - break; - - case UNORDERED: - emit_insn (gen_sunordered (tmp)); - operands[1] = gen_rtx_NE (VOIDmode, tmp, const0_rtx); - break; - - case ORDERED: - emit_insn (gen_sunordered (tmp)); - operands[1] = gen_rtx_EQ (VOIDmode, tmp, const0_rtx); - break; - - case UNEQ: - case UNGE: - case UNGT: - case UNLE: - case UNLT: - case LTGT: - FAIL; - - default: - gcc_unreachable (); - } + operands[1] = sh_emit_cheap_store_flag (GET_MODE (operands[0]), + GET_CODE (operands[1]), + XEXP (operands[1], 0), + XEXP (operands[1], 1)); + if (!operands[1]) + FAIL; } }") @@ -1268,24 +1188,26 @@ " { if ((GET_CODE (operands[1]) == EQ || GET_CODE (operands[1]) == NE) - && GET_MODE (sh_compare_op0) == SImode + && GET_MODE (XEXP (operands[1], 0)) == SImode && (TARGET_SHMEDIA - || (REG_P (sh_compare_op0) && REGNO (sh_compare_op0) == T_REG)) - && sh_compare_op1 == const0_rtx) - operands[1] = gen_rtx_fmt_ee (GET_CODE (operands[1]), VOIDmode, - sh_compare_op0, sh_compare_op1); + || (REG_P (XEXP (operands[1], 0)) + && REGNO (XEXP (operands[1], 0)) == T_REG)) + && XEXP (operands[1], 1) == const0_rtx) + ; + else if (TARGET_PRETEND_CMOVE) { enum rtx_code code = GET_CODE (operands[1]); enum rtx_code new_code = code; - rtx tmp; + rtx op0 = XEXP (operands[1], 0); + rtx op1 = XEXP (operands[1], 1); if (! currently_expanding_to_rtl) FAIL; switch (code) { case LT: case LE: case LEU: case LTU: - if (GET_MODE_CLASS (GET_MODE (sh_compare_op0)) != MODE_INT) + if (GET_MODE_CLASS (GET_MODE (op0)) != MODE_INT) break; case NE: new_code = reverse_condition (code); @@ -1295,92 +1217,21 @@ default: FAIL; } - tmp = prepare_scc_operands (new_code); + sh_emit_scc_to_t (new_code, op0, op1); operands[1] = gen_rtx_fmt_ee (new_code == code ? NE : EQ, VOIDmode, - tmp, const0_rtx); + gen_rtx_REG (SImode, T_REG), const0_rtx); } else { - rtx tmp; - if (!can_create_pseudo_p ()) FAIL; - tmp = gen_reg_rtx (SImode); - - switch (GET_CODE (operands[1])) - { - case EQ: - emit_insn (gen_seq (tmp)); - operands[1] = gen_rtx_NE (VOIDmode, tmp, const0_rtx); - break; - - case NE: - emit_insn (gen_seq (tmp)); - operands[1] = gen_rtx_EQ (VOIDmode, tmp, const0_rtx); - break; - - case GT: - emit_insn (gen_sgt (tmp)); - operands[1] = gen_rtx_NE (VOIDmode, tmp, const0_rtx); - break; - - case LT: - emit_insn (gen_slt (tmp)); - operands[1] = gen_rtx_NE (VOIDmode, tmp, const0_rtx); - break; - - case GE: - emit_insn (gen_slt (tmp)); - operands[1] = gen_rtx_EQ (VOIDmode, tmp, const0_rtx); - break; - - case LE: - emit_insn (gen_sgt (tmp)); - operands[1] = gen_rtx_EQ (VOIDmode, tmp, const0_rtx); - break; - - case GTU: - emit_insn (gen_sgtu (tmp)); - operands[1] = gen_rtx_NE (VOIDmode, tmp, const0_rtx); - break; - - case LTU: - emit_insn (gen_sltu (tmp)); - operands[1] = gen_rtx_NE (VOIDmode, tmp, const0_rtx); - break; - - case GEU: - emit_insn (gen_sltu (tmp)); - operands[1] = gen_rtx_EQ (VOIDmode, tmp, const0_rtx); - break; - - case LEU: - emit_insn (gen_sgtu (tmp)); - operands[1] = gen_rtx_EQ (VOIDmode, tmp, const0_rtx); - break; - - case UNORDERED: - emit_insn (gen_sunordered (tmp)); - operands[1] = gen_rtx_NE (VOIDmode, tmp, const0_rtx); - break; - - case ORDERED: - emit_insn (gen_sunordered (tmp)); - operands[1] = gen_rtx_EQ (VOIDmode, tmp, const0_rtx); - break; - - case UNEQ: - case UNGE: - case UNGT: - case UNLE: - case UNLT: - case LTGT: - FAIL; - - default: - abort (); - } + operands[1] = sh_emit_cheap_store_flag (GET_MODE (operands[0]), + GET_CODE (operands[1]), + XEXP (operands[1], 0), + XEXP (operands[1], 1)); + if (!operands[1]) + FAIL; } }") @@ -1887,8 +1738,9 @@ implemented by comparing with the divisor. */ if (operands[1] == const1_rtx && currently_expanding_to_rtl) { - emit_insn (gen_cmpsi (operands[1], operands[2])); - emit_insn (gen_sgeu (operands[0])); + rtx test = gen_rtx_GEU (VOIDmode, operands[1], operands[2]); + emit_insn (gen_cstoresi4 (operands[0], test, + operands[1], operands[2])); DONE; } else if (operands[2] == const0_rtx) @@ -6877,14 +6729,83 @@ label: ;; Conditional branch insns -(define_expand "beq_media" +(define_expand "cbranchint4_media" [(set (pc) - (if_then_else (eq (match_operand:DI 1 "arith_reg_operand" "r,r") - (match_operand:DI 2 "arith_operand" "r,I06")) - (match_operand 0 "" "") + (if_then_else (match_operator 0 "shmedia_cbranch_comparison_operator" + [(match_operand 1 "" "") + (match_operand 2 "" "")]) + (match_operand 3 "" "") (pc)))] "TARGET_SHMEDIA" - "operands[0] = gen_rtx_LABEL_REF (Pmode, operands[0]);") + " +{ + enum machine_mode mode = GET_MODE (operands[1]); + if (mode == VOIDmode) + mode = GET_MODE (operands[2]); + if (GET_CODE (operands[0]) == EQ || GET_CODE (operands[0]) == NE) + { + operands[1] = force_reg (mode, operands[1]); + if (CONSTANT_P (operands[2]) + && (! satisfies_constraint_I06 (operands[2]))) + operands[2] = force_reg (mode, operands[2]); + } + else + { + if (operands[1] != const0_rtx) + operands[1] = force_reg (mode, operands[1]); + if (operands[2] != const0_rtx) + operands[2] = force_reg (mode, operands[2]); + } + switch (GET_CODE (operands[0])) + { + case LEU: + case LE: + case LTU: + case LT: + operands[0] = gen_rtx_fmt_ee (swap_condition (GET_CODE (operands[0])), + VOIDmode, operands[2], operands[1]); + operands[1] = XEXP (operands[0], 0); + operands[2] = XEXP (operands[0], 1); + break; + default: + operands[0] = gen_rtx_fmt_ee (GET_CODE (operands[0]), + VOIDmode, operands[1], operands[2]); + break; + } + operands[3] = gen_rtx_LABEL_REF (Pmode, operands[3]); +}") + +(define_expand "cbranchfp4_media" + [(set (pc) + (if_then_else (match_operator 0 "sh_float_comparison_operator" + [(match_operand 1 "" "") + (match_operand 2 "" "")]) + (match_operand 3 "" "") + (pc)))] + "TARGET_SHMEDIA" + " +{ + /* hack to generate same code. */ + rtx tmp_di = GET_CODE (operands[0]) == UNORDERED ? NULL : gen_reg_rtx (DImode); + rtx tmp = gen_reg_rtx (SImode); + rtx cmp; + if (GET_CODE (operands[0]) == NE) + cmp = gen_rtx_EQ (SImode, operands[1], operands[2]); + else + cmp = gen_rtx_fmt_ee (GET_CODE (operands[0]), SImode, + operands[1], operands[2]); + + emit_insn (gen_cstore4_media (tmp, cmp, operands[1], operands[2])); + if (tmp_di) emit_insn (gen_extendsidi2 (tmp_di, tmp)); else tmp_di = tmp; + + if (GET_CODE (cmp) == GET_CODE (operands[0])) + operands[0] = gen_rtx_NE (VOIDmode, tmp_di, const0_rtx); + else + operands[0] = gen_rtx_EQ (VOIDmode, tmp_di, const0_rtx); + operands[1] = tmp_di; + operands[2] = const0_rtx; + operands[3] = gen_rtx_LABEL_REF (Pmode, operands[3]); +}") (define_insn "*beq_media_i" [(set (pc) @@ -6912,51 +6833,6 @@ label: b%o3i%' %1, %2, %0%>" [(set_attr "type" "cbranch_media")]) -(define_expand "bne_media" - [(set (pc) - (if_then_else (ne (match_operand:DI 1 "arith_reg_operand" "r,r") - (match_operand:DI 2 "arith_operand" "r,I06")) - (match_operand 0 "" "") - (pc)))] - "TARGET_SHMEDIA" - "operands[0] = gen_rtx_LABEL_REF (Pmode, operands[0]);") - -(define_expand "bgt_media" - [(set (pc) - (if_then_else (gt (match_operand:DI 1 "arith_reg_or_0_operand" "") - (match_operand:DI 2 "arith_reg_or_0_operand" "")) - (match_operand 0 "" "") - (pc)))] - "TARGET_SHMEDIA" - "operands[0] = gen_rtx_LABEL_REF (Pmode, operands[0]);") - -(define_expand "bge_media" - [(set (pc) - (if_then_else (ge (match_operand:DI 1 "arith_reg_or_0_operand" "") - (match_operand:DI 2 "arith_reg_or_0_operand" "")) - (match_operand 0 "" "") - (pc)))] - "TARGET_SHMEDIA" - "operands[0] = gen_rtx_LABEL_REF (Pmode, operands[0]);") - -(define_expand "bgtu_media" - [(set (pc) - (if_then_else (gtu (match_operand:DI 1 "arith_reg_or_0_operand" "") - (match_operand:DI 2 "arith_reg_or_0_operand" "")) - (match_operand 0 "" "") - (pc)))] - "TARGET_SHMEDIA" - "operands[0] = gen_rtx_LABEL_REF (Pmode, operands[0]);") - -(define_expand "bgeu_media" - [(set (pc) - (if_then_else (geu (match_operand:DI 1 "arith_reg_or_0_operand" "") - (match_operand:DI 2 "arith_reg_or_0_operand" "")) - (match_operand 0 "" "") - (pc)))] - "TARGET_SHMEDIA" - "operands[0] = gen_rtx_LABEL_REF (Pmode, operands[0]);") - (define_insn "*bgt_media_i" [(set (pc) (if_then_else (match_operator 3 "greater_comparison_operator" @@ -7003,343 +6879,6 @@ label: "b%o3%' %N2, %N1, %0%>" [(set_attr "type" "cbranch_media")]) -(define_expand "beq" - [(set (pc) - (if_then_else (ne (reg:SI T_REG) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - if (TARGET_SHMEDIA) - { - enum machine_mode mode = GET_MODE (sh_compare_op0); - - if (mode != DImode && mode != SImode) - { - rtx tmp = gen_reg_rtx (DImode); - - emit_insn (gen_seq (tmp)); - emit_jump_insn (gen_bne_media (operands[0], tmp, const0_rtx)); - DONE; - } - - sh_compare_op0 = force_reg (mode, sh_compare_op0); - if (CONSTANT_P (sh_compare_op1) - && (! satisfies_constraint_I06 (sh_compare_op1))) - sh_compare_op1 = force_reg (mode, sh_compare_op1); - emit_jump_insn (gen_beq_media (operands[0], - sh_compare_op0, sh_compare_op1)); - DONE; - } - - from_compare (operands, EQ); -}") - -(define_expand "bne" - [(set (pc) - (if_then_else (eq (reg:SI T_REG) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - if (TARGET_SHMEDIA) - { - enum machine_mode mode = GET_MODE (sh_compare_op0); - - if (mode != DImode && mode != SImode) - { - rtx tmp = gen_reg_rtx (DImode); - - emit_insn (gen_seq (tmp)); - emit_jump_insn (gen_beq_media (operands[0], tmp, const0_rtx)); - DONE; - } - - sh_compare_op0 = force_reg (mode, sh_compare_op0); - if (CONSTANT_P (sh_compare_op1) - && (! satisfies_constraint_I06 (sh_compare_op1))) - sh_compare_op1 = force_reg (mode, sh_compare_op1); - emit_jump_insn (gen_bne_media (operands[0], - sh_compare_op0, sh_compare_op1)); - DONE; - } - - from_compare (operands, EQ); -}") - -(define_expand "bgt" - [(set (pc) - (if_then_else (ne (reg:SI T_REG) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - if (TARGET_SHMEDIA) - { - enum machine_mode mode = GET_MODE (sh_compare_op0); - - if (mode != DImode && mode != SImode) - { - rtx tmp = gen_reg_rtx (DImode); - - emit_insn (gen_sgt (tmp)); - emit_jump_insn (gen_bne_media (operands[0], tmp, const0_rtx)); - DONE; - } - - if (sh_compare_op0 != const0_rtx) - sh_compare_op0 = force_reg (mode, sh_compare_op0); - if (sh_compare_op1 != const0_rtx) - sh_compare_op1 = force_reg (mode, sh_compare_op1); - emit_jump_insn (gen_bgt_media (operands[0], - sh_compare_op0, sh_compare_op1)); - DONE; - } - - from_compare (operands, GT); -}") - -(define_expand "blt" - [(set (pc) - (if_then_else (eq (reg:SI T_REG) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - if (TARGET_SHMEDIA) - { - enum machine_mode mode = GET_MODE (sh_compare_op0); - - if (mode != DImode && mode != SImode) - { - rtx tmp = gen_reg_rtx (DImode); - - emit_insn (gen_slt (tmp)); - emit_jump_insn (gen_bne_media (operands[0], tmp, const0_rtx)); - DONE; - } - - if (sh_compare_op0 != const0_rtx) - sh_compare_op0 = force_reg (mode, sh_compare_op0); - if (sh_compare_op1 != const0_rtx) - sh_compare_op1 = force_reg (mode, sh_compare_op1); - emit_jump_insn (gen_bgt_media (operands[0], - sh_compare_op1, sh_compare_op0)); - DONE; - } - - if (GET_MODE_CLASS (GET_MODE (sh_compare_op0)) == MODE_FLOAT) - { - rtx tmp = sh_compare_op0; - sh_compare_op0 = sh_compare_op1; - sh_compare_op1 = tmp; - emit_insn (gen_bgt (operands[0])); - DONE; - } - from_compare (operands, GE); -}") - -(define_expand "ble" - [(set (pc) - (if_then_else (eq (reg:SI T_REG) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - if (TARGET_SHMEDIA) - { - enum machine_mode mode = GET_MODE (sh_compare_op0); - - if (mode != DImode && mode != SImode) - { - rtx tmp = gen_reg_rtx (DImode); - - emit_insn (gen_sle (tmp)); - emit_jump_insn (gen_bne_media (operands[0], tmp, const0_rtx)); - DONE; - } - - if (sh_compare_op0 != const0_rtx) - sh_compare_op0 = force_reg (mode, sh_compare_op0); - if (sh_compare_op1 != const0_rtx) - sh_compare_op1 = force_reg (mode, sh_compare_op1); - emit_jump_insn (gen_bge_media (operands[0], - sh_compare_op1, sh_compare_op0)); - DONE; - } - - if (TARGET_SH2E - && TARGET_IEEE - && GET_MODE_CLASS (GET_MODE (sh_compare_op0)) == MODE_FLOAT) - { - rtx tmp = sh_compare_op0; - sh_compare_op0 = sh_compare_op1; - sh_compare_op1 = tmp; - emit_insn (gen_bge (operands[0])); - DONE; - } - from_compare (operands, GT); -}") - -(define_expand "bge" - [(set (pc) - (if_then_else (ne (reg:SI T_REG) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - if (TARGET_SHMEDIA) - { - enum machine_mode mode = GET_MODE (sh_compare_op0); - - if (mode != DImode && mode != SImode) - { - rtx tmp = gen_reg_rtx (DImode); - - emit_insn (gen_sge (tmp)); - emit_jump_insn (gen_bne_media (operands[0], tmp, const0_rtx)); - DONE; - } - - if (sh_compare_op0 != const0_rtx) - sh_compare_op0 = force_reg (mode, sh_compare_op0); - if (sh_compare_op1 != const0_rtx) - sh_compare_op1 = force_reg (mode, sh_compare_op1); - emit_jump_insn (gen_bge_media (operands[0], - sh_compare_op0, sh_compare_op1)); - DONE; - } - - if (TARGET_SH2E - && ! TARGET_IEEE - && GET_MODE_CLASS (GET_MODE (sh_compare_op0)) == MODE_FLOAT) - { - rtx tmp = sh_compare_op0; - sh_compare_op0 = sh_compare_op1; - sh_compare_op1 = tmp; - emit_insn (gen_ble (operands[0])); - DONE; - } - from_compare (operands, GE); -}") - -(define_expand "bgtu" - [(set (pc) - (if_then_else (ne (reg:SI T_REG) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - if (TARGET_SHMEDIA) - { - enum machine_mode mode = GET_MODE (sh_compare_op0); - - if (sh_compare_op0 != const0_rtx) - sh_compare_op0 = force_reg (mode, sh_compare_op0); - if (sh_compare_op1 != const0_rtx) - sh_compare_op1 = force_reg (mode, sh_compare_op1); - emit_jump_insn (gen_bgtu_media (operands[0], - sh_compare_op0, sh_compare_op1)); - DONE; - } - - from_compare (operands, GTU); -}") - -(define_expand "bltu" - [(set (pc) - (if_then_else (eq (reg:SI T_REG) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - if (TARGET_SHMEDIA) - { - enum machine_mode mode = GET_MODE (sh_compare_op0); - - if (sh_compare_op0 != const0_rtx) - sh_compare_op0 = force_reg (mode, sh_compare_op0); - if (sh_compare_op1 != const0_rtx) - sh_compare_op1 = force_reg (mode, sh_compare_op1); - emit_jump_insn (gen_bgtu_media (operands[0], - sh_compare_op1, sh_compare_op0)); - DONE; - } - - from_compare (operands, GEU); -}") - -(define_expand "bgeu" - [(set (pc) - (if_then_else (ne (reg:SI T_REG) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - if (TARGET_SHMEDIA) - { - enum machine_mode mode = GET_MODE (sh_compare_op0); - - if (sh_compare_op0 != const0_rtx) - sh_compare_op0 = force_reg (mode, sh_compare_op0); - if (sh_compare_op1 != const0_rtx) - sh_compare_op1 = force_reg (mode, sh_compare_op1); - emit_jump_insn (gen_bgeu_media (operands[0], - sh_compare_op0, sh_compare_op1)); - DONE; - } - - from_compare (operands, GEU); -}") - -(define_expand "bleu" - [(set (pc) - (if_then_else (eq (reg:SI T_REG) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - if (TARGET_SHMEDIA) - { - enum machine_mode mode = GET_MODE (sh_compare_op0); - - if (sh_compare_op0 != const0_rtx) - sh_compare_op0 = force_reg (mode, sh_compare_op0); - if (sh_compare_op1 != const0_rtx) - sh_compare_op1 = force_reg (mode, sh_compare_op1); - emit_jump_insn (gen_bgeu_media (operands[0], - sh_compare_op1, sh_compare_op0)); - DONE; - } - - from_compare (operands, GTU); -}") - -(define_expand "bunordered" - [(set (match_dup 1) (unordered:SI (match_dup 2) (match_dup 3))) - (set (pc) - (if_then_else (ne (match_dup 1) (const_int 0)) - (match_operand 0 "" "") - (pc)))] - "TARGET_SHMEDIA" - " -{ - operands[0] = gen_rtx_LABEL_REF (Pmode, operands[0]); - operands[1] = gen_reg_rtx (SImode); - operands[2] = force_reg (GET_MODE (sh_compare_op0), sh_compare_op0); - operands[3] = force_reg (GET_MODE (sh_compare_op1), sh_compare_op1); -}") - ;; combiner splitter for test-and-branch on single bit in register. This ;; is endian dependent because the non-paradoxical subreg looks different ;; on big endian. @@ -9120,15 +8659,17 @@ mov.l\\t1f,r0\\n\\ rtx reg3 = gen_reg_rtx (Pmode); rtx reg4 = gen_reg_rtx (Pmode); rtx reg5 = gen_reg_rtx (Pmode); - rtx load; + rtx load, test; operands[0] = convert_modes (DImode, SImode, operands[0], 0); operands[1] = convert_modes (DImode, SImode, operands[1], 0); operands[2] = convert_modes (DImode, SImode, operands[2], 1); - emit_jump_insn (gen_bgt_media (operands[4], operands[1], operands[0])); + test = gen_rtx_GT (VOIDmode, operands[1], operands[0]); + emit_jump_insn (gen_cbranchdi4 (test, operands[1], operands[0], operands[4])); emit_move_insn (reg, gen_rtx_MINUS (DImode, operands[0], operands[1])); - emit_jump_insn (gen_bgtu_media (operands[4], reg, operands[2])); + test = gen_rtx_GTU (VOIDmode, reg, operands[2]); + emit_jump_insn (gen_cbranchdi4 (test, reg, operands[2], operands[4])); emit_insn (gen_casesi_shift_media (reg2, reg, operands[3])); emit_move_insn (reg3, gen_datalabel_ref (gen_rtx_LABEL_REF (Pmode, operands[3]))); @@ -9580,536 +9121,133 @@ mov.l\\t1f,r0\\n\\ "movrt\\t%0" [(set_attr "type" "arith")]) -(define_expand "seq" - [(set (match_operand:SI 0 "arith_reg_dest" "") - (match_dup 1))] - "" - " -{ - if (TARGET_SHMEDIA) - { - rtx reg; - - sh_compare_op0 = force_reg (GET_MODE (sh_compare_op0), sh_compare_op0); - if (sh_compare_op1 != const0_rtx) - sh_compare_op1 = force_reg (GET_MODE (sh_compare_op1) == VOIDmode - ? GET_MODE (sh_compare_op0) - : GET_MODE (sh_compare_op1), - sh_compare_op1); - if (GET_MODE_SIZE (GET_MODE (operands[0])) <= 4) - { - if (GET_MODE (operands[0]) != SImode) - operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0); - - switch (GET_MODE (sh_compare_op0)) - { - case SImode: - emit_insn (gen_cmpeqsi_media (operands[0], - sh_compare_op0, sh_compare_op1)); - break; - - case DImode: - emit_insn (gen_cmpeqdi_media (operands[0], - sh_compare_op0, sh_compare_op1)); - break; - - case SFmode: - if (! TARGET_SHMEDIA_FPU) - FAIL; - emit_insn (gen_cmpeqsf_media (operands[0], - sh_compare_op0, sh_compare_op1)); - break; - - case DFmode: - if (! TARGET_SHMEDIA_FPU) - FAIL; - emit_insn (gen_cmpeqdf_media (operands[0], - sh_compare_op0, sh_compare_op1)); - break; - - default: - FAIL; - } - DONE; - } - - reg = operands[0]; - if (GET_MODE (operands[0]) != SImode) - reg = (!can_create_pseudo_p () - ? gen_rtx_SUBREG (SImode, operands[0], 0) - : gen_reg_rtx (SImode)); - - switch (GET_MODE (sh_compare_op0)) - { - case SImode: - emit_insn (gen_cmpeqsi_media (reg, - sh_compare_op0, sh_compare_op1)); - break; - - case DImode: - emit_insn (gen_cmpeqdi_media (reg, - sh_compare_op0, sh_compare_op1)); - break; - - case SFmode: - if (! TARGET_SHMEDIA_FPU) - FAIL; - emit_insn (gen_cmpeqsf_media (reg, - sh_compare_op0, sh_compare_op1)); - break; - - case DFmode: - if (! TARGET_SHMEDIA_FPU) - FAIL; - emit_insn (gen_cmpeqdf_media (reg, - sh_compare_op0, sh_compare_op1)); - break; - - default: - FAIL; - } - - if (GET_MODE (operands[0]) == DImode) - emit_insn (gen_extendsidi2 (operands[0], reg)); - - DONE; - } - if (sh_expand_t_scc (EQ, operands[0])) - DONE; - if (! currently_expanding_to_rtl) - FAIL; - operands[1] = prepare_scc_operands (EQ); -}") - -(define_expand "slt" - [(set (match_operand:SI 0 "arith_reg_operand" "") - (match_dup 1))] - "" +(define_expand "cstore4_media" + [(set (match_operand:SI 0 "register_operand" "=r") + (match_operator:SI 1 "sh_float_comparison_operator" + [(match_operand 2 "logical_operand" "") + (match_operand 3 "cmp_operand" "")]))] + "TARGET_SHMEDIA" " { - if (TARGET_SHMEDIA) + enum machine_mode mode = GET_MODE (operands[2]); + enum rtx_code code = GET_CODE (operands[1]); + bool invert, swap; + if (mode == VOIDmode) + mode = GET_MODE (operands[3]); + if (operands[2] == const0_rtx) { - rtx reg; - - sh_compare_op0 = force_reg (GET_MODE (sh_compare_op0), sh_compare_op0); - if (sh_compare_op1 != const0_rtx) - sh_compare_op1 = force_reg (GET_MODE (sh_compare_op1) == VOIDmode - ? GET_MODE (sh_compare_op0) - : GET_MODE (sh_compare_op1), - sh_compare_op1); - - reg = operands[0]; - if (GET_MODE (operands[0]) != SImode) - reg = (!can_create_pseudo_p () - ? gen_rtx_SUBREG (SImode, operands[0], 0) - : gen_reg_rtx (SImode)); - - switch (GET_MODE (sh_compare_op0)) - { - case SImode: - emit_insn (gen_cmpgtsi_media (reg, - sh_compare_op1, sh_compare_op0)); - break; - - case DImode: - emit_insn (gen_cmpgtdi_media (reg, - sh_compare_op1, sh_compare_op0)); - break; - - case SFmode: - if (! TARGET_SHMEDIA_FPU) - FAIL; - emit_insn (gen_cmpgtsf_media (reg, - sh_compare_op1, sh_compare_op0)); - break; - - case DFmode: - if (! TARGET_SHMEDIA_FPU) - FAIL; - emit_insn (gen_cmpgtdf_media (reg, - sh_compare_op1, sh_compare_op0)); - break; - - default: - FAIL; - } - - if (GET_MODE (operands[0]) == DImode) - emit_insn (gen_extendsidi2 (operands[0], reg)); - - DONE; + if (code == EQ || code == NE) + operands[2] = operands[3], operands[3] = const0_rtx; } - if (! currently_expanding_to_rtl) - FAIL; - operands[1] = prepare_scc_operands (LT); -}") - -(define_expand "sle" - [(match_operand:SI 0 "arith_reg_operand" "")] - "" - " -{ - rtx tmp = sh_compare_op0; + else + operands[2] = force_reg (mode, operands[2]); + if (operands[3] != const0_rtx) + operands[3] = force_reg (mode, operands[3]); - if (TARGET_SHMEDIA) + switch (code) { - rtx reg; - - sh_compare_op0 = force_reg (GET_MODE (sh_compare_op0), sh_compare_op0); - if (sh_compare_op1 != const0_rtx) - sh_compare_op1 = force_reg (GET_MODE (sh_compare_op1) == VOIDmode - ? GET_MODE (sh_compare_op0) - : GET_MODE (sh_compare_op1), - sh_compare_op1); - - reg = operands[0]; - if (GET_MODE (operands[0]) != SImode) - reg = (!can_create_pseudo_p () - ? gen_rtx_SUBREG (SImode, operands[0], 0) - : gen_reg_rtx (SImode)); - - switch (GET_MODE (sh_compare_op0)) - { - case SImode: - { - tmp = !can_create_pseudo_p () ? reg : gen_reg_rtx (SImode); - - emit_insn (gen_cmpgtsi_media (tmp, - sh_compare_op0, sh_compare_op1)); - emit_insn (gen_cmpeqdi_media (reg, tmp, const0_rtx)); - break; - } - - case DImode: - { - tmp = !can_create_pseudo_p () ? reg : gen_reg_rtx (SImode); - - emit_insn (gen_cmpgtdi_media (tmp, - sh_compare_op0, sh_compare_op1)); - emit_insn (gen_cmpeqdi_media (reg, tmp, const0_rtx)); - break; - } - - case SFmode: - if (! TARGET_SHMEDIA_FPU) - FAIL; - emit_insn (gen_cmpgesf_media (reg, - sh_compare_op1, sh_compare_op0)); - break; + case GEU: + case GE: + swap = invert = !FLOAT_MODE_P (mode); + break; - case DFmode: - if (! TARGET_SHMEDIA_FPU) - FAIL; - emit_insn (gen_cmpgedf_media (reg, - sh_compare_op1, sh_compare_op0)); - break; + case LEU: + case LE: + swap = FLOAT_MODE_P (mode), invert = !swap; + break; - default: - FAIL; - } + case LTU: + case LT: + swap = true, invert = false; + break; - if (GET_MODE (operands[0]) == DImode) - emit_insn (gen_extendsidi2 (operands[0], reg)); + case GTU: + case GT: + case EQ: + case UNORDERED: + swap = invert = false; + break; - DONE; - } + case NE: + swap = invert = true; + break; - sh_compare_op0 = sh_compare_op1; - sh_compare_op1 = tmp; - emit_insn (gen_sge (operands[0])); - DONE; -}") + default: + gcc_unreachable (); + } -(define_expand "sgt" - [(set (match_operand:SI 0 "arith_reg_operand" "") - (match_dup 1))] - "" - " -{ - if (TARGET_SHMEDIA) + if (swap) { - rtx reg; - - reg = operands[0]; - if (GET_MODE (operands[0]) != SImode) - reg = (!can_create_pseudo_p () ? - gen_rtx_SUBREG (SImode, operands[0], 0) - : gen_reg_rtx (SImode)); - sh_compare_op0 = force_reg (GET_MODE (sh_compare_op0), sh_compare_op0); - if (sh_compare_op1 != const0_rtx) - sh_compare_op1 = force_reg (GET_MODE (sh_compare_op1) == VOIDmode - ? GET_MODE (sh_compare_op0) - : GET_MODE (sh_compare_op1), - sh_compare_op1); - - switch (GET_MODE (sh_compare_op0)) - { - case SImode: - emit_insn (gen_cmpgtsi_media (reg, - sh_compare_op0, sh_compare_op1)); - break; - - case DImode: - emit_insn (gen_cmpgtdi_media (reg, - sh_compare_op0, sh_compare_op1)); - break; - - case SFmode: - if (! TARGET_SHMEDIA_FPU) - FAIL; - emit_insn (gen_cmpgtsf_media (reg, - sh_compare_op0, sh_compare_op1)); - break; - - case DFmode: - if (! TARGET_SHMEDIA_FPU) - FAIL; - emit_insn (gen_cmpgtdf_media (reg, - sh_compare_op0, sh_compare_op1)); - break; - - default: - FAIL; - } - - if (GET_MODE (operands[0]) == DImode) - emit_insn (gen_extendsidi2 (operands[0], reg)); - - DONE; + rtx tem = operands[2]; + operands[2] = operands[3]; + operands[3] = tem; + code = swap_condition (code); } - if (! currently_expanding_to_rtl) - FAIL; - operands[1] = prepare_scc_operands (GT); -}") -(define_expand "sge" - [(set (match_operand:SI 0 "arith_reg_operand" "") - (match_dup 1))] - "" - " -{ - if (TARGET_SHMEDIA) + if (invert) { - rtx reg; - enum machine_mode mode = GET_MODE (sh_compare_op0); - - if ((mode) == VOIDmode) - mode = GET_MODE (sh_compare_op1); - reg = operands[0]; - if (GET_MODE (operands[0]) != SImode) - reg = (!can_create_pseudo_p () - ? gen_rtx_SUBREG (SImode, operands[0], 0) - : gen_reg_rtx (SImode)); - sh_compare_op0 = force_reg (mode, sh_compare_op0); - if (sh_compare_op1 != const0_rtx) - sh_compare_op1 = force_reg (mode, sh_compare_op1); - - switch (mode) - { - case SImode: - { - rtx tmp = !can_create_pseudo_p () ? reg : gen_reg_rtx (SImode); - - emit_insn (gen_cmpgtsi_media (tmp, - sh_compare_op1, sh_compare_op0)); - emit_insn (gen_cmpeqdi_media (reg, tmp, const0_rtx)); - break; - } - - case DImode: - { - rtx tmp = !can_create_pseudo_p () ? reg : gen_reg_rtx (SImode); - - emit_insn (gen_cmpgtdi_media (tmp, - sh_compare_op1, sh_compare_op0)); - emit_insn (gen_cmpeqdi_media (reg, tmp, const0_rtx)); - break; - } - - case SFmode: - if (! TARGET_SHMEDIA_FPU) - FAIL; - emit_insn (gen_cmpgesf_media (reg, - sh_compare_op0, sh_compare_op1)); - break; - - case DFmode: - if (! TARGET_SHMEDIA_FPU) - FAIL; - emit_insn (gen_cmpgedf_media (reg, - sh_compare_op0, sh_compare_op1)); - break; - - default: - FAIL; - } - - if (GET_MODE (operands[0]) == DImode) - emit_insn (gen_extendsidi2 (operands[0], reg)); - - DONE; + rtx tem = can_create_pseudo_p () ? gen_reg_rtx (SImode) : operands[0]; + code = reverse_condition (code); + operands[1] = gen_rtx_fmt_ee (code, VOIDmode, operands[2], operands[3]); + emit_insn (gen_cstore4_media (tem, operands[1], + operands[2], operands[3])); + code = EQ; + operands[2] = tem; + operands[3] = const0_rtx; } - if (! currently_expanding_to_rtl) - FAIL; - if (GET_MODE_CLASS (GET_MODE (sh_compare_op0)) == MODE_FLOAT) - { - if (TARGET_IEEE) - { - rtx lab = gen_label_rtx (); - prepare_scc_operands (EQ); - emit_jump_insn (gen_branch_true (lab)); - prepare_scc_operands (GT); - emit_label (lab); - emit_insn (gen_movt (operands[0])); - } - else - emit_insn (gen_movnegt (operands[0], prepare_scc_operands (LT))); - DONE; - } - operands[1] = prepare_scc_operands (GE); + operands[1] = gen_rtx_fmt_ee (code, VOIDmode, operands[2], operands[3]); }") -(define_expand "sgtu" - [(set (match_operand:SI 0 "arith_reg_operand" "") - (match_dup 1))] - "" - " -{ - if (TARGET_SHMEDIA) +(define_expand "cstoresi4" + [(set (match_operand:SI 0 "register_operand" "=r") + (match_operator:SI 1 "comparison_operator" + [(match_operand:SI 2 "cmpsi_operand" "") + (match_operand:SI 3 "arith_operand" "")]))] + "TARGET_SH1 || TARGET_SHMEDIA" + "if (TARGET_SHMEDIA) { - rtx reg; - - reg = operands[0]; - if (GET_MODE (operands[0]) == DImode) - reg = (!can_create_pseudo_p () - ? gen_rtx_SUBREG (SImode, operands[0], 0) - : gen_reg_rtx (SImode)); - sh_compare_op0 = force_reg (GET_MODE (sh_compare_op0), sh_compare_op0); - if (sh_compare_op1 != const0_rtx) - sh_compare_op1 = force_reg (GET_MODE (sh_compare_op1) == VOIDmode - ? GET_MODE (sh_compare_op0) - : GET_MODE (sh_compare_op1), - sh_compare_op1); - - emit_insn (gen_cmpgtudi_media (reg, - sh_compare_op0, sh_compare_op1)); - if (GET_MODE (operands[0]) == DImode) - emit_insn (gen_extendsidi2 (operands[0], reg)); - + emit_insn (gen_cstore4_media (operands[0], operands[1], + operands[2], operands[3])); DONE; } - if (! currently_expanding_to_rtl) - FAIL; - operands[1] = prepare_scc_operands (GTU); -}") -(define_expand "sltu" - [(set (match_operand:SI 0 "arith_reg_operand" "") - (match_dup 1))] - "" - " -{ - if (TARGET_SHMEDIA) - { - rtx reg; - - reg = operands[0]; - if (GET_MODE (operands[0]) == DImode) - reg = (!can_create_pseudo_p () - ? gen_rtx_SUBREG (SImode, operands[0], 0) - : gen_reg_rtx (SImode)); - sh_compare_op0 = force_reg (GET_MODE (sh_compare_op0), sh_compare_op0); - if (sh_compare_op1 != const0_rtx) - sh_compare_op1 = force_reg (GET_MODE (sh_compare_op1) == VOIDmode - ? GET_MODE (sh_compare_op0) - : GET_MODE (sh_compare_op1), - sh_compare_op1); - - emit_insn (gen_cmpgtudi_media (reg, - sh_compare_op1, sh_compare_op0)); - if (GET_MODE (operands[0]) == DImode) - emit_insn (gen_extendsidi2 (operands[0], reg)); + if ((GET_CODE (operands[1]) == EQ || GET_CODE (operands[1]) == NE) + && sh_expand_t_scc (operands)) + DONE; - DONE; - } - if (! currently_expanding_to_rtl) - FAIL; - operands[1] = prepare_scc_operands (LTU); -}") + if (! currently_expanding_to_rtl) + FAIL; + + sh_emit_compare_and_set (operands, SImode); + DONE; +") -(define_expand "sleu" - [(set (match_operand:SI 0 "arith_reg_operand" "") - (match_dup 1))] - "" - " -{ - if (TARGET_SHMEDIA) +(define_expand "cstoredi4" + [(set (match_operand:SI 0 "register_operand" "=r") + (match_operator:SI 1 "comparison_operator" + [(match_operand:DI 2 "arith_operand" "") + (match_operand:DI 3 "arith_operand" "")]))] + "TARGET_SH2 || TARGET_SHMEDIA" + "if (TARGET_SHMEDIA) { - rtx tmp, reg; - - reg = operands[0]; - if (GET_MODE (operands[0]) != SImode) - reg = (!can_create_pseudo_p () - ? gen_rtx_SUBREG (SImode, operands[0], 0) - : gen_reg_rtx (SImode)); - sh_compare_op0 = force_reg (GET_MODE (sh_compare_op0), sh_compare_op0); - if (sh_compare_op1 != const0_rtx) - sh_compare_op1 = force_reg (GET_MODE (sh_compare_op1) == VOIDmode - ? GET_MODE (sh_compare_op0) - : GET_MODE (sh_compare_op1), - sh_compare_op1); - - tmp = !can_create_pseudo_p () ? reg : gen_reg_rtx (SImode); - - emit_insn (gen_cmpgtudi_media (tmp, sh_compare_op0, sh_compare_op1)); - emit_insn (gen_cmpeqdi_media (reg, tmp, const0_rtx)); - if (GET_MODE (operands[0]) == DImode) - emit_insn (gen_extendsidi2 (operands[0], reg)); - + emit_insn (gen_cstore4_media (operands[0], operands[1], + operands[2], operands[3])); DONE; } - if (! currently_expanding_to_rtl) - FAIL; - operands[1] = prepare_scc_operands (LEU); -}") -(define_expand "sgeu" - [(set (match_operand:SI 0 "arith_reg_operand" "") - (match_dup 1))] - "" - " -{ - if (TARGET_SHMEDIA) - { - rtx tmp, reg; - - reg = operands[0]; - if (GET_MODE (operands[0]) != SImode) - reg = (!can_create_pseudo_p () - ? gen_rtx_SUBREG (SImode, operands[0], 0) - : gen_reg_rtx (SImode)); - sh_compare_op0 = force_reg (GET_MODE (sh_compare_op0), sh_compare_op0); - if (sh_compare_op1 != const0_rtx) - sh_compare_op1 = force_reg (GET_MODE (sh_compare_op1) == VOIDmode - ? GET_MODE (sh_compare_op0) - : GET_MODE (sh_compare_op1), - sh_compare_op1); + if ((GET_CODE (operands[1]) == EQ || GET_CODE (operands[1]) == NE) + && sh_expand_t_scc (operands)) + DONE; - tmp = !can_create_pseudo_p () ? operands[0] : gen_reg_rtx (SImode); + if (! currently_expanding_to_rtl) + FAIL; + + sh_emit_compare_and_set (operands, DImode); + DONE; +") - emit_insn (gen_cmpgtudi_media (tmp, sh_compare_op1, sh_compare_op0)); - emit_insn (gen_cmpeqdi_media (reg, tmp, const0_rtx)); - if (GET_MODE (operands[0]) == DImode) - emit_insn (gen_extendsidi2 (operands[0], reg)); - DONE; - } - - if (! currently_expanding_to_rtl) - FAIL; - operands[1] = prepare_scc_operands (GEU); -}") ;; sne moves the complement of the T reg to DEST like this: ;; cmp/eq ... @@ -10119,81 +9257,20 @@ mov.l\\t1f,r0\\n\\ ;; not require r0 and further, the -1 may be CSE-ed or lifted out of a ;; loop. -(define_expand "sne" - [(set (match_dup 2) (const_int -1)) - (parallel [(set (match_operand:SI 0 "arith_reg_operand" "") - (neg:SI (plus:SI (match_dup 1) - (match_dup 2)))) +(define_expand "movnegt" + [(set (match_dup 1) (const_int -1)) + (parallel [(set (match_operand:SI 0 "" "") + (neg:SI (plus:SI (reg:SI T_REG) + (match_dup 1)))) (set (reg:SI T_REG) - (ne:SI (ior:SI (match_dup 1) (match_dup 2)) + (ne:SI (ior:SI (reg:SI T_REG) (match_dup 1)) (const_int 0)))])] "" " { - if (TARGET_SHMEDIA) - { - rtx tmp, reg; - - reg = operands[0]; - if (GET_MODE (operands[0]) != SImode) - reg = (!can_create_pseudo_p () - ? gen_rtx_SUBREG (SImode, operands[0], 0) - : gen_reg_rtx (SImode)); - if (! TARGET_SHMEDIA_FPU - && GET_MODE (sh_compare_op0) != DImode - && GET_MODE (sh_compare_op0) != SImode) - FAIL; - - sh_compare_op0 = force_reg (GET_MODE (sh_compare_op0), sh_compare_op0); - if (sh_compare_op1 != const0_rtx) - sh_compare_op1 = force_reg (GET_MODE (sh_compare_op1) == VOIDmode - ? GET_MODE (sh_compare_op0) - : GET_MODE (sh_compare_op1), - sh_compare_op1); - - tmp = !can_create_pseudo_p () ? reg : gen_reg_rtx (SImode); - - emit_insn (gen_seq (tmp)); - emit_insn (gen_cmpeqdi_media (reg, tmp, const0_rtx)); - if (GET_MODE (operands[0]) == DImode) - emit_insn (gen_extendsidi2 (operands[0], reg)); - - DONE; - } - - if (sh_expand_t_scc (NE, operands[0])) - DONE; - if (! currently_expanding_to_rtl) - FAIL; - operands[1] = prepare_scc_operands (EQ); - operands[2] = gen_reg_rtx (SImode); -}") - -(define_expand "sunordered" - [(set (match_operand:SI 0 "arith_reg_operand" "") - (unordered:SI (match_dup 1) (match_dup 2)))] - "TARGET_SHMEDIA_FPU" - " -{ - operands[1] = force_reg (GET_MODE (sh_compare_op0), sh_compare_op0); - operands[2] = force_reg (GET_MODE (sh_compare_op1), sh_compare_op1); + operands[1] = gen_reg_rtx (SImode); }") -;; Use the same trick for FP sle / sge - -;; Apart from the constant use and the T setting, this is like movt, -;; except that it uses the logically negated value of T, i.e. -;; operand[0] := T ? 0 : 1. -(define_expand "movnegt" - [(set (match_dup 2) (const_int -1)) - (parallel [(set (match_operand 0 "" "") - (neg:SI (plus:SI (match_dup 1) - (match_dup 2)))) - (set (reg:SI T_REG) - (ne:SI (ior:SI (match_operand 1 "" "") (match_dup 2)) - (const_int 0)))])] - "TARGET_SH1" - "operands[2] = gen_reg_rtx (SImode);") ;; Recognize mov #-1/negc/neg sequence, and change it to movt/add #-1. ;; This prevents a regression that occurred when we switched from xor to @@ -10208,6 +9285,47 @@ mov.l\\t1f,r0\\n\\ (set (match_dup 0) (plus:SI (match_dup 0) (const_int -1)))] "") +(define_expand "cstoresf4" + [(set (match_operand:SI 0 "register_operand" "=r") + (match_operator:SI 1 "sh_float_comparison_operator" + [(match_operand:SF 2 "arith_operand" "") + (match_operand:SF 3 "arith_operand" "")]))] + "TARGET_SH2E || TARGET_SHMEDIA_FPU" + "if (TARGET_SHMEDIA) + { + emit_insn (gen_cstore4_media (operands[0], operands[1], + operands[2], operands[3])); + DONE; + } + + if (! currently_expanding_to_rtl) + FAIL; + + sh_emit_compare_and_set (operands, SFmode); + DONE; +") + +(define_expand "cstoredf4" + [(set (match_operand:SI 0 "register_operand" "=r") + (match_operator:SI 1 "sh_float_comparison_operator" + [(match_operand:DF 2 "arith_operand" "") + (match_operand:DF 3 "arith_operand" "")]))] + "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU" + "if (TARGET_SHMEDIA) + { + emit_insn (gen_cstore4_media (operands[0], operands[1], + operands[2], operands[3])); + DONE; + } + + if (! currently_expanding_to_rtl) + FAIL; + + sh_emit_compare_and_set (operands, DFmode); + DONE; +") + + ;; ------------------------------------------------------------------------- ;; Instructions to cope with inline literal tables ;; ------------------------------------------------------------------------- @@ -10986,15 +10104,21 @@ mov.l\\t1f,r0\\n\\ "fcmpun.s %1, %2, %0" [(set_attr "type" "fcmp_media")]) -(define_expand "cmpsf" - [(set (reg:SI T_REG) - (compare (match_operand:SF 0 "arith_operand" "") - (match_operand:SF 1 "arith_operand" "")))] +(define_expand "cbranchsf4" + [(set (pc) + (if_then_else (match_operator 0 "sh_float_comparison_operator" + [(match_operand:SF 1 "arith_operand" "") + (match_operand:SF 2 "arith_operand" "")]) + (match_operand 3 "" "") + (pc)))] "TARGET_SH2E || TARGET_SHMEDIA_FPU" " { - sh_compare_op0 = operands[0]; - sh_compare_op1 = operands[1]; + if (TARGET_SHMEDIA) + emit_jump_insn (gen_cbranchfp4_media (operands[0], operands[1], operands[2], + operands[3])); + else + sh_emit_compare_and_branch (operands, SFmode); DONE; }") @@ -11484,18 +10608,25 @@ mov.l\\t1f,r0\\n\\ "fcmpun.d %1,%2,%0" [(set_attr "type" "fcmp_media")]) -(define_expand "cmpdf" - [(set (reg:SI T_REG) - (compare (match_operand:DF 0 "arith_operand" "") - (match_operand:DF 1 "arith_operand" "")))] +(define_expand "cbranchdf4" + [(set (pc) + (if_then_else (match_operator 0 "sh_float_comparison_operator" + [(match_operand:DF 1 "arith_operand" "") + (match_operand:DF 2 "arith_operand" "")]) + (match_operand 3 "" "") + (pc)))] "(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU" " { - sh_compare_op0 = operands[0]; - sh_compare_op1 = operands[1]; + if (TARGET_SHMEDIA) + emit_jump_insn (gen_cbranchfp4_media (operands[0], operands[1], operands[2], + operands[3])); + else + sh_emit_compare_and_branch (operands, DFmode); DONE; }") + (define_expand "negdf2" [(set (match_operand:DF 0 "arith_reg_operand" "") (neg:DF (match_operand:DF 1 "arith_reg_operand" "")))] @@ -14144,15 +13275,21 @@ mov.l\\t1f,r0\\n\\ if (TARGET_SHMEDIA) { rtx tmp = gen_reg_rtx (GET_MODE (operands[0])); + rtx test; + test = gen_rtx_NE (VOIDmode, tmp, const0_rtx); if (TARGET_SHMEDIA64) - emit_insn (gen_stack_protect_test_di_media (tmp, operands[0], - operands[1])); + { + emit_insn (gen_stack_protect_test_di_media (tmp, operands[0], + operands[1])); + emit_jump_insn (gen_cbranchdi4 (test, tmp, const0_rtx, operands[2])); + } else - emit_insn (gen_stack_protect_test_si_media (tmp, operands[0], - operands[1])); - - emit_jump_insn (gen_bne_media (operands[2], tmp, const0_rtx)); + { + emit_insn (gen_stack_protect_test_si_media (tmp, operands[0], + operands[1])); + emit_jump_insn (gen_cbranchsi4 (test, tmp, const0_rtx, operands[2])); + } } else { diff --git a/gcc/config/sparc/sparc-protos.h b/gcc/config/sparc/sparc-protos.h index 40ac75e130c..fd388dd8139 100644 --- a/gcc/config/sparc/sparc-protos.h +++ b/gcc/config/sparc/sparc-protos.h @@ -54,16 +54,14 @@ extern void sparc_output_scratch_registers (FILE *); #ifdef RTX_CODE extern enum machine_mode select_cc_mode (enum rtx_code, rtx, rtx); /* Define the function that build the compare insn for scc and bcc. */ -extern rtx gen_compare_reg (enum rtx_code code); -extern rtx gen_compare_operator (enum rtx_code code); -extern enum rtx_code sparc_emit_float_lib_cmp (rtx, rtx, enum rtx_code); +extern rtx gen_compare_reg (rtx cmp); +extern rtx sparc_emit_float_lib_cmp (rtx, rtx, enum rtx_code); extern void sparc_emit_floatunsdi (rtx [2], enum machine_mode); extern void sparc_emit_fixunsdi (rtx [2], enum machine_mode); extern void emit_tfmode_binop (enum rtx_code, rtx *); extern void emit_tfmode_unop (enum rtx_code, rtx *); extern void emit_tfmode_cvt (enum rtx_code, rtx *); /* This function handles all v9 scc insns */ -extern int gen_v9_scc (enum rtx_code, rtx *); extern void sparc_initialize_trampoline (rtx, rtx, rtx); extern void sparc64_initialize_trampoline (rtx, rtx, rtx); extern bool legitimate_constant_p (rtx); @@ -86,7 +84,8 @@ extern const char *output_return (rtx); extern const char *output_sibcall (rtx, rtx); extern const char *output_v8plus_shift (rtx *, rtx, const char *); extern const char *output_v9branch (rtx, rtx, int, int, int, int, rtx); -extern void emit_v9_brxx_insn (enum rtx_code, rtx, rtx); +extern bool emit_scc_insn (rtx []); +extern void emit_conditional_branch_insn (rtx []); extern void print_operand (FILE *, rtx, int); extern int mems_ok_for_ldd_peep (rtx, rtx, rtx); extern int arith_double_4096_operand (rtx, enum machine_mode); diff --git a/gcc/config/sparc/sparc.c b/gcc/config/sparc/sparc.c index ab2b57bbcd9..330c2c06981 100644 --- a/gcc/config/sparc/sparc.c +++ b/gcc/config/sparc/sparc.c @@ -280,10 +280,6 @@ static GTY(()) alias_set_type sparc_sr_alias_set; /* The alias set for the structure return value. */ static GTY(()) alias_set_type struct_value_alias_set; -/* Save the operands last given to a compare for use when we - generate a scc or bcc insn. */ -rtx sparc_compare_op0, sparc_compare_op1; - /* Vector to say how input registers are mapped to output registers. HARD_FRAME_POINTER_REGNUM cannot be remapped by this function to eliminate it. You must use -fomit-frame-pointer to get that. */ @@ -2005,19 +2001,18 @@ select_cc_mode (enum rtx_code op, rtx x, rtx y ATTRIBUTE_UNUSED) } } -/* Emit the compare insn and return the CC reg for a CODE comparison. */ +/* Emit the compare insn and return the CC reg for a CODE comparison + with operands X and Y. */ -rtx -gen_compare_reg (enum rtx_code code) +static rtx +gen_compare_reg_1 (enum rtx_code code, rtx x, rtx y) { enum machine_mode mode; - rtx x, y, cc_reg; + rtx cc_reg; - if (GET_MODE_CLASS (GET_MODE (sparc_compare_op0)) == MODE_CC) - return sparc_compare_op0; + if (GET_MODE_CLASS (GET_MODE (x)) == MODE_CC) + return x; - x = sparc_compare_op0; - y = sparc_compare_op1; mode = SELECT_CC_MODE (code, x, y); /* ??? We don't have movcc patterns so we cannot generate pseudo regs for the @@ -2073,26 +2068,19 @@ gen_compare_reg (enum rtx_code code) return cc_reg; } -/* Same as above but return the whole compare operator. */ + +/* Emit the compare insn and return the CC reg for the comparison in CMP. */ rtx -gen_compare_operator (enum rtx_code code) +gen_compare_reg (rtx cmp) { - rtx cc_reg; - - if (GET_MODE (sparc_compare_op0) == TFmode && !TARGET_HARD_QUAD) - code - = sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, code); - - cc_reg = gen_compare_reg (code); - return gen_rtx_fmt_ee (code, GET_MODE (cc_reg), cc_reg, const0_rtx); + return gen_compare_reg_1 (GET_CODE (cmp), XEXP (cmp, 0), XEXP (cmp, 1)); } /* This function is used for v9 only. + DEST is the target of the Scc insn. CODE is the code for an Scc's comparison. - OPERANDS[0] is the target of the Scc insn. - OPERANDS[1] is the value we compare against const0_rtx (which hasn't - been generated yet). + X and Y are the values we compare. This function is needed to turn @@ -2106,53 +2094,50 @@ gen_compare_operator (enum rtx_code code) IE: The instruction recognizer needs to see the mode of the comparison to find the right instruction. We could use "gt:DI" right in the - define_expand, but leaving it out allows us to handle DI, SI, etc. + define_expand, but leaving it out allows us to handle DI, SI, etc. */ - We refer to the global sparc compare operands sparc_compare_op0 and - sparc_compare_op1. */ - -int -gen_v9_scc (enum rtx_code compare_code, register rtx *operands) +static int +gen_v9_scc (rtx dest, enum rtx_code compare_code, rtx x, rtx y) { if (! TARGET_ARCH64 - && (GET_MODE (sparc_compare_op0) == DImode - || GET_MODE (operands[0]) == DImode)) + && (GET_MODE (x) == DImode + || GET_MODE (dest) == DImode)) return 0; /* Try to use the movrCC insns. */ if (TARGET_ARCH64 - && GET_MODE_CLASS (GET_MODE (sparc_compare_op0)) == MODE_INT - && sparc_compare_op1 == const0_rtx + && GET_MODE_CLASS (GET_MODE (x)) == MODE_INT + && y == const0_rtx && v9_regcmp_p (compare_code)) { - rtx op0 = sparc_compare_op0; + rtx op0 = x; rtx temp; /* Special case for op0 != 0. This can be done with one instruction if - operands[0] == sparc_compare_op0. */ + dest == x. */ if (compare_code == NE - && GET_MODE (operands[0]) == DImode - && rtx_equal_p (op0, operands[0])) + && GET_MODE (dest) == DImode + && rtx_equal_p (op0, dest)) { - emit_insn (gen_rtx_SET (VOIDmode, operands[0], + emit_insn (gen_rtx_SET (VOIDmode, dest, gen_rtx_IF_THEN_ELSE (DImode, gen_rtx_fmt_ee (compare_code, DImode, op0, const0_rtx), const1_rtx, - operands[0]))); + dest))); return 1; } - if (reg_overlap_mentioned_p (operands[0], op0)) + if (reg_overlap_mentioned_p (dest, op0)) { - /* Handle the case where operands[0] == sparc_compare_op0. + /* Handle the case where dest == x. We "early clobber" the result. */ - op0 = gen_reg_rtx (GET_MODE (sparc_compare_op0)); - emit_move_insn (op0, sparc_compare_op0); + op0 = gen_reg_rtx (GET_MODE (x)); + emit_move_insn (op0, x); } - emit_insn (gen_rtx_SET (VOIDmode, operands[0], const0_rtx)); + emit_insn (gen_rtx_SET (VOIDmode, dest, const0_rtx)); if (GET_MODE (op0) != DImode) { temp = gen_reg_rtx (DImode); @@ -2160,47 +2145,137 @@ gen_v9_scc (enum rtx_code compare_code, register rtx *operands) } else temp = op0; - emit_insn (gen_rtx_SET (VOIDmode, operands[0], - gen_rtx_IF_THEN_ELSE (GET_MODE (operands[0]), + emit_insn (gen_rtx_SET (VOIDmode, dest, + gen_rtx_IF_THEN_ELSE (GET_MODE (dest), gen_rtx_fmt_ee (compare_code, DImode, temp, const0_rtx), const1_rtx, - operands[0]))); + dest))); return 1; } else { - operands[1] = gen_compare_reg (compare_code); + x = gen_compare_reg_1 (compare_code, x, y); + y = const0_rtx; - switch (GET_MODE (operands[1])) - { - case CCmode : - case CCXmode : - case CCFPEmode : - case CCFPmode : - break; - default : - gcc_unreachable (); - } - emit_insn (gen_rtx_SET (VOIDmode, operands[0], const0_rtx)); - emit_insn (gen_rtx_SET (VOIDmode, operands[0], - gen_rtx_IF_THEN_ELSE (GET_MODE (operands[0]), + gcc_assert (GET_MODE (x) != CC_NOOVmode + && GET_MODE (x) != CCX_NOOVmode); + + emit_insn (gen_rtx_SET (VOIDmode, dest, const0_rtx)); + emit_insn (gen_rtx_SET (VOIDmode, dest, + gen_rtx_IF_THEN_ELSE (GET_MODE (dest), gen_rtx_fmt_ee (compare_code, - GET_MODE (operands[1]), - operands[1], const0_rtx), - const1_rtx, operands[0]))); + GET_MODE (x), x, y), + const1_rtx, dest))); return 1; } } + +/* Emit an scc insn. For seq, sne, sgeu, and sltu, we can do this + without jumps using the addx/subx instructions. */ + +bool +emit_scc_insn (rtx operands[]) +{ + rtx tem; + rtx x; + rtx y; + enum rtx_code code; + + /* The quad-word fp compare library routines all return nonzero to indicate + true, which is different from the equivalent libgcc routines, so we must + handle them specially here. */ + if (GET_MODE (operands[2]) == TFmode && ! TARGET_HARD_QUAD) + { + operands[1] = sparc_emit_float_lib_cmp (operands[2], operands[3], + GET_CODE (operands[1])); + operands[2] = XEXP (operands[1], 0); + operands[3] = XEXP (operands[1], 1); + } + + code = GET_CODE (operands[1]); + x = operands[2]; + y = operands[3]; + + /* For seq/sne on v9 we use the same code as v8 (the addx/subx method has + more applications). The exception to this is "reg != 0" which can + be done in one instruction on v9 (so we do it). */ + if (code == EQ) + { + if (GET_MODE (x) == SImode) + { + rtx pat = gen_seqsi_special (operands[0], x, y); + emit_insn (pat); + return true; + } + else if (GET_MODE (x) == DImode) + { + rtx pat = gen_seqdi_special (operands[0], x, y); + emit_insn (pat); + return true; + } + } + + if (code == NE) + { + if (GET_MODE (x) == SImode) + { + rtx pat = gen_snesi_special (operands[0], x, y); + emit_insn (pat); + return true; + } + else if (GET_MODE (x) == DImode) + { + rtx pat = gen_snedi_special (operands[0], x, y); + emit_insn (pat); + return true; + } + } + + /* For the rest, on v9 we can use conditional moves. */ + + if (TARGET_V9) + { + if (gen_v9_scc (operands[0], code, x, y)) + return true; + } + + /* We can do LTU and GEU using the addx/subx instructions too. And + for GTU/LEU, if both operands are registers swap them and fall + back to the easy case. */ + if (code == GTU || code == LEU) + { + if ((GET_CODE (x) == REG || GET_CODE (x) == SUBREG) + && (GET_CODE (y) == REG || GET_CODE (y) == SUBREG)) + { + tem = x; + x = y; + y = tem; + code = swap_condition (code); + } + } + + if (code == LTU || code == GEU) + { + emit_insn (gen_rtx_SET (VOIDmode, operands[0], + gen_rtx_fmt_ee (code, SImode, + gen_compare_reg_1 (code, x, y), + const0_rtx))); + return true; + } + + /* Nope, do branches. */ + return false; +} + /* Emit a conditional jump insn for the v9 architecture using comparison code CODE and jump target LABEL. This function exists to take advantage of the v9 brxx insns. */ -void +static void emit_v9_brxx_insn (enum rtx_code code, rtx op0, rtx label) { - gcc_assert (GET_MODE_CLASS (GET_MODE (sparc_compare_op0)) != MODE_CC); emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx, gen_rtx_IF_THEN_ELSE (VOIDmode, @@ -2210,6 +2285,37 @@ emit_v9_brxx_insn (enum rtx_code code, rtx op0, rtx label) pc_rtx))); } +void +emit_conditional_branch_insn (rtx operands[]) +{ + /* The quad-word fp compare library routines all return nonzero to indicate + true, which is different from the equivalent libgcc routines, so we must + handle them specially here. */ + if (GET_MODE (operands[1]) == TFmode && ! TARGET_HARD_QUAD) + { + operands[0] = sparc_emit_float_lib_cmp (operands[1], operands[2], + GET_CODE (operands[0])); + operands[1] = XEXP (operands[0], 0); + operands[2] = XEXP (operands[0], 1); + } + + if (TARGET_ARCH64 && operands[2] == const0_rtx + && GET_CODE (operands[1]) == REG + && GET_MODE (operands[1]) == DImode) + { + emit_v9_brxx_insn (GET_CODE (operands[0]), operands[1], operands[3]); + return; + } + + operands[1] = gen_compare_reg (operands[0]); + operands[2] = const0_rtx; + operands[0] = gen_rtx_fmt_ee (GET_CODE (operands[0]), VOIDmode, + operands[1], operands[2]); + emit_jump_insn (gen_cbranchcc4 (operands[0], operands[1], operands[2], + operands[3])); +} + + /* Generate a DFmode part of a hard TFmode register. REG is the TFmode hard register, LOW is 1 for the low 64bit of the register and 0 otherwise. @@ -6116,7 +6222,7 @@ output_cbranch (rtx op, rtx dest, int label, int reversed, int annul, values as arguments instead of the TFmode registers themselves, that's why we cannot call emit_float_lib_cmp. */ -enum rtx_code +rtx sparc_emit_float_lib_cmp (rtx x, rtx y, enum rtx_code comparison) { const char *qpfunc; @@ -6207,32 +6313,24 @@ sparc_emit_float_lib_cmp (rtx x, rtx y, enum rtx_code comparison) switch (comparison) { default: - new_comparison = NE; - emit_cmp_insn (result, const0_rtx, new_comparison, NULL_RTX, mode, 0); - break; + return gen_rtx_NE (VOIDmode, result, const0_rtx); case ORDERED: case UNORDERED: new_comparison = (comparison == UNORDERED ? EQ : NE); - emit_cmp_insn (result, GEN_INT(3), new_comparison, NULL_RTX, mode, 0); - break; + return gen_rtx_fmt_ee (new_comparison, VOIDmode, result, GEN_INT(3)); case UNGT: case UNGE: new_comparison = (comparison == UNGT ? GT : NE); - emit_cmp_insn (result, const1_rtx, new_comparison, NULL_RTX, mode, 0); - break; + return gen_rtx_fmt_ee (new_comparison, VOIDmode, result, const1_rtx); case UNLE: - new_comparison = NE; - emit_cmp_insn (result, const2_rtx, new_comparison, NULL_RTX, mode, 0); - break; + return gen_rtx_NE (VOIDmode, result, const2_rtx); case UNLT: tem = gen_reg_rtx (mode); if (TARGET_ARCH32) emit_insn (gen_andsi3 (tem, result, const1_rtx)); else emit_insn (gen_anddi3 (tem, result, const1_rtx)); - new_comparison = NE; - emit_cmp_insn (tem, const0_rtx, new_comparison, NULL_RTX, mode, 0); - break; + return gen_rtx_NE (VOIDmode, tem, const0_rtx); case UNEQ: case LTGT: tem = gen_reg_rtx (mode); @@ -6246,11 +6344,10 @@ sparc_emit_float_lib_cmp (rtx x, rtx y, enum rtx_code comparison) else emit_insn (gen_anddi3 (tem2, tem, const2_rtx)); new_comparison = (comparison == UNEQ ? EQ : NE); - emit_cmp_insn (tem2, const0_rtx, new_comparison, NULL_RTX, mode, 0); - break; + return gen_rtx_fmt_ee (new_comparison, VOIDmode, tem2, const0_rtx); } - return new_comparison; + gcc_unreachable (); } /* Generate an unsigned DImode to FP conversion. This is the same code @@ -9021,15 +9118,12 @@ sparc_expand_compare_and_swap_12 (rtx result, rtx mem, rtx oldval, rtx newval) gen_rtx_AND (SImode, gen_rtx_NOT (SImode, mask), res))); - sparc_compare_op0 = resv; - sparc_compare_op1 = val; - cc = gen_compare_reg (NE); - + cc = gen_compare_reg_1 (NE, resv, val); emit_insn (gen_rtx_SET (VOIDmode, val, resv)); - sparc_compare_op0 = cc; - sparc_compare_op1 = const0_rtx; - emit_jump_insn (gen_bne (loop_label)); + /* Use cbranchcc4 to separate the compare and branch! */ + emit_jump_insn (gen_cbranchcc4 (gen_rtx_NE (VOIDmode, cc, const0_rtx), + cc, const0_rtx, loop_label)); emit_label (end_label); diff --git a/gcc/config/sparc/sparc.h b/gcc/config/sparc/sparc.h index d21900135e2..280036224be 100644 --- a/gcc/config/sparc/sparc.h +++ b/gcc/config/sparc/sparc.h @@ -1558,12 +1558,6 @@ function_arg_padding ((MODE), (TYPE)) && (GET_MODE_ALIGNMENT (MODE) == 128 \ || ((TYPE) && TYPE_ALIGN (TYPE) == 128))) \ ? 128 : PARM_BOUNDARY) - -/* Define the information needed to generate branch and scc insns. This is - stored from the compare operation. */ - -extern GTY(()) rtx sparc_compare_op0; -extern GTY(()) rtx sparc_compare_op1; /* Generate the special assembly code needed to tell the assembler whatever diff --git a/gcc/config/sparc/sparc.md b/gcc/config/sparc/sparc.md index 4fae329cd9a..9e35910f4db 100644 --- a/gcc/config/sparc/sparc.md +++ b/gcc/config/sparc/sparc.md @@ -76,6 +76,18 @@ (UNSPECV_LDSTUB 10) ]) + +(define_mode_iterator P [(SI "Pmode == SImode") (DI "Pmode == DImode")]) +(define_mode_iterator I [QI HI SI DI]) +(define_mode_iterator F [SF DF TF]) + +;; We don't define V1SI because SI should work just fine. +(define_mode_iterator V32 [SF V2HI V4QI]) +(define_mode_iterator V32I [SI V2HI V4QI]) + +(define_mode_iterator V64 [DF V2SI V4HI V8QI]) +(define_mode_iterator V64I [DI V2SI V4HI V8QI]) + ;; The upper 32 fp regs on the v9 can't hold SFmode values. To deal with this ;; a second register class, EXTRA_FP_REGS, exists for the v9 chip. The name ;; is a bit of a misnomer as it covers all 64 fp regs. The corresponding @@ -340,84 +352,11 @@ ;; Compare instructions. -;; We generate RTL for comparisons and branches by having the cmpxx -;; patterns store away the operands. Then, the scc and bcc patterns -;; emit RTL for both the compare and the branch. -;; -;; We do this because we want to generate different code for an sne and -;; seq insn. In those cases, if the second operand of the compare is not -;; const0_rtx, we want to compute the xor of the two operands and test -;; it against zero. -;; -;; We start with the DEFINE_EXPANDs, then the DEFINE_INSNs to match -;; the patterns. Finally, we have the DEFINE_SPLITs for some of the scc -;; insns that actually require more than one machine instruction. - -(define_expand "cmpsi" - [(set (reg:CC 100) - (compare:CC (match_operand:SI 0 "compare_operand" "") - (match_operand:SI 1 "arith_operand" "")))] - "" -{ - if (GET_CODE (operands[0]) == ZERO_EXTRACT && operands[1] != const0_rtx) - operands[0] = force_reg (SImode, operands[0]); - - sparc_compare_op0 = operands[0]; - sparc_compare_op1 = operands[1]; - DONE; -}) - -(define_expand "cmpdi" - [(set (reg:CCX 100) - (compare:CCX (match_operand:DI 0 "compare_operand" "") - (match_operand:DI 1 "arith_operand" "")))] - "TARGET_ARCH64" -{ - if (GET_CODE (operands[0]) == ZERO_EXTRACT && operands[1] != const0_rtx) - operands[0] = force_reg (DImode, operands[0]); - - sparc_compare_op0 = operands[0]; - sparc_compare_op1 = operands[1]; - DONE; -}) - -(define_expand "cmpsf" - ;; The 96 here isn't ever used by anyone. - [(set (reg:CCFP 96) - (compare:CCFP (match_operand:SF 0 "register_operand" "") - (match_operand:SF 1 "register_operand" "")))] - "TARGET_FPU" -{ - sparc_compare_op0 = operands[0]; - sparc_compare_op1 = operands[1]; - DONE; -}) - -(define_expand "cmpdf" - ;; The 96 here isn't ever used by anyone. - [(set (reg:CCFP 96) - (compare:CCFP (match_operand:DF 0 "register_operand" "") - (match_operand:DF 1 "register_operand" "")))] - "TARGET_FPU" -{ - sparc_compare_op0 = operands[0]; - sparc_compare_op1 = operands[1]; - DONE; -}) - -(define_expand "cmptf" - ;; The 96 here isn't ever used by anyone. - [(set (reg:CCFP 96) - (compare:CCFP (match_operand:TF 0 "register_operand" "") - (match_operand:TF 1 "register_operand" "")))] - "TARGET_FPU" -{ - sparc_compare_op0 = operands[0]; - sparc_compare_op1 = operands[1]; - DONE; -}) +;; These are just the DEFINE_INSNs to match the patterns and the +;; DEFINE_SPLITs for some of the scc insns that actually require +;; more than one machine instruction. DEFINE_EXPANDs are further down. -;; Now the compare DEFINE_INSNs. +;; The compare DEFINE_INSNs. (define_insn "*cmpsi_insn" [(set (reg:CC 100) @@ -509,12 +448,41 @@ } [(set_attr "type" "fpcmp")]) -;; Next come the scc insns. For seq, sne, sgeu, and sltu, we can do this -;; without jumps using the addx/subx instructions. For seq/sne on v9 we use -;; the same code as v8 (the addx/subx method has more applications). The -;; exception to this is "reg != 0" which can be done in one instruction on v9 -;; (so we do it). For the rest, on v9 we use conditional moves; on v8, we do -;; branches. +;; Next come the scc insns. + +(define_expand "cstoresi4" + [(use (match_operator 1 "comparison_operator" + [(match_operand:SI 2 "compare_operand" "") + (match_operand:SI 3 "arith_operand" "")])) + (clobber (match_operand:SI 0 "register_operand"))] + "" +{ + if (GET_CODE (operands[2]) == ZERO_EXTRACT && operands[3] != const0_rtx) + operands[2] = force_reg (SImode, operands[2]); + if (emit_scc_insn (operands)) DONE; else FAIL; +}) + +(define_expand "cstoredi4" + [(use (match_operator 1 "comparison_operator" + [(match_operand:DI 2 "compare_operand" "") + (match_operand:DI 3 "arith_operand" "")])) + (clobber (match_operand:SI 0 "register_operand"))] + "TARGET_ARCH64" +{ + if (GET_CODE (operands[2]) == ZERO_EXTRACT && operands[3] != const0_rtx) + operands[2] = force_reg (DImode, operands[2]); + if (emit_scc_insn (operands)) DONE; else FAIL; +}) + +(define_expand "cstore<F:mode>4" + [(use (match_operator 1 "comparison_operator" + [(match_operand:F 2 "register_operand" "") + (match_operand:F 3 "register_operand" "")])) + (clobber (match_operand:SI 0 "register_operand"))] + "TARGET_FPU" + { if (emit_scc_insn (operands)) DONE; else FAIL; }) + + ;; Seq_special[_xxx] and sne_special[_xxx] clobber the CC reg, because they ;; generate addcc/subcc instructions. @@ -533,8 +501,8 @@ [(set (match_dup 3) (xor:DI (match_operand:DI 1 "register_operand" "") (match_operand:DI 2 "register_operand" ""))) - (set (match_operand:DI 0 "register_operand" "") - (eq:DI (match_dup 3) (const_int 0)))] + (set (match_operand:SI 0 "register_operand" "") + (eq:SI (match_dup 3) (const_int 0)))] "TARGET_ARCH64" { operands[3] = gen_reg_rtx (DImode); }) @@ -552,338 +520,11 @@ [(set (match_dup 3) (xor:DI (match_operand:DI 1 "register_operand" "") (match_operand:DI 2 "register_operand" ""))) - (set (match_operand:DI 0 "register_operand" "") - (ne:DI (match_dup 3) (const_int 0)))] - "TARGET_ARCH64" - { operands[3] = gen_reg_rtx (DImode); }) - -(define_expand "seqdi_special_trunc" - [(set (match_dup 3) - (xor:DI (match_operand:DI 1 "register_operand" "") - (match_operand:DI 2 "register_operand" ""))) - (set (match_operand:SI 0 "register_operand" "") - (eq:SI (match_dup 3) (const_int 0)))] - "TARGET_ARCH64" - { operands[3] = gen_reg_rtx (DImode); }) - -(define_expand "snedi_special_trunc" - [(set (match_dup 3) - (xor:DI (match_operand:DI 1 "register_operand" "") - (match_operand:DI 2 "register_operand" ""))) (set (match_operand:SI 0 "register_operand" "") (ne:SI (match_dup 3) (const_int 0)))] "TARGET_ARCH64" { operands[3] = gen_reg_rtx (DImode); }) -(define_expand "seqsi_special_extend" - [(set (match_dup 3) - (xor:SI (match_operand:SI 1 "register_operand" "") - (match_operand:SI 2 "register_operand" ""))) - (parallel [(set (match_operand:DI 0 "register_operand" "") - (eq:DI (match_dup 3) (const_int 0))) - (clobber (reg:CC 100))])] - "TARGET_ARCH64" - { operands[3] = gen_reg_rtx (SImode); }) - -(define_expand "snesi_special_extend" - [(set (match_dup 3) - (xor:SI (match_operand:SI 1 "register_operand" "") - (match_operand:SI 2 "register_operand" ""))) - (parallel [(set (match_operand:DI 0 "register_operand" "") - (ne:DI (match_dup 3) (const_int 0))) - (clobber (reg:CC 100))])] - "TARGET_ARCH64" - { operands[3] = gen_reg_rtx (SImode); }) - -;; ??? v9: Operand 0 needs a mode, so SImode was chosen. -;; However, the code handles both SImode and DImode. -(define_expand "seq" - [(set (match_operand:SI 0 "int_register_operand" "") - (eq:SI (match_dup 1) (const_int 0)))] - "" -{ - if (GET_MODE (sparc_compare_op0) == SImode) - { - rtx pat; - - if (GET_MODE (operands[0]) == SImode) - pat = gen_seqsi_special (operands[0], sparc_compare_op0, - sparc_compare_op1); - else if (! TARGET_ARCH64) - FAIL; - else - pat = gen_seqsi_special_extend (operands[0], sparc_compare_op0, - sparc_compare_op1); - emit_insn (pat); - DONE; - } - else if (GET_MODE (sparc_compare_op0) == DImode) - { - rtx pat; - - if (! TARGET_ARCH64) - FAIL; - else if (GET_MODE (operands[0]) == SImode) - pat = gen_seqdi_special_trunc (operands[0], sparc_compare_op0, - sparc_compare_op1); - else - pat = gen_seqdi_special (operands[0], sparc_compare_op0, - sparc_compare_op1); - emit_insn (pat); - DONE; - } - else if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD) - { - enum rtx_code code - = sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, EQ); - gcc_assert (code == NE); - emit_insn (gen_sne (operands[0])); - DONE; - } - else if (TARGET_V9) - { - if (gen_v9_scc (EQ, operands)) - DONE; - /* fall through */ - } - FAIL; -}) - -;; ??? v9: Operand 0 needs a mode, so SImode was chosen. -;; However, the code handles both SImode and DImode. -(define_expand "sne" - [(set (match_operand:SI 0 "int_register_operand" "") - (ne:SI (match_dup 1) (const_int 0)))] - "" -{ - if (GET_MODE (sparc_compare_op0) == SImode) - { - rtx pat; - - if (GET_MODE (operands[0]) == SImode) - pat = gen_snesi_special (operands[0], sparc_compare_op0, - sparc_compare_op1); - else if (! TARGET_ARCH64) - FAIL; - else - pat = gen_snesi_special_extend (operands[0], sparc_compare_op0, - sparc_compare_op1); - emit_insn (pat); - DONE; - } - else if (GET_MODE (sparc_compare_op0) == DImode) - { - rtx pat; - - if (! TARGET_ARCH64) - FAIL; - else if (GET_MODE (operands[0]) == SImode) - pat = gen_snedi_special_trunc (operands[0], sparc_compare_op0, - sparc_compare_op1); - else - pat = gen_snedi_special (operands[0], sparc_compare_op0, - sparc_compare_op1); - emit_insn (pat); - DONE; - } - else if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD) - { - enum rtx_code code - = sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, NE); - gcc_assert (code == NE); - emit_insn (gen_sne (operands[0])); - DONE; - } - else if (TARGET_V9) - { - if (gen_v9_scc (NE, operands)) - DONE; - /* fall through */ - } - FAIL; -}) - -(define_expand "sgt" - [(set (match_operand:SI 0 "int_register_operand" "") - (gt:SI (match_dup 1) (const_int 0)))] - "" -{ - if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD) - { - enum rtx_code code - = sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, GT); - gcc_assert (code == NE); - emit_insn (gen_sne (operands[0])); - DONE; - } - else if (TARGET_V9) - { - if (gen_v9_scc (GT, operands)) - DONE; - /* fall through */ - } - FAIL; -}) - -(define_expand "slt" - [(set (match_operand:SI 0 "int_register_operand" "") - (lt:SI (match_dup 1) (const_int 0)))] - "" -{ - if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD) - { - enum rtx_code code - = sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, LT); - gcc_assert (code == NE); - emit_insn (gen_sne (operands[0])); - DONE; - } - else if (TARGET_V9) - { - if (gen_v9_scc (LT, operands)) - DONE; - /* fall through */ - } - FAIL; -}) - -(define_expand "sge" - [(set (match_operand:SI 0 "int_register_operand" "") - (ge:SI (match_dup 1) (const_int 0)))] - "" -{ - if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD) - { - enum rtx_code code - = sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, GE); - gcc_assert (code == NE); - emit_insn (gen_sne (operands[0])); - DONE; - } - else if (TARGET_V9) - { - if (gen_v9_scc (GE, operands)) - DONE; - /* fall through */ - } - FAIL; -}) - -(define_expand "sle" - [(set (match_operand:SI 0 "int_register_operand" "") - (le:SI (match_dup 1) (const_int 0)))] - "" -{ - if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD) - { - enum rtx_code code - = sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, LE); - gcc_assert (code == NE); - emit_insn (gen_sne (operands[0])); - DONE; - } - else if (TARGET_V9) - { - if (gen_v9_scc (LE, operands)) - DONE; - /* fall through */ - } - FAIL; -}) - -(define_expand "sgtu" - [(set (match_operand:SI 0 "int_register_operand" "") - (gtu:SI (match_dup 1) (const_int 0)))] - "" -{ - if (! TARGET_V9) - { - rtx tem, pat; - - /* We can do ltu easily, so if both operands are registers, swap them and - do a LTU. */ - if ((GET_CODE (sparc_compare_op0) == REG - || GET_CODE (sparc_compare_op0) == SUBREG) - && (GET_CODE (sparc_compare_op1) == REG - || GET_CODE (sparc_compare_op1) == SUBREG)) - { - tem = sparc_compare_op0; - sparc_compare_op0 = sparc_compare_op1; - sparc_compare_op1 = tem; - pat = gen_sltu (operands[0]); - if (pat == NULL_RTX) - FAIL; - emit_insn (pat); - DONE; - } - } - else - { - if (gen_v9_scc (GTU, operands)) - DONE; - } - FAIL; -}) - -(define_expand "sltu" - [(set (match_operand:SI 0 "int_register_operand" "") - (ltu:SI (match_dup 1) (const_int 0)))] - "" -{ - if (TARGET_V9) - { - if (gen_v9_scc (LTU, operands)) - DONE; - } - operands[1] = gen_compare_reg (LTU); -}) - -(define_expand "sgeu" - [(set (match_operand:SI 0 "int_register_operand" "") - (geu:SI (match_dup 1) (const_int 0)))] - "" -{ - if (TARGET_V9) - { - if (gen_v9_scc (GEU, operands)) - DONE; - } - operands[1] = gen_compare_reg (GEU); -}) - -(define_expand "sleu" - [(set (match_operand:SI 0 "int_register_operand" "") - (leu:SI (match_dup 1) (const_int 0)))] - "" -{ - if (! TARGET_V9) - { - rtx tem, pat; - - /* We can do geu easily, so if both operands are registers, swap them and - do a GEU. */ - if ((GET_CODE (sparc_compare_op0) == REG - || GET_CODE (sparc_compare_op0) == SUBREG) - && (GET_CODE (sparc_compare_op1) == REG - || GET_CODE (sparc_compare_op1) == SUBREG)) - { - tem = sparc_compare_op0; - sparc_compare_op0 = sparc_compare_op1; - sparc_compare_op1 = tem; - pat = gen_sgeu (operands[0]); - if (pat == NULL_RTX) - FAIL; - emit_insn (pat); - DONE; - } - } - else - { - if (gen_v9_scc (LEU, operands)) - DONE; - } - FAIL; -}) ;; Now the DEFINE_INSNs for the scc cases. @@ -1275,344 +916,51 @@ ;; These control RTL generation for conditional jump insns -;; The quad-word fp compare library routines all return nonzero to indicate -;; true, which is different from the equivalent libgcc routines, so we must -;; handle them specially here. - -(define_expand "beq" - [(set (pc) - (if_then_else (eq (match_dup 1) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" -{ - if (TARGET_ARCH64 && sparc_compare_op1 == const0_rtx - && GET_CODE (sparc_compare_op0) == REG - && GET_MODE (sparc_compare_op0) == DImode) - { - emit_v9_brxx_insn (EQ, sparc_compare_op0, operands[0]); - DONE; - } - else if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD) - { - enum rtx_code code - = sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, EQ); - gcc_assert (code == NE); - emit_jump_insn (gen_bne (operands[0])); - DONE; - } - operands[1] = gen_compare_reg (EQ); -}) - -(define_expand "bne" - [(set (pc) - (if_then_else (ne (match_dup 1) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" -{ - if (TARGET_ARCH64 && sparc_compare_op1 == const0_rtx - && GET_CODE (sparc_compare_op0) == REG - && GET_MODE (sparc_compare_op0) == DImode) - { - emit_v9_brxx_insn (NE, sparc_compare_op0, operands[0]); - DONE; - } - else if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD) - { - enum rtx_code code - = sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, NE); - gcc_assert (code == NE); - emit_jump_insn (gen_bne (operands[0])); - DONE; - } - operands[1] = gen_compare_reg (NE); -}) - -(define_expand "bgt" - [(set (pc) - (if_then_else (gt (match_dup 1) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" -{ - if (TARGET_ARCH64 && sparc_compare_op1 == const0_rtx - && GET_CODE (sparc_compare_op0) == REG - && GET_MODE (sparc_compare_op0) == DImode) - { - emit_v9_brxx_insn (GT, sparc_compare_op0, operands[0]); - DONE; - } - else if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD) - { - enum rtx_code code - = sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, GT); - gcc_assert (code == NE); - emit_jump_insn (gen_bne (operands[0])); - DONE; - } - operands[1] = gen_compare_reg (GT); -}) - -(define_expand "bgtu" - [(set (pc) - (if_then_else (gtu (match_dup 1) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" -{ - operands[1] = gen_compare_reg (GTU); -}) - -(define_expand "blt" - [(set (pc) - (if_then_else (lt (match_dup 1) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" -{ - if (TARGET_ARCH64 && sparc_compare_op1 == const0_rtx - && GET_CODE (sparc_compare_op0) == REG - && GET_MODE (sparc_compare_op0) == DImode) - { - emit_v9_brxx_insn (LT, sparc_compare_op0, operands[0]); - DONE; - } - else if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD) - { - enum rtx_code code - = sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, LT); - gcc_assert (code == NE); - emit_jump_insn (gen_bne (operands[0])); - DONE; - } - operands[1] = gen_compare_reg (LT); -}) - -(define_expand "bltu" - [(set (pc) - (if_then_else (ltu (match_dup 1) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" -{ - operands[1] = gen_compare_reg (LTU); -}) - -(define_expand "bge" - [(set (pc) - (if_then_else (ge (match_dup 1) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" -{ - if (TARGET_ARCH64 && sparc_compare_op1 == const0_rtx - && GET_CODE (sparc_compare_op0) == REG - && GET_MODE (sparc_compare_op0) == DImode) - { - emit_v9_brxx_insn (GE, sparc_compare_op0, operands[0]); - DONE; - } - else if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD) - { - enum rtx_code code - = sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, GE); - gcc_assert (code == NE); - emit_jump_insn (gen_bne (operands[0])); - DONE; - } - operands[1] = gen_compare_reg (GE); -}) - -(define_expand "bgeu" - [(set (pc) - (if_then_else (geu (match_dup 1) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" -{ - operands[1] = gen_compare_reg (GEU); -}) - -(define_expand "ble" +(define_expand "cbranchcc4" [(set (pc) - (if_then_else (le (match_dup 1) (const_int 0)) - (label_ref (match_operand 0 "" "")) + (if_then_else (match_operator 0 "comparison_operator" + [(match_operand 1 "compare_operand" "") + (match_operand 2 "const_zero_operand" "")]) + (label_ref (match_operand 3 "" "")) (pc)))] "" -{ - if (TARGET_ARCH64 && sparc_compare_op1 == const0_rtx - && GET_CODE (sparc_compare_op0) == REG - && GET_MODE (sparc_compare_op0) == DImode) - { - emit_v9_brxx_insn (LE, sparc_compare_op0, operands[0]); - DONE; - } - else if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD) - { - enum rtx_code code - = sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, LE); - gcc_assert (code == NE); - emit_jump_insn (gen_bne (operands[0])); - DONE; - } - operands[1] = gen_compare_reg (LE); -}) - -(define_expand "bleu" - [(set (pc) - (if_then_else (leu (match_dup 1) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" -{ - operands[1] = gen_compare_reg (LEU); -}) - -(define_expand "bunordered" - [(set (pc) - (if_then_else (unordered (match_dup 1) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" -{ - if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD) - { - enum rtx_code code - = sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, UNORDERED); - gcc_assert (code == EQ); - emit_jump_insn (gen_beq (operands[0])); - DONE; - } - operands[1] = gen_compare_reg (UNORDERED); -}) - -(define_expand "bordered" - [(set (pc) - (if_then_else (ordered (match_dup 1) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" -{ - if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD) - { - enum rtx_code code - = sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, ORDERED); - gcc_assert (code == NE); - emit_jump_insn (gen_bne (operands[0])); - DONE; - } - operands[1] = gen_compare_reg (ORDERED); -}) - -(define_expand "bungt" - [(set (pc) - (if_then_else (ungt (match_dup 1) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" -{ - if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD) - { - enum rtx_code code - = sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, UNGT); - gcc_assert (code == GT); - emit_jump_insn (gen_bgt (operands[0])); - DONE; - } - operands[1] = gen_compare_reg (UNGT); -}) + "") -(define_expand "bunlt" - [(set (pc) - (if_then_else (unlt (match_dup 1) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] +(define_expand "cbranchsi4" + [(use (match_operator 0 "comparison_operator" + [(match_operand:SI 1 "compare_operand" "") + (match_operand:SI 2 "arith_operand" "")])) + (use (match_operand 3 ""))] "" { - if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD) - { - enum rtx_code code - = sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, UNLT); - gcc_assert (code == NE); - emit_jump_insn (gen_bne (operands[0])); - DONE; - } - operands[1] = gen_compare_reg (UNLT); + if (GET_CODE (operands[1]) == ZERO_EXTRACT && operands[2] != const0_rtx) + operands[1] = force_reg (SImode, operands[1]); + emit_conditional_branch_insn (operands); + DONE; }) -(define_expand "buneq" - [(set (pc) - (if_then_else (uneq (match_dup 1) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" +(define_expand "cbranchdi4" + [(use (match_operator 0 "comparison_operator" + [(match_operand:DI 1 "compare_operand" "") + (match_operand:DI 2 "arith_operand" "")])) + (use (match_operand 3 ""))] + "TARGET_ARCH64" { - if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD) - { - enum rtx_code code - = sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, UNEQ); - gcc_assert (code == EQ); - emit_jump_insn (gen_beq (operands[0])); - DONE; - } - operands[1] = gen_compare_reg (UNEQ); + if (GET_CODE (operands[1]) == ZERO_EXTRACT && operands[2] != const0_rtx) + operands[1] = force_reg (DImode, operands[1]); + emit_conditional_branch_insn (operands); + DONE; }) -(define_expand "bunge" - [(set (pc) - (if_then_else (unge (match_dup 1) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" -{ - if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD) - { - enum rtx_code code - = sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, UNGE); - gcc_assert (code == NE); - emit_jump_insn (gen_bne (operands[0])); - DONE; - } - operands[1] = gen_compare_reg (UNGE); -}) +(define_expand "cbranch<F:mode>4" + [(use (match_operator 0 "comparison_operator" + [(match_operand:F 1 "register_operand" "") + (match_operand:F 2 "register_operand" "")])) + (use (match_operand 3 ""))] + "TARGET_FPU" + { emit_conditional_branch_insn (operands); DONE; }) -(define_expand "bunle" - [(set (pc) - (if_then_else (unle (match_dup 1) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" -{ - if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD) - { - enum rtx_code code - = sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, UNLE); - gcc_assert (code == NE); - emit_jump_insn (gen_bne (operands[0])); - DONE; - } - operands[1] = gen_compare_reg (UNLE); -}) -(define_expand "bltgt" - [(set (pc) - (if_then_else (ltgt (match_dup 1) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" -{ - if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD) - { - enum rtx_code code - = sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, LTGT); - gcc_assert (code == NE); - emit_jump_insn (gen_bne (operands[0])); - DONE; - } - operands[1] = gen_compare_reg (LTGT); -}) - ;; Now match both normal and inverted jump. ;; XXX fpcmp nop braindamage @@ -1755,8 +1103,6 @@ (set_attr "branch_type" "reg")]) -(define_mode_iterator P [(SI "Pmode == SImode") (DI "Pmode == DImode")]) - ;; Load in operand 0 the (absolute) address of operand 1, which is a symbolic ;; value subject to a PC-relative relocation. Operand 2 is a helper function ;; that adds the PC value at the call point to operand 0. @@ -2393,9 +1739,6 @@ ;; Floating point and vector move instructions -;; We don't define V1SI because SI should work just fine. -(define_mode_iterator V32 [SF V2HI V4QI]) - ;; Yes, you guessed it right, the former movsf expander. (define_expand "mov<V32:mode>" [(set (match_operand:V32 0 "nonimmediate_operand" "") @@ -2530,8 +1873,6 @@ [(set (match_dup 0) (high:SF (match_dup 1))) (set (match_dup 0) (lo_sum:SF (match_dup 0) (match_dup 1)))]) -(define_mode_iterator V64 [DF V2SI V4HI V8QI]) - ;; Yes, you again guessed it right, the former movdf expander. (define_expand "mov<V64:mode>" [(set (match_operand:V64 0 "nonimmediate_operand" "") @@ -3073,8 +2414,6 @@ ;; 3 contains the constant if one is present, but we handle either for ;; generality (sparc.c puts a constant in operand 2). -(define_mode_iterator I [QI HI SI DI]) - (define_expand "mov<I:mode>cc" [(set (match_operand:I 0 "register_operand" "") (if_then_else:I (match_operand 1 "comparison_operator" "") @@ -3083,21 +2422,27 @@ "TARGET_V9 && !(<I:MODE>mode == DImode && TARGET_ARCH32)" { enum rtx_code code = GET_CODE (operands[1]); + rtx cc_reg; - if (GET_MODE (sparc_compare_op0) == DImode + if (GET_MODE (XEXP (operands[1], 0)) == DImode && ! TARGET_ARCH64) FAIL; - if (sparc_compare_op1 == const0_rtx - && GET_CODE (sparc_compare_op0) == REG - && GET_MODE (sparc_compare_op0) == DImode + if (GET_MODE (XEXP (operands[1], 0)) == TFmode && !TARGET_HARD_QUAD) + operands[1] + = sparc_emit_float_lib_cmp (XEXP (operands[1], 0), XEXP (operands[1], 1), + GET_CODE (operands[1])); + + if (XEXP (operands[1], 1) == const0_rtx + && GET_CODE (XEXP (operands[1], 0)) == REG + && GET_MODE (XEXP (operands[1], 0)) == DImode && v9_regcmp_p (code)) - operands[1] = gen_rtx_fmt_ee (code, DImode, sparc_compare_op0, const0_rtx); + cc_reg = XEXP (operands[1], 0); else - operands[1] = gen_compare_operator (code); -}) + cc_reg = gen_compare_reg (operands[1]); -(define_mode_iterator F [SF DF TF]) + operands[1] = gen_rtx_fmt_ee (code, GET_MODE (cc_reg), cc_reg, const0_rtx); +}) (define_expand "mov<F:mode>cc" [(set (match_operand:F 0 "register_operand" "") @@ -3107,18 +2452,26 @@ "TARGET_V9 && TARGET_FPU" { enum rtx_code code = GET_CODE (operands[1]); + rtx cc_reg; - if (GET_MODE (sparc_compare_op0) == DImode + if (GET_MODE (XEXP (operands[1], 0)) == DImode && ! TARGET_ARCH64) FAIL; - if (sparc_compare_op1 == const0_rtx - && GET_CODE (sparc_compare_op0) == REG - && GET_MODE (sparc_compare_op0) == DImode + if (GET_MODE (XEXP (operands[1], 0)) == TFmode && !TARGET_HARD_QUAD) + operands[1] + = sparc_emit_float_lib_cmp (XEXP (operands[1], 0), XEXP (operands[1], 1), + GET_CODE (operands[1])); + + if (XEXP (operands[1], 1) == const0_rtx + && GET_CODE (XEXP (operands[1], 0)) == REG + && GET_MODE (XEXP (operands[1], 0)) == DImode && v9_regcmp_p (code)) - operands[1] = gen_rtx_fmt_ee (code, DImode, sparc_compare_op0, const0_rtx); + cc_reg = XEXP (operands[1], 0); else - operands[1] = gen_compare_operator (code); + cc_reg = gen_compare_reg (operands[1]); + + operands[1] = gen_rtx_fmt_ee (code, GET_MODE (cc_reg), cc_reg, const0_rtx); }) ;; Conditional move define_insns @@ -5133,9 +4486,6 @@ ;; We define DImode `and' so with DImode `not' we can get ;; DImode `andn'. Other combinations are possible. -(define_mode_iterator V64I [DI V2SI V4HI V8QI]) -(define_mode_iterator V32I [SI V2HI V4QI]) - (define_expand "and<V64I:mode>3" [(set (match_operand:V64I 0 "register_operand" "") (and:V64I (match_operand:V64I 1 "arith_double_operand" "") @@ -7434,14 +6784,28 @@ "ta\t5" [(set_attr "type" "trap")]) -(define_expand "conditional_trap" - [(trap_if (match_operator 0 "noov_compare_operator" [(match_dup 2) (match_dup 3)]) - (match_operand:SI 1 "arith_operand" ""))] +(define_expand "ctrapsi4" + [(trap_if (match_operator 0 "noov_compare_operator" + [(match_operand:SI 1 "compare_operand" "") + (match_operand:SI 2 "arith_operand" "")]) + (match_operand 3 ""))] "" - "operands[2] = gen_compare_reg (GET_CODE (operands[0])); - if (GET_MODE (operands[2]) != CCmode && GET_MODE (operands[2]) != CCXmode) + "operands[1] = gen_compare_reg (operands[0]); + if (GET_MODE (operands[1]) != CCmode && GET_MODE (operands[1]) != CCXmode) FAIL; - operands[3] = const0_rtx;") + operands[2] = const0_rtx;") + +(define_expand "ctrapdi4" + [(trap_if (match_operator 0 "noov_compare_operator" + [(match_operand:DI 1 "compare_operand" "") + (match_operand:DI 2 "arith_operand" "")]) + (match_operand 3 ""))] + "TARGET_ARCH64" + "operands[1] = gen_compare_reg (operands[0]); + if (GET_MODE (operands[1]) != CCmode && GET_MODE (operands[1]) != CCXmode) + FAIL; + operands[2] = const0_rtx;") + (define_insn "" [(trap_if (match_operator 0 "noov_compare_operator" [(reg:CC 100) (const_int 0)]) @@ -8071,6 +7435,7 @@ (match_operand 2 "" "")] "" { + rtx result, test; #ifdef TARGET_THREAD_SSP_OFFSET rtx tlsreg = gen_rtx_REG (Pmode, 7); rtx addr = gen_rtx_PLUS (Pmode, tlsreg, GEN_INT (TARGET_THREAD_SSP_OFFSET)); @@ -8078,18 +7443,18 @@ #endif if (TARGET_ARCH64) { - rtx temp = gen_reg_rtx (Pmode); - emit_insn (gen_stack_protect_testdi (temp, operands[0], operands[1])); - sparc_compare_op0 = temp; - sparc_compare_op1 = const0_rtx; + result = gen_reg_rtx (Pmode); + emit_insn (gen_stack_protect_testdi (result, operands[0], operands[1])); + test = gen_rtx_EQ (VOIDmode, result, const0_rtx); + emit_jump_insn (gen_cbranchdi4 (test, result, const0_rtx, operands[2])); } else { emit_insn (gen_stack_protect_testsi (operands[0], operands[1])); - sparc_compare_op0 = gen_rtx_REG (CCmode, SPARC_ICC_REG); - sparc_compare_op1 = const0_rtx; + result = gen_rtx_REG (CCmode, SPARC_ICC_REG); + test = gen_rtx_EQ (VOIDmode, result, const0_rtx); + emit_jump_insn (gen_cbranchcc4 (test, result, const0_rtx, operands[2])); } - emit_jump_insn (gen_beq (operands[2])); DONE; }) diff --git a/gcc/config/spu/spu-protos.h b/gcc/config/spu/spu-protos.h index 06e02ba0b48..3e2600b996b 100644 --- a/gcc/config/spu/spu-protos.h +++ b/gcc/config/spu/spu-protos.h @@ -28,8 +28,7 @@ extern int valid_subreg (rtx op); extern void spu_expand_extv (rtx * ops, int unsignedp); extern void spu_expand_insv (rtx * ops); extern int spu_expand_block_move (rtx * ops); -extern void spu_emit_branch_or_set (int is_set, enum rtx_code code, - rtx * operands); +extern void spu_emit_branch_or_set (int is_set, rtx cmp, rtx * operands); extern int spu_emit_vector_cond_expr (rtx, rtx, rtx, rtx, rtx, rtx); extern HOST_WIDE_INT const_double_to_hwint (rtx x); extern rtx hwint_to_const_double (enum machine_mode mode, HOST_WIDE_INT v); diff --git a/gcc/config/spu/spu.c b/gcc/config/spu/spu.c index bb73622f9d5..f73bb217605 100644 --- a/gcc/config/spu/spu.c +++ b/gcc/config/spu/spu.c @@ -212,7 +212,6 @@ static void asm_file_start (void); static unsigned int spu_section_type_flags (tree, const char *, int); extern const char *reg_names[]; -rtx spu_compare_op0, spu_compare_op1; /* Which instruction set architecture to use. */ int spu_arch; @@ -844,42 +843,44 @@ int spu_comp_icode[12][3] = { WORD_MODE, we can generate better code in most cases if we do it ourselves. */ void -spu_emit_branch_or_set (int is_set, enum rtx_code code, rtx operands[]) +spu_emit_branch_or_set (int is_set, rtx cmp, rtx operands[]) { int reverse_compare = 0; int reverse_test = 0; rtx compare_result, eq_result; rtx comp_rtx, eq_rtx; - rtx target = operands[0]; enum machine_mode comp_mode; enum machine_mode op_mode; enum spu_comp_code scode, eq_code; enum insn_code ior_code; + enum rtx_code code = GET_CODE (cmp); + rtx op0 = XEXP (cmp, 0); + rtx op1 = XEXP (cmp, 1); int index; int eq_test = 0; - /* When spu_compare_op1 is a CONST_INT change (X >= C) to (X > C-1), + /* When op1 is a CONST_INT change (X >= C) to (X > C-1), and so on, to keep the constant in operand 1. */ - if (GET_CODE (spu_compare_op1) == CONST_INT) + if (GET_CODE (op1) == CONST_INT) { - HOST_WIDE_INT val = INTVAL (spu_compare_op1) - 1; - if (trunc_int_for_mode (val, GET_MODE (spu_compare_op0)) == val) + HOST_WIDE_INT val = INTVAL (op1) - 1; + if (trunc_int_for_mode (val, GET_MODE (op0)) == val) switch (code) { case GE: - spu_compare_op1 = GEN_INT (val); + op1 = GEN_INT (val); code = GT; break; case LT: - spu_compare_op1 = GEN_INT (val); + op1 = GEN_INT (val); code = LE; break; case GEU: - spu_compare_op1 = GEN_INT (val); + op1 = GEN_INT (val); code = GTU; break; case LTU: - spu_compare_op1 = GEN_INT (val); + op1 = GEN_INT (val); code = LEU; break; default: @@ -888,7 +889,7 @@ spu_emit_branch_or_set (int is_set, enum rtx_code code, rtx operands[]) } comp_mode = SImode; - op_mode = GET_MODE (spu_compare_op0); + op_mode = GET_MODE (op0); switch (code) { @@ -1012,18 +1013,18 @@ spu_emit_branch_or_set (int is_set, enum rtx_code code, rtx operands[]) abort (); } - if (GET_MODE (spu_compare_op1) == DFmode + if (GET_MODE (op1) == DFmode && (scode != SPU_GT && scode != SPU_EQ)) abort (); - if (is_set == 0 && spu_compare_op1 == const0_rtx - && (GET_MODE (spu_compare_op0) == SImode - || GET_MODE (spu_compare_op0) == HImode) && scode == SPU_EQ) + if (is_set == 0 && op1 == const0_rtx + && (GET_MODE (op0) == SImode + || GET_MODE (op0) == HImode) && scode == SPU_EQ) { /* Don't need to set a register with the result when we are comparing against zero and branching. */ reverse_test = !reverse_test; - compare_result = spu_compare_op0; + compare_result = op0; } else { @@ -1031,23 +1032,22 @@ spu_emit_branch_or_set (int is_set, enum rtx_code code, rtx operands[]) if (reverse_compare) { - rtx t = spu_compare_op1; - spu_compare_op1 = spu_compare_op0; - spu_compare_op0 = t; + rtx t = op1; + op1 = op0; + op0 = t; } if (spu_comp_icode[index][scode] == 0) abort (); if (!(*insn_data[spu_comp_icode[index][scode]].operand[1].predicate) - (spu_compare_op0, op_mode)) - spu_compare_op0 = force_reg (op_mode, spu_compare_op0); + (op0, op_mode)) + op0 = force_reg (op_mode, op0); if (!(*insn_data[spu_comp_icode[index][scode]].operand[2].predicate) - (spu_compare_op1, op_mode)) - spu_compare_op1 = force_reg (op_mode, spu_compare_op1); + (op1, op_mode)) + op1 = force_reg (op_mode, op1); comp_rtx = GEN_FCN (spu_comp_icode[index][scode]) (compare_result, - spu_compare_op0, - spu_compare_op1); + op0, op1); if (comp_rtx == 0) abort (); emit_insn (comp_rtx); @@ -1056,8 +1056,7 @@ spu_emit_branch_or_set (int is_set, enum rtx_code code, rtx operands[]) { eq_result = gen_reg_rtx (comp_mode); eq_rtx = GEN_FCN (spu_comp_icode[index][eq_code]) (eq_result, - spu_compare_op0, - spu_compare_op1); + op0, op1); if (eq_rtx == 0) abort (); emit_insn (eq_rtx); @@ -1088,13 +1087,14 @@ spu_emit_branch_or_set (int is_set, enum rtx_code code, rtx operands[]) else bcomp = gen_rtx_NE (comp_mode, compare_result, const0_rtx); - loc_ref = gen_rtx_LABEL_REF (VOIDmode, target); + loc_ref = gen_rtx_LABEL_REF (VOIDmode, operands[3]); emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx, gen_rtx_IF_THEN_ELSE (VOIDmode, bcomp, loc_ref, pc_rtx))); } else if (is_set == 2) { + rtx target = operands[0]; int compare_size = GET_MODE_BITSIZE (comp_mode); int target_size = GET_MODE_BITSIZE (GET_MODE (target)); enum machine_mode mode = mode_for_size (target_size, MODE_INT, 0); @@ -1129,6 +1129,7 @@ spu_emit_branch_or_set (int is_set, enum rtx_code code, rtx operands[]) } else { + rtx target = operands[0]; if (reverse_test) emit_insn (gen_rtx_SET (VOIDmode, compare_result, gen_rtx_NOT (comp_mode, compare_result))); diff --git a/gcc/config/spu/spu.h b/gcc/config/spu/spu.h index ed92715cd01..ddd464ac579 100644 --- a/gcc/config/spu/spu.h +++ b/gcc/config/spu/spu.h @@ -606,11 +606,6 @@ targetm.resolve_overloaded_builtin = spu_resolve_overloaded_builtin; \ } \ } while (0) -/* These are set by the cmp patterns and used while expanding - conditional branches. */ -extern GTY(()) rtx spu_compare_op0; -extern GTY(()) rtx spu_compare_op1; - /* Builtins. */ diff --git a/gcc/config/spu/spu.md b/gcc/config/spu/spu.md index bd6936fd9e3..db42db16111 100644 --- a/gcc/config/spu/spu.md +++ b/gcc/config/spu/spu.md @@ -3657,57 +3657,6 @@ selb\t%0,%4,%0,%3" [(set_attr "type" "br")]) -;; Compare insns are next. Note that the spu has two types of compares, -;; signed & unsigned, and one type of branch. -;; -;; Start with the DEFINE_EXPANDs to generate the rtl for compares, scc -;; insns, and branches. We store the operands of compares until we see -;; how it is used. - -(define_expand "cmp<mode>" - [(set (cc0) - (compare (match_operand:VQHSI 0 "spu_reg_operand" "") - (match_operand:VQHSI 1 "spu_nonmem_operand" "")))] - "" - { - spu_compare_op0 = operands[0]; - spu_compare_op1 = operands[1]; - DONE; - }) - -(define_expand "cmp<mode>" - [(set (cc0) - (compare (match_operand:DTI 0 "spu_reg_operand" "") - (match_operand:DTI 1 "spu_reg_operand" "")))] - "" - { - spu_compare_op0 = operands[0]; - spu_compare_op1 = operands[1]; - DONE; - }) - -(define_expand "cmp<mode>" - [(set (cc0) - (compare (match_operand:VSF 0 "spu_reg_operand" "") - (match_operand:VSF 1 "spu_reg_operand" "")))] - "" - { - spu_compare_op0 = operands[0]; - spu_compare_op1 = operands[1]; - DONE; - }) - -(define_expand "cmpdf" - [(set (cc0) - (compare (match_operand:DF 0 "register_operand" "") - (match_operand:DF 1 "register_operand" "")))] - "" - "{ - spu_compare_op0 = operands[0]; - spu_compare_op1 = operands[1]; - DONE; -}") - ;; vector conditional compare patterns (define_expand "vcond<mode>" [(set (match_operand:VCMP 0 "spu_reg_operand" "=r") @@ -3746,108 +3695,72 @@ selb\t%0,%4,%0,%3" ;; branch on condition -(define_expand "beq" - [(use (match_operand 0 "" ""))] - "" - { spu_emit_branch_or_set (0, EQ, operands); DONE; }) - -(define_expand "bne" - [(use (match_operand 0 "" ""))] - "" - { spu_emit_branch_or_set (0, NE, operands); DONE; }) - -(define_expand "bge" - [(use (match_operand 0 "" ""))] - "" - { spu_emit_branch_or_set (0, GE, operands); DONE; }) - -(define_expand "bgt" - [(use (match_operand 0 "" ""))] - "" - { spu_emit_branch_or_set (0, GT, operands); DONE; }) - -(define_expand "ble" - [(use (match_operand 0 "" ""))] - "" - { spu_emit_branch_or_set (0, LE, operands); DONE; }) - -(define_expand "blt" - [(use (match_operand 0 "" ""))] +(define_expand "cbranch<mode>4" + [(use (match_operator 0 "ordered_comparison_operator" + [(match_operand:VQHSI 1 "spu_reg_operand" "") + (match_operand:VQHSI 2 "spu_nonmem_operand" "")])) + (use (match_operand 3 ""))] "" - { spu_emit_branch_or_set (0, LT, operands); DONE; }) + { spu_emit_branch_or_set (0, operands[0], operands); DONE; }) -(define_expand "bgeu" - [(use (match_operand 0 "" ""))] +(define_expand "cbranch<mode>4" + [(use (match_operator 0 "ordered_comparison_operator" + [(match_operand:DTI 1 "spu_reg_operand" "") + (match_operand:DTI 2 "spu_reg_operand" "")])) + (use (match_operand 3 ""))] "" - { spu_emit_branch_or_set (0, GEU, operands); DONE; }) + { spu_emit_branch_or_set (0, operands[0], operands); DONE; }) -(define_expand "bgtu" - [(use (match_operand 0 "" ""))] +(define_expand "cbranch<mode>4" + [(use (match_operator 0 "ordered_comparison_operator" + [(match_operand:VSF 1 "spu_reg_operand" "") + (match_operand:VSF 2 "spu_reg_operand" "")])) + (use (match_operand 3 ""))] "" - { spu_emit_branch_or_set (0, GTU, operands); DONE; }) + { spu_emit_branch_or_set (0, operands[0], operands); DONE; }) -(define_expand "bleu" - [(use (match_operand 0 "" ""))] +(define_expand "cbranchdf4" + [(use (match_operator 0 "ordered_comparison_operator" + [(match_operand:DF 1 "spu_reg_operand" "") + (match_operand:DF 2 "spu_reg_operand" "")])) + (use (match_operand 3 ""))] "" - { spu_emit_branch_or_set (0, LEU, operands); DONE; }) - -(define_expand "bltu" - [(use (match_operand 0 "" ""))] - "" - { spu_emit_branch_or_set (0, LTU, operands); DONE; }) + { spu_emit_branch_or_set (0, operands[0], operands); DONE; }) ;; set on condition -(define_expand "seq" - [(clobber (match_operand:SI 0 "spu_reg_operand" ""))] - "" - { spu_emit_branch_or_set (1, EQ, operands); DONE; }) - -(define_expand "sne" - [(clobber (match_operand:SI 0 "spu_reg_operand" ""))] - "" - { spu_emit_branch_or_set (1, NE, operands); DONE; }) - -(define_expand "sgt" - [(clobber (match_operand:SI 0 "spu_reg_operand" ""))] - "" - { spu_emit_branch_or_set (1, GT, operands); DONE; }) - -(define_expand "slt" - [(clobber (match_operand:SI 0 "spu_reg_operand" ""))] - "" - { spu_emit_branch_or_set (1, LT, operands); DONE; }) - -(define_expand "sge" - [(clobber (match_operand:SI 0 "spu_reg_operand" ""))] - "" - { spu_emit_branch_or_set (1, GE, operands); DONE; }) - -(define_expand "sle" - [(clobber (match_operand:SI 0 "spu_reg_operand" ""))] - "" - { spu_emit_branch_or_set (1, LE, operands); DONE; }) - -(define_expand "sgtu" - [(clobber (match_operand:SI 0 "spu_reg_operand" ""))] +(define_expand "cstore<mode>4" + [(use (match_operator 1 "ordered_comparison_operator" + [(match_operand:VQHSI 2 "spu_reg_operand" "") + (match_operand:VQHSI 3 "spu_nonmem_operand" "")])) + (clobber (match_operand:SI 0 "spu_reg_operand"))] "" - { spu_emit_branch_or_set (1, GTU, operands); DONE; }) + { spu_emit_branch_or_set (1, operands[1], operands); DONE; }) -(define_expand "sltu" - [(clobber (match_operand:SI 0 "spu_reg_operand" ""))] +(define_expand "cstore<mode>4" + [(use (match_operator 1 "ordered_comparison_operator" + [(match_operand:DTI 2 "spu_reg_operand" "") + (match_operand:DTI 3 "spu_reg_operand" "")])) + (clobber (match_operand:SI 0 "spu_reg_operand"))] "" - { spu_emit_branch_or_set (1, LTU, operands); DONE; }) + { spu_emit_branch_or_set (1, operands[1], operands); DONE; }) -(define_expand "sgeu" - [(clobber (match_operand:SI 0 "spu_reg_operand" ""))] +(define_expand "cstore<mode>4" + [(use (match_operator 1 "ordered_comparison_operator" + [(match_operand:VSF 2 "spu_reg_operand" "") + (match_operand:VSF 3 "spu_reg_operand" "")])) + (clobber (match_operand:SI 0 "spu_reg_operand"))] "" - { spu_emit_branch_or_set (1, GEU, operands); DONE; }) + { spu_emit_branch_or_set (1, operands[1], operands); DONE; }) -(define_expand "sleu" - [(clobber (match_operand:SI 0 "spu_reg_operand" ""))] +(define_expand "cstoredf4" + [(use (match_operator 1 "ordered_comparison_operator" + [(match_operand:DF 2 "spu_reg_operand" "") + (match_operand:DF 3 "spu_reg_operand" "")])) + (clobber (match_operand:SI 0 "spu_reg_operand"))] "" - { spu_emit_branch_or_set (1, LEU, operands); DONE; }) + { spu_emit_branch_or_set (1, operands[1], operands); DONE; }) ;; conditional move @@ -3863,12 +3776,12 @@ selb\t%0,%4,%0,%3" (define_expand "mov<mode>cc" [(set (match_operand:ALL 0 "spu_reg_operand" "") - (if_then_else:ALL (match_operand 1 "comparison_operator" "") + (if_then_else:ALL (match_operand 1 "ordered_comparison_operator" "") (match_operand:ALL 2 "spu_reg_operand" "") (match_operand:ALL 3 "spu_reg_operand" "")))] "" { - spu_emit_branch_or_set(2, GET_CODE(operands[1]), operands); + spu_emit_branch_or_set(2, operands[1], operands); DONE; }) diff --git a/gcc/config/stormy16/stormy16-protos.h b/gcc/config/stormy16/stormy16-protos.h index 58cff8a26e9..bde411b4e3a 100644 --- a/gcc/config/stormy16/stormy16-protos.h +++ b/gcc/config/stormy16/stormy16-protos.h @@ -48,7 +48,7 @@ extern rtx xstormy16_function_value (const_tree, const_tree); #endif #ifdef RTX_CODE -extern void xstormy16_emit_cbranch (enum rtx_code, rtx); +extern void xstormy16_emit_cbranch (enum rtx_code, rtx, rtx, rtx); extern char *xstormy16_output_cbranch_hi (rtx, const char *, int, rtx); extern char *xstormy16_output_cbranch_si (rtx, const char *, int, rtx); extern int xstormy16_mode_dependent_address_p (rtx); diff --git a/gcc/config/stormy16/stormy16.c b/gcc/config/stormy16/stormy16.c index eefc58f0847..4d04cae95d9 100644 --- a/gcc/config/stormy16/stormy16.c +++ b/gcc/config/stormy16/stormy16.c @@ -61,11 +61,6 @@ static bool xstormy16_rtx_costs (rtx, int, int, int *, bool); static int xstormy16_address_cost (rtx, bool); static bool xstormy16_return_in_memory (const_tree, const_tree); -/* Define the information needed to generate branch and scc insns. This is - stored from the compare operation. */ -struct rtx_def * xstormy16_compare_op0; -struct rtx_def * xstormy16_compare_op1; - static GTY(()) section *bss100_section; /* Compute a (partial) cost for rtx X. Return true if the complete @@ -139,10 +134,8 @@ xstormy16_address_cost (rtx x, bool speed ATTRIBUTE_UNUSED) /* Emit a branch of kind CODE to location LOC. */ void -xstormy16_emit_cbranch (enum rtx_code code, rtx loc) +xstormy16_emit_cbranch (enum rtx_code code, rtx op0, rtx op1, rtx loc) { - rtx op0 = xstormy16_compare_op0; - rtx op1 = xstormy16_compare_op1; rtx condition_rtx, loc_ref, branch, cy_clobber; rtvec vec; enum machine_mode mode; @@ -159,10 +152,10 @@ xstormy16_emit_cbranch (enum rtx_code code, rtx loc) if (gt_p) lab = gen_label_rtx (); - xstormy16_emit_cbranch (unsigned_p ? LTU : LT, gt_p ? lab : loc); + xstormy16_emit_cbranch (unsigned_p ? LTU : LT, op0, op1, gt_p ? lab : loc); /* This should be generated as a comparison against the temporary created by the previous insn, but reload can't handle that. */ - xstormy16_emit_cbranch (gt_p ? NE : EQ, loc); + xstormy16_emit_cbranch (gt_p ? NE : EQ, op0, op1, loc); if (gt_p) emit_label (lab); return; @@ -171,6 +164,7 @@ xstormy16_emit_cbranch (enum rtx_code code, rtx loc) && (code == NE || code == EQ) && op1 != const0_rtx) { + rtx op0_word, op1_word; rtx lab = NULL_RTX; int num_words = GET_MODE_BITSIZE (mode) / BITS_PER_WORD; int i; @@ -180,17 +174,17 @@ xstormy16_emit_cbranch (enum rtx_code code, rtx loc) for (i = 0; i < num_words - 1; i++) { - xstormy16_compare_op0 = simplify_gen_subreg (word_mode, op0, mode, - i * UNITS_PER_WORD); - xstormy16_compare_op1 = simplify_gen_subreg (word_mode, op1, mode, - i * UNITS_PER_WORD); - xstormy16_emit_cbranch (NE, code == EQ ? lab : loc); + op0_word = simplify_gen_subreg (word_mode, op0, mode, + i * UNITS_PER_WORD); + op1_word = simplify_gen_subreg (word_mode, op1, mode, + i * UNITS_PER_WORD); + xstormy16_emit_cbranch (NE, op0_word, op1_word, code == EQ ? lab : loc); } - xstormy16_compare_op0 = simplify_gen_subreg (word_mode, op0, mode, - i * UNITS_PER_WORD); - xstormy16_compare_op1 = simplify_gen_subreg (word_mode, op1, mode, - i * UNITS_PER_WORD); - xstormy16_emit_cbranch (code, loc); + op0_word = simplify_gen_subreg (word_mode, op0, mode, + i * UNITS_PER_WORD); + op1_word = simplify_gen_subreg (word_mode, op1, mode, + i * UNITS_PER_WORD); + xstormy16_emit_cbranch (code, op0_word, op1_word, loc); if (code == EQ) emit_label (lab); diff --git a/gcc/config/stormy16/stormy16.h b/gcc/config/stormy16/stormy16.h index 675b94d9949..d626edf6e50 100644 --- a/gcc/config/stormy16/stormy16.h +++ b/gcc/config/stormy16/stormy16.h @@ -801,11 +801,4 @@ do { \ is responsible for updating the value of MORE (typically by (MORE)--). */ /* #define MD_SCHED_VARIABLE_ISSUE (FILE, VERBOSE, INSN, MORE) */ - -/* Define the information needed to generate branch and scc insns. This is - stored from the compare operation. Note that we can't use "rtx" here - since it hasn't been defined! */ - -extern struct rtx_def *xstormy16_compare_op0, *xstormy16_compare_op1; - /* End of xstormy16.h */ diff --git a/gcc/config/stormy16/stormy16.md b/gcc/config/stormy16/stormy16.md index 43e454804a1..9c86d43e627 100644 --- a/gcc/config/stormy16/stormy16.md +++ b/gcc/config/stormy16/stormy16.md @@ -736,40 +736,7 @@ operands[0], operands[2], operands[3]);" [(set_attr "length" "6,10") (set_attr "psw_operand" "clobber,clobber")]) - -;; :::::::::::::::::::: -;; :: -;; :: Comparisons -;; :: -;; :::::::::::::::::::: - -;; Note, we store the operands in the comparison insns, and use them later -;; when generating the branch or scc operation. - -;; First the routines called by the machine independent part of the compiler -(define_expand "cmphi" - [(set (cc0) - (compare (match_operand:HI 0 "register_operand" "") - (match_operand:HI 1 "nonmemory_operand" "")))] - "" - { - xstormy16_compare_op0 = operands[0]; - xstormy16_compare_op1 = operands[1]; - DONE; - }) -; There are no real SImode comparisons, but some can be emulated -; by performing a SImode subtract and looking at the condition flags. -(define_expand "cmpsi" - [(set (cc0) - (compare (match_operand:SI 0 "register_operand" "") - (match_operand:SI 1 "nonmemory_operand" "")))] - "" - { - xstormy16_compare_op0 = operands[0]; - xstormy16_compare_op1 = operands[1]; - DONE; - }) ;; :::::::::::::::::::: ;; :: @@ -777,55 +744,35 @@ ;; :: ;; :::::::::::::::::::: -(define_expand "beq" - [(use (match_operand 0 "" ""))] - "" - { xstormy16_emit_cbranch (EQ, operands[0]); DONE; }) - -(define_expand "bne" - [(use (match_operand 0 "" ""))] - "" - { xstormy16_emit_cbranch (NE, operands[0]); DONE; }) - -(define_expand "bge" - [(use (match_operand 0 "" ""))] - "" - { xstormy16_emit_cbranch (GE, operands[0]); DONE; }) - -(define_expand "bgt" - [(use (match_operand 0 "" ""))] - "" - { xstormy16_emit_cbranch (GT, operands[0]); DONE; }) - -(define_expand "ble" - [(use (match_operand 0 "" ""))] - "" - { xstormy16_emit_cbranch (LE, operands[0]); DONE; }) - -(define_expand "blt" - [(use (match_operand 0 "" ""))] - "" - { xstormy16_emit_cbranch (LT, operands[0]); DONE; }) - -(define_expand "bgeu" - [(use (match_operand 0 "" ""))] - "" - { xstormy16_emit_cbranch (GEU, operands[0]); DONE; }) - -(define_expand "bgtu" - [(use (match_operand 0 "" ""))] - "" - { xstormy16_emit_cbranch (GTU, operands[0]); DONE; }) - -(define_expand "bleu" - [(use (match_operand 0 "" ""))] +(define_expand "cbranchhi4" + [(set (pc) + (if_then_else (match_operator 0 "comparison_operator" + [(match_operand:HI 1 "register_operand" "") + (match_operand:HI 2 "nonmemory_operand" "")]) + (label_ref (match_operand 3 "" "")) + (pc))) + (clobber (reg:BI CARRY_REG))] "" - { xstormy16_emit_cbranch (LEU, operands[0]); DONE; }) + { + xstormy16_emit_cbranch (GET_CODE (operands[0]), operands[1], operands[2], + operands[3]); + DONE; +}) -(define_expand "bltu" - [(use (match_operand 0 "" ""))] +(define_expand "cbranchsi4" + [(set (pc) + (if_then_else (match_operator 0 "comparison_operator" + [(match_operand:SI 1 "register_operand" "") + (match_operand:SI 2 "nonmemory_operand" "")]) + (label_ref (match_operand 3 "" "")) + (pc))) + (clobber (reg:BI CARRY_REG))] "" - { xstormy16_emit_cbranch (LTU, operands[0]); DONE; }) + { + xstormy16_emit_cbranch (GET_CODE (operands[0]), operands[1], operands[2], + operands[3]); + DONE; +}) (define_insn "cbranchhi" [(set (pc) diff --git a/gcc/config/v850/v850.c b/gcc/config/v850/v850.c index a562202538b..f9e8a7dd8b0 100644 --- a/gcc/config/v850/v850.c +++ b/gcc/config/v850/v850.c @@ -464,6 +464,11 @@ v850_rtx_costs (rtx x, *total = 20; return true; + case ZERO_EXTRACT: + if (outer_code == COMPARE) + *total = 0; + return false; + default: return false; } diff --git a/gcc/config/v850/v850.md b/gcc/config/v850/v850.md index dad3cdd885b..69c8d881f89 100644 --- a/gcc/config/v850/v850.md +++ b/gcc/config/v850/v850.md @@ -227,9 +227,11 @@ ;; ---------------------------------------------------------------------- (define_insn "*v850_tst1" - [(set (cc0) (zero_extract:SI (match_operand:QI 0 "memory_operand" "m") - (const_int 1) - (match_operand:QI 1 "const_int_operand" "n")))] + [(set (cc0) + (compare (zero_extract:SI (match_operand:QI 0 "memory_operand" "m") + (const_int 1) + (match_operand:QI 1 "const_int_operand" "n")) + (const_int 0)))] "" "tst1 %1,%0" [(set_attr "length" "4") @@ -237,37 +239,52 @@ ;; This replaces ld.b;sar;andi with tst1;setf nz. -;; ??? The zero_extract sets the Z bit to the opposite of what one would -;; expect. This perhaps should be wrapped in a (eq: X (const_int 0)). - (define_split [(set (match_operand:SI 0 "register_operand" "") - (zero_extract:SI (match_operand:QI 1 "memory_operand" "") - (const_int 1) - (match_operand 2 "const_int_operand" "")))] - "" - [(set (cc0) (zero_extract:SI (match_dup 1) - (const_int 1) - (match_dup 2))) + (compare (zero_extract:SI (match_operand:QI 1 "memory_operand" "") + (const_int 1) + (match_operand 2 "const_int_operand" "")) + (const_int 0)))] + "" + [(set (cc0) (compare (zero_extract:SI (match_dup 1) + (const_int 1) + (match_dup 2)) + (const_int 0))) (set (match_dup 0) (ne:SI (cc0) (const_int 0)))]) -(define_insn "tstsi" - [(set (cc0) (match_operand:SI 0 "register_operand" "r"))] - "" - "cmp %.,%0" - [(set_attr "length" "2") - (set_attr "cc" "set_znv")]) +(define_expand "cbranchsi4" + [(set (cc0) + (compare (match_operand:SI 1 "register_operand" "") + (match_operand:SI 2 "reg_or_int5_operand" ""))) + (set (pc) + (if_then_else + (match_operator 0 "ordered_comparison_operator" [(cc0) + (const_int 0)]) + (label_ref (match_operand 3 "" "")) + (pc)))] + "") + +(define_expand "cstoresi4" + [(set (cc0) + (compare (match_operand:SI 2 "register_operand" "") + (match_operand:SI 3 "reg_or_int5_operand" ""))) + (set (match_operand:SI 0 "register_operand") + (match_operator:SI 1 "ordered_comparison_operator" [(cc0) + (const_int 0)]))] + "") -(define_insn "cmpsi" +(define_insn "*cmpsi" [(set (cc0) - (compare (match_operand:SI 0 "register_operand" "r,r") - (match_operand:SI 1 "reg_or_int5_operand" "r,J")))] + (compare (match_operand:SI 0 "register_operand" "r,r,r") + (match_operand:SI 1 "reg_or_int5_operand" "r,I,J")))] "" "@ cmp %1,%0 + cmp %.,%0 cmp %1,%0" - [(set_attr "length" "2,2") - (set_attr "cc" "compare")]) + [(set_attr "length" "2,2,2") + (set_attr "cc" "compare,set_znv,compare")]) + ;; ---------------------------------------------------------------------- ;; ADD INSTRUCTIONS @@ -688,110 +705,25 @@ ;; Scc INSTRUCTIONS ;; ----------------------------------------------------------------- -(define_insn "sle" - [(set (match_operand:SI 0 "register_operand" "=r") - (le:SI (cc0) (const_int 0)))] - "" - "* -{ - if ((cc_status.flags & CC_OVERFLOW_UNUSABLE) != 0) - return 0; - - return \"setf le,%0\"; -}" - [(set_attr "length" "4") - (set_attr "cc" "none_0hit")]) - -(define_insn "sleu" - [(set (match_operand:SI 0 "register_operand" "=r") - (leu:SI (cc0) (const_int 0)))] - "" - "setf nh,%0" - [(set_attr "length" "4") - (set_attr "cc" "none_0hit")]) - -(define_insn "sge" - [(set (match_operand:SI 0 "register_operand" "=r") - (ge:SI (cc0) (const_int 0)))] - "" - "* -{ - if ((cc_status.flags & CC_OVERFLOW_UNUSABLE) != 0) - return 0; - - return \"setf ge,%0\"; -}" - [(set_attr "length" "4") - (set_attr "cc" "none_0hit")]) - -(define_insn "sgeu" +(define_insn "*setcc" [(set (match_operand:SI 0 "register_operand" "=r") - (geu:SI (cc0) (const_int 0)))] - "" - "setf nl,%0" - [(set_attr "length" "4") - (set_attr "cc" "none_0hit")]) - -(define_insn "slt" - [(set (match_operand:SI 0 "register_operand" "=r") - (lt:SI (cc0) (const_int 0)))] - "" - "* -{ - if ((cc_status.flags & CC_OVERFLOW_UNUSABLE) != 0) - return 0; - - return \"setf lt,%0\"; -}" - [(set_attr "length" "4") - (set_attr "cc" "none_0hit")]) - -(define_insn "sltu" - [(set (match_operand:SI 0 "register_operand" "=r") - (ltu:SI (cc0) (const_int 0)))] - "" - "setf l,%0" - [(set_attr "length" "4") - (set_attr "cc" "none_0hit")]) - -(define_insn "sgt" - [(set (match_operand:SI 0 "register_operand" "=r") - (gt:SI (cc0) (const_int 0)))] + (match_operator:SI 1 "comparison_operator" + [(cc0) (const_int 0)]))] "" "* { - if ((cc_status.flags & CC_OVERFLOW_UNUSABLE) != 0) + if ((cc_status.flags & CC_OVERFLOW_UNUSABLE) != 0 + && (GET_CODE (operands[1]) == GT + || GET_CODE (operands[1]) == GE + || GET_CODE (operands[1]) == LE + || GET_CODE (operands[1]) == LT)) return 0; - return \"setf gt,%0\"; + return \"setf %c1,%0\"; }" [(set_attr "length" "4") (set_attr "cc" "none_0hit")]) -(define_insn "sgtu" - [(set (match_operand:SI 0 "register_operand" "=r") - (gtu:SI (cc0) (const_int 0)))] - "" - "setf h,%0" - [(set_attr "length" "4") - (set_attr "cc" "none_0hit")]) - -(define_insn "seq" - [(set (match_operand:SI 0 "register_operand" "=r") - (eq:SI (cc0) (const_int 0)))] - "" - "setf z,%0" - [(set_attr "length" "4") - (set_attr "cc" "none_0hit")]) - -(define_insn "sne" - [(set (match_operand:SI 0 "register_operand" "=r") - (ne:SI (cc0) (const_int 0)))] - "" - "setf nz,%0" - [(set_attr "length" "4") - (set_attr "cc" "none_0hit")]) - ;; ---------------------------------------------------------------------- ;; CONDITIONAL MOVE INSTRUCTIONS ;; ---------------------------------------------------------------------- @@ -800,25 +732,15 @@ ;; hide the fact that this instruction uses cc0. We do so by including the ;; compare instruction inside it. -;; ??? This is very ugly. The right way to do this is to modify cmpsi so -;; that it doesn't emit RTL, and then modify the bcc/scc patterns so that -;; they emit RTL for the compare instruction. Unfortunately, this requires -;; lots of changes that will be hard to sanitize. So for now, cmpsi still -;; emits RTL, and I get the compare operands here from the previous insn. - (define_expand "movsicc" [(set (match_operand:SI 0 "register_operand" "=r") (if_then_else:SI - (match_operator 1 "comparison_operator" - [(match_dup 4) (match_dup 5)]) + (match_operand 1 "comparison_operator") (match_operand:SI 2 "reg_or_const_operand" "rJ") (match_operand:SI 3 "reg_or_const_operand" "rI")))] "TARGET_V850E" " { - rtx insn = get_last_insn_anywhere (); - rtx src; - if ( (GET_CODE (operands[2]) == CONST_INT && GET_CODE (operands[3]) == CONST_INT)) { @@ -845,28 +767,6 @@ if (GET_CODE (operands[3]) != REG) operands[3] = copy_to_mode_reg (SImode, operands[3]); } - gcc_assert (GET_CODE (insn) == INSN - && GET_CODE (PATTERN (insn)) == SET - && SET_DEST (PATTERN (insn)) == cc0_rtx); - - src = SET_SRC (PATTERN (insn)); - - switch (GET_CODE (src)) - { - case COMPARE: - operands[4] = XEXP (src, 0); - operands[5] = XEXP (src, 1); - break; - - case REG: - case SUBREG: - operands[4] = src; - operands[5] = const0_rtx; - break; - - default: - gcc_unreachable (); - } }") ;; ??? Clobbering the condition codes is overkill. @@ -1037,96 +937,6 @@ ;; Conditional jump instructions -(define_expand "ble" - [(set (pc) - (if_then_else (le (cc0) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "") - -(define_expand "bleu" - [(set (pc) - (if_then_else (leu (cc0) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "") - -(define_expand "bge" - [(set (pc) - (if_then_else (ge (cc0) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "") - -(define_expand "bgeu" - [(set (pc) - (if_then_else (geu (cc0) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "") - -(define_expand "blt" - [(set (pc) - (if_then_else (lt (cc0) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "") - -(define_expand "bltu" - [(set (pc) - (if_then_else (ltu (cc0) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "") - -(define_expand "bgt" - [(set (pc) - (if_then_else (gt (cc0) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "") - -(define_expand "bgtu" - [(set (pc) - (if_then_else (gtu (cc0) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "") - -(define_expand "beq" - [(set (pc) - (if_then_else (eq (cc0) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "") - -(define_expand "bne" - [(set (pc) - (if_then_else (ne (cc0) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "") - (define_insn "*branch_normal" [(set (pc) (if_then_else (match_operator 1 "comparison_operator" @@ -1241,14 +1051,16 @@ { rtx reg = gen_reg_rtx (SImode); rtx tableaddress = gen_reg_rtx (SImode); + rtx test; rtx mem; /* Subtract the lower bound from the index. */ emit_insn (gen_subsi3 (reg, operands[0], operands[1])); - /* Compare the result against the number of table entries. */ - emit_insn (gen_cmpsi (reg, operands[2])); - /* Branch to the default label if out of range of the table. */ - emit_jump_insn (gen_bgtu (operands[4])); + + /* Compare the result against the number of table entries; + branch to the default label if out of range of the table. */ + test = gen_rtx_fmt_ee (GTU, VOIDmode, reg, operands[2]); + emit_jump_insn (gen_cbranchsi4 (test, reg, operands[2], operands[4])); /* Shift index for the table array access. */ emit_insn (gen_ashlsi3 (reg, reg, GEN_INT (TARGET_BIG_SWITCH ? 2 : 1))); diff --git a/gcc/config/vax/vax-protos.h b/gcc/config/vax/vax-protos.h index 9b43d4f86e9..c038b300d91 100644 --- a/gcc/config/vax/vax-protos.h +++ b/gcc/config/vax/vax-protos.h @@ -26,6 +26,7 @@ extern bool legitimate_address_p (enum machine_mode, rtx, bool); extern bool vax_mode_dependent_address_p (rtx); #ifdef RTX_CODE +extern const char *cond_name (rtx); extern bool adjacent_operands_p (rtx, rtx, enum machine_mode); extern const char *rev_cond_name (rtx); extern void print_operand_address (FILE *, rtx); @@ -35,7 +36,6 @@ extern void vax_expand_addsub_di_operands (rtx *, enum rtx_code); extern const char * vax_output_int_move (rtx, rtx *, enum machine_mode); extern const char * vax_output_int_add (rtx, rtx *, enum machine_mode); extern const char * vax_output_int_subtract (rtx, rtx *, enum machine_mode); -extern const char * vax_output_conditional_branch (enum rtx_code); extern const char * vax_output_movmemsi (rtx, rtx *); #endif /* RTX_CODE */ diff --git a/gcc/config/vax/vax.c b/gcc/config/vax/vax.c index e91696947e6..cd66bb4e2d7 100644 --- a/gcc/config/vax/vax.c +++ b/gcc/config/vax/vax.c @@ -428,6 +428,8 @@ print_operand (FILE *file, rtx x, int code) fputc (ASM_DOUBLE_CHAR, file); else if (code == '|') fputs (REGISTER_PREFIX, file); + else if (code == 'c') + fputs (cond_name (x), file); else if (code == 'C') fputs (rev_cond_name (x), file); else if (code == 'D' && CONST_INT_P (x) && INTVAL (x) < 0) @@ -480,6 +482,37 @@ print_operand (FILE *file, rtx x, int code) } const char * +cond_name (rtx op) +{ + switch (GET_CODE (op)) + { + case NE: + return "neq"; + case EQ: + return "eql"; + case GE: + return "geq"; + case GT: + return "gtr"; + case LE: + return "leq"; + case LT: + return "lss"; + case GEU: + return "gequ"; + case GTU: + return "gtru"; + case LEU: + return "lequ"; + case LTU: + return "lssu"; + + default: + gcc_unreachable (); + } +} + +const char * rev_cond_name (rtx op) { switch (GET_CODE (op)) @@ -1516,27 +1549,6 @@ vax_output_int_subtract (rtx insn, rtx *operands, enum machine_mode mode) } } -/* Output a conditional branch. */ -const char * -vax_output_conditional_branch (enum rtx_code code) -{ - switch (code) - { - case EQ: return "jeql %l0"; - case NE: return "jneq %l0"; - case GT: return "jgtr %l0"; - case LT: return "jlss %l0"; - case GTU: return "jgtru %l0"; - case LTU: return "jlssu %l0"; - case GE: return "jgeq %l0"; - case LE: return "jleq %l0"; - case GEU: return "jgequ %l0"; - case LEU: return "jlequ %l0"; - default: - gcc_unreachable (); - } -} - /* True if X is an rtx for a constant that is a valid address. */ bool diff --git a/gcc/config/vax/vax.h b/gcc/config/vax/vax.h index 997029e0f62..7fa2fbb870e 100644 --- a/gcc/config/vax/vax.h +++ b/gcc/config/vax/vax.h @@ -802,6 +802,7 @@ enum reg_class { NO_REGS, ALL_REGS, LIM_REG_CLASSES }; VAX operand formatting codes: letter print + c direct branch condition C reverse branch condition D 64-bit immediate operand B the low 8 bits of the complement of a constant operand diff --git a/gcc/config/vax/vax.md b/gcc/config/vax/vax.md index da3ca48e90b..649f17e36ba 100644 --- a/gcc/config/vax/vax.md +++ b/gcc/config/vax/vax.md @@ -58,30 +58,16 @@ (include "constraints.md") (include "predicates.md") -;; We don't want to allow a constant operand for test insns because -;; (set (cc0) (const_int foo)) has no mode information. Such insns will -;; be folded while optimizing anyway. - -(define_insn "tst<mode>" - [(set (cc0) - (match_operand:VAXint 0 "nonimmediate_operand" "nrmT"))] - "" - "tst<VAXint:isfx> %0") - -(define_insn "tst<mode>" +(define_insn "*cmp<mode>" [(set (cc0) - (match_operand:VAXfp 0 "general_operand" "gF"))] + (compare (match_operand:VAXint 0 "nonimmediate_operand" "nrmT,nrmT") + (match_operand:VAXint 1 "general_operand" "I,nrmT")))] "" - "tst<VAXfp:fsfx> %0") - -(define_insn "cmp<mode>" - [(set (cc0) - (compare (match_operand:VAXint 0 "nonimmediate_operand" "nrmT") - (match_operand:VAXint 1 "general_operand" "nrmT")))] - "" - "cmp<VAXint:isfx> %0,%1") + "@ + tst<VAXint:isfx> %0 + cmp<VAXint:isfx> %0,%1") -(define_insn "cmp<mode>" +(define_insn "*cmp<mode>" [(set (cc0) (compare (match_operand:VAXfp 0 "general_operand" "gF,gF") (match_operand:VAXfp 1 "general_operand" "G,gF")))] @@ -92,8 +78,9 @@ (define_insn "*bit<mode>" [(set (cc0) - (and:VAXint (match_operand:VAXint 0 "general_operand" "nrmT") - (match_operand:VAXint 1 "general_operand" "nrmT")))] + (compare (and:VAXint (match_operand:VAXint 0 "general_operand" "nrmT") + (match_operand:VAXint 1 "general_operand" "nrmT")) + (const_int 0)))] "" "bit<VAXint:isfx> %0,%1") @@ -1078,21 +1065,45 @@ "jbr %l0") ;; Conditional jumps -(define_code_iterator any_cond [eq ne gt lt gtu ltu ge le geu leu]) -(define_insn "b<code>" +(define_expand "cbranch<mode>4" + [(set (cc0) + (compare (match_operand:VAXint 1 "nonimmediate_operand" "") + (match_operand:VAXint 2 "general_operand" ""))) + (set (pc) + (if_then_else + (match_operator 0 "ordered_comparison_operator" [(cc0) + (const_int 0)]) + (label_ref (match_operand 3 "" "")) + (pc)))] + "") + +(define_expand "cbranch<mode>4" + [(set (cc0) + (compare (match_operand:VAXfp 1 "general_operand" "") + (match_operand:VAXfp 2 "general_operand" ""))) + (set (pc) + (if_then_else + (match_operator 0 "ordered_comparison_operator" [(cc0) + (const_int 0)]) + (label_ref (match_operand 3 "" "")) + (pc)))] + "") + +(define_insn "*branch" [(set (pc) - (if_then_else (any_cond (cc0) - (const_int 0)) - (label_ref (match_operand 0 "" "")) + (if_then_else (match_operator 0 "ordered_comparison_operator" + [(cc0) + (const_int 0)]) + (label_ref (match_operand 1 "" "")) (pc)))] "" - "* return vax_output_conditional_branch (<CODE>);") + "j%c0 %l1") ;; Recognize reversed jumps. -(define_insn "" +(define_insn "*branch_reversed" [(set (pc) - (if_then_else (match_operator 0 "comparison_operator" + (if_then_else (match_operator 0 "ordered_comparison_operator" [(cc0) (const_int 0)]) (pc) @@ -1452,6 +1463,8 @@ (match_operand 4 "" "")] "" { + rtx test; + /* i = index - minimum_bound; But only if the lower bound is not already zero. */ if (operands[1] != const0_rtx) @@ -1463,9 +1476,9 @@ operands[0] = index; } - /* if (i > (maximum_bound - minimum_bound + 1) goto default; */ - emit_insn (gen_cmpsi (operands[0], operands[2])); - emit_jump_insn (gen_bgtu (operands[4])); + /* if (i > (maximum_bound - minimum_bound + 1)) goto default; */ + test = gen_rtx_fmt_ee (GTU, VOIDmode, operands[0], operands[2]); + emit_jump_insn (gen_cbranchsi4 (test, operands[0], operands[2], operands[4])); /* casesi (i, 0, table); */ emit_jump_insn (gen_casesi1 (operands[0], operands[2], operands[3])); diff --git a/gcc/config/xtensa/predicates.md b/gcc/config/xtensa/predicates.md index 2cb2a7d1757..27f058de796 100644 --- a/gcc/config/xtensa/predicates.md +++ b/gcc/config/xtensa/predicates.md @@ -167,6 +167,9 @@ (define_predicate "boolean_operator" (match_code "eq,ne")) +(define_predicate "xtensa_cstoresi_operator" + (match_code "eq,ne,gt,ge,lt,le")) + (define_predicate "tls_symbol_operand" (and (match_code "symbol_ref") (match_test "SYMBOL_REF_TLS_MODEL (op) != 0"))) diff --git a/gcc/config/xtensa/xtensa-protos.h b/gcc/config/xtensa/xtensa-protos.h index 5f8cd74fe36..76f10179c75 100644 --- a/gcc/config/xtensa/xtensa-protos.h +++ b/gcc/config/xtensa/xtensa-protos.h @@ -39,9 +39,9 @@ extern int smalloffset_mem_p (rtx); extern int constantpool_address_p (rtx); extern int constantpool_mem_p (rtx); extern void xtensa_extend_reg (rtx, rtx); -extern void xtensa_expand_conditional_branch (rtx *, enum rtx_code); +extern void xtensa_expand_conditional_branch (rtx *, enum machine_mode); extern int xtensa_expand_conditional_move (rtx *, int); -extern int xtensa_expand_scc (rtx *); +extern int xtensa_expand_scc (rtx *, enum machine_mode); extern int xtensa_expand_block_move (rtx *); extern void xtensa_split_operand_pair (rtx *, enum machine_mode); extern int xtensa_emit_move_sequence (rtx *, enum machine_mode); diff --git a/gcc/config/xtensa/xtensa.c b/gcc/config/xtensa/xtensa.c index 50467b4602c..35e399f54b4 100644 --- a/gcc/config/xtensa/xtensa.c +++ b/gcc/config/xtensa/xtensa.c @@ -71,13 +71,6 @@ enum internal_test ITEST_MAX }; -/* Cached operands, and operator to compare for use in set/branch on - condition codes. */ -rtx branch_cmp[2]; - -/* what type of branch to use */ -enum cmp_type branch_type; - /* Array giving truth value on whether or not a given hard register can support a given mode. */ char xtensa_hard_regno_mode_ok[(int) MAX_MACHINE_MODE][FIRST_PSEUDO_REGISTER]; @@ -128,7 +121,7 @@ const enum reg_class xtensa_regno_to_class[FIRST_PSEUDO_REGISTER] = static enum internal_test map_test_to_internal_test (enum rtx_code); static rtx gen_int_relational (enum rtx_code, rtx, rtx, int *); static rtx gen_float_relational (enum rtx_code, rtx, rtx); -static rtx gen_conditional_move (rtx); +static rtx gen_conditional_move (enum rtx_code, enum machine_mode, rtx, rtx); static rtx fixup_subreg_mem (rtx); static struct machine_function * xtensa_init_machine_status (void); static rtx xtensa_legitimize_tls_address (rtx); @@ -712,27 +705,27 @@ gen_float_relational (enum rtx_code test_code, /* relational test (EQ, etc) */ void -xtensa_expand_conditional_branch (rtx *operands, enum rtx_code test_code) +xtensa_expand_conditional_branch (rtx *operands, enum machine_mode mode) { - enum cmp_type type = branch_type; - rtx cmp0 = branch_cmp[0]; - rtx cmp1 = branch_cmp[1]; + enum rtx_code test_code = GET_CODE (operands[0]); + rtx cmp0 = operands[1]; + rtx cmp1 = operands[2]; rtx cmp; int invert; rtx label1, label2; - switch (type) + switch (mode) { - case CMP_DF: + case DFmode: default: fatal_insn ("bad test", gen_rtx_fmt_ee (test_code, VOIDmode, cmp0, cmp1)); - case CMP_SI: + case SImode: invert = FALSE; cmp = gen_int_relational (test_code, cmp0, cmp1, &invert); break; - case CMP_SF: + case SFmode: if (!TARGET_HARD_FLOAT) fatal_insn ("bad test", gen_rtx_fmt_ee (test_code, VOIDmode, cmp0, cmp1)); @@ -743,7 +736,7 @@ xtensa_expand_conditional_branch (rtx *operands, enum rtx_code test_code) /* Generate the branch. */ - label1 = gen_rtx_LABEL_REF (VOIDmode, operands[0]); + label1 = gen_rtx_LABEL_REF (VOIDmode, operands[3]); label2 = pc_rtx; if (invert) @@ -760,14 +753,13 @@ xtensa_expand_conditional_branch (rtx *operands, enum rtx_code test_code) static rtx -gen_conditional_move (rtx cmp) +gen_conditional_move (enum rtx_code code, enum machine_mode mode, + rtx op0, rtx op1) { - enum rtx_code code = GET_CODE (cmp); - rtx op0 = branch_cmp[0]; - rtx op1 = branch_cmp[1]; - - if (branch_type == CMP_SI) + if (mode == SImode) { + rtx cmp; + /* Jump optimization calls get_condition() which canonicalizes comparisons like (GE x <const>) to (GT x <const-1>). Transform those comparisons back to GE, since that is the @@ -825,7 +817,7 @@ gen_conditional_move (rtx cmp) return gen_rtx_fmt_ee (code, VOIDmode, op0, op1); } - if (TARGET_HARD_FLOAT && (branch_type == CMP_SF)) + if (TARGET_HARD_FLOAT && mode == SFmode) return gen_float_relational (code, op0, op1); return 0; @@ -835,36 +827,39 @@ gen_conditional_move (rtx cmp) int xtensa_expand_conditional_move (rtx *operands, int isflt) { - rtx cmp; + rtx dest = operands[0]; + rtx cmp = operands[1]; + enum machine_mode cmp_mode = GET_MODE (XEXP (cmp, 0)); rtx (*gen_fn) (rtx, rtx, rtx, rtx, rtx); - if (!(cmp = gen_conditional_move (operands[1]))) + if (!(cmp = gen_conditional_move (GET_CODE (cmp), cmp_mode, + XEXP (cmp, 0), XEXP (cmp, 1)))) return 0; if (isflt) - gen_fn = (branch_type == CMP_SI + gen_fn = (cmp_mode == SImode ? gen_movsfcc_internal0 : gen_movsfcc_internal1); else - gen_fn = (branch_type == CMP_SI + gen_fn = (cmp_mode == SImode ? gen_movsicc_internal0 : gen_movsicc_internal1); - emit_insn (gen_fn (operands[0], XEXP (cmp, 0), - operands[2], operands[3], cmp)); + emit_insn (gen_fn (dest, XEXP (cmp, 0), operands[2], operands[3], cmp)); return 1; } int -xtensa_expand_scc (rtx *operands) +xtensa_expand_scc (rtx operands[4], enum machine_mode cmp_mode) { rtx dest = operands[0]; - rtx cmp = operands[1]; + rtx cmp; rtx one_tmp, zero_tmp; rtx (*gen_fn) (rtx, rtx, rtx, rtx, rtx); - if (!(cmp = gen_conditional_move (cmp))) + if (!(cmp = gen_conditional_move (GET_CODE (operands[1]), cmp_mode, + operands[2], operands[3]))) return 0; one_tmp = gen_reg_rtx (SImode); @@ -872,7 +867,7 @@ xtensa_expand_scc (rtx *operands) emit_insn (gen_movsi (one_tmp, const_true_rtx)); emit_insn (gen_movsi (zero_tmp, const0_rtx)); - gen_fn = (branch_type == CMP_SI + gen_fn = (cmp_mode == SImode ? gen_movsicc_internal0 : gen_movsicc_internal1); emit_insn (gen_fn (dest, XEXP (cmp, 0), one_tmp, zero_tmp, cmp)); diff --git a/gcc/config/xtensa/xtensa.h b/gcc/config/xtensa/xtensa.h index 73f68ef315f..c01a778bf2b 100644 --- a/gcc/config/xtensa/xtensa.h +++ b/gcc/config/xtensa/xtensa.h @@ -27,17 +27,6 @@ extern int optimize; /* External variables defined in xtensa.c. */ -/* comparison type */ -enum cmp_type { - CMP_SI, /* four byte integers */ - CMP_DI, /* eight byte integers */ - CMP_SF, /* single precision floats */ - CMP_DF, /* double precision floats */ - CMP_MAX /* max comparison type */ -}; - -extern struct rtx_def * branch_cmp[2]; /* operands for compare */ -extern enum cmp_type branch_type; /* what type of branch to use */ extern unsigned xtensa_current_frame_size; /* Macros used in the machine description to select various Xtensa diff --git a/gcc/config/xtensa/xtensa.md b/gcc/config/xtensa/xtensa.md index 63c5db5b476..13883f1d5ca 100644 --- a/gcc/config/xtensa/xtensa.md +++ b/gcc/config/xtensa/xtensa.md @@ -64,15 +64,6 @@ (define_code_attr minmax [(smin "min") (umin "minu") (smax "max") (umax "maxu")]) -;; This code iterator allows all branch instructions to be generated from -;; a single define_expand template. -(define_code_iterator any_cond [eq ne gt ge lt le gtu geu ltu leu - uneq ltgt ungt unge unlt unle - unordered ordered]) - -;; This code iterator is for setting a register from a comparison. -(define_code_iterator any_scc [eq ne gt ge lt le]) - ;; This code iterator is for floating-point comparisons. (define_code_iterator any_scc_sf [eq lt le uneq unlt unle unordered]) (define_code_attr scc_sf [(eq "oeq") (lt "olt") (le "ole") @@ -1131,44 +1122,27 @@ ;; Comparisons. -;; Handle comparisons by stashing away the operands and then using that -;; information in the subsequent conditional branch. +;; Conditional branches. -(define_expand "cmpsi" - [(set (cc0) - (compare:CC (match_operand:SI 0 "register_operand" "") - (match_operand:SI 1 "nonmemory_operand" "")))] +(define_expand "cbranchsi4" + [(match_operator 0 "comparison_operator" + [(match_operand:SI 1 "register_operand") + (match_operand:SI 2 "nonmemory_operand")]) + (match_operand 3 "")] "" { - branch_cmp[0] = operands[0]; - branch_cmp[1] = operands[1]; - branch_type = CMP_SI; + xtensa_expand_conditional_branch (operands, SImode); DONE; }) -(define_expand "cmpsf" - [(set (cc0) - (compare:CC (match_operand:SF 0 "register_operand" "") - (match_operand:SF 1 "register_operand" "")))] +(define_expand "cbranchsf4" + [(match_operator 0 "comparison_operator" + [(match_operand:SF 1 "register_operand") + (match_operand:SF 2 "register_operand")]) + (match_operand 3 "")] "TARGET_HARD_FLOAT" { - branch_cmp[0] = operands[0]; - branch_cmp[1] = operands[1]; - branch_type = CMP_SF; - DONE; -}) - - -;; Conditional branches. - -(define_expand "b<code>" - [(set (pc) - (if_then_else (any_cond (cc0) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" -{ - xtensa_expand_conditional_branch (operands, <CODE>); + xtensa_expand_conditional_branch (operands, SFmode); DONE; }) @@ -1353,18 +1327,31 @@ ;; Setting a register from a comparison. -(define_expand "s<code>" - [(set (match_operand:SI 0 "register_operand" "") - (any_scc:SI (match_dup 1) - (match_dup 2)))] +(define_expand "cstoresi4" + [(match_operand:SI 0 "register_operand") + (match_operator 1 "xtensa_cstoresi_operator" + [(match_operand:SI 2 "register_operand") + (match_operand:SI 3 "nonmemory_operand")])] "" { - operands[1] = gen_rtx_<CODE> (SImode, branch_cmp[0], branch_cmp[1]); - if (!xtensa_expand_scc (operands)) + if (!xtensa_expand_scc (operands, SImode)) FAIL; DONE; }) +(define_expand "cstoresf4" + [(match_operand:SI 0 "register_operand") + (match_operator:SI 1 "comparison_operator" + [(match_operand:SF 2 "register_operand") + (match_operand:SF 3 "register_operand")])] + "TARGET_HARD_FLOAT" +{ + if (!xtensa_expand_scc (operands, SFmode)) + FAIL; + DONE; +}) + + ;; Conditional moves. |