diff options
author | Yvan Roux <yvan.roux@linaro.org> | 2016-09-04 23:31:27 +0200 |
---|---|---|
committer | Yvan Roux <yvan.roux@linaro.org> | 2016-09-07 22:08:46 +0200 |
commit | 55425e4f7318a3ff62c293a83e864f934ebcd226 (patch) | |
tree | 3f799f3c1d6621ab9b5e150b44b2addeeecd1805 /gcc/config | |
parent | 26468e75ad548f769580df46a67be94c00831935 (diff) |
gcc/
Backport from trunk r239739.
2016-08-24 Michael Collison <michael.collison@linaro.org>
Michael Collison <michael.collison@arm.com>
* config/arm/arm-modes.def: Add new condition code mode CC_V
to represent the overflow bit.
* config/arm/arm.c (maybe_get_arm_condition_code):
Add support for CC_Vmode.
(arm_gen_unlikely_cbranch): New function to generate common
rtl conditional branches for overflow patterns.
* config/arm/arm-protos.h: Add prototype for
arm_gen_unlikely_cbranch.
* config/arm/arm.md (addv<mode>4, add<mode>3_compareV,
addsi3_compareV_upper): New patterns to support signed
builtin overflow add operations.
(uaddv<mode>4, add<mode>3_compareC, addsi3_compareV_upper):
New patterns to support unsigned builtin add overflow operations.
(subv<mode>4, sub<mode>3_compare1): New patterns to support signed
builtin overflow subtract operations,
(usubv<mode>4): New patterns to support unsigned builtin subtract
overflow operations.
(negvsi3, negvdi3, negdi2_compare, negsi2_carryin_compare): New patterns
to support builtin overflow negate operations.
gcc/testsuite/
Backport from trunk r239739.
2016-08-24 Michael Collison <michael.collison@linaro.org>
Michael Collison <michael.collison@arm.com>
* gcc.target/arm/builtin_saddl.c: New testcase.
* gcc.target/arm/builtin_saddll.c: New testcase.
* gcc.target/arm/builtin_uaddl.c: New testcase.
* gcc.target/arm/builtin_uaddll.c: New testcase.
* gcc.target/arm/builtin_ssubl.c: New testcase.
* gcc.target/arm/builtin_ssubll.c: New testcase.
* gcc.target/arm/builtin_usubl.c: New testcase.
* gcc.target/arm/builtin_usubll.c: New testcase.
Change-Id: Ie6127770ef110e76e1e43965e448ea697806f833
Diffstat (limited to 'gcc/config')
-rw-r--r-- | gcc/config/arm/arm-modes.def | 1 | ||||
-rw-r--r-- | gcc/config/arm/arm-protos.h | 2 | ||||
-rw-r--r-- | gcc/config/arm/arm.c | 29 | ||||
-rw-r--r-- | gcc/config/arm/arm.md | 325 |
4 files changed, 357 insertions, 0 deletions
diff --git a/gcc/config/arm/arm-modes.def b/gcc/config/arm/arm-modes.def index 18195534e66..69231f29989 100644 --- a/gcc/config/arm/arm-modes.def +++ b/gcc/config/arm/arm-modes.def @@ -59,6 +59,7 @@ CC_MODE (CC_DGEU); CC_MODE (CC_DGTU); CC_MODE (CC_C); CC_MODE (CC_N); +CC_MODE (CC_V); /* Vector modes. */ VECTOR_MODES (INT, 4); /* V4QI V2HI */ diff --git a/gcc/config/arm/arm-protos.h b/gcc/config/arm/arm-protos.h index 1943907ba48..cc4c65a292d 100644 --- a/gcc/config/arm/arm-protos.h +++ b/gcc/config/arm/arm-protos.h @@ -54,6 +54,8 @@ extern rtx arm_simd_vect_par_cnst_half (machine_mode mode, bool high); extern bool arm_simd_check_vect_par_cnst_half_p (rtx op, machine_mode mode, bool high); #ifdef RTX_CODE +extern void arm_gen_unlikely_cbranch (enum rtx_code, machine_mode cc_mode, + rtx label_ref); extern bool arm_vector_mode_supported_p (machine_mode); extern bool arm_small_register_classes_for_mode_p (machine_mode); extern int arm_hard_regno_mode_ok (unsigned int, machine_mode); diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c index a570e06b11a..b351c55c58c 100644 --- a/gcc/config/arm/arm.c +++ b/gcc/config/arm/arm.c @@ -22934,6 +22934,8 @@ maybe_get_arm_condition_code (rtx comparison) { case LTU: return ARM_CS; case GEU: return ARM_CC; + case NE: return ARM_CS; + case EQ: return ARM_CC; default: return ARM_NV; } @@ -22959,6 +22961,14 @@ maybe_get_arm_condition_code (rtx comparison) default: return ARM_NV; } + case CC_Vmode: + switch (comp_code) + { + case NE: return ARM_VS; + case EQ: return ARM_VC; + default: return ARM_NV; + } + case CCmode: switch (comp_code) { @@ -30528,4 +30538,23 @@ arm_can_output_mi_thunk (const_tree, HOST_WIDE_INT, HOST_WIDE_INT vcall_offset, return true; } +/* Generate RTL for a conditional branch with rtx comparison CODE in + mode CC_MODE. The destination of the unlikely conditional branch + is LABEL_REF. */ + +void +arm_gen_unlikely_cbranch (enum rtx_code code, machine_mode cc_mode, + rtx label_ref) +{ + rtx x; + x = gen_rtx_fmt_ee (code, VOIDmode, + gen_rtx_REG (cc_mode, CC_REGNUM), + const0_rtx); + + x = gen_rtx_IF_THEN_ELSE (VOIDmode, x, + gen_rtx_LABEL_REF (VOIDmode, label_ref), + pc_rtx); + emit_unlikely_jump (gen_rtx_SET (pc_rtx, x)); +} + #include "gt-arm.h" diff --git a/gcc/config/arm/arm.md b/gcc/config/arm/arm.md index 59efdecefa5..f90bf1e81f0 100644 --- a/gcc/config/arm/arm.md +++ b/gcc/config/arm/arm.md @@ -543,6 +543,32 @@ (set_attr "type" "multiple")] ) +(define_expand "addv<mode>4" + [(match_operand:SIDI 0 "register_operand") + (match_operand:SIDI 1 "register_operand") + (match_operand:SIDI 2 "register_operand") + (match_operand 3 "")] + "TARGET_32BIT" +{ + emit_insn (gen_add<mode>3_compareV (operands[0], operands[1], operands[2])); + arm_gen_unlikely_cbranch (NE, CC_Vmode, operands[3]); + + DONE; +}) + +(define_expand "uaddv<mode>4" + [(match_operand:SIDI 0 "register_operand") + (match_operand:SIDI 1 "register_operand") + (match_operand:SIDI 2 "register_operand") + (match_operand 3 "")] + "TARGET_32BIT" +{ + emit_insn (gen_add<mode>3_compareC (operands[0], operands[1], operands[2])); + arm_gen_unlikely_cbranch (NE, CC_Cmode, operands[3]); + + DONE; +}) + (define_expand "addsi3" [(set (match_operand:SI 0 "s_register_operand" "") (plus:SI (match_operand:SI 1 "s_register_operand" "") @@ -620,6 +646,165 @@ ] ) +(define_insn_and_split "adddi3_compareV" + [(set (reg:CC_V CC_REGNUM) + (ne:CC_V + (plus:TI + (sign_extend:TI (match_operand:DI 1 "register_operand" "r")) + (sign_extend:TI (match_operand:DI 2 "register_operand" "r"))) + (sign_extend:TI (plus:DI (match_dup 1) (match_dup 2))))) + (set (match_operand:DI 0 "register_operand" "=&r") + (plus:DI (match_dup 1) (match_dup 2)))] + "TARGET_32BIT" + "#" + "&& reload_completed" + [(parallel [(set (reg:CC_C CC_REGNUM) + (compare:CC_C (plus:SI (match_dup 1) (match_dup 2)) + (match_dup 1))) + (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))]) + (parallel [(set (reg:CC_V CC_REGNUM) + (ne:CC_V + (plus:DI (plus:DI + (sign_extend:DI (match_dup 4)) + (sign_extend:DI (match_dup 5))) + (ltu:DI (reg:CC_C CC_REGNUM) (const_int 0))) + (plus:DI (sign_extend:DI + (plus:SI (match_dup 4) (match_dup 5))) + (ltu:DI (reg:CC_C CC_REGNUM) (const_int 0))))) + (set (match_dup 3) (plus:SI (plus:SI + (match_dup 4) (match_dup 5)) + (ltu:SI (reg:CC_C CC_REGNUM) + (const_int 0))))])] + " + { + operands[3] = gen_highpart (SImode, operands[0]); + operands[0] = gen_lowpart (SImode, operands[0]); + operands[4] = gen_highpart (SImode, operands[1]); + operands[1] = gen_lowpart (SImode, operands[1]); + operands[5] = gen_highpart (SImode, operands[2]); + operands[2] = gen_lowpart (SImode, operands[2]); + }" + [(set_attr "conds" "set") + (set_attr "length" "8") + (set_attr "type" "multiple")] +) + +(define_insn "addsi3_compareV" + [(set (reg:CC_V CC_REGNUM) + (ne:CC_V + (plus:DI + (sign_extend:DI (match_operand:SI 1 "register_operand" "r")) + (sign_extend:DI (match_operand:SI 2 "register_operand" "r"))) + (sign_extend:DI (plus:SI (match_dup 1) (match_dup 2))))) + (set (match_operand:SI 0 "register_operand" "=r") + (plus:SI (match_dup 1) (match_dup 2)))] + "TARGET_32BIT" + "adds%?\\t%0, %1, %2" + [(set_attr "conds" "set") + (set_attr "type" "alus_sreg")] +) + +(define_insn "*addsi3_compareV_upper" + [(set (reg:CC_V CC_REGNUM) + (ne:CC_V + (plus:DI + (plus:DI + (sign_extend:DI (match_operand:SI 1 "register_operand" "r")) + (sign_extend:DI (match_operand:SI 2 "register_operand" "r"))) + (ltu:DI (reg:CC_C CC_REGNUM) (const_int 0))) + (plus:DI (sign_extend:DI + (plus:SI (match_dup 1) (match_dup 2))) + (ltu:DI (reg:CC_C CC_REGNUM) (const_int 0))))) + (set (match_operand:SI 0 "register_operand" "=r") + (plus:SI + (plus:SI (match_dup 1) (match_dup 2)) + (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))] + "TARGET_32BIT" + "adcs%?\\t%0, %1, %2" + [(set_attr "conds" "set") + (set_attr "type" "adcs_reg")] +) + +(define_insn_and_split "adddi3_compareC" + [(set (reg:CC_C CC_REGNUM) + (ne:CC_C + (plus:TI + (zero_extend:TI (match_operand:DI 1 "register_operand" "r")) + (zero_extend:TI (match_operand:DI 2 "register_operand" "r"))) + (zero_extend:TI (plus:DI (match_dup 1) (match_dup 2))))) + (set (match_operand:DI 0 "register_operand" "=&r") + (plus:DI (match_dup 1) (match_dup 2)))] + "TARGET_32BIT" + "#" + "&& reload_completed" + [(parallel [(set (reg:CC_C CC_REGNUM) + (compare:CC_C (plus:SI (match_dup 1) (match_dup 2)) + (match_dup 1))) + (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))]) + (parallel [(set (reg:CC_C CC_REGNUM) + (ne:CC_C + (plus:DI (plus:DI + (zero_extend:DI (match_dup 4)) + (zero_extend:DI (match_dup 5))) + (ltu:DI (reg:CC_C CC_REGNUM) (const_int 0))) + (plus:DI (zero_extend:DI + (plus:SI (match_dup 4) (match_dup 5))) + (ltu:DI (reg:CC_C CC_REGNUM) (const_int 0))))) + (set (match_dup 3) (plus:SI + (plus:SI (match_dup 4) (match_dup 5)) + (ltu:SI (reg:CC_C CC_REGNUM) + (const_int 0))))])] + " + { + operands[3] = gen_highpart (SImode, operands[0]); + operands[0] = gen_lowpart (SImode, operands[0]); + operands[4] = gen_highpart (SImode, operands[1]); + operands[5] = gen_highpart (SImode, operands[2]); + operands[1] = gen_lowpart (SImode, operands[1]); + operands[2] = gen_lowpart (SImode, operands[2]); + }" + [(set_attr "conds" "set") + (set_attr "length" "8") + (set_attr "type" "multiple")] +) + +(define_insn "*addsi3_compareC_upper" + [(set (reg:CC_C CC_REGNUM) + (ne:CC_C + (plus:DI + (plus:DI + (zero_extend:DI (match_operand:SI 1 "register_operand" "r")) + (zero_extend:DI (match_operand:SI 2 "register_operand" "r"))) + (ltu:DI (reg:CC_C CC_REGNUM) (const_int 0))) + (plus:DI (zero_extend:DI + (plus:SI (match_dup 1) (match_dup 2))) + (ltu:DI (reg:CC_C CC_REGNUM) (const_int 0))))) + (set (match_operand:SI 0 "register_operand" "=r") + (plus:SI + (plus:SI (match_dup 1) (match_dup 2)) + (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))] + "TARGET_32BIT" + "adcs%?\\t%0, %1, %2" + [(set_attr "conds" "set") + (set_attr "type" "adcs_reg")] +) + +(define_insn "addsi3_compareC" + [(set (reg:CC_C CC_REGNUM) + (ne:CC_C + (plus:DI + (zero_extend:DI (match_operand:SI 1 "register_operand" "r")) + (zero_extend:DI (match_operand:SI 2 "register_operand" "r"))) + (zero_extend:DI + (plus:SI (match_dup 1) (match_dup 2))))) + (set (match_operand:SI 0 "register_operand" "=r") + (plus:SI (match_dup 1) (match_dup 2)))] + "TARGET_32BIT" + "adds%?\\t%0, %1, %2" + [(set_attr "conds" "set") + (set_attr "type" "alus_sreg")] +) + (define_insn "addsi3_compare0" [(set (reg:CC_NOOV CC_REGNUM) (compare:CC_NOOV @@ -869,6 +1054,75 @@ (set_attr "type" "adcs_reg")] ) +(define_expand "subv<mode>4" + [(match_operand:SIDI 0 "register_operand") + (match_operand:SIDI 1 "register_operand") + (match_operand:SIDI 2 "register_operand") + (match_operand 3 "")] + "TARGET_32BIT" +{ + emit_insn (gen_sub<mode>3_compare1 (operands[0], operands[1], operands[2])); + arm_gen_unlikely_cbranch (NE, CC_Vmode, operands[3]); + + DONE; +}) + +(define_expand "usubv<mode>4" + [(match_operand:SIDI 0 "register_operand") + (match_operand:SIDI 1 "register_operand") + (match_operand:SIDI 2 "register_operand") + (match_operand 3 "")] + "TARGET_32BIT" +{ + emit_insn (gen_sub<mode>3_compare1 (operands[0], operands[1], operands[2])); + arm_gen_unlikely_cbranch (LTU, CCmode, operands[3]); + + DONE; +}) + +(define_insn_and_split "subdi3_compare1" + [(set (reg:CC CC_REGNUM) + (compare:CC + (match_operand:DI 1 "register_operand" "r") + (match_operand:DI 2 "register_operand" "r"))) + (set (match_operand:DI 0 "register_operand" "=&r") + (minus:DI (match_dup 1) (match_dup 2)))] + "TARGET_32BIT" + "#" + "&& reload_completed" + [(parallel [(set (reg:CC CC_REGNUM) + (compare:CC (match_dup 1) (match_dup 2))) + (set (match_dup 0) (minus:SI (match_dup 1) (match_dup 2)))]) + (parallel [(set (reg:CC CC_REGNUM) + (compare:CC (match_dup 4) (match_dup 5))) + (set (match_dup 3) (minus:SI (minus:SI (match_dup 4) (match_dup 5)) + (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))])] + { + operands[3] = gen_highpart (SImode, operands[0]); + operands[0] = gen_lowpart (SImode, operands[0]); + operands[4] = gen_highpart (SImode, operands[1]); + operands[1] = gen_lowpart (SImode, operands[1]); + operands[5] = gen_highpart (SImode, operands[2]); + operands[2] = gen_lowpart (SImode, operands[2]); + } + [(set_attr "conds" "set") + (set_attr "length" "8") + (set_attr "type" "multiple")] +) + +(define_insn "subsi3_compare1" + [(set (reg:CC CC_REGNUM) + (compare:CC + (match_operand:SI 1 "register_operand" "r") + (match_operand:SI 2 "register_operand" "r"))) + (set (match_operand:SI 0 "register_operand" "=r") + (minus:SI (match_dup 1) (match_dup 2)))] + "TARGET_32BIT" + "subs%?\\t%0, %1, %2" + [(set_attr "conds" "set") + (set_attr "type" "alus_sreg")] +) + (define_insn "*subsi3_carryin" [(set (match_operand:SI 0 "s_register_operand" "=r,r") (minus:SI (minus:SI (match_operand:SI 1 "reg_or_int_operand" "r,I") @@ -4350,6 +4604,63 @@ ;; Unary arithmetic insns +(define_expand "negvsi3" + [(match_operand:SI 0 "register_operand") + (match_operand:SI 1 "register_operand") + (match_operand 2 "")] + "TARGET_32BIT" +{ + emit_insn (gen_subsi3_compare (operands[0], const0_rtx, operands[1])); + arm_gen_unlikely_cbranch (NE, CC_Vmode, operands[2]); + + DONE; +}) + +(define_expand "negvdi3" + [(match_operand:DI 0 "register_operand") + (match_operand:DI 1 "register_operand") + (match_operand 2 "")] + "TARGET_ARM" +{ + emit_insn (gen_negdi2_compare (operands[0], operands[1])); + arm_gen_unlikely_cbranch (NE, CC_Vmode, operands[2]); + + DONE; +}) + + +(define_insn_and_split "negdi2_compare" + [(set (reg:CC CC_REGNUM) + (compare:CC + (const_int 0) + (match_operand:DI 1 "register_operand" "0,r"))) + (set (match_operand:DI 0 "register_operand" "=r,&r") + (minus:DI (const_int 0) (match_dup 1)))] + "TARGET_ARM" + "#" + "&& reload_completed" + [(parallel [(set (reg:CC CC_REGNUM) + (compare:CC (const_int 0) (match_dup 1))) + (set (match_dup 0) (minus:SI (const_int 0) + (match_dup 1)))]) + (parallel [(set (reg:CC CC_REGNUM) + (compare:CC (const_int 0) (match_dup 3))) + (set (match_dup 2) + (minus:SI + (minus:SI (const_int 0) (match_dup 3)) + (ltu:SI (reg:CC_C CC_REGNUM) + (const_int 0))))])] + { + operands[2] = gen_highpart (SImode, operands[0]); + operands[0] = gen_lowpart (SImode, operands[0]); + operands[3] = gen_highpart (SImode, operands[1]); + operands[1] = gen_lowpart (SImode, operands[1]); + } + [(set_attr "conds" "set") + (set_attr "length" "8") + (set_attr "type" "multiple")] +) + (define_expand "negdi2" [(parallel [(set (match_operand:DI 0 "s_register_operand" "") @@ -4390,6 +4701,20 @@ (set_attr "type" "multiple")] ) +(define_insn "*negsi2_carryin_compare" + [(set (reg:CC CC_REGNUM) + (compare:CC (const_int 0) + (match_operand:SI 1 "s_register_operand" "r"))) + (set (match_operand:SI 0 "s_register_operand" "=r") + (minus:SI (minus:SI (const_int 0) + (match_dup 1)) + (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))] + "TARGET_ARM" + "rscs\\t%0, %1, #0" + [(set_attr "conds" "set") + (set_attr "type" "alus_imm")] +) + (define_expand "negsi2" [(set (match_operand:SI 0 "s_register_operand" "") (neg:SI (match_operand:SI 1 "s_register_operand" "")))] |