From c8cd4696473a9c803b9454adeee57c90565c2fad Mon Sep 17 00:00:00 2001 From: Michael Collison Date: Wed, 24 Aug 2016 19:31:20 +0000 Subject: [PATCH] arm-modes.def: Add new condition code mode CC_V to represent the overflow bit. 2016-08-24 Michael Collison Michael Collison * 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 (addv4, add3_compareV, addsi3_compareV_upper): New patterns to support signed builtin overflow add operations. (uaddv4, add3_compareC, addsi3_compareV_upper): New patterns to support unsigned builtin add overflow operations. (subv4, sub3_compare1): New patterns to support signed builtin overflow subtract operations, (usubv4): 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.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. Co-Authored-By: Michael Collison From-SVN: r239739 --- gcc/ChangeLog | 23 ++ gcc/config/arm/arm-modes.def | 1 + gcc/config/arm/arm-protos.h | 2 + gcc/config/arm/arm.c | 29 ++ gcc/config/arm/arm.md | 325 ++++++++++++++++++ gcc/testsuite/ChangeLog | 12 + gcc/testsuite/gcc.target/arm/builtin_saddl.c | 17 + gcc/testsuite/gcc.target/arm/builtin_saddll.c | 18 + gcc/testsuite/gcc.target/arm/builtin_ssubl.c | 17 + gcc/testsuite/gcc.target/arm/builtin_ssubll.c | 18 + gcc/testsuite/gcc.target/arm/builtin_uaddl.c | 17 + gcc/testsuite/gcc.target/arm/builtin_uaddll.c | 18 + gcc/testsuite/gcc.target/arm/builtin_usubl.c | 17 + gcc/testsuite/gcc.target/arm/builtin_usubll.c | 18 + 14 files changed, 532 insertions(+) create mode 100644 gcc/testsuite/gcc.target/arm/builtin_saddl.c create mode 100644 gcc/testsuite/gcc.target/arm/builtin_saddll.c create mode 100644 gcc/testsuite/gcc.target/arm/builtin_ssubl.c create mode 100644 gcc/testsuite/gcc.target/arm/builtin_ssubll.c create mode 100644 gcc/testsuite/gcc.target/arm/builtin_uaddl.c create mode 100644 gcc/testsuite/gcc.target/arm/builtin_uaddll.c create mode 100644 gcc/testsuite/gcc.target/arm/builtin_usubl.c create mode 100644 gcc/testsuite/gcc.target/arm/builtin_usubll.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 66ec428cc8e..ef08c0a40fc 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,26 @@ +2016-08-24 Michael Collison + Michael Collison + + * 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 (addv4, add3_compareV, + addsi3_compareV_upper): New patterns to support signed + builtin overflow add operations. + (uaddv4, add3_compareC, addsi3_compareV_upper): + New patterns to support unsigned builtin add overflow operations. + (subv4, sub3_compare1): New patterns to support signed + builtin overflow subtract operations, + (usubv4): New patterns to support unsigned builtin subtract + overflow operations. + (negvsi3, negvdi3, negdi2_compare, negsi2_carryin_compare): New patterns + to support builtin overflow negate operations. + 2016-08-24 Andreas Krebbel Revert 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 3975612f94b..374836cbdd5 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 c1d010cecbc..c775807e76b 100644 --- a/gcc/config/arm/arm.c +++ b/gcc/config/arm/arm.c @@ -22992,6 +22992,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; } @@ -23017,6 +23019,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) { @@ -30575,4 +30585,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 ec1a9ad3324..318db75ece9 100644 --- a/gcc/config/arm/arm.md +++ b/gcc/config/arm/arm.md @@ -547,6 +547,32 @@ (set_attr "type" "multiple")] ) +(define_expand "addv4" + [(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_add3_compareV (operands[0], operands[1], operands[2])); + arm_gen_unlikely_cbranch (NE, CC_Vmode, operands[3]); + + DONE; +}) + +(define_expand "uaddv4" + [(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_add3_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" "") @@ -624,6 +650,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 @@ -873,6 +1058,75 @@ (set_attr "type" "adcs_reg")] ) +(define_expand "subv4" + [(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_sub3_compare1 (operands[0], operands[1], operands[2])); + arm_gen_unlikely_cbranch (NE, CC_Vmode, operands[3]); + + DONE; +}) + +(define_expand "usubv4" + [(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_sub3_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") @@ -4360,6 +4614,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" "") @@ -4400,6 +4711,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" "")))] diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 354e485de44..2393eb5ce57 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,15 @@ +2016-08-24 Michael Collison + Michael Collison + + * 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. + 2016-08-24 Uros Bizjak PR target/77270 diff --git a/gcc/testsuite/gcc.target/arm/builtin_saddl.c b/gcc/testsuite/gcc.target/arm/builtin_saddl.c new file mode 100644 index 00000000000..af85594b9d3 --- /dev/null +++ b/gcc/testsuite/gcc.target/arm/builtin_saddl.c @@ -0,0 +1,17 @@ +/* { dg-do compile } */ +/* { dg-options "-O2" } */ +/* { dg-require-effective-target arm32 } */ +extern void overflow_handler (); + +long overflow_add (long x, long y) +{ + long r; + + int ovr = __builtin_saddl_overflow (x, y, &r); + if (ovr) + overflow_handler (); + + return r; +} + +/* { dg-final { scan-assembler "adds" } } */ diff --git a/gcc/testsuite/gcc.target/arm/builtin_saddll.c b/gcc/testsuite/gcc.target/arm/builtin_saddll.c new file mode 100644 index 00000000000..62fe6eff01f --- /dev/null +++ b/gcc/testsuite/gcc.target/arm/builtin_saddll.c @@ -0,0 +1,18 @@ +/* { dg-do compile } */ +/* { dg-options "-O2" } */ +/* { dg-require-effective-target arm32 } */ +extern void overflow_handler (); + +long long overflow_add (long long x, long long y) +{ + long long r; + + int ovr = __builtin_saddll_overflow (x, y, &r); + if (ovr) + overflow_handler (); + + return r; +} + +/* { dg-final { scan-assembler "adds" } } */ +/* { dg-final { scan-assembler "adcs" } } */ diff --git a/gcc/testsuite/gcc.target/arm/builtin_ssubl.c b/gcc/testsuite/gcc.target/arm/builtin_ssubl.c new file mode 100644 index 00000000000..8c5a4c92168 --- /dev/null +++ b/gcc/testsuite/gcc.target/arm/builtin_ssubl.c @@ -0,0 +1,17 @@ +/* { dg-do compile } */ +/* { dg-options "-O2" } */ +/* { dg-require-effective-target arm32 } */ +extern void overflow_handler (); + +long overflow_sub (long x, long y) +{ + long r; + + int ovr = __builtin_ssubl_overflow (x, y, &r); + if (ovr) + overflow_handler (); + + return r; +} + +/* { dg-final { scan-assembler "subs" } } */ diff --git a/gcc/testsuite/gcc.target/arm/builtin_ssubll.c b/gcc/testsuite/gcc.target/arm/builtin_ssubll.c new file mode 100644 index 00000000000..2048d7915ea --- /dev/null +++ b/gcc/testsuite/gcc.target/arm/builtin_ssubll.c @@ -0,0 +1,18 @@ +/* { dg-do compile } */ +/* { dg-options "-O2" } */ +/* { dg-require-effective-target arm32 } */ +extern void overflow_handler (); + +long long overflow_sub (long long x, long long y) +{ + long long r; + + int ovr = __builtin_ssubll_overflow (x, y, &r); + if (ovr) + overflow_handler (); + + return r; +} + +/* { dg-final { scan-assembler "subs" } } */ +/* { dg-final { scan-assembler "sbcs" } } */ diff --git a/gcc/testsuite/gcc.target/arm/builtin_uaddl.c b/gcc/testsuite/gcc.target/arm/builtin_uaddl.c new file mode 100644 index 00000000000..ac25766c157 --- /dev/null +++ b/gcc/testsuite/gcc.target/arm/builtin_uaddl.c @@ -0,0 +1,17 @@ +/* { dg-do compile } */ +/* { dg-options "-O2" } */ +/* { dg-require-effective-target arm32 } */ +extern void overflow_handler (); + +unsigned long overflow_add (unsigned long x, unsigned long y) +{ + unsigned long r; + + int ovr = __builtin_uaddl_overflow (x, y, &r); + if (ovr) + overflow_handler (); + + return r; +} + +/* { dg-final { scan-assembler "adds" } } */ diff --git a/gcc/testsuite/gcc.target/arm/builtin_uaddll.c b/gcc/testsuite/gcc.target/arm/builtin_uaddll.c new file mode 100644 index 00000000000..ec3188e9067 --- /dev/null +++ b/gcc/testsuite/gcc.target/arm/builtin_uaddll.c @@ -0,0 +1,18 @@ +/* { dg-do compile } */ +/* { dg-options "-O2" } */ +/* { dg-require-effective-target arm32 } */ +extern void overflow_handler (); + +unsigned long long overflow_add (unsigned long long x, unsigned long long y) +{ + unsigned long long r; + + int ovr = __builtin_uaddll_overflow (x, y, &r); + if (ovr) + overflow_handler (); + + return r; +} + +/* { dg-final { scan-assembler "adds" } } */ +/* { dg-final { scan-assembler "adcs" } } */ diff --git a/gcc/testsuite/gcc.target/arm/builtin_usubl.c b/gcc/testsuite/gcc.target/arm/builtin_usubl.c new file mode 100644 index 00000000000..99782083d45 --- /dev/null +++ b/gcc/testsuite/gcc.target/arm/builtin_usubl.c @@ -0,0 +1,17 @@ +/* { dg-do compile } */ +/* { dg-options "-O2" } */ +/* { dg-require-effective-target arm32 } */ +extern void overflow_handler (); + +unsigned long overflow_sub (unsigned long x, unsigned long y) +{ + unsigned long r; + + int ovr = __builtin_usubl_overflow (x, y, &r); + if (ovr) + overflow_handler (); + + return r; +} + +/* { dg-final { scan-assembler "subs" } } */ diff --git a/gcc/testsuite/gcc.target/arm/builtin_usubll.c b/gcc/testsuite/gcc.target/arm/builtin_usubll.c new file mode 100644 index 00000000000..8d64660a813 --- /dev/null +++ b/gcc/testsuite/gcc.target/arm/builtin_usubll.c @@ -0,0 +1,18 @@ +/* { dg-do compile } */ +/* { dg-options "-O2" } */ +/* { dg-require-effective-target arm32 } */ +extern void overflow_handler (); + +unsigned long long overflow_sub (unsigned long long x, unsigned long long y) +{ + unsigned long long r; + + int ovr = __builtin_usubll_overflow (x, y, &r); + if (ovr) + overflow_handler (); + + return r; +} + +/* { dg-final { scan-assembler "subs" } } */ +/* { dg-final { scan-assembler "sbcs" } } */ -- 2.30.2