From patchwork Fri Oct 18 19:48:51 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: 1179642 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=gcc.gnu.org (client-ip=209.132.180.131; helo=sourceware.org; envelope-from=gcc-patches-return-511330-incoming=patchwork.ozlabs.org@gcc.gnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=arm.com Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.b="WBPJLhPY"; dkim-atps=neutral Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 46vxgW5SyWz9sP7 for ; Sat, 19 Oct 2019 06:59:03 +1100 (AEDT) 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=IK2OiCWOkyUC7BgF Gz8A7Jn3/3T59V0oDSe78JId/vljMg9JZJQCTRqCqQsEy0CP0OjdR/QlOxMzBoeA LRaabVxeILD4e7nBfBk73Kv3HFr7p+DWFKHQWlJGZawLYCgEgkgk69L4Rx0r3nyP YmnCHYPFv6yk8ZswvTyCblNLp/4= 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=pUy9ZSwki18MhLmyj/0IRR Hprro=; b=WBPJLhPYLs0OYiDbiIQSiSQUaSdU/dzCxJjX4qt6YGg/+IxwMiF+76 U5Fu3YJ8zm96oiVWth6zA/EIKKJgvppEhkNouWm/leri/xEzKzUxzdq56kSSJm34 HOOy3eRPpAZ8OD0HaYe7IPheOlevSUshUqbS2eBx+lCxUx8sTPq1E= Received: (qmail 115587 invoked by alias); 18 Oct 2019 19:55:49 -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 114987 invoked by uid 89); 18 Oct 2019 19:55:45 -0000 Authentication-Results: sourceware.org; auth=none X-Spam-SWARE-Status: No, score=-19.1 required=5.0 tests=AWL, BAYES_00, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, SPF_FAIL autolearn=ham version=3.3.1 spammy= X-HELO: eggs.gnu.org Received: from eggs.gnu.org (HELO eggs.gnu.org) (209.51.188.92) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Fri, 18 Oct 2019 19:55:43 +0000 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1iLYLd-0005AT-5P for gcc-patches@gcc.gnu.org; Fri, 18 Oct 2019 15:55:42 -0400 Received: from [217.140.110.172] (port=42766 helo=foss.arm.com) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1iLYLc-00055W-TB for gcc-patches@gcc.gnu.org; Fri, 18 Oct 2019 15:55:41 -0400 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 30E51175A; Fri, 18 Oct 2019 12:49:26 -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 B262B3F6C4; Fri, 18 Oct 2019 12:49:25 -0700 (PDT) From: Richard Earnshaw To: gcc-patches@gcc.gnu.org Cc: Richard Earnshaw Subject: [PATCH 20/29] [arm] Early expansion of uaddvdi4. Date: Fri, 18 Oct 2019 20:48:51 +0100 Message-Id: <20191018194900.34795-21-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 X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 217.140.110.172 This code borrows strongly on the uaddvti4 expansion for aarch64 since the principles are similar. Firstly, if the one of the low words of the expansion is 0, we can simply copy the other low word to the destination and use uaddvsi4 for the upper word. If that doesn't work we have to handle three possible cases for the upper work (the lower word is simply an add-with-carry operation as for adddi3): zero in the upper word, some other constant and a register (each has a different canonicalization). We use CC_ADCmode (a new CC mode variant) to describe the cases as the introduction of the carry means we can no-longer use the normal overflow trick of comparing the sum against one of the operands. * config/arm/arm-modes.def (CC_ADC): New CC mode. * config/arm/arm.c (arm_select_cc_mode): Detect selection of CC_ADCmode. (maybe_get_arm_condition_code): Handle CC_ADCmode. * config/arm/arm.md (uaddvdi4): Early expansion of unsigned addition with overflow. (addsi3_cin_cout_reg, addsi3_cin_cout_imm, addsi3_cin_cout_0): New expand patterns. (addsi3_cin_cout_reg_insn, addsi3_cin_cout_0_insn): New insn patterns (addsi3_cin_cout_imm_insn): Likewise. (adddi3_compareC): Delete insn. * config/arm/predicates.md (arm_carry_operation): Handle CC_ADCmode. --- gcc/config/arm/arm-modes.def | 4 + gcc/config/arm/arm.c | 16 ++++ gcc/config/arm/arm.md | 171 +++++++++++++++++++++++++++++++---- gcc/config/arm/predicates.md | 2 +- 4 files changed, 173 insertions(+), 20 deletions(-) diff --git a/gcc/config/arm/arm-modes.def b/gcc/config/arm/arm-modes.def index f0eb8415b93..a6b520df32d 100644 --- a/gcc/config/arm/arm-modes.def +++ b/gcc/config/arm/arm-modes.def @@ -42,6 +42,9 @@ ADJUST_FLOAT_FORMAT (HF, ((arm_fp16_format == ARM_FP16_FORMAT_ALTERNATIVE) CC_Bmode should be used if only the C flag is correct after a subtract (eg after an unsigned borrow with carry-in propagation). (used for DImode signed comparisons). + CC_ADCmode is used when the carry is formed from the output of ADC for an + addtion. In this case we cannot use the trick of comparing the sum + against one of the other operands. CCmode should be used otherwise. */ CC_MODE (CC_NOOV); @@ -65,6 +68,7 @@ CC_MODE (CC_C); CC_MODE (CC_B); CC_MODE (CC_N); CC_MODE (CC_V); +CC_MODE (CC_ADC); /* Vector modes. */ VECTOR_MODES (INT, 4); /* V4QI V2HI */ diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c index 6da2a368d9f..eebbdc3d9c2 100644 --- a/gcc/config/arm/arm.c +++ b/gcc/config/arm/arm.c @@ -15387,6 +15387,14 @@ arm_select_cc_mode (enum rtx_code op, rtx x, rtx y) && (rtx_equal_p (XEXP (x, 0), y) || rtx_equal_p (XEXP (x, 1), y))) return CC_Cmode; + if (GET_MODE (x) == DImode + && GET_CODE (x) == PLUS + && GET_CODE (XEXP (x, 1)) == ZERO_EXTEND + && CONST_INT_P (y) + && UINTVAL (y) == 0x800000000 + && (op == GEU || op == LTU)) + return CC_ADCmode; + if (GET_MODE (x) == DImode && (op == GE || op == LT) && GET_CODE (x) == SIGN_EXTEND @@ -23952,6 +23960,14 @@ maybe_get_arm_condition_code (rtx comparison) default: return ARM_NV; } + case E_CC_ADCmode: + switch (comp_code) + { + case GEU: return ARM_CS; + case LTU: return ARM_CC; + default: return ARM_NV; + } + case E_CCmode: case E_CC_RSBmode: switch (comp_code) diff --git a/gcc/config/arm/arm.md b/gcc/config/arm/arm.md index 4ea6f4b226c..9f0e43571fd 100644 --- a/gcc/config/arm/arm.md +++ b/gcc/config/arm/arm.md @@ -517,16 +517,165 @@ (define_expand "uaddvsi4" (define_expand "uaddvdi4" [(match_operand:DI 0 "s_register_operand") (match_operand:DI 1 "s_register_operand") - (match_operand:DI 2 "s_register_operand") + (match_operand:DI 2 "reg_or_int_operand") (match_operand 3 "")] "TARGET_32BIT" { - emit_insn (gen_adddi3_compareC (operands[0], operands[1], operands[2])); - arm_gen_unlikely_cbranch (LTU, CC_Cmode, 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); + + gen_uaddvsi4 (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_cout_0 (hi_result, hi_op1)); + else if (CONST_INT_P (hi_op2)) + emit_insn (gen_addsi3_cin_cout_imm (hi_result, hi_op1, hi_op2)); + else + emit_insn (gen_addsi3_cin_cout_reg (hi_result, hi_op1, hi_op2)); + + arm_gen_unlikely_cbranch (GEU, CC_ADCmode, operands[3]); + } DONE; }) +(define_expand "addsi3_cin_cout_reg" + [(parallel + [(set (match_dup 3) + (compare:CC_ADC + (plus:DI + (plus:DI (match_dup 4) + (zero_extend:DI (match_operand:SI 1 "s_register_operand"))) + (zero_extend:DI (match_operand:SI 2 "s_register_operand"))) + (const_int 4294967296))) + (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_ADCmode, 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_cout_reg_insn" + [(set (reg:CC_ADC CC_REGNUM) + (compare:CC_ADC + (plus:DI + (plus:DI + (match_operand:DI 3 "arm_carry_operation" "") + (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%0,r"))) + (zero_extend:DI (match_operand:SI 2 "s_register_operand" "l,r"))) + (const_int 4294967296))) + (set (match_operand:SI 0 "s_register_operand" "=l,r") + (plus:SI (plus:SI (match_operand:SI 4 "arm_carry_operation" "") + (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_cout_imm" + [(parallel + [(set (match_dup 3) + (compare:CC_ADC + (plus:DI + (plus:DI (match_dup 4) + (zero_extend:DI (match_operand:SI 1 "s_register_operand"))) + (match_dup 6)) + (const_int 4294967296))) + (set (match_operand:SI 0 "s_register_operand") + (plus:SI (plus:SI (match_dup 5) (match_dup 1)) + (match_operand:SI 2 "arm_adcimm_operand")))])] + "TARGET_32BIT" + { + operands[3] = gen_rtx_REG (CC_ADCmode, 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); + operands[6] = GEN_INT (UINTVAL (operands[2]) & 0xffffffff); + } +) + +(define_insn "*addsi3_cin_cout_imm_insn" + [(set (reg:CC_ADC CC_REGNUM) + (compare:CC_ADC + (plus:DI + (plus:DI + (match_operand:DI 3 "arm_carry_operation" "") + (zero_extend:DI (match_operand:SI 1 "s_register_operand" "r,r"))) + (match_operand:DI 5 "const_int_operand" "n,n")) + (const_int 4294967296))) + (set (match_operand:SI 0 "s_register_operand" "=r,r") + (plus:SI (plus:SI (match_operand:SI 4 "arm_carry_operation" "") + (match_dup 1)) + (match_operand:SI 2 "arm_adcimm_operand" "I,K")))] + "TARGET_32BIT + && (UINTVAL (operands[2]) & 0xffffffff) == UINTVAL (operands[5])" + "@ + adcs%?\\t%0, %1, %2 + sbcs%?\\t%0, %1, #%B2" + [(set_attr "type" "alus_imm")] +) + +(define_expand "addsi3_cin_cout_0" + [(parallel + [(set (match_dup 2) + (compare:CC_ADC + (plus:DI (match_dup 3) + (zero_extend:DI (match_operand:SI 1 "s_register_operand"))) + (const_int 4294967296))) + (set (match_operand:SI 0 "s_register_operand") + (plus:SI (match_dup 4) (match_dup 1)))])] + "TARGET_32BIT" + { + operands[2] = gen_rtx_REG (CC_ADCmode, 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_cout_0_insn" + [(set (reg:CC_ADC CC_REGNUM) + (compare:CC_ADC + (plus:DI + (match_operand:DI 2 "arm_carry_operation" "") + (zero_extend:DI (match_operand:SI 1 "s_register_operand" "r"))) + (const_int 4294967296))) + (set (match_operand:SI 0 "s_register_operand" "=r") + (plus:SI (match_operand:SI 3 "arm_carry_operation" "") (match_dup 1)))] + "TARGET_32BIT" + "adcs%?\\t%0, %1, #0" + [(set_attr "type" "alus_imm")] +) + (define_expand "addsi3" [(set (match_operand:SI 0 "s_register_operand") (plus:SI (match_operand:SI 1 "s_register_operand") @@ -636,22 +785,6 @@ (define_insn "addsi3_compareV" (set_attr "type" "alus_sreg")] ) -(define_insn "adddi3_compareC" - [(set (reg:CC_C CC_REGNUM) - (compare:CC_C - (plus:DI - (match_operand:DI 1 "register_operand" "r") - (match_operand:DI 2 "register_operand" "r")) - (match_dup 1))) - (set (match_operand:DI 0 "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_compare0" [(set (reg:CC_NOOV CC_REGNUM) (compare:CC_NOOV diff --git a/gcc/config/arm/predicates.md b/gcc/config/arm/predicates.md index d9470df8093..8a8f10ccb50 100644 --- a/gcc/config/arm/predicates.md +++ b/gcc/config/arm/predicates.md @@ -376,7 +376,7 @@ (define_special_predicate "arm_carry_operation" machine_mode ccmode = GET_MODE (op0); if (ccmode == CC_Cmode) return GET_CODE (op) == LTU; - else if (ccmode == CCmode || ccmode == CC_RSBmode) + else if (ccmode == CCmode || ccmode == CC_RSBmode || ccmode == CC_ADCmode) return GET_CODE (op) == GEU; return false;