From patchwork Thu Jul 18 14:02:04 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: 1133743 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=gcc.gnu.org (client-ip=209.132.180.131; helo=sourceware.org; envelope-from=gcc-patches-return-505273-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="NyMQ2HeF"; 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 45qG6V1NC6z9sBF for ; Fri, 19 Jul 2019 00:02:19 +1000 (AEST) 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=GUdOTuQ3BvBlc90EBZiNnZL6UN1liAFN8zUR6wjnQRkSVA0/y4 V4algB2NEfy/SFqxIWw8ilbObURWXo3oK0htF2OaxIOHVwvLNAFY7oTWE0omqECt oUA7FG6MRWhnCO5HiGCjxzb3JvnbtIePJtOwOQLsDAx3gnjUBK8lOt0QU= 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=MXtZrzCe3751U5OWYpln6N1bSDE=; b=NyMQ2HeFWqs1v0qaFRFK DQ1JIA47wo4IacqqpEUWG94dckzM3FZ+p4EkPWrbb5m9IXP1hKe6wuhdMJfKDPz5 D4cWqp+0FsTXVW5ppTLAtPY0NzWNdJF+GdGkiYmtfEA1MIbFnW5NHKQav+KJy77Z oZBKUzlB2rnewGsFJkcloXE= Received: (qmail 14306 invoked by alias); 18 Jul 2019 14:02:11 -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 14297 invoked by uid 89); 18 Jul 2019 14:02:11 -0000 Authentication-Results: sourceware.org; auth=none X-Spam-SWARE-Status: No, score=-17.8 required=5.0 tests=AWL, BAYES_00, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, SPF_PASS autolearn=ham version=3.3.1 spammy= X-HELO: foss.arm.com Received: from foss.arm.com (HELO foss.arm.com) (217.140.110.172) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Thu, 18 Jul 2019 14:02:08 +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 CB95B344; Thu, 18 Jul 2019 07:02:06 -0700 (PDT) Received: from e120077-lin.cambridge.arm.com (e120077-lin.cambridge.arm.com [10.2.206.226]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 38D9F3F71F; Thu, 18 Jul 2019 07:02:06 -0700 (PDT) To: gcc-patches@gcc.gnu.org From: "Richard Earnshaw (lists)" Subject: [arm] Fix incorrect modes with 'borrow' operations Message-ID: <908503fe-d87f-c9b7-7796-9662fa96e594@arm.com> Date: Thu, 18 Jul 2019 15:02:04 +0100 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:60.0) Gecko/20100101 Thunderbird/60.7.1 MIME-Version: 1.0 Looking through the arm backend I noticed that the modes used to pass comparison types into subtract-with-carry operations were being incorrectly set. The result is that the compiler is not truly self-consistent. To clean this up I've introduced a new predicate, arm_borrow_operation (borrowed from the AArch64 backend which can match the comparison type with the required mode and then fixed all the patterns to use this. The split patterns that were generating incorrect modes have all obviously been fixed as well. The basic rule for the use of a borrow is: - if the condition code was set by a 'subtract-like' operation (subs, cmp), then use CCmode and LTU. - if the condition code was by unsigned overflow of addition (adds), then use CC_Cmode and GEU. * config/arm/predicates.md (arm_borrow_operation): New predicate. * config/arm/arm.c (subdi3_compare1): Use CCmode for the split. (arm_subdi3, subdi_di_zesidi, subdi_di_sesidi): Likewise. (subdi_zesidi_zesidi): Likewise. (negdi2_compare, negdi2_insn): Likewise. (negdi_extensidi): Likewise. (negdi_zero_extendsidi): Likewise. (arm_cmpdi_insn): Likewise. (subsi3_carryin): Use arm_borrow_operation. (subsi3_carryin_const): Likewise. (subsi3_carryin_const0): Likewise. (subsi3_carryin_compare): Likewise. (subsi3_carryin_compare_const): Likewise. (subsi3_carryin_compare_const0): Likewise. (subsi3_carryin_shift): Likewise. (rsbsi3_carryin_shift): Likewise. (negsi2_carryin_compare): Likewise. diff --git a/gcc/config/arm/arm.md b/gcc/config/arm/arm.md index 8f4a4c26ea8..dcb57372192 100644 --- a/gcc/config/arm/arm.md +++ b/gcc/config/arm/arm.md @@ -1110,7 +1110,7 @@ (define_insn_and_split "subdi3_compare1" (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))))])] + (ltu:SI (reg:CC CC_REGNUM) (const_int 0))))])] { operands[3] = gen_highpart (SImode, operands[0]); operands[0] = gen_lowpart (SImode, operands[0]); @@ -1141,7 +1141,7 @@ (define_insn "*subsi3_carryin" [(set (match_operand:SI 0 "s_register_operand" "=r,r,r") (minus:SI (minus:SI (match_operand:SI 1 "reg_or_int_operand" "r,I,Pz") (match_operand:SI 2 "s_register_operand" "r,r,r")) - (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))] + (match_operand:SI 3 "arm_borrow_operation" "")))] "TARGET_32BIT" "@ sbc%?\\t%0, %1, %2 @@ -1155,9 +1155,10 @@ (define_insn "*subsi3_carryin" (define_insn "*subsi3_carryin_const" [(set (match_operand:SI 0 "s_register_operand" "=r") - (minus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "r") - (match_operand:SI 2 "arm_neg_immediate_operand" "L")) - (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))] + (minus:SI (plus:SI + (match_operand:SI 1 "s_register_operand" "r") + (match_operand:SI 2 "arm_neg_immediate_operand" "L")) + (match_operand:SI 3 "arm_borrow_operation" "")))] "TARGET_32BIT" "sbc\\t%0, %1, #%n2" [(set_attr "conds" "use") @@ -1166,8 +1167,8 @@ (define_insn "*subsi3_carryin_const" (define_insn "*subsi3_carryin_const0" [(set (match_operand:SI 0 "s_register_operand" "=r") - (minus:SI (match_operand:SI 1 "s_register_operand" "r") - (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))] + (minus:SI (match_operand:SI 1 "s_register_operand" "r") + (match_operand:SI 2 "arm_borrow_operation" "")))] "TARGET_32BIT" "sbc\\t%0, %1, #0" [(set_attr "conds" "use") @@ -1176,12 +1177,11 @@ (define_insn "*subsi3_carryin_const0" (define_insn "*subsi3_carryin_compare" [(set (reg:CC CC_REGNUM) - (compare:CC (match_operand:SI 1 "s_register_operand" "r") - (match_operand:SI 2 "s_register_operand" "r"))) + (compare:CC (match_operand:SI 1 "s_register_operand" "r") + (match_operand:SI 2 "s_register_operand" "r"))) (set (match_operand:SI 0 "s_register_operand" "=r") - (minus:SI (minus:SI (match_dup 1) - (match_dup 2)) - (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))] + (minus:SI (minus:SI (match_dup 1) (match_dup 2)) + (match_operand:SI 3 "arm_borrow_operation" "")))] "TARGET_32BIT" "sbcs\\t%0, %1, %2" [(set_attr "conds" "set") @@ -1190,12 +1190,13 @@ (define_insn "*subsi3_carryin_compare" (define_insn "*subsi3_carryin_compare_const" [(set (reg:CC CC_REGNUM) - (compare:CC (match_operand:SI 1 "reg_or_int_operand" "r") - (match_operand:SI 2 "const_int_I_operand" "I"))) + (compare:CC (match_operand:SI 1 "reg_or_int_operand" "r") + (match_operand:SI 2 "const_int_I_operand" "I"))) (set (match_operand:SI 0 "s_register_operand" "=r") - (minus:SI (plus:SI (match_dup 1) - (match_operand:SI 3 "arm_neg_immediate_operand" "L")) - (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))] + (minus:SI (plus:SI + (match_dup 1) + (match_operand:SI 3 "arm_neg_immediate_operand" "L")) + (match_operand:SI 4 "arm_borrow_operation" "")))] "TARGET_32BIT && (INTVAL (operands[2]) == trunc_int_for_mode (-INTVAL (operands[3]), SImode))" @@ -1206,11 +1207,11 @@ (define_insn "*subsi3_carryin_compare_const" (define_insn "*subsi3_carryin_compare_const0" [(set (reg:CC CC_REGNUM) - (compare:CC (match_operand:SI 1 "reg_or_int_operand" "r") + (compare:CC (match_operand:SI 1 "reg_or_int_operand" "r") (const_int 0))) (set (match_operand:SI 0 "s_register_operand" "=r") - (minus:SI (match_dup 1) - (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))] + (minus:SI (match_dup 1) + (match_operand:SI 2 "arm_borrow_operation" "")))] "TARGET_32BIT" "sbcs\\t%0, %1, #0" [(set_attr "conds" "set") @@ -1220,28 +1221,28 @@ (define_insn "*subsi3_carryin_compare_const0" (define_insn "*subsi3_carryin_shift" [(set (match_operand:SI 0 "s_register_operand" "=r") (minus:SI (minus:SI - (match_operand:SI 1 "s_register_operand" "r") - (match_operator:SI 2 "shift_operator" - [(match_operand:SI 3 "s_register_operand" "r") - (match_operand:SI 4 "reg_or_int_operand" "rM")])) - (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))] + (match_operand:SI 1 "s_register_operand" "r") + (match_operator:SI 2 "shift_operator" + [(match_operand:SI 3 "s_register_operand" "r") + (match_operand:SI 4 "reg_or_int_operand" "rM")])) + (match_operand:SI 5 "arm_borrow_operation" "")))] "TARGET_32BIT" "sbc%?\\t%0, %1, %3%S2" [(set_attr "conds" "use") (set_attr "predicable" "yes") (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "") - (const_string "alu_shift_imm") - (const_string "alu_shift_reg")))] + (const_string "alu_shift_imm") + (const_string "alu_shift_reg")))] ) (define_insn "*rsbsi3_carryin_shift" [(set (match_operand:SI 0 "s_register_operand" "=r") (minus:SI (minus:SI - (match_operator:SI 2 "shift_operator" - [(match_operand:SI 3 "s_register_operand" "r") - (match_operand:SI 4 "reg_or_int_operand" "rM")]) + (match_operator:SI 2 "shift_operator" + [(match_operand:SI 3 "s_register_operand" "r") + (match_operand:SI 4 "reg_or_int_operand" "rM")]) (match_operand:SI 1 "s_register_operand" "r")) - (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))] + (match_operand:SI 5 "arm_borrow_operation" "")))] "TARGET_ARM" "rsc%?\\t%0, %1, %3%S2" [(set_attr "conds" "use") @@ -1311,7 +1312,7 @@ (define_insn_and_split "*arm_subdi3" (compare:CC (match_dup 1) (match_dup 2))) (set (match_dup 0) (minus:SI (match_dup 1) (match_dup 2)))]) (set (match_dup 3) (minus:SI (minus:SI (match_dup 4) (match_dup 5)) - (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))] + (ltu:SI (reg:CC CC_REGNUM) (const_int 0))))] { operands[3] = gen_highpart (SImode, operands[0]); operands[0] = gen_lowpart (SImode, operands[0]); @@ -1338,7 +1339,7 @@ (define_insn_and_split "*subdi_di_zesidi" (compare:CC (match_dup 1) (match_dup 2))) (set (match_dup 0) (minus:SI (match_dup 1) (match_dup 2)))]) (set (match_dup 3) (minus:SI (match_dup 4) - (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))] + (ltu:SI (reg:CC CC_REGNUM) (const_int 0))))] { operands[3] = gen_highpart (SImode, operands[0]); operands[0] = gen_lowpart (SImode, operands[0]); @@ -1365,7 +1366,7 @@ (define_insn_and_split "*subdi_di_sesidi" (set (match_dup 3) (minus:SI (minus:SI (match_dup 4) (ashiftrt:SI (match_dup 2) (const_int 31))) - (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))] + (ltu:SI (reg:CC CC_REGNUM) (const_int 0))))] { operands[3] = gen_highpart (SImode, operands[0]); operands[0] = gen_lowpart (SImode, operands[0]); @@ -1392,7 +1393,7 @@ (define_insn_and_split "*subdi_zesidi_di" (compare:CC (match_dup 2) (match_dup 1))) (set (match_dup 0) (minus:SI (match_dup 2) (match_dup 1)))]) (set (match_dup 3) (minus:SI (minus:SI (const_int 0) (match_dup 4)) - (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))] + (ltu:SI (reg:CC CC_REGNUM) (const_int 0))))] { operands[3] = gen_highpart (SImode, operands[0]); operands[0] = gen_lowpart (SImode, operands[0]); @@ -1422,7 +1423,7 @@ (define_insn_and_split "*subdi_sesidi_di" (ashiftrt:SI (match_dup 2) (const_int 31)) (match_dup 4)) - (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))] + (ltu:SI (reg:CC CC_REGNUM) (const_int 0))))] { operands[3] = gen_highpart (SImode, operands[0]); operands[0] = gen_lowpart (SImode, operands[0]); @@ -1448,7 +1449,7 @@ (define_insn_and_split "*subdi_zesidi_zesidi" (compare:CC (match_dup 1) (match_dup 2))) (set (match_dup 0) (minus:SI (match_dup 1) (match_dup 2)))]) (set (match_dup 3) (minus:SI (minus:SI (match_dup 1) (match_dup 1)) - (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))] + (ltu:SI (reg:CC CC_REGNUM) (const_int 0))))] { operands[3] = gen_highpart (SImode, operands[0]); operands[0] = gen_lowpart (SImode, operands[0]); @@ -4661,7 +4662,7 @@ (define_insn_and_split "negdi2_compare" (set (match_dup 2) (minus:SI (minus:SI (const_int 0) (match_dup 3)) - (ltu:SI (reg:CC_C CC_REGNUM) + (ltu:SI (reg:CC CC_REGNUM) (const_int 0))))])] { operands[2] = gen_highpart (SImode, operands[0]); @@ -4703,7 +4704,7 @@ (define_insn_and_split "*negdi2_insn" (compare:CC (const_int 0) (match_dup 1))) (set (match_dup 0) (minus:SI (const_int 0) (match_dup 1)))]) (set (match_dup 2) (minus:SI (minus:SI (const_int 0) (match_dup 3)) - (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))] + (ltu:SI (reg:CC CC_REGNUM) (const_int 0))))] { operands[2] = gen_highpart (SImode, operands[0]); operands[0] = gen_lowpart (SImode, operands[0]); @@ -4722,7 +4723,7 @@ (define_insn "*negsi2_carryin_compare" (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))))] + (match_operand:SI 2 "arm_borrow_operation" "")))] "TARGET_ARM" "rscs\\t%0, %1, #0" [(set_attr "conds" "set") @@ -4799,7 +4800,7 @@ (define_insn_and_split "*negdi_extendsidi" asr Rhi, Rin, #31 rsbs Rlo, Rin, #0 rsc Rhi, Rhi, #0 (thumb2: sbc Rhi, Rhi, Rhi, lsl #1). */ - rtx cc_reg = gen_rtx_REG (CC_Cmode, CC_REGNUM); + rtx cc_reg = gen_rtx_REG (CCmode, CC_REGNUM); emit_insn (gen_rtx_SET (high, gen_rtx_ASHIFTRT (SImode, operands[1], @@ -4861,10 +4862,10 @@ (define_insn_and_split "*negdi_zero_extendsidi" ;; since we just need to propagate the carry. "&& 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)))]) + (compare:CC (const_int 0) (match_dup 1))) + (set (match_dup 0) (minus:SI (const_int 0) (match_dup 1)))]) (set (match_dup 2) (minus:SI (minus:SI (match_dup 2) (match_dup 2)) - (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))] + (ltu:SI (reg:CC CC_REGNUM) (const_int 0))))] { operands[2] = gen_highpart (SImode, operands[0]); operands[0] = gen_lowpart (SImode, operands[0]); @@ -7448,12 +7449,12 @@ (define_insn_and_split "*arm_cmpdi_insn" "#" ; "cmp\\t%Q0, %Q1\;sbcs\\t%2, %R0, %R1" "&& reload_completed" [(set (reg:CC CC_REGNUM) - (compare:CC (match_dup 0) (match_dup 1))) + (compare:CC (match_dup 0) (match_dup 1))) (parallel [(set (reg:CC CC_REGNUM) - (compare:CC (match_dup 3) (match_dup 4))) - (set (match_dup 2) - (minus:SI (match_dup 5) - (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))])] + (compare:CC (match_dup 3) (match_dup 4))) + (set (match_dup 2) + (minus:SI (match_dup 5) + (ltu:SI (reg:CC CC_REGNUM) (const_int 0))))])] { operands[3] = gen_highpart (SImode, operands[0]); operands[0] = gen_lowpart (SImode, operands[0]); diff --git a/gcc/config/arm/predicates.md b/gcc/config/arm/predicates.md index f53378a250e..25f86471ded 100644 --- a/gcc/config/arm/predicates.md +++ b/gcc/config/arm/predicates.md @@ -358,6 +358,27 @@ (define_predicate "arm_comparison_operator_mode" (define_special_predicate "lt_ge_comparison_operator" (match_code "lt,ge")) +;; Match a "borrow" operation for use with SBC. The precise code will +;; depend on the form of the comparison. This is generally the inverse of +;; a carry operation, since the logic of SBC uses "not borrow" in it's +;; calculation. +(define_special_predicate "arm_borrow_operation" + (match_code "geu,ltu") + { + if (XEXP (op, 1) != const0_rtx) + return false; + rtx op0 = XEXP (op, 0); + if (!REG_P (op0) || REGNO (op0) != CC_REGNUM) + return false; + machine_mode ccmode = GET_MODE (op0); + if (ccmode == CC_Cmode) + return GET_CODE (op) == GEU; + else if (ccmode == CCmode) + return GET_CODE (op) == LTU; + return false; + } +) + ;; The vsel instruction only accepts the ARM condition codes listed below. (define_special_predicate "arm_vsel_comparison_operator" (and (match_operand 0 "expandable_comparison_operator")