diff options
Diffstat (limited to 'gcc/config/arc')
-rw-r--r-- | gcc/config/arc/arc-modes.def | 1 | ||||
-rw-r--r-- | gcc/config/arc/arc-protos.h | 1 | ||||
-rw-r--r-- | gcc/config/arc/arc.cc | 32 | ||||
-rw-r--r-- | gcc/config/arc/arc.md | 163 | ||||
-rw-r--r-- | gcc/config/arc/predicates.md | 9 |
5 files changed, 200 insertions, 6 deletions
diff --git a/gcc/config/arc/arc-modes.def b/gcc/config/arc/arc-modes.def index cab46d7..7c7dff9 100644 --- a/gcc/config/arc/arc-modes.def +++ b/gcc/config/arc/arc-modes.def @@ -24,6 +24,7 @@ along with GCC; see the file COPYING3. If not see CC_MODE (CC_ZN); CC_MODE (CC_Z); +CC_MODE (CC_V); CC_MODE (CC_C); CC_MODE (CC_FP_GT); CC_MODE (CC_FP_GE); diff --git a/gcc/config/arc/arc-protos.h b/gcc/config/arc/arc-protos.h index cd82aa1..2db643c 100644 --- a/gcc/config/arc/arc-protos.h +++ b/gcc/config/arc/arc-protos.h @@ -55,6 +55,7 @@ extern bool arc_check_mov_const (HOST_WIDE_INT ); extern bool arc_split_mov_const (rtx *); extern bool arc_can_use_return_insn (void); extern bool arc_split_move_p (rtx *); +extern void arc_gen_unlikely_cbranch (enum rtx_code, machine_mode, rtx); #endif /* RTX_CODE */ diff --git a/gcc/config/arc/arc.cc b/gcc/config/arc/arc.cc index 3b4b038..bb5db97 100644 --- a/gcc/config/arc/arc.cc +++ b/gcc/config/arc/arc.cc @@ -1436,6 +1436,13 @@ get_arc_condition_code (rtx comparison) case GEU : return ARC_CC_NC; default : gcc_unreachable (); } + case E_CC_Vmode: + switch (GET_CODE (comparison)) + { + case EQ : return ARC_CC_NV; + case NE : return ARC_CC_V; + default : gcc_unreachable (); + } case E_CC_FP_GTmode: if (TARGET_ARGONAUT_SET && TARGET_SPFP) switch (GET_CODE (comparison)) @@ -1546,6 +1553,13 @@ arc_select_cc_mode (enum rtx_code op, rtx x, rtx y) machine_mode mode = GET_MODE (x); rtx x1; + /* Matches all instructions which can do .f and clobbers only Z flag. */ + if (GET_MODE_CLASS (mode) == MODE_INT + && y == const0_rtx + && GET_CODE (x) == MULT + && (op == EQ || op == NE)) + return CC_Zmode; + /* For an operation that sets the condition codes as a side-effect, the C and V flags is not set as for cmp, so we can only use comparisons where this doesn't matter. (For LT and GE we can use "mi" and "pl" @@ -8218,8 +8232,7 @@ hwloop_optimize (hwloop_info loop) insn = emit_insn (gen_arc_lp (loop->start_label, loop->end_label)); - seq = get_insns (); - end_sequence (); + seq = end_sequence (); entry_after = BB_END (entry_bb); if (!single_succ_p (entry_bb) || vec_safe_length (loop->incoming) > 1 @@ -11544,6 +11557,21 @@ arc_libm_function_max_error (unsigned cfn, machine_mode mode, return default_libm_function_max_error (cfn, mode, boundary_p); } +void +arc_gen_unlikely_cbranch (enum rtx_code cmp, machine_mode cc_mode, rtx label) +{ + rtx cc_reg, x; + + cc_reg = gen_rtx_REG (cc_mode, CC_REG); + label = gen_rtx_LABEL_REF (VOIDmode, label); + + x = gen_rtx_fmt_ee (cmp, VOIDmode, cc_reg, const0_rtx); + x = gen_rtx_IF_THEN_ELSE (VOIDmode, x, label, pc_rtx); + + emit_unlikely_jump (gen_rtx_SET (pc_rtx, x)); +} + + #undef TARGET_USE_ANCHORS_FOR_SYMBOL_P #define TARGET_USE_ANCHORS_FOR_SYMBOL_P arc_use_anchors_for_symbol_p diff --git a/gcc/config/arc/arc.md b/gcc/config/arc/arc.md index 1344d9c..d119464 100644 --- a/gcc/config/arc/arc.md +++ b/gcc/config/arc/arc.md @@ -842,6 +842,9 @@ archs4x, archs4xd" ; Optab prefix for sign/zero-extending operations (define_code_attr su_optab [(sign_extend "") (zero_extend "u")]) +;; Code iterator for sign/zero extension +(define_code_iterator ANY_EXTEND [sign_extend zero_extend]) + (define_insn "*<SEZ_prefix>xt<SQH_postfix>_cmp0_noout" [(set (match_operand 0 "cc_set_register" "") (compare:CC_ZN (SEZ:SI (match_operand:SQH 1 "register_operand" "r")) @@ -1068,11 +1071,67 @@ archs4x, archs4xd" (set_attr "cond" "set_zn") (set_attr "length" "*,4,4,4,8")]) -;; The next two patterns are for plos, ior, xor, and, and mult. +(define_expand "<su_optab>mulvsi4" + [(ANY_EXTEND:DI (match_operand:SI 0 "register_operand")) + (ANY_EXTEND:DI (match_operand:SI 1 "register_operand")) + (ANY_EXTEND:DI (match_operand:SI 2 "register_operand")) + (label_ref (match_operand 3 "" ""))] + "TARGET_MPY" + { + emit_insn (gen_<su_optab>mulsi3_Vcmp (operands[0], operands[1], + operands[2])); + arc_gen_unlikely_cbranch (NE, CC_Vmode, operands[3]); + DONE; + }) + +(define_insn "<su_optab>mulsi3_Vcmp" + [(parallel + [(set + (reg:CC_V CC_REG) + (compare:CC_V + (mult:DI + (ANY_EXTEND:DI (match_operand:SI 1 "register_operand" "%0,r,r,r")) + (ANY_EXTEND:DI (match_operand:SI 2 "nonmemory_operand" "I,L,r,C32"))) + (ANY_EXTEND:DI (mult:SI (match_dup 1) (match_dup 2))))) + (set (match_operand:SI 0 "register_operand" "=r,r,r,r") + (mult:SI (match_dup 1) (match_dup 2)))])] + "register_operand (operands[1], SImode) + || register_operand (operands[2], SImode)" + "mpy<su_optab>.f\\t%0,%1,%2" + [(set_attr "length" "4,4,4,8") + (set_attr "type" "multi")]) + +(define_insn "*mulsi3_cmp0" + [(set (reg:CC_Z CC_REG) + (compare:CC_Z + (mult:SI + (match_operand:SI 1 "register_operand" "%r,0,r") + (match_operand:SI 2 "nonmemory_operand" "rL,I,i")) + (const_int 0))) + (set (match_operand:SI 0 "register_operand" "=r,r,r") + (mult:SI (match_dup 1) (match_dup 2)))] + "TARGET_MPY" + "mpy%?.f\\t%0,%1,%2" + [(set_attr "length" "4,4,8") + (set_attr "type" "multi")]) + +(define_insn "*mulsi3_cmp0_noout" + [(set (reg:CC_Z CC_REG) + (compare:CC_Z + (mult:SI + (match_operand:SI 0 "register_operand" "%r,r,r") + (match_operand:SI 1 "nonmemory_operand" "rL,I,i")) + (const_int 0)))] + "TARGET_MPY" + "mpy%?.f\\t0,%0,%1" + [(set_attr "length" "4,4,8") + (set_attr "type" "multi")]) + +;; The next two patterns are for plus, ior, xor, and. (define_insn "*commutative_binary_cmp0_noout" [(set (match_operand 0 "cc_set_register" "") (match_operator 4 "zn_compare_operator" - [(match_operator:SI 3 "commutative_operator" + [(match_operator:SI 3 "commutative_operator_sans_mult" [(match_operand:SI 1 "register_operand" "%r,r") (match_operand:SI 2 "nonmemory_operand" "rL,Cal")]) (const_int 0)]))] @@ -1085,7 +1144,7 @@ archs4x, archs4xd" (define_insn "*commutative_binary_cmp0" [(set (match_operand 3 "cc_set_register" "") (match_operator 5 "zn_compare_operator" - [(match_operator:SI 4 "commutative_operator" + [(match_operator:SI 4 "commutative_operator_sans_mult" [(match_operand:SI 1 "register_operand" "%0, 0,r,r") (match_operand:SI 2 "nonmemory_operand" "rL,rI,r,Cal")]) (const_int 0)])) @@ -2734,6 +2793,56 @@ archs4x, archs4xd" } [(set_attr "length" "8")]) +(define_insn "addsi3_v" + [(set (match_operand:SI 0 "register_operand" "=r,r,r, r") + (plus:SI (match_operand:SI 1 "register_operand" "r,r,0, r") + (match_operand:SI 2 "nonmemory_operand" "r,L,I,C32"))) + (set (reg:CC_V CC_REG) + (compare:CC_V (sign_extend:DI (plus:SI (match_dup 1) + (match_dup 2))) + (plus:DI (sign_extend:DI (match_dup 1)) + (sign_extend:DI (match_dup 2)))))] + "" + "add.f\\t%0,%1,%2" + [(set_attr "cond" "set") + (set_attr "type" "compare") + (set_attr "length" "4,4,4,8")]) + +(define_expand "addvsi4" + [(match_operand:SI 0 "register_operand") + (match_operand:SI 1 "register_operand") + (match_operand:SI 2 "nonmemory_operand") + (label_ref (match_operand 3 "" ""))] + "" + "emit_insn (gen_addsi3_v (operands[0], operands[1], operands[2])); + arc_gen_unlikely_cbranch (NE, CC_Vmode, operands[3]); + DONE;") + +(define_insn "addsi3_c" + [(set (match_operand:SI 0 "register_operand" "=r,r,r, r") + (plus:SI (match_operand:SI 1 "register_operand" "r,r,0, r") + (match_operand:SI 2 "nonmemory_operand" "r,L,I,C32"))) + (set (reg:CC_C CC_REG) + (compare:CC_C (plus:SI (match_dup 1) + (match_dup 2)) + (match_dup 1)))] + "" + "add.f\\t%0,%1,%2" + [(set_attr "cond" "set") + (set_attr "type" "compare") + (set_attr "length" "4,4,4,8")]) + +(define_expand "uaddvsi4" + [(match_operand:SI 0 "register_operand") + (match_operand:SI 1 "register_operand") + (match_operand:SI 2 "nonmemory_operand") + (label_ref (match_operand 3 "" ""))] + "" + "emit_insn (gen_addsi3_c (operands[0], operands[1], operands[2])); + arc_gen_unlikely_cbranch (LTU, CC_Cmode, operands[3]); + DONE;") + + (define_insn "add_f" [(set (reg:CC_C CC_REG) (compare:CC_C @@ -2914,6 +3023,54 @@ archs4x, archs4xd" (set_attr "cpu_facility" "*,cd,*,*,*,*,*,*,*,*") ]) +(define_insn "subsi3_v" + [(set (match_operand:SI 0 "register_operand" "=r,r,r, r") + (minus:SI (match_operand:SI 1 "register_operand" "r,r,0, r") + (match_operand:SI 2 "nonmemory_operand" "r,L,I,C32"))) + (set (reg:CC_V CC_REG) + (compare:CC_V (sign_extend:DI (minus:SI (match_dup 1) + (match_dup 2))) + (minus:DI (sign_extend:DI (match_dup 1)) + (sign_extend:DI (match_dup 2)))))] + "" + "sub.f\\t%0,%1,%2" + [(set_attr "cond" "set") + (set_attr "type" "compare") + (set_attr "length" "4,4,4,8")]) + +(define_expand "subvsi4" + [(match_operand:SI 0 "register_operand") + (match_operand:SI 1 "register_operand") + (match_operand:SI 2 "nonmemory_operand") + (label_ref (match_operand 3 "" ""))] + "" + "emit_insn (gen_subsi3_v (operands[0], operands[1], operands[2])); + arc_gen_unlikely_cbranch (NE, CC_Vmode, operands[3]); + DONE;") + +(define_insn "subsi3_c" + [(set (match_operand:SI 0 "register_operand" "=r,r,r, r") + (minus:SI (match_operand:SI 1 "register_operand" "r,r,0, r") + (match_operand:SI 2 "nonmemory_operand" "r,L,I,C32"))) + (set (reg:CC_C CC_REG) + (compare:CC_C (match_dup 1) + (match_dup 2)))] + "" + "sub.f\\t%0,%1,%2" + [(set_attr "cond" "set") + (set_attr "type" "compare") + (set_attr "length" "4,4,4,8")]) + +(define_expand "usubvsi4" + [(match_operand:SI 0 "register_operand") + (match_operand:SI 1 "register_operand") + (match_operand:SI 2 "nonmemory_operand") + (label_ref (match_operand 3 "" ""))] + "" + "emit_insn (gen_subsi3_c (operands[0], operands[1], operands[2])); + arc_gen_unlikely_cbranch (LTU, CC_Cmode, operands[3]); + DONE;") + (define_expand "subdi3" [(set (match_operand:DI 0 "register_operand" "") (minus:DI (match_operand:DI 1 "register_operand" "") diff --git a/gcc/config/arc/predicates.md b/gcc/config/arc/predicates.md index 209cda9..f506cee 100644 --- a/gcc/config/arc/predicates.md +++ b/gcc/config/arc/predicates.md @@ -419,6 +419,8 @@ return code == EQ || code == NE; case E_CC_Cmode: return code == LTU || code == GEU; + case E_CC_Vmode: + return code == EQ || code == NE; case E_CC_FP_GTmode: return code == GT || code == UNLE; case E_CC_FP_GEmode: @@ -451,7 +453,12 @@ }) (define_predicate "equality_comparison_operator" - (match_code "eq, ne")) + (match_code "eq, ne") + { + machine_mode opmode = GET_MODE (XEXP (op, 0)); + return opmode != CC_Vmode; + } +) (define_predicate "ge_lt_comparison_operator" (match_code "ge, lt")) |