* 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<mode>_sne): Likewise.
(cbranch<mode>4): Use ordered_comparison_operator.
(cbranch<mode>4_insn): Likewise.
(cbranchsi4_btst_insn): Adjust.
From-SVN: r240969
+2016-10-11 Eric Botcazou <ebotcazou@adacore.com>
+
+ * 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<mode>_sne): Likewise.
+ (cbranch<mode>4): Use ordered_comparison_operator.
+ (cbranch<mode>4_insn): Likewise.
+ (cbranchsi4_btst_insn): Adjust.
+
2016-10-11 Tom de Vries <tom@codesourcery.com>
PR middle-end/77558
(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"
(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.
/* 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);
/* 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;
}
}
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. */
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);
}
}
+ /* This is for the cmp<mode>_sne pattern. */
+ if (op1 == constm1_rtx)
+ return CCCmode;
+
+ /* This is for the add<mode>3_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;
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. */
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";
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";
break;
case UNGE:
- cond = "nc";
+ cond = "cc"; /* or "nc" */
break;
case UNGT:
(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")
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" "")
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" "")
"sub<s> %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" "")))]
; 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")])
[(set_attr "type" "cmp")])
(define_insn "*cmp<mode>_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<s> r0,%0"
[(set_attr "type" "cmp")])
(define_expand "cbranch<mode>4"
[(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 ""))
(define_insn_and_split "*cbranch<mode>4_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 ""))
(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)