* RISC-V: Use extension instructions instead of bitwise "and"
@ 2023-05-23 19:46 Jivan Hakobyan
2023-05-29 13:57 ` Jeff Law
0 siblings, 1 reply; 2+ messages in thread
From: Jivan Hakobyan @ 2023-05-23 19:46 UTC (permalink / raw)
To: gcc-patches
[-- Attachment #1.1: Type: text/plain, Size: 1050 bytes --]
In the case where the target supports extension instructions,
it is preferable to use that instead of doing the same in other ways.
For the following case
void foo (unsigned long a, unsigned long* ptr) {
ptr[0] = a & 0xffffffffUL;
ptr[1] &= 0xffffffffUL;
}
GCC generates
foo:
li a5,-1
srli a5,a5,32
and a0,a0,a5
sd a0,0(a1)
ld a4,8(a1)
and a5,a4,a5
sd a5,8(a1)
ret
but it will be profitable to generate this one
foo:
zext.w a0,a0
sd a0,0(a1)
lwu a5,8(a1)
sd a5,8(a1)
ret
This patch fixes mentioned issue.
It supports HI -> DI, HI->SI and SI -> DI extensions.
gcc/ChangeLog:
* config/riscv/riscv.md (and<mode>3): New expander.
(*and<mode>3) New pattern.
* config/riscv/predicates.md (arith_operand_or_mode_mask): New
predicate.
gcc/testsuite/ChangeLog:
* gcc.target/riscv/and-extend-1.c: New test
* gcc.target/riscv/and-extend-2.c: New test
--
With the best regards
Jivan Hakobyan
[-- Attachment #2: and_extend.patch --]
[-- Type: text/x-patch, Size: 4233 bytes --]
diff --git a/gcc/config/riscv/predicates.md b/gcc/config/riscv/predicates.md
index ffcbb9a7589..70f570153ae 100644
--- a/gcc/config/riscv/predicates.md
+++ b/gcc/config/riscv/predicates.md
@@ -27,6 +27,12 @@
(ior (match_operand 0 "const_arith_operand")
(match_operand 0 "register_operand")))
+(define_predicate "arith_operand_or_mode_mask"
+ (ior (match_operand 0 "arith_operand")
+ (and (match_code "const_int")
+ (match_test "INTVAL (op) == GET_MODE_MASK (HImode)
+ || INTVAL (op) == GET_MODE_MASK (SImode)"))))
+
(define_predicate "lui_operand"
(and (match_code "const_int")
(match_test "LUI_OPERAND (INTVAL (op))")))
diff --git a/gcc/config/riscv/riscv.md b/gcc/config/riscv/riscv.md
index 124d8c95804..33336492812 100644
--- a/gcc/config/riscv/riscv.md
+++ b/gcc/config/riscv/riscv.md
@@ -1342,9 +1342,46 @@
;; For RV64, we don't expose the SImode operations to the rtl expanders,
;; but SImode versions exist for combine.
+(define_expand "and<mode>3"
+ [(set (match_operand:X 0 "register_operand")
+ (and:X (match_operand:X 1 "register_operand")
+ (match_operand:X 2 "arith_operand_or_mode_mask")))]
+ ""
+{
+ if (CONST_INT_P (operands[2]))
+ {
+ enum machine_mode tmode = VOIDmode;
+ if (INTVAL (operands[2]) == GET_MODE_MASK (HImode))
+ tmode = HImode;
+ else if (INTVAL (operands[2]) == GET_MODE_MASK (SImode))
+ tmode = SImode;
+
+ if (tmode != VOIDmode)
+ {
+ rtx tmp = gen_lowpart (tmode, operands[1]);
+ emit_insn (gen_extend_insn (operands[0], tmp, <MODE>mode, tmode, 1));
+ DONE;
+ }
+ }
+ else
+ {
+ emit_move_insn (operands[0], gen_rtx_AND (<MODE>mode, operands[1], operands[2]));
+ DONE;
+ }
+})
+
+(define_insn "*and<mode>3"
+ [(set (match_operand:X 0 "register_operand" "=r,r")
+ (and:X (match_operand:X 1 "register_operand" "%r,r")
+ (match_operand:X 2 "arith_operand" " r,I")))]
+ ""
+ "and%i2\t%0,%1,%2"
+ [(set_attr "type" "logical")
+ (set_attr "mode" "<MODE>")])
+
(define_insn "<optab><mode>3"
[(set (match_operand:X 0 "register_operand" "=r,r")
- (any_bitwise:X (match_operand:X 1 "register_operand" "%r,r")
+ (any_or:X (match_operand:X 1 "register_operand" "%r,r")
(match_operand:X 2 "arith_operand" " r,I")))]
""
"<insn>%i2\t%0,%1,%2"
diff --git a/gcc/testsuite/gcc.target/riscv/and-extend-1.c b/gcc/testsuite/gcc.target/riscv/and-extend-1.c
new file mode 100644
index 00000000000..a270d287374
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/and-extend-1.c
@@ -0,0 +1,30 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gc_zba_zbb -mabi=lp64" } */
+/* { dg-skip-if "" { *-*-* } { "-O0" } } */
+
+void
+foo(unsigned long a, unsigned long* ptr)
+{
+ ptr[0] = a & 0xffffffffUL;
+ ptr[1] &= 0xffffffffUL;
+}
+
+void
+foo2(unsigned long a, unsigned long* ptr)
+{
+ ptr[0] = a & 0xffff;
+ ptr[1] &= 0xffff;
+}
+
+void
+foo3(unsigned int a, unsigned int* ptr)
+{
+ ptr[0] = a & 0xffff;
+ ptr[1] &= 0xffff;
+}
+
+/* { dg-final { scan-assembler-times "zext.w" 1 } } */
+/* { dg-final { scan-assembler-times "zext.h" 2 } } */
+/* { dg-final { scan-assembler-times "lwu" 1 } } */
+/* { dg-final { scan-assembler-times "lhu" 2 } } */
+/* { dg-final { scan-assembler-not "and\t" } } */
diff --git a/gcc/testsuite/gcc.target/riscv/and-extend-2.c b/gcc/testsuite/gcc.target/riscv/and-extend-2.c
new file mode 100644
index 00000000000..fe639cd1e82
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/and-extend-2.c
@@ -0,0 +1,28 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv32gc_zba_zbb -mabi=ilp32" } */
+/* { dg-skip-if "" { *-*-* } { "-O0" } } */
+
+void
+foo(unsigned long a, unsigned long* ptr)
+{
+ ptr[0] = a & 0xffffffffUL;
+ ptr[1] &= 0xffffffffUL;
+}
+
+void
+foo2(unsigned long a, unsigned long* ptr)
+{
+ ptr[0] = a & 0xffff;
+ ptr[1] &= 0xffff;
+}
+
+void
+foo3(unsigned int a, unsigned int* ptr)
+{
+ ptr[0] = a & 0xffff;
+ ptr[1] &= 0xffff;
+}
+
+/* { dg-final { scan-assembler-times "zext.h" 2 } } */
+/* { dg-final { scan-assembler-times "lhu" 2 } } */
+/* { dg-final { scan-assembler-not "and\t" } } */
^ permalink raw reply [flat|nested] 2+ messages in thread
* Re: RISC-V: Use extension instructions instead of bitwise "and"
2023-05-23 19:46 RISC-V: Use extension instructions instead of bitwise "and" Jivan Hakobyan
@ 2023-05-29 13:57 ` Jeff Law
0 siblings, 0 replies; 2+ messages in thread
From: Jeff Law @ 2023-05-29 13:57 UTC (permalink / raw)
To: Jivan Hakobyan, gcc-patches
On 5/23/23 13:46, Jivan Hakobyan via Gcc-patches wrote:
> In the case where the target supports extension instructions,
> it is preferable to use that instead of doing the same in other ways.
> For the following case
>
> void foo (unsigned long a, unsigned long* ptr) {
> ptr[0] = a & 0xffffffffUL;
> ptr[1] &= 0xffffffffUL;
> }
>
> GCC generates
> foo:
> li a5,-1
> srli a5,a5,32
> and a0,a0,a5
> sd a0,0(a1)
> ld a4,8(a1)
> and a5,a4,a5
> sd a5,8(a1)
> ret
>
> but it will be profitable to generate this one
>
> foo:
> zext.w a0,a0
> sd a0,0(a1)
> lwu a5,8(a1)
> sd a5,8(a1)
> ret
>
> This patch fixes mentioned issue.
> It supports HI -> DI, HI->SI and SI -> DI extensions.
>
> gcc/ChangeLog:
> * config/riscv/riscv.md (and<mode>3): New expander.
> (*and<mode>3) New pattern.
> * config/riscv/predicates.md (arith_operand_or_mode_mask): New
> predicate.
>
> gcc/testsuite/ChangeLog:
> * gcc.target/riscv/and-extend-1.c: New test
> * gcc.target/riscv/and-extend-2.c: New test
Thanks. I made some minor whitespace fixes and pushed this to the trunk.
Jeff
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2023-05-29 13:58 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-05-23 19:46 RISC-V: Use extension instructions instead of bitwise "and" Jivan Hakobyan
2023-05-29 13:57 ` 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).