diff mbox series

[to-be-committed,RISC-V,PR,target/115921] Improve reassociation for rv64

Message ID bc60f2f0-4ce5-461c-a49f-b1e51012f5c8@gmail.com
State New
Headers show
Series [to-be-committed,RISC-V,PR,target/115921] Improve reassociation for rv64 | expand

Commit Message

Jeff Law Sept. 2, 2024, 6:53 p.m. UTC
This time with the RISC-V marker so the pre-commit testing system will 
pick it up...


-------- Forwarded Message --------
Subject: [to-be-committed] [PR target/115921] Improve reassociation for rv64
Date: Mon, 2 Sep 2024 11:53:44 -0600
From: Jeff Law <jeffreyalaw@gmail.com>
To: gcc-patches@gcc.gnu.org <gcc-patches@gcc.gnu.org>


As Jovan pointed out in pr115921, we're not reassociating expressions 
like this on rv64:

(x & 0x3e) << 12

It generates something like this:

          li      a5,258048
          slli    a0,a0,12
          and     a0,a0,a5


We have a pattern that's designed to clean this up.  Essentially 
reassociating the operations so that we don't need to load the constant 
resulting in something like this:

          andi    a0,a0,63
          slli    a0,a0,12


That pattern wasn't working for certain constants due to its condition. 
The condition is trying to avoid cases where this kind of reassociation 
would hinder shadd generation on rv64.  That condition was just written 
poorly.

This patch tightens up that condition in a few ways.  First, there's no 
need to worry about shadd cases if ZBA is not enabled.  Second we can't 
use shadd if the shift value isn't 1, 2 or 3.  Finally rather than 
open-coding one of the tests, we can use an existing operand predicate.

The net is we'll start performing this transformation in more cases on 
rv64 while still avoiding reassociation if it would spoil shadd generation.

Waiting on the pre-commit testing before taking any further action.

Jeff

Comments

Patrick O'Neill Sept. 2, 2024, 7:20 p.m. UTC | #1
On Mon, Sep 2, 2024 at 11:54 AM Jeff Law <jeffreyalaw@gmail.com> wrote:

>
> This time with the RISC-V marker so the pre-commit testing system will
> pick it up...


Hi Jeff,

Just a meta-note about precommit:
If the patch contains riscv or risc-v anywhere in the patch file pre commit
will run [1]. You can also cc patchworks-ci@rivosinc.com to run it.

Since this patch edits something in the riscv/ directory, it doesn’t need
the risc-v tag to trigger pre-commit [2].

Regardless, thanks for using the patchworks tester! :)

Patrick

[1]
https://github.com/patrick-rivos/riscv-gnu-toolchain/blob/1496f76a9ad4081c0afdde8f7f8ffb22573a1789/scripts/create_patches_files.py#L89
[2]
https://patchwork.sourceware.org/project/gcc/patch/7c038242-8663-4d94-9175-ea23397faae2@gmail.com/


>
>
> -------- Forwarded Message --------
> Subject: [to-be-committed] [PR target/115921] Improve reassociation for
> rv64
> Date: Mon, 2 Sep 2024 11:53:44 -0600
> From: Jeff Law <jeffreyalaw@gmail.com>
> To: gcc-patches@gcc.gnu.org <gcc-patches@gcc.gnu.org>
>
>
> As Jovan pointed out in pr115921, we're not reassociating expressions
> like this on rv64:
>
> (x & 0x3e) << 12
>
> It generates something like this:
>
>           li      a5,258048
>           slli    a0,a0,12
>           and     a0,a0,a5
>
>
> We have a pattern that's designed to clean this up.  Essentially
> reassociating the operations so that we don't need to load the constant
> resulting in something like this:
>
>           andi    a0,a0,63
>           slli    a0,a0,12
>
>
> That pattern wasn't working for certain constants due to its condition.
> The condition is trying to avoid cases where this kind of reassociation
> would hinder shadd generation on rv64.  That condition was just written
> poorly.
>
> This patch tightens up that condition in a few ways.  First, there's no
> need to worry about shadd cases if ZBA is not enabled.  Second we can't
> use shadd if the shift value isn't 1, 2 or 3.  Finally rather than
> open-coding one of the tests, we can use an existing operand predicate.
>
> The net is we'll start performing this transformation in more cases on
> rv64 while still avoiding reassociation if it would spoil shadd generation.
>
> Waiting on the pre-commit testing before taking any further action.
>
> Jeff
Xi Ruoyao Sept. 4, 2024, 2:08 p.m. UTC | #2
Hi Jeff,

On Mon, 2024-09-02 at 12:53 -0600, Jeff Law wrote:
>  (define_insn_and_split "<optab>_shift_reverse<X:mode>"
>    [(set (match_operand:X 0 "register_operand" "=r")
>      (any_bitwise:X (ashift:X (match_operand:X 1 "register_operand" "r")
> @@ -2934,9 +2936,9 @@ (define_insn_and_split "<optab>_shift_reverse<X:mode>"
>    "(!SMALL_OPERAND (INTVAL (operands[3]))
>      && SMALL_OPERAND (INTVAL (operands[3]) >> INTVAL (operands[2]))
>      && popcount_hwi (INTVAL (operands[3])) > 1

I'm wondering why we need to check the popcount.  With this patch
applied:

long
test1 (long x)
{
  return (x & 0x110) << 12;
}

is compiled to:

test1:
	andi	a0,a0,272
	slli	a0,a0,12
	ret

as we've expected, but:

long
test2 (long x)
{
  return (x & 0x100) << 12;
}

is compiled to:

test:
	li	a5,1048576
	slli	a0,a0,12
	and	a0,a0,a5
	ret

So why must we spend an instruction to load the single-bit immediate?
Jeff Law Sept. 4, 2024, 4:58 p.m. UTC | #3
On 9/4/24 8:08 AM, Xi Ruoyao wrote:
> Hi Jeff,
> 
> On Mon, 2024-09-02 at 12:53 -0600, Jeff Law wrote:
>>   (define_insn_and_split "<optab>_shift_reverse<X:mode>"
>>     [(set (match_operand:X 0 "register_operand" "=r")
>>       (any_bitwise:X (ashift:X (match_operand:X 1 "register_operand" "r")
>> @@ -2934,9 +2936,9 @@ (define_insn_and_split "<optab>_shift_reverse<X:mode>"
>>     "(!SMALL_OPERAND (INTVAL (operands[3]))
>>       && SMALL_OPERAND (INTVAL (operands[3]) >> INTVAL (operands[2]))
>>       && popcount_hwi (INTVAL (operands[3])) > 1
> 
> I'm wondering why we need to check the popcount.  With this patch
> applied:
Zbs can do these things with the single bit manipulation instructions. 
It would be reasonable to make it (TARGET_ZBS && popcount_hwi ...)

jeff
diff mbox series

Patch

diff --git a/gcc/config/riscv/riscv.md b/gcc/config/riscv/riscv.md
index 3289ed2155a..58b31658e0a 100644
--- a/gcc/config/riscv/riscv.md
+++ b/gcc/config/riscv/riscv.md
@@ -2925,7 +2925,9 @@  (define_insn_and_split "*<optab>si3_extend_mask"
 ;; for IOR/XOR.  It probably doesn't matter for AND.
 ;;
 ;; We also don't want to do this if the immediate already fits in a simm12
-;; field.
+;; field, or is a single bit operand, or when we might be able to generate
+;; a shift-add sequence via the splitter in bitmanip.md
+;; in bitmanip.md for masks that are a run of consecutive ones.
 (define_insn_and_split "<optab>_shift_reverse<X:mode>"
   [(set (match_operand:X 0 "register_operand" "=r")
     (any_bitwise:X (ashift:X (match_operand:X 1 "register_operand" "r")
@@ -2934,9 +2936,9 @@  (define_insn_and_split "<optab>_shift_reverse<X:mode>"
   "(!SMALL_OPERAND (INTVAL (operands[3]))
     && SMALL_OPERAND (INTVAL (operands[3]) >> INTVAL (operands[2]))
     && popcount_hwi (INTVAL (operands[3])) > 1
-    && (!TARGET_64BIT
-	|| (exact_log2 ((INTVAL (operands[3]) >> INTVAL (operands[2])) + 1)
-	     == -1))
+    && (!(TARGET_64BIT && TARGET_ZBA)
+	|| !consecutive_bits_operand (operands[3], VOIDmode)
+	|| !imm123_operand (operands[2], VOIDmode))
     && (INTVAL (operands[3]) & ((1ULL << INTVAL (operands[2])) - 1)) == 0)"
   "#"
   "&& 1"
diff --git a/gcc/testsuite/gcc.target/riscv/pr115921.c b/gcc/testsuite/gcc.target/riscv/pr115921.c
new file mode 100644
index 00000000000..e508e7ce790
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/pr115921.c
@@ -0,0 +1,13 @@ 
+/* { dg-do compile } */
+/* { dg-options "-O2 -march=rv64gc_zba" { target { rv64 } } }  */
+/* { dg-options "-O2 -march=rv32gc_zba" { target { rv32 } } }  */
+
+typedef unsigned long target_wide_uint_t;
+
+target_wide_uint_t test_ashift_and(target_wide_uint_t x) {
+    return (x & 0x3f) << 12;
+}
+
+/* { dg-final { scan-assembler-times "\\sandi" 1 } } */
+/* { dg-final { scan-assembler-times "\\sslli" 1 } } */
+