aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJivan Hakobyan <jivanhakobyan9@gmail.com>2023-05-29 07:55:29 -0600
committerJeff Law <jlaw@ventanamicro.com>2023-05-29 07:57:20 -0600
commit10680bc36aca7bfaee542a653a78813cf0d4fb1f (patch)
tree70a71a3e79623feea2007741b9c64006fdca0f0e
parent6b828454246c5aef7f984bb6a2888699f8dcfb2d (diff)
downloadgcc-10680bc36aca7bfaee542a653a78813cf0d4fb1f.zip
gcc-10680bc36aca7bfaee542a653a78813cf0d4fb1f.tar.gz
gcc-10680bc36aca7bfaee542a653a78813cf0d4fb1f.tar.bz2
RISC-V: Use extension instructions instead of bitwise "and"
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
-rw-r--r--gcc/config/riscv/predicates.md6
-rw-r--r--gcc/config/riscv/riscv.md41
-rw-r--r--gcc/testsuite/gcc.target/riscv/and-extend-1.c30
-rw-r--r--gcc/testsuite/gcc.target/riscv/and-extend-2.c28
4 files changed, 104 insertions, 1 deletions
diff --git a/gcc/config/riscv/predicates.md b/gcc/config/riscv/predicates.md
index ffcbb9a..f7c4a3f 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 124d8c9..aba2033 100644
--- a/gcc/config/riscv/riscv.md
+++ b/gcc/config/riscv/riscv.md
@@ -1342,9 +1342,48 @@
;; 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 the second operand is a mode mask, emit an extension
+ insn instead. */
+ 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 0000000..a270d28
--- /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 0000000..fe639cd
--- /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" } } */