[PATCH] RISC-V: Fix wrong partial subreg check for bsetidisi

2023-02-27 Thread Lin Sinan via Gcc-patches
From: Lin Sinan 

The partial subreg check should be for subreg operand(operand 1) instead of
the immediate operand(operand 2). This change also fix pr68648.c in zbs.

gcc/ChangeLog:

* config/riscv/bitmanip.md: Fix wrong index in the check.

---
 gcc/config/riscv/bitmanip.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/gcc/config/riscv/bitmanip.md b/gcc/config/riscv/bitmanip.md
index 14d18edbe62..58a86bd929f 100644
--- a/gcc/config/riscv/bitmanip.md
+++ b/gcc/config/riscv/bitmanip.md
@@ -442,7 +442,7 @@
(ior:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "r"))
(match_operand 2 "single_bit_mask_operand" "i")))]
   "TARGET_ZBS && TARGET_64BIT
-   && !partial_subreg_p (operands[2])"
+   && !partial_subreg_p (operands[1])"
   "bseti\t%0,%1,%S2"
   [(set_attr "type" "bitmanip")])
 
-- 
2.34.1



[PATCH RESEND] riscv: improve the cost model for loading a 64bit constant in rv32.

2022-11-10 Thread Lin Sinan via Gcc-patches
The motivation of this patch is to correct the wrong estimation of the number 
of instructions needed for loading a 64bit constant in rv32 in the current cost 
model(riscv_interger_cost). According to the current implementation, if a 
constant requires more than 3 instructions(riscv_const_insn and 
riscv_legitimate_constant_p), then the constant will be put into constant pool 
when expanding gimple to rtl(legitimate_constant_p hook and emit_move_insn). So 
the inaccurate cost model leads to the suboptimal codegen in rv32 and the wrong 
estimation part could be corrected through this fix.

e.g. the current codegen for loading 0x839290001 in rv32

  lui a5,%hi(.LC0)
  lw  a0,%lo(.LC0)(a5)
  lw  a1,%lo(.LC0+4)(a5)
.LC0:
  .word   958988289
  .word   8

output after this patch

  li a0,958988288
  addi a0,a0,1
  li a1,8

gcc/ChangeLog:

* config/riscv/riscv.cc (riscv_build_integer): Handle the case of 
loading 64bit constant in rv32.

gcc/testsuite/ChangeLog:

* gcc.target/riscv/rv32-load-64bit-constant.c: New test.

Signed-off-by: Lin Sinan 
---
 gcc/config/riscv/riscv.cc | 23 +++
 .../riscv/rv32-load-64bit-constant.c  | 38 +++
 2 files changed, 61 insertions(+)
 create mode 100644 gcc/testsuite/gcc.target/riscv/rv32-load-64bit-constant.c

diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc
index 32f9ef9ade9..9dffabdc5e3 100644
--- a/gcc/config/riscv/riscv.cc
+++ b/gcc/config/riscv/riscv.cc
@@ -618,6 +618,29 @@ riscv_build_integer (struct riscv_integer_op *codes, 
HOST_WIDE_INT value,
}
 }
 
+  if ((value > INT32_MAX || value < INT32_MIN) && !TARGET_64BIT)
+{
+  unsigned HOST_WIDE_INT loval = sext_hwi (value, 32);
+  unsigned HOST_WIDE_INT hival = sext_hwi ((value - loval) >> 32, 32);
+  struct riscv_integer_op alt_codes[RISCV_MAX_INTEGER_OPS],
+   hicode[RISCV_MAX_INTEGER_OPS];
+  int hi_cost, lo_cost;
+
+  hi_cost = riscv_build_integer_1 (hicode, hival, mode);
+  if (hi_cost < cost)
+   {
+ lo_cost = riscv_build_integer_1 (alt_codes, loval, mode);
+ if (lo_cost + hi_cost < cost)
+   {
+ memcpy (codes, alt_codes,
+ lo_cost * sizeof (struct riscv_integer_op));
+ memcpy (codes + lo_cost, hicode,
+ hi_cost * sizeof (struct riscv_integer_op));
+ cost = lo_cost + hi_cost;
+   }
+   }
+}
+
   return cost;
 }
 
diff --git a/gcc/testsuite/gcc.target/riscv/rv32-load-64bit-constant.c 
b/gcc/testsuite/gcc.target/riscv/rv32-load-64bit-constant.c
new file mode 100644
index 000..61d482fb283
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rv32-load-64bit-constant.c
@@ -0,0 +1,38 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv32im -mabi=ilp32 -O1" } */
+
+/* This test only applies to RV32. Some of 64bit constants in this test will 
be put
+into the constant pool in RV64, since RV64 might need one extra instruction to 
load
+64bit constant. */
+
+unsigned long long
+rv32_mov_64bit_int1 (void)
+{
+  return 0x739290001LL;
+}
+
+unsigned long long
+rv32_mov_64bit_int2 (void)
+{
+  return 0x839290001LL;
+}
+
+unsigned long long
+rv32_mov_64bit_int3 (void)
+{
+  return 0x392900013929LL;
+}
+
+unsigned long long
+rv32_mov_64bit_int4 (void)
+{
+  return 0x392900113929LL;
+}
+
+unsigned long long
+rv32_mov_64bit_int5 (void)
+{
+  return 0x14736def3929LL;
+}
+
+/* { dg-final { scan-assembler-not "lw\t" } } */
-- 
2.36.0



[PATCH] RISC-V: avoid splitting small constant in i_extrabit pattern

2023-04-09 Thread Lin Sinan via Gcc-patches
From: Sinan Lin 

there is no need to split an xori/ori with an small constant. take the test
case `int foo(int idx) { return idx|3; }` as an example,

rv64im_zba generates:
ori a0,a0,3
ret
but, rv64im_zba_zbs generates:
ori a0,a0,1
ori a0,a0,2
ret

with this change, insn `ori r2,r1,3` will not be splitted in zbs.
---
 gcc/config/riscv/predicates.md |  2 +-
 .../gcc.target/riscv/zbs-extra-bit-or-twobits.c| 14 ++
 2 files changed, 15 insertions(+), 1 deletion(-)
 create mode 100644 gcc/testsuite/gcc.target/riscv/zbs-extra-bit-or-twobits.c

diff --git a/gcc/config/riscv/predicates.md b/gcc/config/riscv/predicates.md
index 0d9d7701c7e..8654dbc5943 100644
--- a/gcc/config/riscv/predicates.md
+++ b/gcc/config/riscv/predicates.md
@@ -399,7 +399,7 @@
 (define_predicate "uimm_extra_bit_or_twobits"
   (and (match_code "const_int")
(ior (match_operand 0 "uimm_extra_bit_operand")
-   (match_operand 0 "const_twobits_operand"
+   (match_operand 0 "const_twobits_not_arith_operand"
 
 ;; A CONST_INT operand that fits into the negative half of a
 ;; signed-immediate after a single cleared top bit has been
diff --git a/gcc/testsuite/gcc.target/riscv/zbs-extra-bit-or-twobits.c 
b/gcc/testsuite/gcc.target/riscv/zbs-extra-bit-or-twobits.c
new file mode 100644
index 000..ef7ed60461a
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/zbs-extra-bit-or-twobits.c
@@ -0,0 +1,14 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gc_zbs -mabi=lp64" } */
+/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" } } */
+
+int or_two_bit(int idx) {
+return idx|3;
+}
+
+int xor_two_bit(int idx) {
+return idx^3;
+}
+
+/* { dg-final { scan-assembler-times "\tori\t" 1 } } */
+/* { dg-final { scan-assembler-times "\txori\t" 1 } } */
-- 
2.19.1.6.gb485710b



[PATCH] RISC-V: add TARGET_ZBKB to the condition of bswapsi2, bswapdi2 and rotr3 patterns

2023-04-10 Thread Lin Sinan via Gcc-patches
From: Sinan Lin 

tell gcc that zbkb has these two spn to enable some optimizations. e.g.
1) the rrotate_expr could match to rotrm3 during expand; 2) hook up
__builtin_bswap64 with `rev8` in zbkb64.
---
 gcc/config/riscv/bitmanip.md | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/gcc/config/riscv/bitmanip.md b/gcc/config/riscv/bitmanip.md
index 7aa591689ba..3ed9f5d403a 100644
--- a/gcc/config/riscv/bitmanip.md
+++ b/gcc/config/riscv/bitmanip.md
@@ -297,7 +297,7 @@
   [(set (match_operand:GPR 0 "register_operand")
(rotatert:GPR (match_operand:GPR 1 "register_operand")
 (match_operand:QI 2 "arith_operand")))]
-  "TARGET_ZBB || TARGET_XTHEADBB"
+  "TARGET_ZBB || TARGET_XTHEADBB || TARGET_ZBKB"
 {
   if (TARGET_XTHEADBB && !immediate_operand (operands[2], VOIDmode))
 FAIL;
@@ -362,12 +362,12 @@
 (define_expand "bswapdi2"
   [(set (match_operand:DI 0 "register_operand")
(bswap:DI (match_operand:DI 1 "register_operand")))]
-  "TARGET_64BIT && (TARGET_ZBB || TARGET_XTHEADBB)")
+  "TARGET_64BIT && (TARGET_ZBB || TARGET_XTHEADBB || TARGET_ZBKB)")
 
 (define_expand "bswapsi2"
   [(set (match_operand:SI 0 "register_operand")
(bswap:SI (match_operand:SI 1 "register_operand")))]
-  "(!TARGET_64BIT && TARGET_ZBB) || TARGET_XTHEADBB")
+  "(!TARGET_64BIT && (TARGET_ZBB || TARGET_ZBKB)) || TARGET_XTHEADBB")
 
 (define_insn "*bswap2"
   [(set (match_operand:X 0 "register_operand" "=r")
-- 
2.19.1.6.gb485710b