From patchwork Fri Oct 18 19:48:54 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: 176953 Delivered-To: patch@linaro.org Received: by 2002:ac9:3c86:0:0:0:0:0 with SMTP id w6csp1293369ocf; Fri, 18 Oct 2019 12:56:46 -0700 (PDT) X-Google-Smtp-Source: APXvYqxvJ4JGVOsdFPRCZBJtviBviG0Rf3izGXr6BmT8wlRvGNHo8rsXFA+LF4nhZklxXTPgxO2l X-Received: by 2002:a05:6402:b17:: with SMTP id bm23mr11519702edb.6.1571428605995; Fri, 18 Oct 2019 12:56:45 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1571428605; cv=none; d=google.com; s=arc-20160816; b=ewQqbOKR0dBvB3vZnre9lyOLaZHZpf0ZWXkDGUQBIzymdkoj69szyTsTt6j6n+H5p4 xHKQHh+DDFyoWcrt1qpWUAK3b7CAax3yNNGKaq/P+9o+zSvqz+PkRWRBJp62gnq2sHTZ uUMuvP9mfDbVNdtevwO++4H++xIbvZlYs5L0QSQiiodWlvIxlm285AqskyQTeitZ/5vU 8dradbeAaSYSuLjrGwYTMOPo5haAdDuNpRqsjAdlge2zj1ZdvdWeWd+p5igbK5MNh2e5 9/y2EbuqPIZT0dzBAcGy1W6ImzRwqnMHHpUGcijC3tIK70CEWF71FF14vJ8adlRWfkkz FBrA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=mime-version:references:in-reply-to:message-id:date:subject:cc:to :from:delivered-to:sender:list-help:list-post:list-archive :list-unsubscribe:list-id:precedence:mailing-list:dkim-signature :domainkey-signature; bh=/ffmu43nMR49xGS+KGPLCy8Bfj5PnPaJ4PyTTvclIEU=; b=Vh1eeRJJxL7jBy+XiOKg/vWrrS/g9DLIyOU/zepTLZBuzxI9ubt7ec+kBAlJ7He79U ZFnI5suF3EeJondyN7EDP2yVUXh4jMKnD/v4EBW1TgMy5MtchJUvIOkuwDv2E/PIN9wn aN02x4G1cVKtCPTuZiCQdE+H4VK5DbNAhHqBDWzi9TeDntwX7sEF+lXc9Fe6O5AT0+XH vfIHceF/qm8ElGNtZ/imQGroxrzjeWzRfg3vArOf4pCphWDMskUbO3cwCpAMc/pNNPJw IuXBlbArNUsc/f07PPbRMQ8K4g62c1GbVKx54UTmR0aAU3XoiDg6yx/GvH81PyYBRgVm iwPw== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@gcc.gnu.org header.s=default header.b=Y9B09AxR; spf=pass (google.com: domain of gcc-patches-return-511319-patch=linaro.org@gcc.gnu.org designates 209.132.180.131 as permitted sender) smtp.mailfrom="gcc-patches-return-511319-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 g24si4054276ejo.355.2019.10.18.12.56.45 for (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Fri, 18 Oct 2019 12:56:45 -0700 (PDT) Received-SPF: pass (google.com: domain of gcc-patches-return-511319-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=Y9B09AxR; spf=pass (google.com: domain of gcc-patches-return-511319-patch=linaro.org@gcc.gnu.org designates 209.132.180.131 as permitted sender) smtp.mailfrom="gcc-patches-return-511319-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:from :to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-type; q=dns; s=default; b=dktlg+jdi5SPhsLz 7L1/Ku0MKtKMogwPC2v+Ki/8vDnjdq1Rg+BA4ss/9ZMHTpAeIjQ55m6MQEYYHUP0 uU0dywBl1AAhEIiBumr5qxpuNgPSoFqibrpBJVuQ2MWv3C91PA3tFJqXX/OwvCE/ QKBuzp1/LiNYYfvVE/hjYcrII+g= 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:from :to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-type; s=default; bh=ZzEHw71hKg2vr1Zhnj9oxq Yanug=; b=Y9B09AxRcG01g8TtsJ4lyxr3xS4qmitgST/crfE5o+12E4X0gsbDgh PLOi5B8ydPM7dDUOPch4AmaAnn9a3IRwWU5qbBjnCXucn4XgQehMp/Z0ZVwsH06h Gj6t2kJg+Ynrmiswv0i8AIbAL+Oam3jFdIYfiG5t9V4cDQ8q6ImkE= Received: (qmail 112767 invoked by alias); 18 Oct 2019 19:55:40 -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 110479 invoked by uid 89); 18 Oct 2019 19:55:32 -0000 Authentication-Results: sourceware.org; auth=none X-Spam-SWARE-Status: No, score=-18.4 required=5.0 tests=AWL, BAYES_00, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, KAM_NUMSUBJECT, SPF_PASS autolearn=ham version=3.3.1 spammy=1, 41 X-HELO: foss.arm.com Received: from Unknown (HELO foss.arm.com) (217.140.110.172) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Fri, 18 Oct 2019 19:55:30 +0000 Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 40C401763; Fri, 18 Oct 2019 12:49:28 -0700 (PDT) Received: from eagle.buzzard.freeserve.co.uk (unknown [172.31.20.19]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id C22C43F6C4; Fri, 18 Oct 2019 12:49:27 -0700 (PDT) From: Richard Earnshaw To: gcc-patches@gcc.gnu.org Cc: Richard Earnshaw Subject: [PATCH 23/29] [arm] Early split addvdi4 Date: Fri, 18 Oct 2019 20:48:54 +0100 Message-Id: <20191018194900.34795-24-Richard.Earnshaw@arm.com> In-Reply-To: <20191018194900.34795-1-Richard.Earnshaw@arm.com> References: <20191018194900.34795-1-Richard.Earnshaw@arm.com> MIME-Version: 1.0 This patch adds early splitting for addvdi4; it's very similar to the uaddvdi4 splitter, but the details are just different enough in places, especially for the patterns that match the splitting, where we have to compare against the non-widened version to detect if overflow occurred. I've also added a testcase to the testsuite for a couple of constants that caught me out during the development of this patch. They're probably arm-specific values, but the test is generic enough that I've included it for all targets. [gcc] * config/arm/arm.c (arm_select_cc_mode): Allow either the first or second operand of the PLUS inside a DImode equality test to be sign-extend when selecting CC_Vmode. * config/arm/arm.md (addvdi4): Early-split the operation into SImode instructions. (addsi3_cin_vout_reg, addsi3_cin_vout_imm, addsi3_cin_vout_0): New expand patterns. (addsi3_cin_vout_reg_insn, addsi3_cin_vout_imm_insn): New patterns. (addsi3_cin_vout_0): Likewise. (adddi3_compareV): Delete. [gcc/testsuite] * gcc.dg/builtin-arith-overflow-3.c: New test. --- gcc/config/arm/arm.c | 3 +- gcc/config/arm/arm.md | 181 ++++++++++++++++-- .../gcc.dg/builtin-arith-overflow-3.c | 41 ++++ 3 files changed, 203 insertions(+), 22 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/builtin-arith-overflow-3.c diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c index 638c82df25f..c9abbb0f91d 100644 --- a/gcc/config/arm/arm.c +++ b/gcc/config/arm/arm.c @@ -15414,7 +15414,8 @@ arm_select_cc_mode (enum rtx_code op, rtx x, rtx y) if (GET_MODE (x) == DImode && (op == EQ || op == NE) && GET_CODE (x) == PLUS - && GET_CODE (XEXP (x, 0)) == SIGN_EXTEND + && (GET_CODE (XEXP (x, 0)) == SIGN_EXTEND + || GET_CODE (XEXP (x, 1)) == SIGN_EXTEND) && GET_CODE (y) == SIGN_EXTEND && GET_CODE (XEXP (y, 0)) == PLUS) return CC_Vmode; diff --git a/gcc/config/arm/arm.md b/gcc/config/arm/arm.md index be002f77382..e9e0ca925d2 100644 --- a/gcc/config/arm/arm.md +++ b/gcc/config/arm/arm.md @@ -505,18 +505,173 @@ (define_expand "addvsi4" }) (define_expand "addvdi4" - [(match_operand:DI 0 "register_operand") - (match_operand:DI 1 "register_operand") - (match_operand:DI 2 "register_operand") + [(match_operand:DI 0 "s_register_operand") + (match_operand:DI 1 "s_register_operand") + (match_operand:DI 2 "reg_or_int_operand") (match_operand 3 "")] "TARGET_32BIT" { - emit_insn (gen_adddi3_compareV (operands[0], operands[1], operands[2])); - arm_gen_unlikely_cbranch (NE, CC_Vmode, operands[3]); + rtx lo_result, hi_result; + rtx lo_op1, hi_op1, lo_op2, hi_op2; + arm_decompose_di_binop (operands[1], operands[2], &lo_op1, &hi_op1, + &lo_op2, &hi_op2); + lo_result = gen_lowpart (SImode, operands[0]); + hi_result = gen_highpart (SImode, operands[0]); + + if (lo_op2 == const0_rtx) + { + emit_move_insn (lo_result, lo_op1); + if (!arm_add_operand (hi_op2, SImode)) + hi_op2 = force_reg (SImode, hi_op2); + + emit_insn (gen_addvsi4 (hi_result, hi_op1, hi_op2, operands[3])); + } + else + { + if (!arm_add_operand (lo_op2, SImode)) + lo_op2 = force_reg (SImode, lo_op2); + if (!arm_not_operand (hi_op2, SImode)) + hi_op2 = force_reg (SImode, hi_op2); + + emit_insn (gen_addsi3_compare_op1 (lo_result, lo_op1, lo_op2)); + + if (hi_op2 == const0_rtx) + emit_insn (gen_addsi3_cin_vout_0 (hi_result, hi_op1)); + else if (CONST_INT_P (hi_op2)) + emit_insn (gen_addsi3_cin_vout_imm (hi_result, hi_op1, hi_op2)); + else + emit_insn (gen_addsi3_cin_vout_reg (hi_result, hi_op1, hi_op2)); + + arm_gen_unlikely_cbranch (NE, CC_Vmode, operands[3]); + } DONE; }) +(define_expand "addsi3_cin_vout_reg" + [(parallel + [(set (match_dup 3) + (compare:CC_V + (plus:DI + (plus:DI (match_dup 4) + (sign_extend:DI (match_operand:SI 1 "s_register_operand"))) + (sign_extend:DI (match_operand:SI 2 "s_register_operand"))) + (sign_extend:DI (plus:SI (plus:SI (match_dup 5) (match_dup 1)) + (match_dup 2))))) + (set (match_operand:SI 0 "s_register_operand") + (plus:SI (plus:SI (match_dup 5) (match_dup 1)) + (match_dup 2)))])] + "TARGET_32BIT" + { + operands[3] = gen_rtx_REG (CC_Vmode, CC_REGNUM); + rtx ccin = gen_rtx_REG (CC_Cmode, CC_REGNUM); + operands[4] = gen_rtx_LTU (DImode, ccin, const0_rtx); + operands[5] = gen_rtx_LTU (SImode, ccin, const0_rtx); + } +) + +(define_insn "*addsi3_cin_vout_reg_insn" + [(set (reg:CC_V CC_REGNUM) + (compare:CC_V + (plus:DI + (plus:DI + (match_operand:DI 3 "arm_carry_operation" "") + (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%0,r"))) + (sign_extend:DI (match_operand:SI 2 "s_register_operand" "l,r"))) + (sign_extend:DI + (plus:SI (plus:SI (match_operand:SI 4 "arm_carry_operation" "") + (match_dup 1)) + (match_dup 2))))) + (set (match_operand:SI 0 "s_register_operand" "=l,r") + (plus:SI (plus:SI (match_dup 4) (match_dup 1)) + (match_dup 2)))] + "TARGET_32BIT" + "@ + adcs%?\\t%0, %0, %2 + adcs%?\\t%0, %1, %2" + [(set_attr "type" "alus_sreg") + (set_attr "arch" "t2,*") + (set_attr "length" "2,4")] +) + +(define_expand "addsi3_cin_vout_imm" + [(parallel + [(set (match_dup 3) + (compare:CC_V + (plus:DI + (plus:DI (match_dup 4) + (sign_extend:DI (match_operand:SI 1 "s_register_operand"))) + (match_dup 2)) + (sign_extend:DI (plus:SI (plus:SI (match_dup 5) (match_dup 1)) + (match_dup 2))))) + (set (match_operand:SI 0 "s_register_operand") + (plus:SI (plus:SI (match_dup 5) (match_dup 1)) + (match_operand 2 "arm_adcimm_operand")))])] + "TARGET_32BIT" + { + operands[3] = gen_rtx_REG (CC_Vmode, CC_REGNUM); + rtx ccin = gen_rtx_REG (CC_Cmode, CC_REGNUM); + operands[4] = gen_rtx_LTU (DImode, ccin, const0_rtx); + operands[5] = gen_rtx_LTU (SImode, ccin, const0_rtx); + } +) + +(define_insn "*addsi3_cin_vout_imm_insn" + [(set (reg:CC_V CC_REGNUM) + (compare:CC_V + (plus:DI + (plus:DI + (match_operand:DI 3 "arm_carry_operation" "") + (sign_extend:DI (match_operand:SI 1 "s_register_operand" "r,r"))) + (match_operand 2 "arm_adcimm_operand" "I,K")) + (sign_extend:DI + (plus:SI (plus:SI (match_operand:SI 4 "arm_carry_operation" "") + (match_dup 1)) + (match_dup 2))))) + (set (match_operand:SI 0 "s_register_operand" "=r,r") + (plus:SI (plus:SI (match_dup 4) (match_dup 1)) + (match_dup 2)))] + "TARGET_32BIT" + "@ + adcs%?\\t%0, %1, %2 + sbcs%?\\t%0, %1, #%B2" + [(set_attr "type" "alus_imm")] +) + +(define_expand "addsi3_cin_vout_0" + [(parallel + [(set (match_dup 2) + (compare:CC_V + (plus:DI (match_dup 3) + (sign_extend:DI (match_operand:SI 1 "s_register_operand"))) + (sign_extend:DI (plus:SI (match_dup 4) (match_dup 1))))) + (set (match_operand:SI 0 "s_register_operand") + (plus:SI (match_dup 4) (match_dup 1)))])] + "TARGET_32BIT" + { + operands[2] = gen_rtx_REG (CC_Vmode, CC_REGNUM); + rtx ccin = gen_rtx_REG (CC_Cmode, CC_REGNUM); + operands[3] = gen_rtx_LTU (DImode, ccin, const0_rtx); + operands[4] = gen_rtx_LTU (SImode, ccin, const0_rtx); + } +) + +(define_insn "*addsi3_cin_vout_0_insn" + [(set (reg:CC_V CC_REGNUM) + (compare:CC_V + (plus:DI + (match_operand:DI 2 "arm_carry_operation" "") + (sign_extend:DI (match_operand:SI 1 "s_register_operand" "r"))) + (sign_extend:DI (plus:SI + (match_operand:SI 3 "arm_carry_operation" "") + (match_dup 1))))) + (set (match_operand:SI 0 "s_register_operand" "=r") + (plus:SI (match_dup 3) (match_dup 1)))] + "TARGET_32BIT" + "adcs%?\\t%0, %1, #0" + [(set_attr "type" "alus_imm")] +) + (define_expand "uaddvsi4" [(match_operand:SI 0 "s_register_operand") (match_operand:SI 1 "s_register_operand") @@ -770,22 +925,6 @@ (define_insn_and_split "*arm_addsi3" ] ) -(define_insn "adddi3_compareV" - [(set (reg:CC_V CC_REGNUM) - (ne:CC_V - (plus:TI - (sign_extend:TI (match_operand:DI 1 "s_register_operand" "r")) - (sign_extend:TI (match_operand:DI 2 "s_register_operand" "r"))) - (sign_extend:TI (plus:DI (match_dup 1) (match_dup 2))))) - (set (match_operand:DI 0 "s_register_operand" "=&r") - (plus:DI (match_dup 1) (match_dup 2)))] - "TARGET_32BIT" - "adds\\t%Q0, %Q1, %Q2;adcs\\t%R0, %R1, %R2" - [(set_attr "conds" "set") - (set_attr "length" "8") - (set_attr "type" "multiple")] -) - (define_insn "addsi3_compareV_reg" [(set (reg:CC_V CC_REGNUM) (compare:CC_V diff --git a/gcc/testsuite/gcc.dg/builtin-arith-overflow-3.c b/gcc/testsuite/gcc.dg/builtin-arith-overflow-3.c new file mode 100644 index 00000000000..6feae1eb42f --- /dev/null +++ b/gcc/testsuite/gcc.dg/builtin-arith-overflow-3.c @@ -0,0 +1,41 @@ +/* { dg-do run } */ +/* { dg-options "-O2" } */ + +static int cnt = 0; + +#define LL_MIN ((long long)(-__LONG_LONG_MAX__ - 1)) + +#define SC1 (LL_MIN + 5) +#define UC1 ((1ULL << (__LONG_LONG_WIDTH__ - 1)) | 5ULL) +#define UC2 (~UC1) + +long long __attribute__ ((noinline, noclone)) +f1 (long long a) +{ + long long x; + if (__builtin_add_overflow (a, SC1, &x)) cnt++; + return x; +} + +unsigned long long __attribute__ ((noinline, noclone)) +f2 (unsigned long long a) +{ + unsigned long long x; + if (__builtin_add_overflow (a, UC1, &x)) + cnt++; + return x; +} + +int main () +{ + if (f1 (-5) != LL_MIN) __builtin_abort (); + if (cnt != 0) __builtin_abort (); + f1 (-6); + if (cnt != 1) __builtin_abort (); + cnt = 0; + if (f2 (UC2) != ~0ULL) __builtin_abort (); + if (cnt != 0) __builtin_abort (); + if (f2 (UC2 + 1) != 0) __builtin_abort (); + if (cnt != 1) __builtin_abort (); + return 0; +}