From patchwork Fri Aug 27 21:06:46 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Jeff Law X-Patchwork-Id: 1521795 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=2620:52:3:1:0:246e:9693:128c; helo=sourceware.org; envelope-from=gcc-patches-bounces+incoming=patchwork.ozlabs.org@gcc.gnu.org; receiver=) Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.a=rsa-sha256 header.s=default header.b=aAMIWreP; dkim-atps=neutral Received: from sourceware.org (server2.sourceware.org [IPv6:2620:52:3:1:0:246e:9693:128c]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 4GxC3Q2Md5z9sPf for ; Sat, 28 Aug 2021 07:07:45 +1000 (AEST) Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 97A11385781A for ; Fri, 27 Aug 2021 21:07:42 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 97A11385781A DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1630098462; bh=7jW5ZBNoPzxkD3pEhqnWeP+sfJayt3al+CK73pBH+U0=; h=To:Subject:Date:List-Id:List-Unsubscribe:List-Archive:List-Post: List-Help:List-Subscribe:From:Reply-To:From; b=aAMIWrePWWKASGob3QtFgE7W2U8J4kIzOZ3mtW4+dLcX7Z6cF6WJXRL7AM4qYfrP7 7FPjxKDMQUvWkKvKOE3h6NfsTkenjWjcBYo469EENUPNhNvC1cFEIAJTjfBvMWHNri /qesbsIHYutwbM58fnwGziEEGCbysV/jAeXuZSMo= X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from mail-pl1-x635.google.com (mail-pl1-x635.google.com [IPv6:2607:f8b0:4864:20::635]) by sourceware.org (Postfix) with ESMTPS id CE5633858C60 for ; Fri, 27 Aug 2021 21:06:50 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org CE5633858C60 Received: by mail-pl1-x635.google.com with SMTP id n12so4687883plk.10 for ; Fri, 27 Aug 2021 14:06:50 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:subject:message-id:date:user-agent :mime-version:content-language; bh=7jW5ZBNoPzxkD3pEhqnWeP+sfJayt3al+CK73pBH+U0=; b=kFvPOum8DuKIOBvrFjmIgQSiuSjZ1peDdrwaCANTNSOPR99dMx6LyUGf1mLUX0ZkPo Hzhas2y8BOG5b/41fm4wHeyewg/kLfhS70irgInwcM4AD1OsSYCbbL+yP2YB5KH0QcNA 3kNKpS12lM5/HzBLYyhG2c8YwL9GWdJKQO1d17G6baDKP3gZD0/ggdMO2jQL5kqk/YQO OGYOvf1PV2uJ5wUdMLgC5hf6NSf+atL5MMxMuuauER6FLpFfPY6d5v8xM2E5MBsPFpTI EG+y0MZoMU1QaFNp2GFRYU802LOug8xqrnlqzpQf0lxCDCSKkTn3kTHiJN4SdeIlwWFI D4HQ== X-Gm-Message-State: AOAM533PZY1ya97jscCzR0TpPsQFuZky5XzoZTrT7fmXJcwWnQc9gIPx guuRQOzB01VfFhSINqCH3dif5l70k0lWvA== X-Google-Smtp-Source: ABdhPJxewmplaKle8YOe2Vh69AuSA07zXjIA3iEzGDvLxnD4sWb8uAncxJohZ7wGUgWwvSBFlmiy/w== X-Received: by 2002:a17:90a:6502:: with SMTP id i2mr25412901pjj.129.1630098409447; Fri, 27 Aug 2021 14:06:49 -0700 (PDT) Received: from [172.31.0.175] (c-98-202-48-222.hsd1.ut.comcast.net. [98.202.48.222]) by smtp.gmail.com with ESMTPSA id y5sm6840922pfa.5.2021.08.27.14.06.47 for (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Fri, 27 Aug 2021 14:06:48 -0700 (PDT) To: GCC Patches Subject: [committed] Support limited setcc for H8 Message-ID: <3248b49d-a34e-6f3c-ff2e-a193a7caa85a@gmail.com> Date: Fri, 27 Aug 2021 15:06:46 -0600 User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:78.0) Gecko/20100101 Thunderbird/78.13.0 MIME-Version: 1.0 Content-Language: en-US X-Spam-Status: No, score=-8.2 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, FREEMAIL_FROM, GIT_PATCH_0, KAM_NUMSUBJECT, RCVD_IN_DNSWL_NONE, SPF_HELO_NONE, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.4 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on server2.sourceware.org X-BeenThere: gcc-patches@gcc.gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gcc-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-Patchwork-Original-From: Jeff Law via Gcc-patches From: Jeff Law Reply-To: Jeff Law Errors-To: gcc-patches-bounces+incoming=patchwork.ozlabs.org@gcc.gnu.org Sender: "Gcc-patches" One of the (few) remaining issues related to cc0 elimination from the H8 port was the fact that I dropped all setcc support.  While we only had setcc on the H8/SX variant, it seems a shame to regress like that. Meanwhile my primary motivation behind the recent work on the H8 port is to speed up testing, particularly the builtin-arith tests.  While I have some support that significantly improves things, it's still not as good as it could be. "Naturally" those two issues started to intersect and I started thinking a lot about setcc on the H8 last weekend and cobbled together some code that makes another notable improvement in those tests. This patch was extracted from the weekend's work and stands on its own as a nice little improvement.  In particular it allows us to support setcc style insns that move the state of the C bit into a GPR. Handling the C bit is the easiest to implement.  In fact, we can implement C bit handling on all the H8 variants and the implementation is actually better than what the H8/SX was previously doing. We have a variety of ways to get C bit information into GPRs.  We can insert it into an arbitrary position in an 8 bit register, we can use it in an 8 bit {add,subtract}-with-carry instruction, or we can use it in 8, 16 or 32 bit rotates. The first decision is should setcc generate -1, 0 or 1, 0.  -1, 0 is easiest (subx), but we're often going to need to negate the result.  -1, 0 is also going to be painful for the other bits we're going to want to support (Z, N, V) as we don't have as much flexibility in getting the bit into a GPR. 1, 0 isn't too hard.  We can use xor to clear the target register (of any size), then do a bld to insert C into the low bit.  Good. We can also use bild to insert inverted C into the low bit.  This allows us to implement efficient setcc for leu/gtu.  At worst it's equivalent to a branchy sequence in terms of speed and space and it's often better, even in isolation.  It also often allows combinations with subsequent instructions that extend the result to wider types which further improves things. While this could be easily extended to put the C bit at an arbitrary location in an 8 or 16 bit register or in the sign bit of a 32bit register, I haven't seen enough code that would significantly benefit.  So I haven't implemented this. While this does occasionally make things larger by twiddling register allocation decisions, these are relatively rare and dwarfed the regular and larger improvements we see in general. Tested without regressions on the H8.  Installing onto the trunk. Jeff commit ee914ec4f811243ad72aceea4748687c74f38bc6 Author: Jeff Law Date: Fri Aug 27 17:01:37 2021 -0400 Support limited setcc for H8 gcc/ * config/h8300/bitfield.md (cstore4): Remove expander. * config/h8300/h8300.c (h8300_expand_branch): Remove function. * config/h8300/h8300-protos.h (h8300_expadn_branch): Remove prototype. * config/h8300/h8300.md (eqne): New code iterator. (geultu, geultu_to_c): Similarly. * config/h8300/testcompare.md (cstore4): Dummy expander. (store_c_, store_c_i_): New define_insn_and_splits (cmp_c): New pattern diff --git a/gcc/config/h8300/bitfield.md b/gcc/config/h8300/bitfield.md index 82cb161d126..0d28c750a6a 100644 --- a/gcc/config/h8300/bitfield.md +++ b/gcc/config/h8300/bitfield.md @@ -338,17 +338,6 @@ } [(set_attr "length_table" "bitfield")]) -;;(define_expand "cstore4" -;; [(use (match_operator 1 "eqne_operator" -;; [(match_operand:QHSI 2 "h8300_dst_operand" "") -;; (match_operand:QHSI 3 "h8300_src_operand" "")])) -;; (clobber (match_operand:QHSI 0 "register_operand"))] -;; "TARGET_H8300SX" -;; { -;; h8300_expand_store (operands); -;; DONE; -;; }) - ;;(define_insn "*bstzhireg" ;; [(set (match_operand:HI 0 "register_operand" "=r") ;; (match_operator:HI 1 "eqne_operator" [(cc0) (const_int 0)]))] diff --git a/gcc/config/h8300/h8300-protos.h b/gcc/config/h8300/h8300-protos.h index 3d344018ff2..4a9624f91d6 100644 --- a/gcc/config/h8300/h8300-protos.h +++ b/gcc/config/h8300/h8300-protos.h @@ -45,7 +45,6 @@ extern int compute_a_shift_cc (rtx *, rtx_code); #ifdef HAVE_ATTR_cc extern enum attr_cc compute_plussi_cc (rtx *); #endif -extern void h8300_expand_branch (rtx[]); extern void h8300_expand_store (rtx[]); extern bool expand_a_shift (machine_mode, enum rtx_code, rtx[]); extern int h8300_shift_needs_scratch_p (int, machine_mode, rtx_code); diff --git a/gcc/config/h8300/h8300.c b/gcc/config/h8300/h8300.c index 5f7251ab78d..a63c3220e66 100644 --- a/gcc/config/h8300/h8300.c +++ b/gcc/config/h8300/h8300.c @@ -3256,30 +3256,8 @@ compute_logical_op_length (machine_mode mode, rtx_code code, rtx *operands, rtx_ return length; } - #if 0 -/* Expand a conditional branch. */ - -void -h8300_expand_branch (rtx operands[]) -{ - enum rtx_code code = GET_CODE (operands[0]); - rtx op0 = operands[1]; - rtx op1 = operands[2]; - rtx label = operands[3]; - rtx tmp; - - tmp = gen_rtx_COMPARE (VOIDmode, op0, op1); - emit_insn (gen_rtx_SET (cc0_rtx, tmp)); - - tmp = gen_rtx_fmt_ee (code, VOIDmode, cc0_rtx, const0_rtx); - tmp = gen_rtx_IF_THEN_ELSE (VOIDmode, tmp, - gen_rtx_LABEL_REF (VOIDmode, label), - pc_rtx); - emit_jump_insn (gen_rtx_SET (pc_rtx, tmp)); -} - - + /* Expand a conditional store. */ void diff --git a/gcc/config/h8300/h8300.md b/gcc/config/h8300/h8300.md index 7f49e4284f2..89bfcf11126 100644 --- a/gcc/config/h8300/h8300.md +++ b/gcc/config/h8300/h8300.md @@ -233,6 +233,14 @@ (define_code_iterator logicals [ior xor and]) (define_code_iterator ors [ior xor]) + +(define_code_iterator eqne [eq ne]) + +;; For storing the C flag, map from the unsigned comparison to the right +;; code for testing the C bit. +(define_code_iterator geultu [geu ltu]) +(define_code_attr geultu_to_c [(geu "eq") (ltu "ne")]) + (include "movepush.md") (include "mova.md") diff --git a/gcc/config/h8300/testcompare.md b/gcc/config/h8300/testcompare.md index 29190532e49..9ff7a51077e 100644 --- a/gcc/config/h8300/testcompare.md +++ b/gcc/config/h8300/testcompare.md @@ -70,6 +70,22 @@ "mov.w %e0,%e0" [(set_attr "length" "2")]) +(define_insn "*cmp_c" + [(set (reg:CCC CC_REG) + (ltu (match_operand:QHSI 0 "h8300_dst_operand" "rQ") + (match_operand:QHSI 1 "h8300_src_operand" "rQi")))] + "reload_completed" + { + if (mode == QImode) + return "cmp.b %X1,%X0"; + else if (mode == HImode) + return "cmp.w %T1,%T0"; + else if (mode == SImode) + return "cmp.l %S1,%S0"; + gcc_unreachable (); + } + [(set_attr "length_table" "add")]) + (define_insn "*cmpqi" [(set (reg:CC CC_REG) (compare (match_operand:QI 0 "h8300_dst_operand" "rQ") @@ -144,3 +160,67 @@ [(parallel [(set (reg:CCZN CC_REG) (compare:CCZN (match_dup 1) (const_int 0))) (set (match_dup 0) (match_dup 1))])]) +;; This exists solely to convince ifcvt to try some store-flag sequences. +;; +;; Essentially we don't want to expose a general store-flag capability. +;; The only generally useful/profitable case is when we want to test the +;; C bit. In that case we can use addx, subx, bst, or bist to get the bit +;; into a GPR. +;; +;; Others could be handled with stc, shifts and masking, but it likely isn't +;; profitable. +;; +(define_expand "cstore4" + [(use (match_operator 1 "eqne_operator" + [(match_operand:QHSI 2 "h8300_dst_operand" "") + (match_operand:QHSI 3 "h8300_src_operand" "")])) + (clobber (match_operand:QHSI 0 "register_operand"))] + "" + { + FAIL; + }) + +;; Storing the C bit is pretty simple since there are many ways to +;; introduce it into a GPR. addx, subx and a variety of bit manipulation +;; instructions +;; +(define_insn "*store_c_" + [(set (match_operand:QHSI 0 "register_operand" "=r") + (eqne:QHSI (reg:CCC CC_REG) (const_int 0)))] + "reload_completed" + { + if ( == NE) + { + if (mode == QImode) + return "xor.b\t%X0,%X0\;bst\t#0,%X0"; + else if (mode == HImode) + return "xor.w\t%T0,%T0\;bst\t#0,%s0"; + else if (mode == SImode) + return "xor.l\t%S0,%S0\;bst\t#0,%w0"; + gcc_unreachable (); + } + else if ( == EQ) + { + if (mode == QImode) + return "xor.b\t%X0,%X0\;bist\t#0,%X0"; + else if (mode == HImode) + return "xor.w\t%T0,%T0\;bist\t#0,%s0"; + else if (mode == SImode) + return "xor.l\t%S0,%S0\;bist\t#0,%w0"; + gcc_unreachable (); + } + } + [(set (attr "length") (symbol_ref "mode == SImode ? 6 : 4"))]) + +;; Recognize this scc and generate code we can match +(define_insn_and_split "*store_c_i_" + [(set (match_operand:QHSI 0 "register_operand" "=r") + (geultu:QHSI (match_operand:QHSI 1 "register_operand" "r") + (match_operand:QHSI 2 "register_operand" "r")))] + "" + "#" + "&& reload_completed" + [(set (reg:CCC CC_REG) + (ltu:CCC (match_dup 1) (match_dup 2))) + (set (match_dup 0) + (:QHSI (reg:CCC CC_REG) (const_int 0)))])