RISC-V: Short-forward-branch opt for SiFive 7 series cores.
authorAndrew Waterman <andrew@sifive.com>
Tue, 30 Apr 2019 23:45:36 +0000 (16:45 -0700)
committerJim Wilson <wilson@gcc.gnu.org>
Tue, 30 Apr 2019 23:45:36 +0000 (16:45 -0700)
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<mode>): Renamed from branch_order<mode>.  Change predicate for
operand 3 to reg_or_0_operand.  In output string, change %3 to %z3.
(branch_zero<mode>): Delete.
(mov<mode>cc): New.
(mov<GPR:mode><X:mode>cc): Likewise.
* config/riscv/sifive-7.md (sifive_7_sfb_alu): New.  Use in bypasses.

From-SVN: r270758

gcc/ChangeLog
gcc/config/riscv/constraints.md
gcc/config/riscv/predicates.md
gcc/config/riscv/riscv-protos.h
gcc/config/riscv/riscv.c
gcc/config/riscv/riscv.h
gcc/config/riscv/riscv.md
gcc/config/riscv/sifive-7.md

index 6de1565143c189472be586c5abf02129f8428ff3..805ab8aa5c0e748c1bcb14ed196614c103c66ea8 100644 (file)
@@ -1,3 +1,19 @@
+2019-04-30  Jim Wilson  <jimw@sifive.com>
+
+       * 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<mode>): Renamed from branch_order<mode>.  Change predicate for
+       operand 3 to reg_or_0_operand.  In output string, change %3 to %z3.
+       (branch_zero<mode>): Delete.
+       (mov<mode>cc): New.
+       (mov<GPR:mode><X:mode>cc): Likewise.
+       * config/riscv/sifive-7.md (sifive_7_sfb_alu): New.  Use in bypasses.
+
 2019-04-30  Nathan Sidwell  <nathan@acm.org>
 
        * tree.h (MARK_TS_EXP): New.
index b4de83f8324b24089b80793e240a89be44b3d517..40faf0e0380462ab97c176693a4ed3dc6eca16d4 100644 (file)
   (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"
index 83fc4bd663dc465563dca87020a59bf974b73f9b..aa5e1327dd538e0cb1abb1646607c6c307837f17 100644 (file)
   (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)")))
index 5c1002bbc291550d5f5066d1d9215a723e84df34..69e39f7a2083e62bfd8c045accf8f541c5b752e1 100644 (file)
@@ -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);
index 6fb6c6ad3728af95edd32b089feb2eae6549b6b7..3f66b9d8487e183fa815335c9a50c1d4445f0063 100644 (file)
@@ -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.  */
index c93743f95498506c67f485cb2376bfc90e752a43..4edd2a6019477d9cee27021d7c7f9f199e31b693 100644 (file)
@@ -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.  */
index fc81daa43eff5dffafae5b65ca5dd1b46d28daff..8b21c1963d7d226d33d3dc8efd7da4c91e4cafc3 100644 (file)
 (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,
 
 ;; Conditional branches
 
-(define_insn "*branch_order<mode>"
+(define_insn "*branch<mode>"
   [(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<mode>"
-  [(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 "mov<mode>cc"
+  [(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 "*mov<GPR:mode><X:mode>cc"
+  [(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" "<GPR:MODE>")])
 
 ;; Used to implement built-in functions.
 (define_expand "condjump"
index d58e01f8936d12e6f10ffc0ae000fca13eb21a39..526278e46d492dbf9b040fdbb8ce56fc89f77a8b 100644 (file)
        (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"))
        (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"