From patchwork Tue Apr 30 23:47:41 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jim Wilson X-Patchwork-Id: 1093523 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-499946-incoming=patchwork.ozlabs.org@gcc.gnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=sifive.com Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.b="LYJ+88Ky"; dkim=pass (2048-bit key; unprotected) header.d=sifive.com header.i=@sifive.com header.b="XTczvWKh"; 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 44tyrf5xkQz9s5c for ; Wed, 1 May 2019 09:47:58 +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:from :to:cc:subject:date:message-id; q=dns; s=default; b=SvM4IB2c/i+A pcMCmdb+VbEd2MdFUaJTcOpVuW7JhZbFXOUc8CH8RRFdwe1anTpsS22C58WIuu8a vK3Qm+HKqd5N7OBcLRulBQ+QYhYaT1kAlxeCWKqOTVhpMHjF1Md46zcgrvsVzcsB aazzFdcB75tnsz+x6UjiRfuIXeJdLMU= 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; s=default; bh=QW+VgqgT1I+XAwayzJ 5+nSmJfHA=; b=LYJ+88KyqYqRO8/yDdxhazAP/LvfoWsNkz+3bZ883WFxawKZ1b jWuL7cUFuFMFJ3kWYKzGcPFzfnoPXUgDRTnOspwiEmnPThpD7PNLXXc8QTY+BRK8 BcLLhX/xtDV8FKvRNVPN0RRI6spMOB+oX8RqR25FgSMWauub25Un4SPyM= Received: (qmail 86687 invoked by alias); 30 Apr 2019 23:47:50 -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 86678 invoked by uid 89); 30 Apr 2019 23:47:50 -0000 Authentication-Results: sourceware.org; auth=none X-Spam-SWARE-Status: No, score=-22.2 required=5.0 tests=AWL, BAYES_00, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, RCVD_IN_DNSWL_NONE, SPF_PASS autolearn=ham version=3.3.1 spammy=HX-Received:4643, const_int, sk:logical X-HELO: mail-pl1-f195.google.com Received: from mail-pl1-f195.google.com (HELO mail-pl1-f195.google.com) (209.85.214.195) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Tue, 30 Apr 2019 23:47:48 +0000 Received: by mail-pl1-f195.google.com with SMTP id ck18so3178569plb.1 for ; Tue, 30 Apr 2019 16:47:47 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sifive.com; s=google; h=from:to:cc:subject:date:message-id; bh=E8C8lDwWpUq7ZYlsSzTjDL9vr3yQHjRbLKhydOoGPT0=; b=XTczvWKhqX6oAe6jfCM0rK1AdlTvXDiDzvyZKHkeANmBQnOS2zDvOwarx8mrXV65xw p/5YxEwZ+cYuFpUyN7fuyIPB7efcsbE448y4r+lEcMDhyWl62npa2TK2weEUFog8n75P eSe2JZL1L8GiP6oSJ6AyC+c5Vj6/bVCyWkRCXQw46/WM9nX473G1GwWbeIQWUU+N7hTe GPrZl8tz5VexU9kwMDLfP/XOwd/zesam6ld0j/IDq5oa5uh8Dij3Gd2NtZAHzcwcoE4E bWofDBfHPbJmUzt4NXRgvm3lxZFtzFw0AiPBZfhndZmxHso6Yu43fJJI+kGnmYAUI4pm KdJw== Received: from rohan.sifive.com ([12.206.222.5]) by smtp.gmail.com with ESMTPSA id j67sm99208148pfc.72.2019.04.30.16.47.45 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 30 Apr 2019 16:47:45 -0700 (PDT) From: Jim Wilson To: gcc-patches@gcc.gnu.org Cc: Jim Wilson Subject: [PATCH] RISC-V: Short-forward-branch opt for SiFive 7 series cores. Date: Tue, 30 Apr 2019 16:47:41 -0700 Message-Id: <20190430234741.8120-1-jimw@sifive.com> X-IsSubscribed: yes The SiFive 7 series cores have macro fusion support to convert a branch over a single instruction into a conditionally executed instruction. This adds a conditional move pattern, enabled only for the SiFive 7 series cores, that implements the initial optimization support for this feature. This gives us about a 10% increase in coremark scores for this core. To reduce duplication of patterns, this simplifies the existing two pattern support for branches to one pattern. This requires an assembler optimization to convert 3 operand branches comparing against zero into a compressed instruction. This gas patch missed the deadline for binutils-2.32, so this gcc patch had to wait until after the gcc-9 branch was made. This was tested with 32-bit/elf and 64-bit/linux cross builds and checks, configured for the default rocket target, and for the sifive-7-series target. There were no regressions. Adding a conditional move pattern enables the cselim tree pass unconditionally, so this does accidentally affect other targets, but I'm seeing smaller code sizes with the patch except in uncommon cases, so this does not appear to be a problem. For the sifive-7-series target, code size does increase slightly, but the performance benefit outweighs the code size increase. Committed. Jim gcc/ * config/riscv/constraints.md (L): New. * config/riscv/predicates.md (lui_operand): New. (sfb_alu_operand): New. * config/riscv/riscv-protos.h (riscv_expand_conditional_move): Declare. * config/riscv/riscv.c (riscv_expand_conditional_move): New. * config/riscv/riscv.h (TARGET_SFB_ALU): New. * config/riscv/risc.md (type): Add sfb_alu. (branch): Renamed from branch_order. Change predicate for operand 3 to reg_or_0_operand. In output string, change %3 to %z3. (branch_zero): Delete. (movcc): New. (movcc): Likewise. * config/riscv/sifive-7.md (sifive_7_sfb_alu): New. Use in bypasses. --- gcc/config/riscv/constraints.md | 5 ++++ gcc/config/riscv/predicates.md | 8 +++++ gcc/config/riscv/riscv-protos.h | 1 + gcc/config/riscv/riscv.c | 12 ++++++++ gcc/config/riscv/riscv.h | 11 +++++++ gcc/config/riscv/riscv.md | 53 +++++++++++++++++++++++---------- gcc/config/riscv/sifive-7.md | 12 ++++++-- 7 files changed, 84 insertions(+), 18 deletions(-) diff --git a/gcc/config/riscv/constraints.md b/gcc/config/riscv/constraints.md index b4de83f8324..40faf0e0380 100644 --- a/gcc/config/riscv/constraints.md +++ b/gcc/config/riscv/constraints.md @@ -49,6 +49,11 @@ (and (match_code "const_int") (match_test "IN_RANGE (ival, 0, 31)"))) +(define_constraint "L" + "A U-type 20-bit signed immediate." + (and (match_code "const_int") + (match_test "LUI_OPERAND (ival)"))) + ;; Floating-point constant +0.0, used for FCVT-based moves when FMV is ;; not available in RV32. (define_constraint "G" diff --git a/gcc/config/riscv/predicates.md b/gcc/config/riscv/predicates.md index 83fc4bd663d..aa5e1327dd5 100644 --- a/gcc/config/riscv/predicates.md +++ b/gcc/config/riscv/predicates.md @@ -27,6 +27,14 @@ (ior (match_operand 0 "const_arith_operand") (match_operand 0 "register_operand"))) +(define_predicate "lui_operand" + (and (match_code "const_int") + (match_test "LUI_OPERAND (INTVAL (op))"))) + +(define_predicate "sfb_alu_operand" + (ior (match_operand 0 "arith_operand") + (match_operand 0 "lui_operand"))) + (define_predicate "const_csr_operand" (and (match_code "const_int") (match_test "IN_RANGE (INTVAL (op), 0, 31)"))) diff --git a/gcc/config/riscv/riscv-protos.h b/gcc/config/riscv/riscv-protos.h index 5c1002bbc29..69e39f7a208 100644 --- a/gcc/config/riscv/riscv-protos.h +++ b/gcc/config/riscv/riscv-protos.h @@ -59,6 +59,7 @@ extern const char *riscv_output_return (); extern void riscv_expand_int_scc (rtx, enum rtx_code, rtx, rtx); extern void riscv_expand_float_scc (rtx, enum rtx_code, rtx, rtx); extern void riscv_expand_conditional_branch (rtx, enum rtx_code, rtx, rtx); +extern void riscv_expand_conditional_move (rtx, rtx, rtx, rtx_code, rtx, rtx); #endif extern rtx riscv_legitimize_call_address (rtx); extern void riscv_set_return_address (rtx, rtx); diff --git a/gcc/config/riscv/riscv.c b/gcc/config/riscv/riscv.c index 6fb6c6ad372..3f66b9d8487 100644 --- a/gcc/config/riscv/riscv.c +++ b/gcc/config/riscv/riscv.c @@ -2324,6 +2324,18 @@ riscv_expand_conditional_branch (rtx label, rtx_code code, rtx op0, rtx op1) emit_jump_insn (gen_condjump (condition, label)); } +/* If (CODE OP0 OP1) holds, move CONS to DEST; else move ALT to DEST. */ + +void +riscv_expand_conditional_move (rtx dest, rtx cons, rtx alt, rtx_code code, + rtx op0, rtx op1) +{ + riscv_emit_int_compare (&code, &op0, &op1); + rtx cond = gen_rtx_fmt_ee (code, GET_MODE (op0), op0, op1); + emit_insn (gen_rtx_SET (dest, gen_rtx_IF_THEN_ELSE (GET_MODE (dest), cond, + cons, alt))); +} + /* Implement TARGET_FUNCTION_ARG_BOUNDARY. Every parameter gets at least PARM_BOUNDARY bits of alignment, but will be given anything up to PREFERRED_STACK_BOUNDARY bits if the type requires it. */ diff --git a/gcc/config/riscv/riscv.h b/gcc/config/riscv/riscv.h index c93743f9549..4edd2a60194 100644 --- a/gcc/config/riscv/riscv.h +++ b/gcc/config/riscv/riscv.h @@ -662,6 +662,17 @@ typedef struct { #define BRANCH_COST(speed_p, predictable_p) \ ((!(speed_p) || (predictable_p)) ? 2 : riscv_branch_cost) +/* True if the target optimizes short forward branches around integer + arithmetic instructions into predicated operations, e.g., for + conditional-move operations. The macro assumes that all branch + instructions (BEQ, BNE, BLT, BLTU, BGE, BGEU, C.BEQZ, and C.BNEZ) + support this feature. The macro further assumes that any integer + arithmetic and logical operation (ADD[I], SUB, SLL[I], SRL[I], SRA[I], + SLT[I][U], AND[I], XOR[I], OR[I], LUI, AUIPC, and their compressed + counterparts, including C.MV and C.LI) can be in the branch shadow. */ + +#define TARGET_SFB_ALU (riscv_microarchitecture == sifive_7) + #define LOGICAL_OP_NON_SHORT_CIRCUIT 0 /* Control the assembler format that we output. */ diff --git a/gcc/config/riscv/riscv.md b/gcc/config/riscv/riscv.md index fc81daa43ef..8b21c1963d7 100644 --- a/gcc/config/riscv/riscv.md +++ b/gcc/config/riscv/riscv.md @@ -156,7 +156,7 @@ (define_attr "type" "unknown,branch,jump,call,load,fpload,store,fpstore, mtc,mfc,const,arith,logical,shift,slt,imul,idiv,move,fmove,fadd,fmul, - fmadd,fdiv,fcmp,fcvt,fsqrt,multi,auipc,nop,ghost" + fmadd,fdiv,fcmp,fcvt,fsqrt,multi,auipc,sfb_alu,nop,ghost" (cond [(eq_attr "got" "load") (const_string "load") ;; If a doubleword move uses these expensive instructions, @@ -1804,31 +1804,52 @@ ;; Conditional branches -(define_insn "*branch_order" +(define_insn "*branch" [(set (pc) (if_then_else (match_operator 1 "order_operator" [(match_operand:X 2 "register_operand" "r") - (match_operand:X 3 "register_operand" "r")]) + (match_operand:X 3 "reg_or_0_operand" "rJ")]) (label_ref (match_operand 0 "" "")) (pc)))] "" - "b%C1\t%2,%3,%0" + "b%C1\t%2,%z3,%0" [(set_attr "type" "branch") (set_attr "mode" "none")]) -(define_insn "*branch_zero" - [(set (pc) - (if_then_else - (match_operator 1 "signed_order_operator" - [(match_operand:X 2 "register_operand" "r") - (const_int 0)]) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "b%C1z\t%2,%0" - [(set_attr "type" "branch") - (set_attr "mode" "none")]) +;; Patterns for implementations that optimize short forward branches. + +(define_expand "movcc" + [(set (match_operand:GPR 0 "register_operand") + (if_then_else:GPR (match_operand 1 "comparison_operator") + (match_operand:GPR 2 "register_operand") + (match_operand:GPR 3 "sfb_alu_operand")))] + "TARGET_SFB_ALU" +{ + rtx cmp = operands[1]; + /* We only handle word mode integer compares for now. */ + if (GET_MODE (XEXP (cmp, 0)) != word_mode) + FAIL; + riscv_expand_conditional_move (operands[0], operands[2], operands[3], + GET_CODE (cmp), XEXP (cmp, 0), XEXP (cmp, 1)); + DONE; +}) + +(define_insn "*movcc" + [(set (match_operand:GPR 0 "register_operand" "=r,r") + (if_then_else:GPR + (match_operator 5 "order_operator" + [(match_operand:X 1 "register_operand" "r,r") + (match_operand:X 2 "reg_or_0_operand" "rJ,rJ")]) + (match_operand:GPR 3 "register_operand" "0,0") + (match_operand:GPR 4 "sfb_alu_operand" "rJ,IL")))] + "TARGET_SFB_ALU" + "@ + b%C5 %1,%z2,1f; mv %0,%z4; 1: # movcc + b%C5 %1,%z2,1f; li %0,%4; 1: # movcc" + [(set_attr "length" "8") + (set_attr "type" "sfb_alu") + (set_attr "mode" "")]) ;; Used to implement built-in functions. (define_expand "condjump" diff --git a/gcc/config/riscv/sifive-7.md b/gcc/config/riscv/sifive-7.md index d58e01f8936..526278e46d4 100644 --- a/gcc/config/riscv/sifive-7.md +++ b/gcc/config/riscv/sifive-7.md @@ -37,6 +37,11 @@ (eq_attr "type" "branch")) "sifive_7_B") +(define_insn_reservation "sifive_7_sfb_alu" 2 + (and (eq_attr "tune" "sifive_7") + (eq_attr "type" "sfb_alu")) + "sifive_7_A+sifive_7_B") + (define_insn_reservation "sifive_7_jump" 1 (and (eq_attr "tune" "sifive_7") (eq_attr "type" "jump,call")) @@ -101,10 +106,13 @@ (eq_attr "type" "mfc")) "sifive_7_A") -(define_bypass 1 "sifive_7_load,sifive_7_alu,sifive_7_mul,sifive_7_f2i" +(define_bypass 1 "sifive_7_load,sifive_7_alu,sifive_7_mul,sifive_7_f2i,sifive_7_sfb_alu" "sifive_7_alu,sifive_7_branch") -(define_bypass 1 "sifive_7_load,sifive_7_alu,sifive_7_mul,sifive_7_f2i" +(define_bypass 1 "sifive_7_alu,sifive_7_sfb_alu" + "sifive_7_sfb_alu") + +(define_bypass 1 "sifive_7_load,sifive_7_alu,sifive_7_mul,sifive_7_f2i,sifive_7_sfb_alu" "sifive_7_store" "riscv_store_data_bypass_p") (define_bypass 2 "sifive_7_i2f"