public inbox for gcc-cvs@sourceware.org
help / color / mirror / Atom feed
* [gcc(refs/vendors/riscv/heads/gcc-13-with-riscv-opts)] RISC-V: Add `movMODEcc' implementation for generic targets
@ 2023-11-22  5:11 Jeff Law
  0 siblings, 0 replies; only message in thread
From: Jeff Law @ 2023-11-22  5:11 UTC (permalink / raw)
  To: gcc-cvs

https://gcc.gnu.org/g:1bea5fb99ce0afa76fe49c6c961ddf4fecee8172

commit 1bea5fb99ce0afa76fe49c6c961ddf4fecee8172
Author: Maciej W. Rozycki <macro@embecosm.com>
Date:   Wed Nov 22 01:18:28 2023 +0000

    RISC-V: Add `movMODEcc' implementation for generic targets
    
    Provide RTL expansion of conditional-move operations for generic targets
    using a suitable sequence of base integer machine instructions according
    to cost evaluation by if-conversion.  Add `-mmovcc' command line option
    to enable this transformation, off by default.
    
    For the generic sequences small immediates as per the `arith_operand'
    predicate are cost-equivalent to registers as we can use them as input,
    alternative to a register, to the respective AND[I] machine operations,
    however we need to reject immediates fulfilling `lui_operand', because
    they would require reloading into a register, making the operation more
    costly.  Therefore add `movcc_operand' predicate and use it accordingly.
    
    There is a need to adjust zbs-bext-02.c, which can also serve as emitted
    code example, because with certain compilation options an AND operation
    can now legitimately appear in output despite BEXT having been produced
    as expected, such as with `-march=rv64gc -O2':
    
    foo:
            mv      a3,a0
            li      a5,0
            mv      a0,a1
            li      a2,64
            li      a1,1
    .L3:
            sll     a4,a1,a5
            and     a4,a4,a3
            addiw   a5,a5,1
            beq     a4,zero,.L2
            addiw   a0,a0,1
    .L2:
            bne     a5,a2,.L3
            ret
    
    vs `-march=rv64gc_zbs -O2':
    
    foo:
            mv      a4,a0
            li      a5,0
            mv      a0,a1
            li      a3,64
    .L3:
            bext    a2,a4,a5
            beq     a2,zero,.L2
            addiw   a0,a0,1
    .L2:
            addiw   a5,a5,1
            bne     a5,a3,.L3
            ret
    
    and then with `-march=rv64gc -mmovcc -mbranch-cost=7':
    
    foo:
            mv      a6,a0
            li      a4,0
            mv      a0,a1
            li      a7,1
            li      a1,64
    .L3:
            sll     a5,a7,a4
            and     a5,a5,a6
            snez    a5,a5
            neg     a5,a5
            not     a2,a5
            addiw   a3,a0,1
            and     a5,a5,a3
            and     a0,a2,a0
            addiw   a4,a4,1
            or      a0,a5,a0
            bne     a4,a1,.L3
            ret
    
    vs `-march=rv64gc_zbs -mmovcc -mbranch-cost=7':
    
    foo:
            mv      a6,a0
            li      a4,0
            mv      a0,a1
            li      a1,64
    .L3:
            bext    a5,a6,a4
            neg     a5,a5
            not     a2,a5
            addiw   a3,a0,1
            and     a5,a5,a3
            and     a0,a2,a0
            addiw   a4,a4,1
            or      a0,a5,a0
            bne     a4,a1,.L3
            ret
    
    However BEXT is supposed to replace an SLL operation so adjust the test
    case to reject SLL rather than AND, letting the test case pass even with
    `/-mmovcc/-mbranch-cost=7' specified as DejaGNU test flags (and in the
    absence of target-specific conditional-move operations enabled either by
    default or with other test flags).
    
            gcc/
            * config/riscv/predicates.md (movcc_operand): New predicate.
            * config/riscv/riscv.cc (riscv_expand_conditional_move): Handle
            generic targets.
            * config/riscv/riscv.md (mov<mode>cc): Likewise.
            * config/riscv/riscv.opt (mmovcc): New option.
            * doc/invoke.texi (Option Summary): Document it.
    
            gcc/testsuite/
            * gcc.target/riscv/zbs-bext-02.c: Adjust to reject SLL rather
            than AND.
    
    (cherry picked from commit dc95b338c04281224f5c9c058acec170e4008b5c)

Diff:
---
 gcc/config/riscv/predicates.md               |  6 ++++
 gcc/config/riscv/riscv.cc                    | 41 +++++++++++++++++++++++-----
 gcc/config/riscv/riscv.md                    |  7 +++--
 gcc/config/riscv/riscv.opt                   |  4 +++
 gcc/doc/invoke.texi                          |  9 ++++++
 gcc/testsuite/gcc.target/riscv/zbs-bext-02.c |  2 +-
 6 files changed, 58 insertions(+), 11 deletions(-)

diff --git a/gcc/config/riscv/predicates.md b/gcc/config/riscv/predicates.md
index 90567a817a7..f943f31f4db 100644
--- a/gcc/config/riscv/predicates.md
+++ b/gcc/config/riscv/predicates.md
@@ -41,6 +41,12 @@
   (ior (match_operand 0 "arith_operand")
        (match_operand 0 "lui_operand")))
 
+(define_predicate "movcc_operand"
+  (if_then_else (match_test "TARGET_SFB_ALU || TARGET_XTHEADCONDMOV
+			     || TARGET_ZICOND_LIKE")
+		(match_operand 0 "sfb_alu_operand")
+		(match_operand 0 "arith_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.cc b/gcc/config/riscv/riscv.cc
index 5198da6d936..df08e9c831a 100644
--- a/gcc/config/riscv/riscv.cc
+++ b/gcc/config/riscv/riscv.cc
@@ -4128,7 +4128,9 @@ riscv_expand_conditional_move (rtx dest, rtx op, rtx cons, rtx alt)
   rtx op0 = XEXP (op, 0);
   rtx op1 = XEXP (op, 1);
 
-  if ((TARGET_ZICOND_LIKE && GET_MODE_CLASS (mode) == MODE_INT)
+  if (((TARGET_ZICOND_LIKE
+	|| (arith_operand (cons, mode) && arith_operand (alt, mode)))
+       && (GET_MODE_CLASS (mode) == MODE_INT))
       || TARGET_SFB_ALU || TARGET_XTHEADCONDMOV)
     {
       machine_mode mode0 = GET_MODE (op0);
@@ -4142,6 +4144,15 @@ riscv_expand_conditional_move (rtx dest, rtx op, rtx cons, rtx alt)
 	  || (mode1 != word_mode && mode1 != VOIDmode))
 	return false;
 
+      /* In the fallback generic case use MODE rather than WORD_MODE for
+	 the output of the SCC instruction, to match the mode of the NEG
+	 operation below.  The output of SCC is 0 or 1 boolean, so it is
+	 valid for input in any scalar integer mode.  */
+      rtx tmp = gen_reg_rtx ((TARGET_ZICOND_LIKE
+			      || TARGET_SFB_ALU || TARGET_XTHEADCONDMOV)
+			     ? word_mode : mode);
+      bool invert = false;
+
       /* Canonicalize the comparison.  It must be an equality comparison
 	 of integer operands, or with SFB it can be any comparison of
 	 integer operands.  If it isn't, then emit an SCC instruction
@@ -4150,7 +4161,6 @@ riscv_expand_conditional_move (rtx dest, rtx op, rtx cons, rtx alt)
 	  || !INTEGRAL_MODE_P (mode0))
 	{
 	  bool *invert_ptr = nullptr;
-	  bool invert = false;
 
 	  /* If riscv_expand_int_scc inverts the condition, then it will
 	     flip the value of INVERT.  We need to know where so that
@@ -4158,11 +4168,9 @@ riscv_expand_conditional_move (rtx dest, rtx op, rtx cons, rtx alt)
 	  if (code == LE || code == LEU || code == GE || code == GEU)
 	    invert_ptr = &invert;
 
-	  /* Emit an scc like instruction into a temporary
-	     so that we can use an EQ/NE comparison.  */
-	  rtx tmp = gen_reg_rtx (word_mode);
-
-	  /* We can support both FP and integer conditional moves.  */
+	  /* Emit an SCC-like instruction into a temporary so that we can
+	     use an EQ/NE comparison.  We can support both FP and integer
+	     conditional moves.  */
 	  if (INTEGRAL_MODE_P (mode0))
 	    riscv_expand_int_scc (tmp, code, op0, op1, invert_ptr);
 	  else if (FLOAT_MODE_P (mode0)
@@ -4178,6 +4186,8 @@ riscv_expand_conditional_move (rtx dest, rtx op, rtx cons, rtx alt)
 	  op0 = XEXP (op, 0);
 	  op1 = XEXP (op, 1);
 	}
+      else if (!TARGET_ZICOND_LIKE && !TARGET_SFB_ALU && !TARGET_XTHEADCONDMOV)
+	riscv_expand_int_scc (tmp, code, op0, op1, &invert);
 
       if (TARGET_SFB_ALU || TARGET_XTHEADCONDMOV)
 	{
@@ -4195,6 +4205,23 @@ riscv_expand_conditional_move (rtx dest, rtx op, rtx cons, rtx alt)
 							      cons, alt)));
 	  return true;
 	}
+      else if (!TARGET_ZICOND_LIKE)
+	{
+	  if (invert)
+	    std::swap (cons, alt);
+
+	  rtx reg1 = gen_reg_rtx (mode);
+	  rtx reg2 = gen_reg_rtx (mode);
+	  rtx reg3 = gen_reg_rtx (mode);
+	  rtx reg4 = gen_reg_rtx (mode);
+
+	  riscv_emit_unary (NEG, reg1, tmp);
+	  riscv_emit_binary (AND, reg2, reg1, cons);
+	  riscv_emit_unary (NOT, reg3, reg1);
+	  riscv_emit_binary (AND, reg4, reg3, alt);
+	  riscv_emit_binary (IOR, dest, reg2, reg4);
+	  return true;
+	}
       /* 0, reg or 0, imm */
       else if (cons == CONST0_RTX (mode)
 	       && (REG_P (alt)
diff --git a/gcc/config/riscv/riscv.md b/gcc/config/riscv/riscv.md
index e6d90c2265f..37860cfe4d6 100644
--- a/gcc/config/riscv/riscv.md
+++ b/gcc/config/riscv/riscv.md
@@ -2658,9 +2658,10 @@
 (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 "sfb_alu_operand")
-			  (match_operand:GPR 3 "sfb_alu_operand")))]
-  "TARGET_SFB_ALU || TARGET_XTHEADCONDMOV || TARGET_ZICOND_LIKE"
+			  (match_operand:GPR 2 "movcc_operand")
+			  (match_operand:GPR 3 "movcc_operand")))]
+  "TARGET_SFB_ALU || TARGET_XTHEADCONDMOV || TARGET_ZICOND_LIKE
+   || TARGET_MOVCC"
 {
   if (riscv_expand_conditional_move (operands[0], operands[1],
 				     operands[2], operands[3]))
diff --git a/gcc/config/riscv/riscv.opt b/gcc/config/riscv/riscv.opt
index 555288e682a..11526f9cc2a 100644
--- a/gcc/config/riscv/riscv.opt
+++ b/gcc/config/riscv/riscv.opt
@@ -460,6 +460,10 @@ misa-spec=
 Target RejectNegative Joined Enum(isa_spec_class) Var(riscv_isa_spec) Init(TARGET_DEFAULT_ISA_SPEC)
 Set the version of RISC-V ISA spec.
 
+mmovcc
+Target Var(TARGET_MOVCC)
+Enable conditional moves unconditionally.
+
 minline-atomics
 Target Var(TARGET_INLINE_SUBWORD_ATOMIC) Init(1)
 Always inline subword atomic operations.
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index bb30dfc9479..2667a7d7acc 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -1228,6 +1228,7 @@ See RS/6000 and PowerPC Options.
 -mstack-protector-guard=@var{guard}  -mstack-protector-guard-reg=@var{reg}
 -mstack-protector-guard-offset=@var{offset}
 -mcsr-check -mno-csr-check
+-mmovcc  -mno-movcc
 -minline-atomics  -mno-inline-atomics
 -minline-strlen  -mno-inline-strlen
 -minline-strcmp  -mno-inline-strcmp
@@ -29032,6 +29033,14 @@ Do or don't use smaller but slower prologue and epilogue code that uses
 library function calls.  The default is to use fast inline prologues and
 epilogues.
 
+@opindex mmovcc
+@item -mmovcc
+@itemx -mno-movcc
+Do or don't produce branchless conditional-move code sequences even with
+targets that do not have specific instructions for conditional operations.
+If enabled, sequences of ALU operations are produced using base integer
+ISA instructions where profitable.
+
 @opindex minline-atomics
 @item -minline-atomics
 @itemx -mno-inline-atomics
diff --git a/gcc/testsuite/gcc.target/riscv/zbs-bext-02.c b/gcc/testsuite/gcc.target/riscv/zbs-bext-02.c
index 8c5d8c7a41a..81d826d9dd4 100644
--- a/gcc/testsuite/gcc.target/riscv/zbs-bext-02.c
+++ b/gcc/testsuite/gcc.target/riscv/zbs-bext-02.c
@@ -15,4 +15,4 @@ foo(const long long B, int a)
 
 /* { dg-final { scan-assembler-times "bext\t" 1 } } */
 /* { dg-final { scan-assembler-not {\mbset} } } */
-/* { dg-final { scan-assembler-not {\mand} } } */
+/* { dg-final { scan-assembler-not {\msll} } } */

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2023-11-22  5:11 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-11-22  5:11 [gcc(refs/vendors/riscv/heads/gcc-13-with-riscv-opts)] RISC-V: Add `movMODEcc' implementation for generic targets Jeff Law

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).