diff options
author | Michael Collison <michael.collison@arm.com> | 2018-07-19 20:24:47 +0000 |
---|---|---|
committer | Michael Collison <collison@gcc.gnu.org> | 2018-07-19 20:24:47 +0000 |
commit | 30c460535576882863fe4e0db740b4ac4bcfaba9 (patch) | |
tree | e3f57437a11137166c2b81807d77c72acaaa42d7 /gcc | |
parent | c01f9216b73597b7dc03d9387ac7e21a5089f801 (diff) | |
download | gcc-30c460535576882863fe4e0db740b4ac4bcfaba9.zip gcc-30c460535576882863fe4e0db740b4ac4bcfaba9.tar.gz gcc-30c460535576882863fe4e0db740b4ac4bcfaba9.tar.bz2 |
aarch64.md (subv<GPI>4, [...]): New patterns.
2018-07-19 Michael Collison <michael.collison@arm.com>
Richard Henderson <rth@redhat.com>
* config/aarch64/aarch64.md (subv<GPI>4, usubv<GPI>4): New patterns.
(subti): Handle op1 zero.
(subvti4, usub4ti4): New.
(*sub<GPI>3_compare1_imm): New.
(sub<GPI>3_carryinCV): New.
(*sub<GPI>3_carryinCV_z1_z2, *sub<GPI>3_carryinCV_z1): New.
(*sub<GPI>3_carryinCV_z2, *sub<GPI>3_carryinCV): New.
2018-07-19 Michael Collison <michael.collison@arm.com>
Richard Henderson <rth@redhat.com>
* config/aarch64/aarch64.md: (addv<GPI>4, uaddv<GPI>4): New.
(addti3): Create simpler code if low part is already known to be 0.
(addvti4, uaddvti4): New.
(*add<GPI>3_compareC_cconly_imm): New.
(*add<GPI>3_compareC_cconly): New.
(*add<GPI>3_compareC_imm): New.
(*add<GPI>3_compareC): Rename from add<GPI>3_compare1; do not
handle constants within this pattern..
(*add<GPI>3_compareV_cconly_imm): New.
(*add<GPI>3_compareV_cconly): New.
(*add<GPI>3_compareV_imm): New.
(add<GPI>3_compareV): New.
(add<GPI>3_carryinC, add<GPI>3_carryinV): New.
(*add<GPI>3_carryinC_zero, *add<GPI>3_carryinV_zero): New.
(*add<GPI>3_carryinC, *add<GPI>3_carryinV): New.
((*add<GPI>3_compareC_cconly_imm): Replace 'ne' operator
with 'comparison' operator.
(*add<GPI>3_compareV_cconly_imm): Ditto.
(*add<GPI>3_compareV_cconly): Ditto.
(*add<GPI>3_compareV_imm): Ditto.
(add<GPI>3_compareV): Ditto.
(add<mode>3_carryinC): Ditto.
(*add<mode>3_carryinC_zero): Ditto.
(*add<mode>3_carryinC): Ditto.
(add<mode>3_carryinV): Ditto.
(*add<mode>3_carryinV_zero): Ditto.
(*add<mode>3_carryinV): Ditto.
2018-07-19 Michael Collison <michael.collison@arm.com>
Richard Henderson <rth@redhat.com>
* config/aarch64/aarch64-modes.def (CC_V): New.
* config/aarch64/aarch64-protos.h
(aarch64_addti_scratch_regs): Declare
(aarch64_subvti_scratch_regs): Declare.
(aarch64_expand_subvti): Declare.
(aarch64_gen_unlikely_cbranch): Declare
* config/aarch64/aarch64.c (aarch64_select_cc_mode): Test
for signed overflow using CC_Vmode.
(aarch64_get_condition_code_1): Handle CC_Vmode.
(aarch64_gen_unlikely_cbranch): New function.
(aarch64_addti_scratch_regs): New function.
(aarch64_subvti_scratch_regs): New function.
(aarch64_expand_subvti): New function.
2018-07-19 Michael Collison <michael.collison@arm.com>
Richard Henderson <rth@redhat.com>
* gcc.target/aarch64/builtin_sadd_128.c: New testcase.
* gcc.target/aarch64/builtin_saddl.c: New testcase.
* gcc.target/aarch64/builtin_saddll.c: New testcase.
* gcc.target/aarch64/builtin_uadd_128.c: New testcase.
* gcc.target/aarch64/builtin_uaddl.c: New testcase.
* gcc.target/aarch64/builtin_uaddll.c: New testcase.
* gcc.target/aarch64/builtin_ssub_128.c: New testcase.
* gcc.target/aarch64/builtin_ssubl.c: New testcase.
* gcc.target/aarch64/builtin_ssubll.c: New testcase.
* gcc.target/aarch64/builtin_usub_128.c: New testcase.
* gcc.target/aarch64/builtin_usubl.c: New testcase.
* gcc.target/aarch64/builtin_usubll.c: New testcase.
Co-Authored-By: Richard Henderson <rth@redhat.com>
From-SVN: r262890
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 59 | ||||
-rw-r--r-- | gcc/config/aarch64/aarch64-modes.def | 1 | ||||
-rw-r--r-- | gcc/config/aarch64/aarch64-protos.h | 13 | ||||
-rw-r--r-- | gcc/config/aarch64/aarch64.c | 141 | ||||
-rw-r--r-- | gcc/config/aarch64/aarch64.md | 501 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 16 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/aarch64/builtin_sadd_128.c | 18 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/aarch64/builtin_saddl.c | 17 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/aarch64/builtin_saddll.c | 18 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/aarch64/builtin_ssub_128.c | 18 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/aarch64/builtin_ssubl.c | 17 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/aarch64/builtin_ssubll.c | 18 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/aarch64/builtin_uadd_128.c | 18 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/aarch64/builtin_uaddl.c | 17 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/aarch64/builtin_uaddll.c | 18 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/aarch64/builtin_usub_128.c | 18 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/aarch64/builtin_usubl.c | 17 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/aarch64/builtin_usubll.c | 18 |
18 files changed, 922 insertions, 21 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 0c998af..bb4ed8e 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,62 @@ +2018-07-19 Michael Collison <michael.collison@arm.com> + Richard Henderson <rth@redhat.com> + + * config/aarch64/aarch64.md (subv<GPI>4, usubv<GPI>4): New patterns. + (subti): Handle op1 zero. + (subvti4, usub4ti4): New. + (*sub<GPI>3_compare1_imm): New. + (sub<GPI>3_carryinCV): New. + (*sub<GPI>3_carryinCV_z1_z2, *sub<GPI>3_carryinCV_z1): New. + (*sub<GPI>3_carryinCV_z2, *sub<GPI>3_carryinCV): New. + +2018-07-19 Michael Collison <michael.collison@arm.com> + Richard Henderson <rth@redhat.com> + + * config/aarch64/aarch64.md: (addv<GPI>4, uaddv<GPI>4): New. + (addti3): Create simpler code if low part is already known to be 0. + (addvti4, uaddvti4): New. + (*add<GPI>3_compareC_cconly_imm): New. + (*add<GPI>3_compareC_cconly): New. + (*add<GPI>3_compareC_imm): New. + (*add<GPI>3_compareC): Rename from add<GPI>3_compare1; do not + handle constants within this pattern.. + (*add<GPI>3_compareV_cconly_imm): New. + (*add<GPI>3_compareV_cconly): New. + (*add<GPI>3_compareV_imm): New. + (add<GPI>3_compareV): New. + (add<GPI>3_carryinC, add<GPI>3_carryinV): New. + (*add<GPI>3_carryinC_zero, *add<GPI>3_carryinV_zero): New. + (*add<GPI>3_carryinC, *add<GPI>3_carryinV): New. + ((*add<GPI>3_compareC_cconly_imm): Replace 'ne' operator + with 'comparison' operator. + (*add<GPI>3_compareV_cconly_imm): Ditto. + (*add<GPI>3_compareV_cconly): Ditto. + (*add<GPI>3_compareV_imm): Ditto. + (add<GPI>3_compareV): Ditto. + (add<mode>3_carryinC): Ditto. + (*add<mode>3_carryinC_zero): Ditto. + (*add<mode>3_carryinC): Ditto. + (add<mode>3_carryinV): Ditto. + (*add<mode>3_carryinV_zero): Ditto. + (*add<mode>3_carryinV): Ditto. + +2018-07-19 Michael Collison <michael.collison@arm.com> + Richard Henderson <rth@redhat.com> + + * config/aarch64/aarch64-modes.def (CC_V): New. + * config/aarch64/aarch64-protos.h + (aarch64_addti_scratch_regs): Declare + (aarch64_subvti_scratch_regs): Declare. + (aarch64_expand_subvti): Declare. + (aarch64_gen_unlikely_cbranch): Declare + * config/aarch64/aarch64.c (aarch64_select_cc_mode): Test + for signed overflow using CC_Vmode. + (aarch64_get_condition_code_1): Handle CC_Vmode. + (aarch64_gen_unlikely_cbranch): New function. + (aarch64_addti_scratch_regs): New function. + (aarch64_subvti_scratch_regs): New function. + (aarch64_expand_subvti): New function. + 2018-07-19 Andre Vieira <andre.simoesdiasvieira@arm.com> * config/aarch64/aarch64-option-extensions.def: New entry for profile diff --git a/gcc/config/aarch64/aarch64-modes.def b/gcc/config/aarch64/aarch64-modes.def index 1a05b6c..ea7ecc2 100644 --- a/gcc/config/aarch64/aarch64-modes.def +++ b/gcc/config/aarch64/aarch64-modes.def @@ -24,6 +24,7 @@ CC_MODE (CC_SWP); CC_MODE (CC_NZ); /* Only N and Z bits of condition flags are valid. */ CC_MODE (CC_Z); /* Only Z bit of condition flags is valid. */ CC_MODE (CC_C); /* Only C bit of condition flags is valid. */ +CC_MODE (CC_V); /* Only V bit of condition flags is valid. */ /* Half-precision floating point for __fp16. */ FLOAT_MODE (HF, 2, 0); diff --git a/gcc/config/aarch64/aarch64-protos.h b/gcc/config/aarch64/aarch64-protos.h index 5d07583..af5db9c 100644 --- a/gcc/config/aarch64/aarch64-protos.h +++ b/gcc/config/aarch64/aarch64-protos.h @@ -472,6 +472,16 @@ void aarch64_relayout_simd_types (void); void aarch64_reset_previous_fndecl (void); bool aarch64_return_address_signing_enabled (void); void aarch64_save_restore_target_globals (tree); +void aarch64_addti_scratch_regs (rtx, rtx, rtx *, + rtx *, rtx *, + rtx *, rtx *, + rtx *); +void aarch64_subvti_scratch_regs (rtx, rtx, rtx *, + rtx *, rtx *, + rtx *, rtx *, rtx *); +void aarch64_expand_subvti (rtx, rtx, rtx, + rtx, rtx, rtx, rtx); + /* Initialize builtins for SIMD intrinsics. */ void init_aarch64_simd_builtins (void); @@ -498,7 +508,8 @@ void aarch64_split_simd_move (rtx, rtx); bool aarch64_float_const_representable_p (rtx); #if defined (RTX_CODE) - +void aarch64_gen_unlikely_cbranch (enum rtx_code, machine_mode cc_mode, + rtx label_ref); bool aarch64_legitimate_address_p (machine_mode, rtx, bool, aarch64_addr_query_type = ADDR_QUERY_M); machine_mode aarch64_select_cc_mode (RTX_CODE, rtx, rtx); diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c index 046195c..fa01475 100644 --- a/gcc/config/aarch64/aarch64.c +++ b/gcc/config/aarch64/aarch64.c @@ -6414,6 +6414,13 @@ aarch64_select_cc_mode (RTX_CODE code, rtx x, rtx y) && GET_CODE (y) == ZERO_EXTEND) return CC_Cmode; + /* A test for signed overflow. */ + if ((GET_MODE (x) == DImode || GET_MODE (x) == TImode) + && code == NE + && GET_CODE (x) == PLUS + && GET_CODE (y) == SIGN_EXTEND) + return CC_Vmode; + /* For everything else, return CCmode. */ return CCmode; } @@ -6520,6 +6527,15 @@ aarch64_get_condition_code_1 (machine_mode mode, enum rtx_code comp_code) } break; + case E_CC_Vmode: + switch (comp_code) + { + case NE: return AARCH64_VS; + case EQ: return AARCH64_VC; + default: return -1; + } + break; + default: return -1; } @@ -16274,6 +16290,131 @@ aarch64_split_dimode_const_store (rtx dst, rtx src) 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 +aarch64_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); + aarch64_emit_unlikely_jump (gen_rtx_SET (pc_rtx, x)); +} + +/* Generate DImode scratch registers for 128-bit (TImode) addition. + + OP1 represents the TImode destination operand 1 + OP2 represents the TImode destination operand 2 + LOW_DEST represents the low half (DImode) of TImode operand 0 + LOW_IN1 represents the low half (DImode) of TImode operand 1 + LOW_IN2 represents the low half (DImode) of TImode operand 2 + HIGH_DEST represents the high half (DImode) of TImode operand 0 + HIGH_IN1 represents the high half (DImode) of TImode operand 1 + HIGH_IN2 represents the high half (DImode) of TImode operand 2. */ + +void +aarch64_addti_scratch_regs (rtx op1, rtx op2, rtx *low_dest, + rtx *low_in1, rtx *low_in2, + rtx *high_dest, rtx *high_in1, + rtx *high_in2) +{ + *low_dest = gen_reg_rtx (DImode); + *low_in1 = gen_lowpart (DImode, op1); + *low_in2 = simplify_gen_subreg (DImode, op2, TImode, + subreg_lowpart_offset (DImode, TImode)); + *high_dest = gen_reg_rtx (DImode); + *high_in1 = gen_highpart (DImode, op1); + *high_in2 = simplify_gen_subreg (DImode, op2, TImode, + subreg_highpart_offset (DImode, TImode)); +} + +/* Generate DImode scratch registers for 128-bit (TImode) subtraction. + + This function differs from 'arch64_addti_scratch_regs' in that + OP1 can be an immediate constant (zero). We must call + subreg_highpart_offset with DImode and TImode arguments, otherwise + VOIDmode will be used for the const_int which generates an internal + error from subreg_size_highpart_offset which does not expect a size of zero. + + OP1 represents the TImode destination operand 1 + OP2 represents the TImode destination operand 2 + LOW_DEST represents the low half (DImode) of TImode operand 0 + LOW_IN1 represents the low half (DImode) of TImode operand 1 + LOW_IN2 represents the low half (DImode) of TImode operand 2 + HIGH_DEST represents the high half (DImode) of TImode operand 0 + HIGH_IN1 represents the high half (DImode) of TImode operand 1 + HIGH_IN2 represents the high half (DImode) of TImode operand 2. */ + + +void +aarch64_subvti_scratch_regs (rtx op1, rtx op2, rtx *low_dest, + rtx *low_in1, rtx *low_in2, + rtx *high_dest, rtx *high_in1, + rtx *high_in2) +{ + *low_dest = gen_reg_rtx (DImode); + *low_in1 = simplify_gen_subreg (DImode, op1, TImode, + subreg_lowpart_offset (DImode, TImode)); + + *low_in2 = simplify_gen_subreg (DImode, op2, TImode, + subreg_lowpart_offset (DImode, TImode)); + *high_dest = gen_reg_rtx (DImode); + + *high_in1 = simplify_gen_subreg (DImode, op1, TImode, + subreg_highpart_offset (DImode, TImode)); + *high_in2 = simplify_gen_subreg (DImode, op2, TImode, + subreg_highpart_offset (DImode, TImode)); +} + +/* Generate RTL for 128-bit (TImode) subtraction with overflow. + + OP0 represents the TImode destination operand 0 + LOW_DEST represents the low half (DImode) of TImode operand 0 + LOW_IN1 represents the low half (DImode) of TImode operand 1 + LOW_IN2 represents the low half (DImode) of TImode operand 2 + HIGH_DEST represents the high half (DImode) of TImode operand 0 + HIGH_IN1 represents the high half (DImode) of TImode operand 1 + HIGH_IN2 represents the high half (DImode) of TImode operand 2. */ + +void +aarch64_expand_subvti (rtx op0, rtx low_dest, rtx low_in1, + rtx low_in2, rtx high_dest, rtx high_in1, + rtx high_in2) +{ + if (low_in2 == const0_rtx) + { + low_dest = low_in1; + emit_insn (gen_subdi3_compare1 (high_dest, high_in1, + force_reg (DImode, high_in2))); + } + else + { + if (CONST_INT_P (low_in2)) + { + low_in2 = force_reg (DImode, GEN_INT (-UINTVAL (low_in2))); + high_in2 = force_reg (DImode, high_in2); + emit_insn (gen_adddi3_compareC (low_dest, low_in1, low_in2)); + } + else + emit_insn (gen_subdi3_compare1 (low_dest, low_in1, low_in2)); + emit_insn (gen_subdi3_carryinCV (high_dest, + force_reg (DImode, high_in1), + high_in2)); + } + + emit_move_insn (gen_lowpart (DImode, op0), low_dest); + emit_move_insn (gen_highpart (DImode, op0), high_dest); + +} + /* Implement the TARGET_ASAN_SHADOW_OFFSET hook. */ static unsigned HOST_WIDE_INT diff --git a/gcc/config/aarch64/aarch64.md b/gcc/config/aarch64/aarch64.md index a014a01..e9c16f9 100644 --- a/gcc/config/aarch64/aarch64.md +++ b/gcc/config/aarch64/aarch64.md @@ -1726,25 +1726,133 @@ } ) +(define_expand "addv<mode>4" + [(match_operand:GPI 0 "register_operand") + (match_operand:GPI 1 "register_operand") + (match_operand:GPI 2 "register_operand") + (label_ref (match_operand 3 "" ""))] + "" +{ + emit_insn (gen_add<mode>3_compareV (operands[0], operands[1], operands[2])); + aarch64_gen_unlikely_cbranch (NE, CC_Vmode, operands[3]); + + DONE; +}) + +(define_expand "uaddv<mode>4" + [(match_operand:GPI 0 "register_operand") + (match_operand:GPI 1 "register_operand") + (match_operand:GPI 2 "register_operand") + (label_ref (match_operand 3 "" ""))] + "" +{ + emit_insn (gen_add<mode>3_compareC (operands[0], operands[1], operands[2])); + aarch64_gen_unlikely_cbranch (NE, CC_Cmode, operands[3]); + + DONE; +}) + (define_expand "addti3" [(set (match_operand:TI 0 "register_operand" "") (plus:TI (match_operand:TI 1 "register_operand" "") - (match_operand:TI 2 "register_operand" "")))] + (match_operand:TI 2 "aarch64_reg_or_imm" "")))] "" { - rtx low = gen_reg_rtx (DImode); - emit_insn (gen_adddi3_compareC (low, gen_lowpart (DImode, operands[1]), - gen_lowpart (DImode, operands[2]))); + rtx low_dest, op1_low, op2_low, high_dest, op1_high, op2_high; - rtx high = gen_reg_rtx (DImode); - emit_insn (gen_adddi3_carryin (high, gen_highpart (DImode, operands[1]), - gen_highpart (DImode, operands[2]))); + aarch64_addti_scratch_regs (operands[1], operands[2], + &low_dest, &op1_low, &op2_low, + &high_dest, &op1_high, &op2_high); - emit_move_insn (gen_lowpart (DImode, operands[0]), low); - emit_move_insn (gen_highpart (DImode, operands[0]), high); + if (op2_low == const0_rtx) + { + low_dest = op1_low; + if (!aarch64_pluslong_operand (op2_high, DImode)) + op2_high = force_reg (DImode, op2_high); + emit_insn (gen_adddi3 (high_dest, op1_high, op2_high)); + } + else + { + emit_insn (gen_adddi3_compareC (low_dest, op1_low, + force_reg (DImode, op2_low))); + emit_insn (gen_adddi3_carryin (high_dest, op1_high, + force_reg (DImode, op2_high))); + } + + emit_move_insn (gen_lowpart (DImode, operands[0]), low_dest); + emit_move_insn (gen_highpart (DImode, operands[0]), high_dest); + + DONE; +}) + +(define_expand "addvti4" + [(match_operand:TI 0 "register_operand" "") + (match_operand:TI 1 "register_operand" "") + (match_operand:TI 2 "aarch64_reg_or_imm" "") + (label_ref (match_operand 3 "" ""))] + "" +{ + rtx low_dest, op1_low, op2_low, high_dest, op1_high, op2_high; + + aarch64_addti_scratch_regs (operands[1], operands[2], + &low_dest, &op1_low, &op2_low, + &high_dest, &op1_high, &op2_high); + + if (op2_low == const0_rtx) + { + low_dest = op1_low; + emit_insn (gen_adddi3_compareV (high_dest, op1_high, + force_reg (DImode, op2_high))); + } + else + { + emit_insn (gen_adddi3_compareC (low_dest, op1_low, + force_reg (DImode, op2_low))); + emit_insn (gen_adddi3_carryinV (high_dest, op1_high, + force_reg (DImode, op2_high))); + } + + emit_move_insn (gen_lowpart (DImode, operands[0]), low_dest); + emit_move_insn (gen_highpart (DImode, operands[0]), high_dest); + + aarch64_gen_unlikely_cbranch (NE, CC_Vmode, operands[3]); DONE; }) +(define_expand "uaddvti4" + [(match_operand:TI 0 "register_operand" "") + (match_operand:TI 1 "register_operand" "") + (match_operand:TI 2 "aarch64_reg_or_imm" "") + (label_ref (match_operand 3 "" ""))] + "" +{ + rtx low_dest, op1_low, op2_low, high_dest, op1_high, op2_high; + + aarch64_addti_scratch_regs (operands[1], operands[2], + &low_dest, &op1_low, &op2_low, + &high_dest, &op1_high, &op2_high); + + if (op2_low == const0_rtx) + { + low_dest = op1_low; + emit_insn (gen_adddi3_compareC (high_dest, op1_high, + force_reg (DImode, op2_high))); + } + else + { + emit_insn (gen_adddi3_compareC (low_dest, op1_low, + force_reg (DImode, op2_low))); + emit_insn (gen_adddi3_carryinC (high_dest, op1_high, + force_reg (DImode, op2_high))); + } + + emit_move_insn (gen_lowpart (DImode, operands[0]), low_dest); + emit_move_insn (gen_highpart (DImode, operands[0]), high_dest); + + aarch64_gen_unlikely_cbranch (NE, CC_Cmode, operands[3]); + DONE; + }) + (define_insn "add<mode>3_compare0" [(set (reg:CC_NZ CC_REGNUM) (compare:CC_NZ @@ -1830,7 +1938,7 @@ (define_insn "add<mode>3_compareC" [(set (reg:CC_C CC_REGNUM) - (ne:CC_C + (compare:CC_C (plus:<DWI> (zero_extend:<DWI> (match_operand:GPI 1 "register_operand" "r")) (zero_extend:<DWI> (match_operand:GPI 2 "register_operand" "r"))) @@ -1843,10 +1951,71 @@ [(set_attr "type" "alus_sreg")] ) +(define_insn "*add<mode>3_compareV_cconly_imm" + [(set (reg:CC_V CC_REGNUM) + (compare:CC_V + (plus:<DWI> + (sign_extend:<DWI> (match_operand:GPI 0 "register_operand" "r,r")) + (match_operand:<DWI> 1 "const_scalar_int_operand" "")) + (sign_extend:<DWI> + (plus:GPI + (match_dup 0) + (match_operand:GPI 2 "aarch64_plus_immediate" "I,J")))))] + "INTVAL (operands[1]) == INTVAL (operands[2])" + "@ + cmn\\t%<w>0, %<w>1 + cmp\\t%<w>0, #%n1" + [(set_attr "type" "alus_imm")] +) + +(define_insn "*add<mode>3_compareV_cconly" + [(set (reg:CC_V CC_REGNUM) + (compare:CC_V + (plus:<DWI> + (sign_extend:<DWI> (match_operand:GPI 0 "register_operand" "r")) + (sign_extend:<DWI> (match_operand:GPI 1 "register_operand" "r"))) + (sign_extend:<DWI> (plus:GPI (match_dup 0) (match_dup 1)))))] + "" + "cmn\\t%<w>0, %<w>1" + [(set_attr "type" "alus_sreg")] +) + +(define_insn "*add<mode>3_compareV_imm" + [(set (reg:CC_V CC_REGNUM) + (compare:CC_V + (plus:<DWI> + (sign_extend:<DWI> + (match_operand:GPI 1 "register_operand" "r,r")) + (match_operand:GPI 2 "aarch64_plus_immediate" "I,J")) + (sign_extend:<DWI> + (plus:GPI (match_dup 1) (match_dup 2))))) + (set (match_operand:GPI 0 "register_operand" "=r,r") + (plus:GPI (match_dup 1) (match_dup 2)))] + "" + "@ + adds\\t%<w>0, %<w>1, %<w>2 + subs\\t%<w>0, %<w>1, #%n2" + [(set_attr "type" "alus_imm,alus_imm")] +) + +(define_insn "add<mode>3_compareV" + [(set (reg:CC_V CC_REGNUM) + (compare:CC_V + (plus:<DWI> + (sign_extend:<DWI> (match_operand:GPI 1 "register_operand" "r")) + (sign_extend:<DWI> (match_operand:GPI 2 "register_operand" "r"))) + (sign_extend:<DWI> (plus:GPI (match_dup 1) (match_dup 2))))) + (set (match_operand:GPI 0 "register_operand" "=r") + (plus:GPI (match_dup 1) (match_dup 2)))] + "" + "adds\\t%<w>0, %<w>1, %<w>2" + [(set_attr "type" "alus_sreg")] +) + (define_insn "*adds_shift_imm_<mode>" [(set (reg:CC_NZ CC_REGNUM) (compare:CC_NZ - (plus:GPI (ASHIFT:GPI + (plus:GPI (ASHIFT:GPI (match_operand:GPI 1 "register_operand" "r") (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n")) (match_operand:GPI 3 "register_operand" "r")) @@ -2213,6 +2382,138 @@ [(set_attr "type" "adc_reg")] ) +(define_expand "add<mode>3_carryinC" + [(parallel + [(set (match_dup 3) + (compare:CC_C + (plus:<DWI> + (plus:<DWI> + (match_dup 4) + (zero_extend:<DWI> + (match_operand:GPI 1 "register_operand" ""))) + (zero_extend:<DWI> + (match_operand:GPI 2 "register_operand" ""))) + (zero_extend:<DWI> + (plus:GPI + (plus:GPI (match_dup 5) (match_dup 1)) + (match_dup 2))))) + (set (match_operand:GPI 0 "register_operand") + (plus:GPI + (plus:GPI (match_dup 5) (match_dup 1)) + (match_dup 2)))])] + "" +{ + operands[3] = gen_rtx_REG (CC_Cmode, CC_REGNUM); + operands[4] = gen_rtx_NE (<DWI>mode, operands[3], const0_rtx); + operands[5] = gen_rtx_NE (<MODE>mode, operands[3], const0_rtx); +}) + +(define_insn "*add<mode>3_carryinC_zero" + [(set (reg:CC_C CC_REGNUM) + (compare:CC_C + (plus:<DWI> + (match_operand:<DWI> 2 "aarch64_carry_operation" "") + (zero_extend:<DWI> (match_operand:GPI 1 "register_operand" "r"))) + (zero_extend:<DWI> + (plus:GPI + (match_operand:GPI 3 "aarch64_carry_operation" "") + (match_dup 1))))) + (set (match_operand:GPI 0 "register_operand") + (plus:GPI (match_dup 3) (match_dup 1)))] + "" + "adcs\\t%<w>0, %<w>1, <w>zr" + [(set_attr "type" "adc_reg")] +) + +(define_insn "*add<mode>3_carryinC" + [(set (reg:CC_C CC_REGNUM) + (compare:CC_C + (plus:<DWI> + (plus:<DWI> + (match_operand:<DWI> 3 "aarch64_carry_operation" "") + (zero_extend:<DWI> (match_operand:GPI 1 "register_operand" "r"))) + (zero_extend:<DWI> (match_operand:GPI 2 "register_operand" "r"))) + (zero_extend:<DWI> + (plus:GPI + (plus:GPI + (match_operand:GPI 4 "aarch64_carry_operation" "") + (match_dup 1)) + (match_dup 2))))) + (set (match_operand:GPI 0 "register_operand") + (plus:GPI + (plus:GPI (match_dup 4) (match_dup 1)) + (match_dup 2)))] + "" + "adcs\\t%<w>0, %<w>1, %<w>2" + [(set_attr "type" "adc_reg")] +) + +(define_expand "add<mode>3_carryinV" + [(parallel + [(set (reg:CC_V CC_REGNUM) + (compare:CC_V + (plus:<DWI> + (plus:<DWI> + (match_dup 3) + (sign_extend:<DWI> + (match_operand:GPI 1 "register_operand" ""))) + (sign_extend:<DWI> + (match_operand:GPI 2 "register_operand" ""))) + (sign_extend:<DWI> + (plus:GPI + (plus:GPI (match_dup 4) (match_dup 1)) + (match_dup 2))))) + (set (match_operand:GPI 0 "register_operand") + (plus:GPI + (plus:GPI (match_dup 4) (match_dup 1)) + (match_dup 2)))])] + "" +{ + rtx cc = gen_rtx_REG (CC_Cmode, CC_REGNUM); + operands[3] = gen_rtx_NE (<DWI>mode, cc, const0_rtx); + operands[4] = gen_rtx_NE (<MODE>mode, cc, const0_rtx); +}) + +(define_insn "*add<mode>3_carryinV_zero" + [(set (reg:CC_V CC_REGNUM) + (compare:CC_V + (plus:<DWI> + (match_operand:<DWI> 2 "aarch64_carry_operation" "") + (sign_extend:<DWI> (match_operand:GPI 1 "register_operand" "r"))) + (sign_extend:<DWI> + (plus:GPI + (match_operand:GPI 3 "aarch64_carry_operation" "") + (match_dup 1))))) + (set (match_operand:GPI 0 "register_operand") + (plus:GPI (match_dup 3) (match_dup 1)))] + "" + "adcs\\t%<w>0, %<w>1, <w>zr" + [(set_attr "type" "adc_reg")] +) + +(define_insn "*add<mode>3_carryinV" + [(set (reg:CC_V CC_REGNUM) + (compare:CC_V + (plus:<DWI> + (plus:<DWI> + (match_operand:<DWI> 3 "aarch64_carry_operation" "") + (sign_extend:<DWI> (match_operand:GPI 1 "register_operand" "r"))) + (sign_extend:<DWI> (match_operand:GPI 2 "register_operand" "r"))) + (sign_extend:<DWI> + (plus:GPI + (plus:GPI + (match_operand:GPI 4 "aarch64_carry_operation" "") + (match_dup 1)) + (match_dup 2))))) + (set (match_operand:GPI 0 "register_operand") + (plus:GPI + (plus:GPI (match_dup 4) (match_dup 1)) + (match_dup 2)))] + "" + "adcs\\t%<w>0, %<w>1, %<w>2" + [(set_attr "type" "adc_reg")] +) + (define_insn "*add_uxt<mode>_shift2" [(set (match_operand:GPI 0 "register_operand" "=rk") (plus:GPI (and:GPI @@ -2309,22 +2610,87 @@ (set_attr "simd" "*,yes")] ) +(define_expand "subv<mode>4" + [(match_operand:GPI 0 "register_operand") + (match_operand:GPI 1 "aarch64_reg_or_zero") + (match_operand:GPI 2 "aarch64_reg_or_zero") + (label_ref (match_operand 3 "" ""))] + "" +{ + emit_insn (gen_sub<mode>3_compare1 (operands[0], operands[1], operands[2])); + aarch64_gen_unlikely_cbranch (NE, CC_Vmode, operands[3]); + + DONE; +}) + +(define_expand "usubv<mode>4" + [(match_operand:GPI 0 "register_operand") + (match_operand:GPI 1 "aarch64_reg_or_zero") + (match_operand:GPI 2 "aarch64_reg_or_zero") + (label_ref (match_operand 3 "" ""))] + "" +{ + emit_insn (gen_sub<mode>3_compare1 (operands[0], operands[1], operands[2])); + aarch64_gen_unlikely_cbranch (LTU, CCmode, operands[3]); + + DONE; +}) + (define_expand "subti3" [(set (match_operand:TI 0 "register_operand" "") - (minus:TI (match_operand:TI 1 "register_operand" "") + (minus:TI (match_operand:TI 1 "aarch64_reg_or_zero" "") (match_operand:TI 2 "register_operand" "")))] "" { - rtx low = gen_reg_rtx (DImode); - emit_insn (gen_subdi3_compare1 (low, gen_lowpart (DImode, operands[1]), - gen_lowpart (DImode, operands[2]))); + rtx low_dest, op1_low, op2_low, high_dest, op1_high, op2_high; - rtx high = gen_reg_rtx (DImode); - emit_insn (gen_subdi3_carryin (high, gen_highpart (DImode, operands[1]), - gen_highpart (DImode, operands[2]))); + aarch64_subvti_scratch_regs (operands[1], operands[2], + &low_dest, &op1_low, &op2_low, + &high_dest, &op1_high, &op2_high); - emit_move_insn (gen_lowpart (DImode, operands[0]), low); - emit_move_insn (gen_highpart (DImode, operands[0]), high); + emit_insn (gen_subdi3_compare1 (low_dest, op1_low, op2_low)); + emit_insn (gen_subdi3_carryin (high_dest, op1_high, op2_high)); + + emit_move_insn (gen_lowpart (DImode, operands[0]), low_dest); + emit_move_insn (gen_highpart (DImode, operands[0]), high_dest); + DONE; +}) + +(define_expand "subvti4" + [(match_operand:TI 0 "register_operand") + (match_operand:TI 1 "aarch64_reg_or_zero") + (match_operand:TI 2 "aarch64_reg_or_imm") + (label_ref (match_operand 3 "" ""))] + "" +{ + rtx low_dest, op1_low, op2_low, high_dest, op1_high, op2_high; + + aarch64_subvti_scratch_regs (operands[1], operands[2], + &low_dest, &op1_low, &op2_low, + &high_dest, &op1_high, &op2_high); + aarch64_expand_subvti (operands[0], low_dest, op1_low, op2_low, + high_dest, op1_high, op2_high); + + aarch64_gen_unlikely_cbranch (NE, CC_Vmode, operands[3]); + DONE; +}) + +(define_expand "usubvti4" + [(match_operand:TI 0 "register_operand") + (match_operand:TI 1 "aarch64_reg_or_zero") + (match_operand:TI 2 "aarch64_reg_or_imm") + (label_ref (match_operand 3 "" ""))] + "" +{ + rtx low_dest, op1_low, op2_low, high_dest, op1_high, op2_high; + + aarch64_subvti_scratch_regs (operands[1], operands[2], + &low_dest, &op1_low, &op2_low, + &high_dest, &op1_high, &op2_high); + aarch64_expand_subvti (operands[0], low_dest, op1_low, op2_low, + high_dest, op1_high, op2_high); + + aarch64_gen_unlikely_cbranch (LTU, CCmode, operands[3]); DONE; }) @@ -2353,6 +2719,22 @@ [(set_attr "type" "alus_sreg")] ) +(define_insn "*sub<mode>3_compare1_imm" + [(set (reg:CC CC_REGNUM) + (compare:CC + (match_operand:GPI 1 "aarch64_reg_or_zero" "rZ,rZ") + (match_operand:GPI 2 "aarch64_plus_immediate" "I,J"))) + (set (match_operand:GPI 0 "register_operand" "=r,r") + (plus:GPI + (match_dup 1) + (match_operand:GPI 3 "aarch64_plus_immediate" "J,I")))] + "UINTVAL (operands[2]) == -UINTVAL (operands[3])" + "@ + subs\\t%<w>0, %<w>1, #%n3 + adds\\t%<w>0, %<w>1, %3" + [(set_attr "type" "alus_imm")] +) + (define_insn "sub<mode>3_compare1" [(set (reg:CC CC_REGNUM) (compare:CC @@ -2669,6 +3051,85 @@ [(set_attr "type" "adc_reg")] ) +(define_expand "sub<mode>3_carryinCV" + [(parallel + [(set (reg:CC CC_REGNUM) + (compare:CC + (sign_extend:<DWI> + (match_operand:GPI 1 "aarch64_reg_or_zero" "")) + (plus:<DWI> + (sign_extend:<DWI> + (match_operand:GPI 2 "register_operand" "")) + (ltu:<DWI> (reg:CC CC_REGNUM) (const_int 0))))) + (set (match_operand:GPI 0 "register_operand" "") + (minus:GPI + (minus:GPI (match_dup 1) (match_dup 2)) + (ltu:GPI (reg:CC CC_REGNUM) (const_int 0))))])] + "" +) + +(define_insn "*sub<mode>3_carryinCV_z1_z2" + [(set (reg:CC CC_REGNUM) + (compare:CC + (const_int 0) + (match_operand:<DWI> 2 "aarch64_borrow_operation" ""))) + (set (match_operand:GPI 0 "register_operand" "=r") + (neg:GPI (match_operand:GPI 1 "aarch64_borrow_operation" "")))] + "" + "sbcs\\t%<w>0, <w>zr, <w>zr" + [(set_attr "type" "adc_reg")] +) + +(define_insn "*sub<mode>3_carryinCV_z1" + [(set (reg:CC CC_REGNUM) + (compare:CC + (const_int 0) + (plus:<DWI> + (sign_extend:<DWI> + (match_operand:GPI 1 "register_operand" "r")) + (match_operand:<DWI> 2 "aarch64_borrow_operation" "")))) + (set (match_operand:GPI 0 "register_operand" "=r") + (minus:GPI + (neg:GPI (match_dup 1)) + (match_operand:GPI 3 "aarch64_borrow_operation" "")))] + "" + "sbcs\\t%<w>0, <w>zr, %<w>1" + [(set_attr "type" "adc_reg")] +) + +(define_insn "*sub<mode>3_carryinCV_z2" + [(set (reg:CC CC_REGNUM) + (compare:CC + (sign_extend:<DWI> + (match_operand:GPI 1 "register_operand" "r")) + (match_operand:<DWI> 2 "aarch64_borrow_operation" ""))) + (set (match_operand:GPI 0 "register_operand" "=r") + (minus:GPI + (match_dup 1) + (match_operand:GPI 3 "aarch64_borrow_operation" "")))] + "" + "sbcs\\t%<w>0, %<w>1, <w>zr" + [(set_attr "type" "adc_reg")] +) + +(define_insn "*sub<mode>3_carryinCV" + [(set (reg:CC CC_REGNUM) + (compare:CC + (sign_extend:<DWI> + (match_operand:GPI 1 "register_operand" "r")) + (plus:<DWI> + (sign_extend:<DWI> + (match_operand:GPI 2 "register_operand" "r")) + (match_operand:<DWI> 3 "aarch64_borrow_operation" "")))) + (set (match_operand:GPI 0 "register_operand" "=r") + (minus:GPI + (minus:GPI (match_dup 1) (match_dup 2)) + (match_operand:GPI 4 "aarch64_borrow_operation" "")))] + "" + "sbcs\\t%<w>0, %<w>1, %<w>2" + [(set_attr "type" "adc_reg")] +) + (define_insn "*sub_uxt<mode>_shift2" [(set (match_operand:GPI 0 "register_operand" "=rk") (minus:GPI (match_operand:GPI 4 "register_operand" "rk") diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index f55ecc3..b8b309f 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,19 @@ +2018-07-19 Michael Collison <michael.collison@arm.com> + Richard Henderson <rth@redhat.com> + + * gcc.target/aarch64/builtin_sadd_128.c: New testcase. + * gcc.target/aarch64/builtin_saddl.c: New testcase. + * gcc.target/aarch64/builtin_saddll.c: New testcase. + * gcc.target/aarch64/builtin_uadd_128.c: New testcase. + * gcc.target/aarch64/builtin_uaddl.c: New testcase. + * gcc.target/aarch64/builtin_uaddll.c: New testcase. + * gcc.target/aarch64/builtin_ssub_128.c: New testcase. + * gcc.target/aarch64/builtin_ssubl.c: New testcase. + * gcc.target/aarch64/builtin_ssubll.c: New testcase. + * gcc.target/aarch64/builtin_usub_128.c: New testcase. + * gcc.target/aarch64/builtin_usubl.c: New testcase. + * gcc.target/aarch64/builtin_usubll.c: New testcase. + 2018-07-19 Paolo Carlini <paolo.carlini@oracle.com> Revert fix for c++/59480 (and testsuite followup) diff --git a/gcc/testsuite/gcc.target/aarch64/builtin_sadd_128.c b/gcc/testsuite/gcc.target/aarch64/builtin_sadd_128.c new file mode 100644 index 0000000..0b31500 --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/builtin_sadd_128.c @@ -0,0 +1,18 @@ +/* { dg-do compile } */ +/* { dg-options "-O2" } */ + +extern void overflow_handler (); + +__int128 overflow_add (__int128 x, __int128 y) +{ + __int128 r; + + int ovr = __builtin_add_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/aarch64/builtin_saddl.c b/gcc/testsuite/gcc.target/aarch64/builtin_saddl.c new file mode 100644 index 0000000..9768a98 --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/builtin_saddl.c @@ -0,0 +1,17 @@ +/* { dg-do compile } */ +/* { dg-options "-O2" } */ + +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/aarch64/builtin_saddll.c b/gcc/testsuite/gcc.target/aarch64/builtin_saddll.c new file mode 100644 index 0000000..126a526 --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/builtin_saddll.c @@ -0,0 +1,18 @@ +/* { dg-do compile } */ +/* { dg-options "-O2" } */ + +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" } } */ + diff --git a/gcc/testsuite/gcc.target/aarch64/builtin_ssub_128.c b/gcc/testsuite/gcc.target/aarch64/builtin_ssub_128.c new file mode 100644 index 0000000..c1261e3 --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/builtin_ssub_128.c @@ -0,0 +1,18 @@ +/* { dg-do compile } */ +/* { dg-options "-O2" } */ + +extern void overflow_handler (); + +__int128 overflow_sub (__int128 x, __int128 y) +{ + __int128 r; + + int ovr = __builtin_sub_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/aarch64/builtin_ssubl.c b/gcc/testsuite/gcc.target/aarch64/builtin_ssubl.c new file mode 100644 index 0000000..1040464 --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/builtin_ssubl.c @@ -0,0 +1,17 @@ +/* { dg-do compile } */ +/* { dg-options "-O2" } */ + +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/aarch64/builtin_ssubll.c b/gcc/testsuite/gcc.target/aarch64/builtin_ssubll.c new file mode 100644 index 0000000..a03df88 --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/builtin_ssubll.c @@ -0,0 +1,18 @@ +/* { dg-do compile } */ +/* { dg-options "-O2" } */ + +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" } } */ + diff --git a/gcc/testsuite/gcc.target/aarch64/builtin_uadd_128.c b/gcc/testsuite/gcc.target/aarch64/builtin_uadd_128.c new file mode 100644 index 0000000..c573c2a --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/builtin_uadd_128.c @@ -0,0 +1,18 @@ +/* { dg-do compile } */ +/* { dg-options "-O2" } */ + +extern void overflow_handler (); + +unsigned __int128 overflow_add (unsigned __int128 x, unsigned __int128 y) +{ + unsigned __int128 r; + + int ovr = __builtin_add_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/aarch64/builtin_uaddl.c b/gcc/testsuite/gcc.target/aarch64/builtin_uaddl.c new file mode 100644 index 0000000..e325591 --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/builtin_uaddl.c @@ -0,0 +1,17 @@ +/* { dg-do compile } */ +/* { dg-options "-O2" } */ + +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/aarch64/builtin_uaddll.c b/gcc/testsuite/gcc.target/aarch64/builtin_uaddll.c new file mode 100644 index 0000000..5f42886 --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/builtin_uaddll.c @@ -0,0 +1,18 @@ +/* { dg-do compile } */ +/* { dg-options "-O2" } */ + +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" } } */ + diff --git a/gcc/testsuite/gcc.target/aarch64/builtin_usub_128.c b/gcc/testsuite/gcc.target/aarch64/builtin_usub_128.c new file mode 100644 index 0000000..a84f4a4 --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/builtin_usub_128.c @@ -0,0 +1,18 @@ +/* { dg-do compile } */ +/* { dg-options "-O2" } */ + +extern void overflow_handler (); + +unsigned __int128 overflow_sub (unsigned __int128 x, unsigned __int128 y) +{ + unsigned __int128 r; + + int ovr = __builtin_sub_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/aarch64/builtin_usubl.c b/gcc/testsuite/gcc.target/aarch64/builtin_usubl.c new file mode 100644 index 0000000..ed033da --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/builtin_usubl.c @@ -0,0 +1,17 @@ +/* { dg-do compile } */ +/* { dg-options "-O2" } */ + +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/aarch64/builtin_usubll.c b/gcc/testsuite/gcc.target/aarch64/builtin_usubll.c new file mode 100644 index 0000000..a742f0c --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/builtin_usubll.c @@ -0,0 +1,18 @@ +/* { dg-do compile } */ +/* { dg-options "-O2" } */ + +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" } } */ + |