diff options
Diffstat (limited to 'gcc/config/visium')
-rw-r--r-- | gcc/config/visium/visium-protos.h | 3 | ||||
-rw-r--r-- | gcc/config/visium/visium.c | 100 | ||||
-rw-r--r-- | gcc/config/visium/visium.md | 98 |
3 files changed, 127 insertions, 74 deletions
diff --git a/gcc/config/visium/visium-protos.h b/gcc/config/visium/visium-protos.h index 484d01e477d..9dcbc67035f 100644 --- a/gcc/config/visium/visium-protos.h +++ b/gcc/config/visium/visium-protos.h @@ -49,7 +49,8 @@ extern void visium_split_cbranch (enum rtx_code, rtx, rtx, rtx); extern const char *output_ubranch (rtx, rtx_insn *); extern const char *output_cbranch (rtx, enum rtx_code, enum machine_mode, int, rtx_insn *); -extern void split_double_move (rtx *, enum machine_mode); +extern void visium_split_double_move (rtx *, enum machine_mode); +extern void visium_split_double_add (enum rtx_code, rtx, rtx, rtx); extern void visium_expand_copysign (rtx *, enum machine_mode); extern void visium_expand_int_cstore (rtx *, enum machine_mode); extern void visium_expand_fp_cstore (rtx *, enum machine_mode); diff --git a/gcc/config/visium/visium.c b/gcc/config/visium/visium.c index cd28f9bf90a..44f471a1a49 100644 --- a/gcc/config/visium/visium.c +++ b/gcc/config/visium/visium.c @@ -2026,7 +2026,7 @@ visium_rtx_costs (rtx x, machine_mode mode, int outer_code ATTRIBUTE_UNUSED, /* Split a double move of OPERANDS in MODE. */ void -split_double_move (rtx *operands, enum machine_mode mode) +visium_split_double_move (rtx *operands, enum machine_mode mode) { bool swap = false; @@ -2076,14 +2076,74 @@ split_double_move (rtx *operands, enum machine_mode mode) } } +/* Split a double addition or subtraction of operands. */ + +void +visium_split_double_add (enum rtx_code code, rtx op0, rtx op1, rtx op2) +{ + rtx op3 = gen_lowpart (SImode, op0); + rtx op4 = gen_lowpart (SImode, op1); + rtx op5; + rtx op6 = gen_highpart (SImode, op0); + rtx op7 = (op1 == const0_rtx ? op1 : gen_highpart (SImode, op1)); + rtx op8; + + /* If operand #2 is a small constant, then its high part is null. */ + if (CONST_INT_P (op2)) + { + HOST_WIDE_INT val = INTVAL (op2); + + if (val < 0) + { + code = (code == MINUS ? PLUS : MINUS); + val = -val; + } + + op5 = gen_int_mode (val, SImode); + op8 = const0_rtx; + } + else + { + op5 = gen_lowpart (SImode, op2); + op8 = gen_highpart (SImode, op2); + } + + /* This is the {add,sub,neg}si3_insn_set_flags pattern. */ + rtx x; + if (op4 == const0_rtx) + x = gen_rtx_NEG (SImode, op5); + else + x = gen_rtx_fmt_ee (code, SImode, op4, op5); + rtx pat = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (2)); + XVECEXP (pat, 0, 0) = gen_rtx_SET (op3, x); + rtx 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); + emit_insn (pat); + + /* This is the plus_[plus_]sltu_flags or minus_[minus_]sltu_flags pattern. */ + if (op8 == const0_rtx) + x = op7; + else + x = gen_rtx_fmt_ee (code, SImode, op7, op8); + 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); + flags = gen_rtx_REG (CCmode, FLAGS_REGNUM); + XVECEXP (pat, 0, 1) = gen_rtx_CLOBBER (VOIDmode, flags); + emit_insn (pat); + + visium_flags_exposed = true; +} + /* Expand a copysign of OPERANDS in MODE. */ void visium_expand_copysign (rtx *operands, enum machine_mode mode) { - rtx dest = operands[0]; - rtx op0 = operands[1]; - rtx op1 = operands[2]; + rtx op0 = operands[0]; + rtx op1 = operands[1]; + rtx op2 = operands[2]; rtx mask = force_reg (SImode, GEN_INT (0x7fffffff)); rtx x; @@ -2091,37 +2151,37 @@ visium_expand_copysign (rtx *operands, enum machine_mode mode) the FPU on the MCM have a non-standard behavior wrt NaNs. */ gcc_assert (mode == SFmode); - /* First get all the non-sign bits of OP0. */ - if (GET_CODE (op0) == CONST_DOUBLE) + /* First get all the non-sign bits of op1. */ + if (GET_CODE (op1) == CONST_DOUBLE) { - if (real_isneg (CONST_DOUBLE_REAL_VALUE (op0))) - op0 = simplify_unary_operation (ABS, mode, op0, mode); - if (op0 != CONST0_RTX (mode)) + if (real_isneg (CONST_DOUBLE_REAL_VALUE (op1))) + op1 = simplify_unary_operation (ABS, mode, op1, mode); + if (op1 != CONST0_RTX (mode)) { long l; - REAL_VALUE_TO_TARGET_SINGLE (*CONST_DOUBLE_REAL_VALUE (op0), l); - op0 = force_reg (SImode, GEN_INT (trunc_int_for_mode (l, SImode))); + REAL_VALUE_TO_TARGET_SINGLE (*CONST_DOUBLE_REAL_VALUE (op1), l); + op1 = force_reg (SImode, GEN_INT (trunc_int_for_mode (l, SImode))); } } else { - op0 = copy_to_mode_reg (SImode, gen_lowpart (SImode, op0)); - op0 = force_reg (SImode, gen_rtx_AND (SImode, op0, mask)); + op1 = copy_to_mode_reg (SImode, gen_lowpart (SImode, op1)); + op1 = force_reg (SImode, gen_rtx_AND (SImode, op1, mask)); } - /* Then get the sign bit of OP1. */ + /* Then get the sign bit of op2. */ mask = force_reg (SImode, gen_rtx_NOT (SImode, mask)); - op1 = copy_to_mode_reg (SImode, gen_lowpart (SImode, op1)); - op1 = force_reg (SImode, gen_rtx_AND (SImode, op1, mask)); + op2 = copy_to_mode_reg (SImode, gen_lowpart (SImode, op2)); + op2 = force_reg (SImode, gen_rtx_AND (SImode, op2, mask)); /* Finally OR the two values. */ - if (op0 == CONST0_RTX (SFmode)) - x = op1; + if (op1 == CONST0_RTX (SFmode)) + x = op2; else - x = force_reg (SImode, gen_rtx_IOR (SImode, op0, op1)); + x = force_reg (SImode, gen_rtx_IOR (SImode, op1, op2)); /* And move the result to the destination. */ - emit_insn (gen_rtx_SET (dest, gen_lowpart (SFmode, x))); + emit_insn (gen_rtx_SET (op0, gen_lowpart (SFmode, x))); } /* Expand a cstore of OPERANDS in MODE for EQ/NE/LTU/GTU/GEU/LEU. We generate diff --git a/gcc/config/visium/visium.md b/gcc/config/visium/visium.md index 09d136f5f0f..41e3e5c5719 100644 --- a/gcc/config/visium/visium.md +++ b/gcc/config/visium/visium.md @@ -627,7 +627,7 @@ [(set (match_dup 2) (match_dup 3)) (set (match_dup 4) (match_dup 5))] { - split_double_move (operands, DImode); + visium_split_double_move (operands, DImode); }) ;; @@ -726,7 +726,7 @@ [(set (match_dup 2) (match_dup 3)) (set (match_dup 4) (match_dup 5))] { - split_double_move (operands, DFmode); + visium_split_double_move (operands, DFmode); }) ;; @@ -815,31 +815,20 @@ (match_operand:DI 2 "add_operand" "")))] "") +; Disfavour the use of add.l because of the early clobber. + (define_insn_and_split "*addi3_insn" [(set (match_operand:DI 0 "register_operand" "=r,r,&r") (plus:DI (match_operand:DI 1 "register_operand" "%0,0, r") - (match_operand:DI 2 "add_operand" " J,L, r")))] + (match_operand:DI 2 "add_operand" " L,J, r")))] "ok_for_simple_arith_logic_operands (operands, DImode)" "#" "reload_completed" - [(parallel [(set (match_dup 0) - (plus:DI (match_dup 1) (match_dup 2))) - (clobber (reg:CC R_FLAGS))])] - "" - [(set_attr "type" "arith2")]) - -; Disfavour the use of add.l because of the early clobber. - -(define_insn "*adddi3_insn_flags" - [(set (match_operand:DI 0 "register_operand" "=r,r,&r") - (plus:DI (match_operand:DI 1 "register_operand" "%0,0, r") - (match_operand:DI 2 "add_operand" " J,L, r"))) - (clobber (reg:CC R_FLAGS))] - "reload_completed" - "@ - addi %d0,%2\n\tadc.l %0,%0,r0 - subi %d0,%n2\n\tsubc.l %0,%0,r0 - add.l %d0,%d1,%d2\n\tadc.l %0,%1,%2" + [(const_int 0)] +{ + visium_split_double_add (PLUS, operands[0], operands[1], operands[2]); + DONE; +} [(set_attr "type" "arith2")]) ;; @@ -847,7 +836,7 @@ ;; ;; Integer Add with Carry ;; -;; Only SI mode is supported as slt[u] for the sake of cstore. +;; Only SI mode is supported. ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; @@ -869,6 +858,16 @@ "adc.l %0,%1,r0" [(set_attr "type" "arith")]) +(define_insn "*plus_plus_sltu<subst_arith>" + [(set (match_operand:SI 0 "register_operand" "=r") + (plus:SI (plus:SI (match_operand:SI 1 "register_operand" "r") + (match_operand:SI 2 "register_operand" "r")) + (ltu:SI (reg R_FLAGS) (const_int 0)))) + (clobber (reg:CC R_FLAGS))] + "reload_completed" + "adc.l %0,%1,%2" + [(set_attr "type" "arith")]) + ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; @@ -955,31 +954,20 @@ (match_operand:DI 2 "add_operand" "")))] "") +; Disfavour the use of the sub.l because of the early clobber. + (define_insn_and_split "*subdi3_insn" [(set (match_operand:DI 0 "register_operand" "=r,r,&r") (minus:DI (match_operand:DI 1 "register_operand" " 0,0, r") - (match_operand:DI 2 "add_operand" " J,L, r")))] + (match_operand:DI 2 "add_operand" " L,J, r")))] "ok_for_simple_arith_logic_operands (operands, DImode)" "#" "reload_completed" - [(parallel [(set (match_dup 0) - (minus:DI (match_dup 1) (match_dup 2))) - (clobber (reg:CC R_FLAGS))])] - "" - [(set_attr "type" "arith2")]) - -; Disfavour the use of the sub.l because of the early clobber. - -(define_insn "*subdi3_insn_flags" - [(set (match_operand:DI 0 "register_operand" "=r,r,&r") - (minus:DI (match_operand:DI 1 "register_operand" " 0,0, r") - (match_operand:DI 2 "add_operand" " J,L, r"))) - (clobber (reg:CC R_FLAGS))] - "reload_completed" - "@ - subi %d0,%2\n\tsubc.l %0,%0,r0 - addi %d0,%n2\n\tadc.l %0,%0,r0 - sub.l %d0,%d1,%d2\n\tsubc.l %0,%1,%2" + [(const_int 0)] +{ + visium_split_double_add (MINUS, operands[0], operands[1], operands[2]); + DONE; +} [(set_attr "type" "arith2")]) ;; @@ -987,7 +975,7 @@ ;; ;; Integer Subtract with Carry ;; -;; Only SI mode is supported as neg<slt[u]> for the sake of cstore. +;; Only SI mode is supported. ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; @@ -1009,6 +997,16 @@ "subc.l %0,%1,r0" [(set_attr "type" "arith")]) +(define_insn "*minus_minus_sltu<subst_arith>" + [(set (match_operand:SI 0 "register_operand" "=r") + (minus:SI (minus:SI (match_operand:SI 1 "reg_or_0_operand" "rO") + (match_operand:SI 2 "register_operand" "r")) + (ltu:SI (reg R_FLAGS) (const_int 0)))) + (clobber (reg:CC R_FLAGS))] + "reload_completed" + "subc.l %0,%r1,%2" + [(set_attr "type" "arith")]) + ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; @@ -1054,17 +1052,11 @@ "ok_for_simple_arith_logic_operands (operands, DImode)" "#" "reload_completed" - [(parallel [(set (match_dup 0) (neg:DI (match_dup 1))) - (clobber (reg:CC R_FLAGS))])] - "" - [(set_attr "type" "arith2")]) - -(define_insn "*negdi2_insn_flags" - [(set (match_operand:DI 0 "register_operand" "=&r") - (neg:DI (match_operand:DI 1 "register_operand" "r"))) - (clobber (reg:CC R_FLAGS))] - "reload_completed" - "sub.l %d0,r0,%d1\n\tsubc.l %0,r0,%1" + [(const_int 0)] +{ + visium_split_double_add (MINUS, operands[0], const0_rtx, operands[1]); + DONE; +} [(set_attr "type" "arith2")]) ;; |