From 8d946ecc4695b2075da22d77fff79de6a36401b9 Mon Sep 17 00:00:00 2001 From: Eric Botcazou Date: Tue, 11 Oct 2016 08:19:17 +0000 Subject: [PATCH] visium-modes.def (CC_NOOV): Rename into... * config/visium/visium-modes.def (CC_NOOV): Rename into... (CCNZ): ...this. (CC_BTST): Rename into... (CCC): ...this. * config/visium/predicates.md (real_add_operand): New. (visium_btst_operator): Rename into... (visium_equality_comparison_operator): ...this. (visium_noov_operator): Rename into... (visium_nz_comparison_operator): ...this. (visium_c_comparison_operator): New. (visium_branch_operator): Adjust and deal with all CC modes. * config/visium/visium.c (visium_adjust_cost): Adjust. (visium_split_double_add): Use the *_set_carry patterns. (visium_select_cc_mode): Add support for CCC mode and adjust. (output_cbranch): Adjust and use the carry-based operators for floating-point comparisons. * config/visium/visium.md (flags_subst_arith): Adjust. (addsi3_insn_set_carry): New instruction. (subsi3_insn_set_carry): Likewise. (negsi2_insn_set_carry): Likewise. (btst): Adjust. (cmp_sne): Likewise. (cbranch4): Use ordered_comparison_operator. (cbranch4_insn): Likewise. (cbranchsi4_btst_insn): Adjust. From-SVN: r240969 --- gcc/ChangeLog | 28 ++++++++++++++ gcc/config/visium/predicates.md | 51 +++++++++++++++--------- gcc/config/visium/visium-modes.def | 17 ++++---- gcc/config/visium/visium.c | 58 ++++++++++++++++------------ gcc/config/visium/visium.md | 62 +++++++++++++++++++++++------- 5 files changed, 152 insertions(+), 64 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 06d2c23583e..e2cc1bb7a39 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,31 @@ +2016-10-11 Eric Botcazou + + * config/visium/visium-modes.def (CC_NOOV): Rename into... + (CCNZ): ...this. + (CC_BTST): Rename into... + (CCC): ...this. + * config/visium/predicates.md (real_add_operand): New. + (visium_btst_operator): Rename into... + (visium_equality_comparison_operator): ...this. + (visium_noov_operator): Rename into... + (visium_nz_comparison_operator): ...this. + (visium_c_comparison_operator): New. + (visium_branch_operator): Adjust and deal with all CC modes. + * config/visium/visium.c (visium_adjust_cost): Adjust. + (visium_split_double_add): Use the *_set_carry patterns. + (visium_select_cc_mode): Add support for CCC mode and adjust. + (output_cbranch): Adjust and use the carry-based operators for + floating-point comparisons. + * config/visium/visium.md (flags_subst_arith): Adjust. + (addsi3_insn_set_carry): New instruction. + (subsi3_insn_set_carry): Likewise. + (negsi2_insn_set_carry): Likewise. + (btst): Adjust. + (cmp_sne): Likewise. + (cbranch4): Use ordered_comparison_operator. + (cbranch4_insn): Likewise. + (cbranchsi4_btst_insn): Adjust. + 2016-10-11 Tom de Vries PR middle-end/77558 diff --git a/gcc/config/visium/predicates.md b/gcc/config/visium/predicates.md index b08b06ef06a..5e08768666a 100644 --- a/gcc/config/visium/predicates.md +++ b/gcc/config/visium/predicates.md @@ -112,6 +112,13 @@ (and (match_code "const_int") (match_test ("INTVAL (op) >= -65535 && INTVAL (op) <= 65535"))))) +;; Return true if OP can be used as the second operand in a 32-bit or 64-bit +;; add or subtract instruction directly, i.e. without the reverse trick. +(define_predicate "real_add_operand" + (ior (match_operand 0 "gpc_reg_operand") + (and (match_code "const_int") + (match_test ("INTVAL (op) >= 0 && INTVAL (op) <= 65535"))))) + ;; Return true if OP is (or could be) outside the range 0 .. 65535, which is ;; the range of the immediate operands, but accept -1 for NOT. (define_predicate "large_immediate_operand" @@ -119,33 +126,41 @@ (and (match_code "const_int") (match_test ("INTVAL (op) < -1 || INTVAL (op) > 65535"))))) +;; Return true if OP is an equality comparison operator. +(define_predicate "visium_equality_comparison_operator" + (match_code "eq,ne")) + +;; Return true if OP is a valid comparison operator for CCNZmode. +(define_special_predicate "visium_nz_comparison_operator" + (match_code "eq,ne,lt,ge")) + +;; Return true if OP is a valid comparison operator for CCCmode. +(define_special_predicate "visium_c_comparison_operator" + (match_code "eq,ne,ltu,geu")) + ;; Return true if OP is a valid FP comparison operator. (define_predicate "visium_fp_comparison_operator" (match_code "eq,ne,ordered,unordered,unlt,unle,ungt,unge,lt,le,gt,ge")) -;; Return true if OP is a valid comparison operator for CC_BTSTmode. -(define_special_predicate "visium_btst_operator" - (match_code "eq,ne")) - -;; Return true if OP is a valid comparison operator for CC_NOOVmode. -(define_special_predicate "visium_noov_operator" - (match_code "eq,ne,ge,lt")) - ;; Return true if OP is a valid comparison operator for a branch. This allows ;; the use of MATCH_OPERATOR to recognize all the branch insns. (define_predicate "visium_branch_operator" (match_operand 0 "comparison_operator") { - enum rtx_code code = GET_CODE (op); - /* These 2 comparison codes are not supported. */ - if (code == UNEQ || code == LTGT) - return false; - enum machine_mode cc_mode = GET_MODE (XEXP (op, 0)); - if (cc_mode == CC_NOOVmode) - return visium_noov_operator (op, mode); - if (cc_mode == CC_BTSTmode) - return visium_btst_operator (op, mode); - return true; + switch (GET_MODE (XEXP (op, 0))) + { + case CCmode: + return ordered_comparison_operator (op, mode); + case CCNZmode: + return visium_nz_comparison_operator (op, mode); + case CCCmode: + return visium_c_comparison_operator (op, mode); + case CCFPmode: + case CCFPEmode: + return visium_fp_comparison_operator (op, mode); + default: + return false; + } }) ;; Return true if OP is a valid comparison operator for an integer cstore. diff --git a/gcc/config/visium/visium-modes.def b/gcc/config/visium/visium-modes.def index 5af2db9737e..980745ebfe7 100644 --- a/gcc/config/visium/visium-modes.def +++ b/gcc/config/visium/visium-modes.def @@ -19,19 +19,22 @@ along with GCC; see the file COPYING3. If not see /* Add any extra modes needed to represent the condition code. - On the Visium, we have a "no-overflow" mode which is used when arithmetic - instructions set the condition code. Different branches are used in this - case for some operations. + We have a CCNZ mode which is used for implicit comparisons with zero when + arithmetic instructions set the condition code. Only the N and Z flags + are valid in this mode, which means that only the =,!= and <,>= operators + can be used in conjunction with it. - We also have a "bit-test" mode which is used when the bit-test instruction - sets the condition code. + We also have a CCCmode which is used by the arithmetic instructions when + they explicitly set the C flag (unsigned overflow) and by the bit-test + instruction. Only the =,!= and unsigned <,>= operators can be used in + conjunction with it. We also have two modes to indicate that the condition code is set by the the floating-point unit. One for comparisons which generate an exception if the result is unordered (CCFPEmode) and one for comparisons which never generate such an exception (CCFPmode). */ -CC_MODE (CC_NOOV); -CC_MODE (CC_BTST); +CC_MODE (CCNZ); +CC_MODE (CCC); CC_MODE (CCFP); CC_MODE (CCFPE); diff --git a/gcc/config/visium/visium.c b/gcc/config/visium/visium.c index af58f99aef1..4585af57894 100644 --- a/gcc/config/visium/visium.c +++ b/gcc/config/visium/visium.c @@ -561,11 +561,12 @@ visium_adjust_cost (rtx_insn *insn, int dep_type, rtx_insn *dep_insn, int cost, /* The logical instructions use CCmode and thus work with any comparison operator, whereas the arithmetic instructions use - CC_NOOVmode and thus work with only a small subset. */ + CCNZmode and thus work with only a small subset. */ if (dep_attr_type == TYPE_LOGIC || (dep_attr_type == TYPE_ARITH - && visium_noov_operator (XEXP (src, 0), - GET_MODE (XEXP (src, 0))))) + && visium_nz_comparison_operator (XEXP (src, 0), + GET_MODE + (XEXP (src, 0))))) return 0; } } @@ -2113,16 +2114,12 @@ visium_split_double_add (enum rtx_code code, rtx op0, rtx op1, rtx op2) op8 = gen_highpart (SImode, op2); } - /* This is the {add,sub,neg}si3_insn_set_flags pattern. */ if (op4 == const0_rtx) - x = gen_rtx_NEG (SImode, op5); + pat = gen_negsi2_insn_set_carry (op3, op5); + else if (code == MINUS) + pat = gen_subsi3_insn_set_carry (op3, op4, op5); else - x = gen_rtx_fmt_ee (code, SImode, op4, op5); - pat = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (2)); - XVECEXP (pat, 0, 0) = gen_rtx_SET (op3, x); - flags = gen_rtx_REG (CC_NOOVmode, FLAGS_REGNUM); - x = gen_rtx_COMPARE (CC_NOOVmode, shallow_copy_rtx (x), const0_rtx); - XVECEXP (pat, 0, 1) = gen_rtx_SET (flags, x); + pat = gen_addsi3_insn_set_carry (op3, op4, op5); emit_insn (pat); /* This is the plus_[plus_]sltu_flags or minus_[minus_]sltu_flags pattern. */ @@ -2130,6 +2127,7 @@ visium_split_double_add (enum rtx_code code, rtx op0, rtx op1, rtx op2) x = op7; else x = gen_rtx_fmt_ee (code, SImode, op7, op8); + flags = gen_rtx_REG (CCCmode, FLAGS_REGNUM); x = gen_rtx_fmt_ee (code, SImode, x, gen_rtx_LTU (SImode, flags, const0_rtx)); pat = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (2)); XVECEXP (pat, 0, 0) = gen_rtx_SET (op6, x); @@ -2814,6 +2812,16 @@ visium_select_cc_mode (enum rtx_code code, rtx op0, rtx op1) } } + /* This is for the cmp_sne pattern. */ + if (op1 == constm1_rtx) + return CCCmode; + + /* This is for the add3_insn_set_carry pattern. */ + if ((code == LTU || code == GEU) + && GET_CODE (op0) == PLUS + && rtx_equal_p (XEXP (op0, 0), op1)) + return CCCmode; + if (op1 != const0_rtx) return CCmode; @@ -2825,17 +2833,17 @@ visium_select_cc_mode (enum rtx_code code, rtx op0, rtx op1) case ASHIFT: case LTU: case LT: - /* The V flag may be set differently from a COMPARE with zero. - The consequence is that a comparison operator testing V must - be turned into another operator not testing V and yielding - the same result for a comparison with zero. That's possible - for GE/LT which become NC/NS respectively, but not for GT/LE - for which the altered operator doesn't exist on the Visium. */ - return CC_NOOVmode; + /* The C and V flags may be set differently from a COMPARE with zero. + The consequence is that a comparison operator testing C or V must + be turned into another operator not testing C or V and yielding + the same result for a comparison with zero. That's possible for + GE/LT which become NC/NS respectively, but not for GT/LE for which + the altered operator doesn't exist on the Visium. */ + return CCNZmode; case ZERO_EXTRACT: /* This is a btst, the result is in C instead of Z. */ - return CC_BTSTmode; + return CCCmode; case CONST_INT: /* This is a degenerate case, typically an uninitialized variable. */ @@ -3077,21 +3085,21 @@ output_cbranch (rtx label, enum rtx_code code, enum machine_mode cc_mode, switch (code) { case NE: - if (cc_mode == CC_BTSTmode) + if (cc_mode == CCCmode) cond = "cs"; else cond = "ne"; break; case EQ: - if (cc_mode == CC_BTSTmode) + if (cc_mode == CCCmode) cond = "cc"; else cond = "eq"; break; case GE: - if (cc_mode == CC_NOOVmode) + if (cc_mode == CCNZmode) cond = "nc"; else cond = "ge"; @@ -3110,8 +3118,8 @@ output_cbranch (rtx label, enum rtx_code code, enum machine_mode cc_mode, case LT: if (cc_mode == CCFPmode || cc_mode == CCFPEmode) - cond = "ns"; - else if (cc_mode == CC_NOOVmode) + cond = "cs"; /* or "ns" */ + else if (cc_mode == CCNZmode) cond = "ns"; else cond = "lt"; @@ -3142,7 +3150,7 @@ output_cbranch (rtx label, enum rtx_code code, enum machine_mode cc_mode, break; case UNGE: - cond = "nc"; + cond = "cc"; /* or "nc" */ break; case UNGT: diff --git a/gcc/config/visium/visium.md b/gcc/config/visium/visium.md index 41e3e5c5719..de1c710f441 100644 --- a/gcc/config/visium/visium.md +++ b/gcc/config/visium/visium.md @@ -257,8 +257,8 @@ (clobber (reg:CC R_FLAGS))] "" [(set (match_dup 0) (match_dup 1)) - (set (reg:CC_NOOV R_FLAGS) - (compare:CC_NOOV (match_dup 1) (const_int 0)))]) + (set (reg:CCNZ R_FLAGS) + (compare:CCNZ (match_dup 1) (const_int 0)))]) (define_subst_attr "subst_arith" "flags_subst_arith" "_flags" "_set_flags") @@ -809,6 +809,19 @@ addi %0,%2" [(set_attr "type" "arith")]) +(define_insn "addsi3_insn_set_carry" + [(set (match_operand:SI 0 "register_operand" "=r,r") + (plus:SI (match_operand:SI 1 "register_operand" "%r,0") + (match_operand:SI 2 "real_add_operand" " r,J"))) + (set (reg:CCC R_FLAGS) + (compare:CCC (plus:SI (match_dup 1) (match_dup 2)) + (match_dup 1)))] + "reload_completed" + "@ + add.l %0,%1,%2 + addi %0,%2" + [(set_attr "type" "arith")]) + (define_expand "adddi3" [(set (match_operand:DI 0 "register_operand" "") (plus:DI (match_operand:DI 1 "register_operand" "") @@ -948,6 +961,18 @@ subi %0,%2" [(set_attr "type" "arith")]) +(define_insn "subsi3_insn_set_carry" + [(set (match_operand:SI 0 "register_operand" "=r,r") + (minus:SI (match_operand:SI 1 "register_operand" " r,0") + (match_operand:SI 2 "real_add_operand" " r,J"))) + (set (reg:CC R_FLAGS) + (compare:CC (match_dup 1) (match_dup 2)))] + "reload_completed" + "@ + sub.l %0,%r1,%2 + subi %0,%2" + [(set_attr "type" "arith")]) + (define_expand "subdi3" [(set (match_operand:DI 0 "register_operand" "") (minus:DI (match_operand:DI 1 "register_operand" "") @@ -1041,6 +1066,15 @@ "sub %0,r0,%1" [(set_attr "type" "arith")]) +(define_insn "negsi2_insn_set_carry" + [(set (match_operand:SI 0 "register_operand" "=r") + (neg:SI (match_operand:SI 1 "register_operand" "r"))) + (set (reg:CCC R_FLAGS) + (compare:CCC (not:SI (match_dup 1)) (const_int -1)))] + "reload_completed" + "sub.l %0,r0,%1" + [(set_attr "type" "arith")]) + (define_expand "negdi2" [(set (match_operand:DI 0 "register_operand" "") (neg:DI (match_operand:DI 1 "register_operand" "")))] @@ -1803,12 +1837,12 @@ ; BITS_BIG_ENDIAN is defined to 1 so operand #1 counts from the MSB. (define_insn "*btst" - [(set (reg:CC_BTST R_FLAGS) - (compare:CC_BTST (zero_extract:SI - (match_operand:SI 0 "register_operand" "r") - (const_int 1) - (match_operand:QI 1 "const_shift_operand" "K")) - (const_int 0)))] + [(set (reg:CCC R_FLAGS) + (compare:CCC (zero_extract:SI + (match_operand:SI 0 "register_operand" "r") + (const_int 1) + (match_operand:QI 1 "const_shift_operand" "K")) + (const_int 0)))] "reload_completed" "lsr.l r0,%0,32-%1" [(set_attr "type" "logic")]) @@ -1832,9 +1866,9 @@ [(set_attr "type" "cmp")]) (define_insn "*cmp_sne" - [(set (reg:CC R_FLAGS) - (compare:CC (not:I (match_operand:I 0 "register_operand" "r")) - (const_int -1)))] + [(set (reg:CCC R_FLAGS) + (compare:CCC (not:I (match_operand:I 0 "register_operand" "r")) + (const_int -1)))] "reload_completed" "cmp r0,%0" [(set_attr "type" "cmp")]) @@ -2065,7 +2099,7 @@ (define_expand "cbranch4" [(set (pc) - (if_then_else (match_operator 0 "comparison_operator" + (if_then_else (match_operator 0 "ordered_comparison_operator" [(match_operand:I 1 "register_operand") (match_operand:I 2 "reg_or_0_operand")]) (label_ref (match_operand 3 "")) @@ -2075,7 +2109,7 @@ (define_insn_and_split "*cbranch4_insn" [(set (pc) - (if_then_else (match_operator 0 "comparison_operator" + (if_then_else (match_operator 0 "ordered_comparison_operator" [(match_operand:I 1 "register_operand" "r") (match_operand:I 2 "reg_or_0_operand" "rO")]) (label_ref (match_operand 3 "")) @@ -2093,7 +2127,7 @@ (define_insn_and_split "*cbranchsi4_btst_insn" [(set (pc) - (if_then_else (match_operator 0 "visium_btst_operator" + (if_then_else (match_operator 0 "visium_equality_comparison_operator" [(zero_extract:SI (match_operand:SI 1 "register_operand" "r") (const_int 1) -- 2.30.2