From patchwork Mon Jan 7 14:50:14 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Richard Earnshaw \(lists\)" X-Patchwork-Id: 154883 Delivered-To: patch@linaro.org Received: by 2002:a2e:299d:0:0:0:0:0 with SMTP id p29-v6csp3562953ljp; Mon, 7 Jan 2019 06:50:39 -0800 (PST) X-Google-Smtp-Source: ALg8bN5p4yfFYLmRi0XoVR9RbS6cIkC71pNA5uA7T8i8w+qFYhXDi32mjK/1l7p4esBigJJ3rTkJ X-Received: by 2002:a65:4b82:: with SMTP id t2mr11243227pgq.189.1546872638824; Mon, 07 Jan 2019 06:50:38 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1546872638; cv=none; d=google.com; s=arc-20160816; b=AUu2EwkkFvymRd/VMZrnI5E3XW36c6Qpu9FSzYXSdM7LnjkVBbiqfYjDy/oAdvy4ok Zlp799/FuyQnzCzsU5xc10HOiaWyJQuP/eOXhIJ/E9+X20FXOio/sVI79NbZ/YEPrF4J GTCkyZT8RYJQe1lHSZwVSoHfNB+6ssAin4Ay7EM3Bt3R0hrMAwi36RM6275a8w7MWJk8 FqoQ8JAjQR2VJ6BtUBH1JT4RJqHxlZOWxYYrkUx2tMB18Ljt7y5v6VEuditxCy3J1DjI +z3HpWleKRE7vYfJwv8LSIa9kxR+tgLrWCssWsWOSPl0bXYzeBVK5zsq1Fq0UW7/rOZ6 GwfQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=mime-version:user-agent:date:message-id:openpgp:subject:from:to :delivered-to:sender:list-help:list-post:list-archive :list-unsubscribe:list-id:precedence:mailing-list:dkim-signature :domainkey-signature; bh=DYVvIppjzzWisCXQMVh1HA0ZEPxdJncDl5jG8aSmJR8=; b=CiT+2GeqK5wX2vAzr+vK3J5DMnhcGzfQsHSPPj2o7Iscgev4TVc4bVO9wH8TjWTgTF yfcwP/Ij6L+IJJ7cWuj3IBgdLBEYUdd3OG58nNVZo2A7g3DA4hnrOOC4fKhRcoTR64Ys 3ZrPibz+o1MHJTheKHbv/W6UkSpaowt8Jut5TVxeg0N3RbnDVkLCORdTQqKfn0tSzXO9 /YrXcbRWQtlDTS7cdmSDNLiYhFaJY4xVNzVMG+qraBWvR2xzTrEfb1sC/n6IX6O4Y+np gQQBCRiAoEbHWEpNup5rl2KVxp/mqr/VaHQOh48u/neeM2/DYnrtcgMcDxkm1SOFBE40 GQtQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@gcc.gnu.org header.s=default header.b=NOM05NKP; spf=pass (google.com: domain of gcc-patches-return-493539-patch=linaro.org@gcc.gnu.org designates 209.132.180.131 as permitted sender) smtp.mailfrom="gcc-patches-return-493539-patch=linaro.org@gcc.gnu.org" Return-Path: Received: from sourceware.org (server1.sourceware.org. [209.132.180.131]) by mx.google.com with ESMTPS id b6si19268856pgd.292.2019.01.07.06.50.38 for (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 07 Jan 2019 06:50:38 -0800 (PST) Received-SPF: pass (google.com: domain of gcc-patches-return-493539-patch=linaro.org@gcc.gnu.org designates 209.132.180.131 as permitted sender) client-ip=209.132.180.131; Authentication-Results: mx.google.com; dkim=pass header.i=@gcc.gnu.org header.s=default header.b=NOM05NKP; spf=pass (google.com: domain of gcc-patches-return-493539-patch=linaro.org@gcc.gnu.org designates 209.132.180.131 as permitted sender) smtp.mailfrom="gcc-patches-return-493539-patch=linaro.org@gcc.gnu.org" DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:to :from:subject:message-id:date:mime-version:content-type; q=dns; s=default; b=BA4lQ8Z3FpIcfT012nPkvZNGT+sGeXyFJI5Bp+IhYXZ17wwkgI 6R0ADcmt3jdIzcjb3JJhtJ9Qj7K824wVWhVAOhWZ4q54KNNfCvZMCryeOjacbUva RPUS9rfZLq+xfB82teMsy+rlEOCyiTefjKpqNSrahab0AdFLrMwJMwAG0= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:to :from:subject:message-id:date:mime-version:content-type; s= default; bh=UNlyY7WEdW/5wRISzf38nuRW9iM=; b=NOM05NKPuM5iRHvntzpX 9u8TJITp3d36YOONZOs9jjXyNeMYG/5rkXVP6sKpZhKugbg8FKDeTRR1h4UzeF+D hh0IbiOd6ur+cRQB0J2zwY3t1Cn7RLqntcYkjz3+HC0eHxT69xSqXRKLexvxL5qL i7tEq9nNhOAKUk7NKV5rwPw= Received: (qmail 79503 invoked by alias); 7 Jan 2019 14:50:25 -0000 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org Received: (qmail 78899 invoked by uid 89); 7 Jan 2019 14:50:25 -0000 Authentication-Results: sourceware.org; auth=none X-Spam-SWARE-Status: No, score=-26.4 required=5.0 tests=BAYES_00, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, KAM_NUMSUBJECT, SPF_PASS autolearn=ham version=3.3.2 spammy=ji, 11, 5, half X-HELO: foss.arm.com Received: from usa-sjc-mx-foss1.foss.arm.com (HELO foss.arm.com) (217.140.101.70) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Mon, 07 Jan 2019 14:50:19 +0000 Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.72.51.249]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 8D45E80D; Mon, 7 Jan 2019 06:50:16 -0800 (PST) Received: from e120077-lin.cambridge.arm.com (e120077-lin.cambridge.arm.com [10.2.206.231]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id E4C423F5B7; Mon, 7 Jan 2019 06:50:15 -0800 (PST) To: gcc-patches From: "Richard Earnshaw (lists)" Subject: PR target/86891 __builtin_sub_overflow issues on AArch64 Openpgp: preference=signencrypt Message-ID: <4ebcb0f2-0e8c-5d19-ce8f-402336614638@arm.com> Date: Mon, 7 Jan 2019 14:50:14 +0000 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:60.0) Gecko/20100101 Thunderbird/60.2.1 MIME-Version: 1.0 Investigating PR target/86891 revealed a number of issues with the way the AArch64 backend was handing overflow detection patterns. Firstly, expansion for signed and unsigned types is not the same as in one form the overflow is detected via the C flag and in the other it is done via the V flag in the PSR. Secondly, particular care has to be taken when describing overflow of signed types: the comparison has to be performed conceptually on a value that cannot overflow and compared to a value that might have overflowed. It became apparent that some of the patterns were simply unmatchable (they collapse to NEG in the RTL rather than subtracting from zero) and a number of patterns were overly restrictive in terms of the immediate constants that they supported. I've tried to address all of these issues as well. Committed to trunk. gcc: PR target/86891 * config/aarch64/aarch64.c (aarch64_expand_subvti): New parameter unsigned_p. Handle signed and unsigned overflow correction as required. * config/aarch64/aarch64-protos.h (aarch64_expand_subvti): Update prototype. * config/aarch64/aarch64.md (addv4): Use aarch64_plus_operand for operand 2. (add3_compareV_imm): Make this callable for expanding. (subv4): Use register_operand for operand 1. Use aarch64_plus_operand for operand 2. (subv_insn): New insn pattern. (subv_imm): Likewise. (negv3): New expand pattern. (negv_insn): New insn pattern. (negv_cmp_only): Likewise. (cmpv_insn): Likewise. (subvti4): Use register_operand for operand 1. Update call to aarch64_expand_subvti. (usubvti4): Likewise. (negvti3): New expand pattern. (negdi_carryout): New insn pattern. (negvdi_carryinV): New insn pattern. (sub_compare1_imm): Delete named insn pattern, make anonymous version the named version. (peepholes to convert to sub_compare1_imm): Adjust order of operands. (usub3_carryinC, usub3_carryinC_z1): New insn patterns. (usub3_carryinC_z2, usub3_carryinC): New insn patterns. (sub3_carryinCV, sub3_carryinCV_z1_z2): Delete. (sub3_carryinCV_z1, sub3_carryinCV_z2): Delete. (sub3_carryinCV): Delete. (sub3_carryinV): New expand pattern. sub3_carryinV, sub3_carryinV_z2): New insn patterns. testsuite: * gcc.target/aarch64/subs_compare_2.c: Make '#' immediate prefix optional in scan pattern. diff --git a/gcc/config/aarch64/aarch64-protos.h b/gcc/config/aarch64/aarch64-protos.h index 9a8f81e..209c09b 100644 --- a/gcc/config/aarch64/aarch64-protos.h +++ b/gcc/config/aarch64/aarch64-protos.h @@ -530,7 +530,7 @@ void aarch64_subvti_scratch_regs (rtx, rtx, rtx *, rtx *, rtx *, rtx *, rtx *, rtx *); void aarch64_expand_subvti (rtx, rtx, rtx, - rtx, rtx, rtx, rtx); + rtx, rtx, rtx, rtx, bool); /* Initialize builtins for SIMD intrinsics. */ diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c index c5036c8..c879940 100644 --- a/gcc/config/aarch64/aarch64.c +++ b/gcc/config/aarch64/aarch64.c @@ -16668,32 +16668,38 @@ aarch64_subvti_scratch_regs (rtx op1, rtx op2, rtx *low_dest, 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. */ - + HIGH_IN2 represents the high half (DImode) of TImode operand 2 + UNSIGNED_P is true if the operation is being performed on unsigned + values. */ void aarch64_expand_subvti (rtx op0, rtx low_dest, rtx low_in1, rtx low_in2, rtx high_dest, rtx high_in1, - rtx high_in2) + rtx high_in2, bool unsigned_p) { if (low_in2 == const0_rtx) { low_dest = low_in1; - emit_insn (gen_subdi3_compare1 (high_dest, high_in1, - force_reg (DImode, high_in2))); + high_in2 = force_reg (DImode, high_in2); + if (unsigned_p) + emit_insn (gen_subdi3_compare1 (high_dest, high_in1, high_in2)); + else + emit_insn (gen_subvdi_insn (high_dest, high_in1, 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)); + emit_insn (gen_subdi3_compare1_imm (low_dest, low_in1, low_in2, + GEN_INT (-INTVAL (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)); + + if (unsigned_p) + emit_insn (gen_usubdi3_carryinC (high_dest, high_in1, high_in2)); + else + emit_insn (gen_subdi3_carryinV (high_dest, high_in1, high_in2)); } emit_move_insn (gen_lowpart (DImode, op0), low_dest); diff --git a/gcc/config/aarch64/aarch64.md b/gcc/config/aarch64/aarch64.md index d2642ef..37322fb 100644 --- a/gcc/config/aarch64/aarch64.md +++ b/gcc/config/aarch64/aarch64.md @@ -1842,11 +1842,15 @@ (define_split (define_expand "addv4" [(match_operand:GPI 0 "register_operand") (match_operand:GPI 1 "register_operand") - (match_operand:GPI 2 "register_operand") + (match_operand:GPI 2 "aarch64_plus_operand") (label_ref (match_operand 3 "" ""))] "" { - emit_insn (gen_add3_compareV (operands[0], operands[1], operands[2])); + if (CONST_INT_P (operands[2])) + emit_insn (gen_add3_compareV_imm (operands[0], operands[1], + operands[2])); + else + emit_insn (gen_add3_compareV (operands[0], operands[1], operands[2])); aarch64_gen_unlikely_cbranch (NE, CC_Vmode, operands[3]); DONE; @@ -2093,7 +2097,7 @@ (define_insn "*add3_compareV_cconly" [(set_attr "type" "alus_sreg")] ) -(define_insn "*add3_compareV_imm" +(define_insn "add3_compareV_imm" [(set (reg:CC_V CC_REGNUM) (compare:CC_V (plus: @@ -2723,19 +2727,109 @@ (define_insn "subdi3" (set_attr "arch" "*,simd")] ) -(define_expand "subv4" +(define_expand "subv4" [(match_operand:GPI 0 "register_operand") - (match_operand:GPI 1 "aarch64_reg_or_zero") - (match_operand:GPI 2 "aarch64_reg_or_zero") + (match_operand:GPI 1 "register_operand") + (match_operand:GPI 2 "aarch64_plus_operand") (label_ref (match_operand 3 "" ""))] "" { - emit_insn (gen_sub3_compare1 (operands[0], operands[1], operands[2])); + if (CONST_INT_P (operands[2])) + emit_insn (gen_subv_imm (operands[0], operands[1], operands[2])); + else + emit_insn (gen_subv_insn (operands[0], operands[1], operands[2])); aarch64_gen_unlikely_cbranch (NE, CC_Vmode, operands[3]); DONE; }) +(define_insn "subv_insn" + [(set (reg:CC_V CC_REGNUM) + (compare:CC_V + (sign_extend: + (minus:GPI + (match_operand:GPI 1 "register_operand" "rk") + (match_operand:GPI 2 "register_operand" "r"))) + (minus: (sign_extend: (match_dup 1)) + (sign_extend: (match_dup 2))))) + (set (match_operand:GPI 0 "register_operand" "=r") + (minus:GPI (match_dup 1) (match_dup 2)))] + "" + "subs\\t%0, %1, %2" + [(set_attr "type" "alus_sreg")] +) + +(define_insn "subv_imm" + [(set (reg:CC_V CC_REGNUM) + (compare:CC_V + (sign_extend: + (minus:GPI + (match_operand:GPI 1 "register_operand" "rk,rk") + (match_operand:GPI 2 "aarch64_plus_immediate" "I,J"))) + (minus: (sign_extend: (match_dup 1)) + (match_dup 2)))) + (set (match_operand:GPI 0 "register_operand" "=r,r") + (minus:GPI (match_dup 1) (match_dup 2)))] + "" + "@ + subs\\t%0, %1, %2 + adds\\t%0, %1, #%n2" + [(set_attr "type" "alus_sreg")] +) + +(define_expand "negv3" + [(match_operand:GPI 0 "register_operand") + (match_operand:GPI 1 "register_operand") + (label_ref (match_operand 2 "" ""))] + "" + { + emit_insn (gen_negv_insn (operands[0], operands[1])); + aarch64_gen_unlikely_cbranch (NE, CC_Vmode, operands[2]); + + DONE; + } +) + +(define_insn "negv_insn" + [(set (reg:CC_V CC_REGNUM) + (compare:CC_V + (sign_extend: + (neg:GPI (match_operand:GPI 1 "register_operand" "r"))) + (neg: (sign_extend: (match_dup 1))))) + (set (match_operand:GPI 0 "register_operand" "=r") + (neg:GPI (match_dup 1)))] + "" + "negs\\t%0, %1" + [(set_attr "type" "alus_sreg")] +) + +(define_insn "negv_cmp_only" + [(set (reg:CC_V CC_REGNUM) + (compare:CC_V + (sign_extend: + (neg:GPI (match_operand:GPI 0 "register_operand" "r"))) + (neg: (sign_extend: (match_dup 0)))))] + "" + "negs\\t%zr, %0" + [(set_attr "type" "alus_sreg")] +) + +(define_insn "*cmpv_insn" + [(set (reg:CC_V CC_REGNUM) + (compare:CC_V + (sign_extend: + (minus:GPI (match_operand:GPI 0 "register_operand" "r,r,r") + (match_operand:GPI 1 "aarch64_plus_operand" "r,I,J"))) + (minus: (sign_extend: (match_dup 0)) + (sign_extend: (match_dup 1)))))] + "" + "@ + cmp\\t%0, %1 + cmp\\t%0, %1 + cmp\\t%0, #%n1" + [(set_attr "type" "alus_sreg")] +) + (define_expand "usubv4" [(match_operand:GPI 0 "register_operand") (match_operand:GPI 1 "aarch64_reg_or_zero") @@ -2771,7 +2865,7 @@ (define_expand "subti3" (define_expand "subvti4" [(match_operand:TI 0 "register_operand") - (match_operand:TI 1 "aarch64_reg_or_zero") + (match_operand:TI 1 "register_operand") (match_operand:TI 2 "aarch64_reg_or_imm") (label_ref (match_operand 3 "" ""))] "" @@ -2782,7 +2876,7 @@ (define_expand "subvti4" &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); + high_dest, op1_high, op2_high, false); aarch64_gen_unlikely_cbranch (NE, CC_Vmode, operands[3]); DONE; @@ -2790,7 +2884,7 @@ (define_expand "subvti4" (define_expand "usubvti4" [(match_operand:TI 0 "register_operand") - (match_operand:TI 1 "aarch64_reg_or_zero") + (match_operand:TI 1 "register_operand") (match_operand:TI 2 "aarch64_reg_or_imm") (label_ref (match_operand 3 "" ""))] "" @@ -2801,12 +2895,56 @@ (define_expand "usubvti4" &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); + high_dest, op1_high, op2_high, true); aarch64_gen_unlikely_cbranch (LTU, CCmode, operands[3]); DONE; }) +(define_expand "negvti3" + [(match_operand:TI 0 "register_operand") + (match_operand:TI 1 "register_operand") + (label_ref (match_operand 2 "" ""))] + "" + { + emit_insn (gen_negdi_carryout (gen_lowpart (DImode, operands[0]), + gen_lowpart (DImode, operands[1]))); + emit_insn (gen_negvdi_carryinV (gen_highpart (DImode, operands[0]), + gen_highpart (DImode, operands[1]))); + aarch64_gen_unlikely_cbranch (NE, CC_Vmode, operands[2]); + + DONE; + } +) + +(define_insn "negdi_carryout" + [(set (reg:CC CC_REGNUM) + (compare:CC + (const_int 0) (match_operand:DI 1 "register_operand" "r"))) + (set (match_operand:DI 0 "register_operand" "=r") + (neg:DI (match_dup 1)))] + "" + "negs\\t%0, %1" + [(set_attr "type" "alus_sreg")] +) + +(define_insn "negvdi_carryinV" + [(set (reg:CC_V CC_REGNUM) + (compare:CC_V + (neg:TI (plus:TI + (ltu:TI (reg:CC CC_REGNUM) (const_int 0)) + (sign_extend:TI (match_operand:DI 1 "register_operand" "r")))) + (sign_extend:TI + (neg:DI (plus:DI (ltu:DI (reg:CC CC_REGNUM) (const_int 0)) + (match_dup 1)))))) + (set (match_operand:DI 0 "register_operand" "=r") + (neg:DI (plus:DI (ltu:DI (reg:CC CC_REGNUM) (const_int 0)) + (match_dup 1))))] + "" + "ngcs\\t%0, %1" + [(set_attr "type" "alus_sreg")] +) + (define_insn "*sub3_compare0" [(set (reg:CC_NZ CC_REGNUM) (compare:CC_NZ (minus:GPI (match_operand:GPI 1 "register_operand" "r") @@ -2832,7 +2970,7 @@ (define_insn "*subsi3_compare0_uxtw" [(set_attr "type" "alus_sreg")] ) -(define_insn "*sub3_compare1_imm" +(define_insn "sub3_compare1_imm" [(set (reg:CC CC_REGNUM) (compare:CC (match_operand:GPI 1 "aarch64_reg_or_zero" "rZ,rZ") @@ -2843,8 +2981,8 @@ (define_insn "*sub3_compare1_imm" (match_operand:GPI 3 "aarch64_plus_immediate" "J,I")))] "UINTVAL (operands[2]) == -UINTVAL (operands[3])" "@ - subs\\t%0, %1, #%n3 - adds\\t%0, %1, %3" + subs\\t%0, %1, %2 + adds\\t%0, %1, #%n2" [(set_attr "type" "alus_imm")] ) @@ -2860,19 +2998,6 @@ (define_insn "sub3_compare1" [(set_attr "type" "alus_sreg")] ) -(define_insn "sub3_compare1_imm" - [(set (reg:CC CC_REGNUM) - (compare:CC - (match_operand:GPI 1 "register_operand" "r") - (match_operand:GPI 3 "const_int_operand" "n"))) - (set (match_operand:GPI 0 "register_operand" "=r") - (plus:GPI (match_dup 1) - (match_operand:GPI 2 "aarch64_sub_immediate" "J")))] - "INTVAL (operands[3]) == -INTVAL (operands[2])" - "subs\\t%0, %1, #%n2" - [(set_attr "type" "alus_sreg")] -) - (define_peephole2 [(set (match_operand:GPI 0 "register_operand") (minus:GPI (match_operand:GPI 1 "aarch64_reg_or_zero") @@ -2914,7 +3039,7 @@ (define_peephole2 (define_peephole2 [(set (match_operand:GPI 0 "register_operand") (plus:GPI (match_operand:GPI 1 "register_operand") - (match_operand:GPI 2 "aarch64_sub_immediate"))) + (match_operand:GPI 2 "aarch64_plus_immediate"))) (set (reg:CC CC_REGNUM) (compare:CC (match_dup 1) @@ -2924,7 +3049,7 @@ (define_peephole2 [(const_int 0)] { emit_insn (gen_sub3_compare1_imm (operands[0], operands[1], - operands[2], operands[3])); + operands[3], operands[2])); DONE; } ) @@ -2939,12 +3064,12 @@ (define_peephole2 (match_operand:GPI 3 "const_int_operand"))) (set (match_operand:GPI 0 "register_operand") (plus:GPI (match_dup 1) - (match_operand:GPI 2 "aarch64_sub_immediate")))] + (match_operand:GPI 2 "aarch64_plus_immediate")))] "INTVAL (operands[3]) == -INTVAL (operands[2])" [(const_int 0)] { emit_insn (gen_sub3_compare1_imm (operands[0], operands[1], - operands[2], operands[3])); + operands[3], operands[2])); DONE; } ) @@ -3164,14 +3289,14 @@ (define_insn "*subsi3_carryin_alt_uxtw" [(set_attr "type" "adc_reg")] ) -(define_expand "sub3_carryinCV" +(define_expand "usub3_carryinC" [(parallel [(set (reg:CC CC_REGNUM) (compare:CC - (sign_extend: + (zero_extend: (match_operand:GPI 1 "aarch64_reg_or_zero" "")) (plus: - (sign_extend: + (zero_extend: (match_operand:GPI 2 "register_operand" "")) (ltu: (reg:CC CC_REGNUM) (const_int 0))))) (set (match_operand:GPI 0 "register_operand" "") @@ -3181,24 +3306,12 @@ (define_expand "sub3_carryinCV" "" ) -(define_insn "*sub3_carryinCV_z1_z2" - [(set (reg:CC CC_REGNUM) - (compare:CC - (const_int 0) - (match_operand: 2 "aarch64_borrow_operation" ""))) - (set (match_operand:GPI 0 "register_operand" "=r") - (neg:GPI (match_operand:GPI 1 "aarch64_borrow_operation" "")))] - "" - "sbcs\\t%0, zr, zr" - [(set_attr "type" "adc_reg")] -) - -(define_insn "*sub3_carryinCV_z1" +(define_insn "*usub3_carryinC_z1" [(set (reg:CC CC_REGNUM) (compare:CC (const_int 0) (plus: - (sign_extend: + (zero_extend: (match_operand:GPI 1 "register_operand" "r")) (match_operand: 2 "aarch64_borrow_operation" "")))) (set (match_operand:GPI 0 "register_operand" "=r") @@ -3210,10 +3323,10 @@ (define_insn "*sub3_carryinCV_z1" [(set_attr "type" "adc_reg")] ) -(define_insn "*sub3_carryinCV_z2" +(define_insn "*usub3_carryinC_z2" [(set (reg:CC CC_REGNUM) (compare:CC - (sign_extend: + (zero_extend: (match_operand:GPI 1 "register_operand" "r")) (match_operand: 2 "aarch64_borrow_operation" ""))) (set (match_operand:GPI 0 "register_operand" "=r") @@ -3225,13 +3338,13 @@ (define_insn "*sub3_carryinCV_z2" [(set_attr "type" "adc_reg")] ) -(define_insn "*sub3_carryinCV" +(define_insn "*usub3_carryinC" [(set (reg:CC CC_REGNUM) (compare:CC - (sign_extend: + (zero_extend: (match_operand:GPI 1 "register_operand" "r")) (plus: - (sign_extend: + (zero_extend: (match_operand:GPI 2 "register_operand" "r")) (match_operand: 3 "aarch64_borrow_operation" "")))) (set (match_operand:GPI 0 "register_operand" "=r") @@ -3243,6 +3356,69 @@ (define_insn "*sub3_carryinCV" [(set_attr "type" "adc_reg")] ) +(define_expand "sub3_carryinV" + [(parallel + [(set (reg:CC_V CC_REGNUM) + (compare:CC_V + (minus: + (sign_extend: + (match_operand:GPI 1 "aarch64_reg_or_zero" "")) + (plus: + (sign_extend: + (match_operand:GPI 2 "register_operand" "")) + (ltu: (reg:CC CC_REGNUM) (const_int 0)))) + (sign_extend: + (minus:GPI (match_dup 1) + (plus:GPI (ltu:GPI (reg:CC CC_REGNUM) (const_int 0)) + (match_dup 2)))))) + (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 "*sub3_carryinV_z2" + [(set (reg:CC_V CC_REGNUM) + (compare:CC_V + (minus: + (sign_extend: (match_operand:GPI 1 "register_operand" "r")) + (match_operand: 2 "aarch64_borrow_operation" "")) + (sign_extend: + (minus:GPI (match_dup 1) + (match_operand:GPI 3 "aarch64_borrow_operation" ""))))) + (set (match_operand:GPI 0 "register_operand" "=r") + (minus:GPI + (match_dup 1) (match_dup 3)))] + "" + "sbcs\\t%0, %1, zr" + [(set_attr "type" "adc_reg")] +) + +(define_insn "*sub3_carryinV" + [(set (reg:CC_V CC_REGNUM) + (compare:CC_V + (minus: + (sign_extend: + (match_operand:GPI 1 "register_operand" "r")) + (plus: + (sign_extend: + (match_operand:GPI 2 "register_operand" "r")) + (match_operand: 3 "aarch64_borrow_operation" ""))) + (sign_extend: + (minus:GPI + (match_dup 1) + (plus:GPI (match_operand:GPI 4 "aarch64_borrow_operation" "") + (match_dup 2)))))) + (set (match_operand:GPI 0 "register_operand" "=r") + (minus:GPI + (minus:GPI (match_dup 1) (match_dup 2)) + (match_dup 4)))] + "" + "sbcs\\t%0, %1, %2" + [(set_attr "type" "adc_reg")] +) + (define_insn "*sub_uxt_shift2" [(set (match_operand:GPI 0 "register_operand" "=rk") (minus:GPI (match_operand:GPI 4 "register_operand" "rk") diff --git a/gcc/testsuite/gcc.target/aarch64/subs_compare_2.c b/gcc/testsuite/gcc.target/aarch64/subs_compare_2.c index 60c6d9e..41a2566 100644 --- a/gcc/testsuite/gcc.target/aarch64/subs_compare_2.c +++ b/gcc/testsuite/gcc.target/aarch64/subs_compare_2.c @@ -11,5 +11,5 @@ foo (int a, int b) return 0; } -/* { dg-final { scan-assembler-times "subs\\tw\[0-9\]+, w\[0-9\]+, #4" 1 } } */ +/* { dg-final { scan-assembler-times "subs\\tw\[0-9\]+, w\[0-9\]+, \[#\]?4" 1 } } */ /* { dg-final { scan-assembler-not "cmp\\tw\[0-9\]+, w\[0-9\]+" } } */