[gcc(refs/vendors/riscv/heads/gcc-15-with-riscv-opts)] RISC-V: Extract vector stepped for expand_const_vector [NFC]

2026-01-29 Thread Jeff Law via Gcc-cvs
https://gcc.gnu.org/g:adc27650094be752953a3453c38c07bf2496742b

commit adc27650094be752953a3453c38c07bf2496742b
Author: Pan Li 
Date:   Thu Apr 17 10:27:17 2025 +0800

RISC-V: Extract vector stepped for expand_const_vector [NFC]

Consider the expand_const_vector is quit long (about 500 lines)
and complicated, we would like to extract the different case
into different functions.  For example, the const vector stepped
will be extracted into expand_const_vector_stepped.

The below test suites are passed for this patch.
* The rv64gcv fully regression test.

gcc/ChangeLog:

* config/riscv/riscv-v.cc (expand_const_vector): Extract
const vector stepped into separated func.
(expand_const_vector_single_step_npatterns): Add new func
to take care of single step.
(expand_const_vector_interleaved_stepped_npatterns): Add new
func to take care of interleaved step.
(expand_const_vector_stepped): Add new func to take care of
const vector stepped.

Signed-off-by: Pan Li 
(cherry picked from commit ab22b8c630769330b4f37eb64d2bc285344a647a)

Diff:
---
 gcc/config/riscv/riscv-v.cc | 592 ++--
 1 file changed, 300 insertions(+), 292 deletions(-)

diff --git a/gcc/config/riscv/riscv-v.cc b/gcc/config/riscv/riscv-v.cc
index b6c906e3211a..c26158260c02 100644
--- a/gcc/config/riscv/riscv-v.cc
+++ b/gcc/config/riscv/riscv-v.cc
@@ -1340,334 +1340,342 @@ expand_const_vector_duplicate (rtx target, 
rvv_builder *builder)
 }
 
 static void
-expand_const_vector (rtx target, rtx src)
+expand_const_vector_single_step_npatterns (rtx target, rvv_builder *builder)
 {
   machine_mode mode = GET_MODE (target);
   rtx result = register_operand (target, mode) ? target : gen_reg_rtx (mode);
-  rtx elt;
 
-  if (const_vec_duplicate_p (src, &elt))
-return expand_const_vec_duplicate (target, src, elt);
+  /* Describe the case by choosing NPATTERNS = 4 as an example.  */
+  insn_code icode;
 
-  /* Support scalable const series vector.  */
-  rtx base, step;
-  if (const_vec_series_p (src, &base, &step))
-return expand_const_vec_series (target, base, step);
+  /* Step 1: Generate vid = { 0, 1, 2, 3, 4, 5, 6, 7, ... }.  */
+  rtx vid = gen_reg_rtx (builder->mode ());
+  rtx vid_ops[] = {vid};
+  icode = code_for_pred_series (builder->mode ());
+  emit_vlmax_insn (icode, NULLARY_OP, vid_ops);
+
+  if (builder->npatterns_all_equal_p ())
+{
+  /* Generate the variable-length vector following this rule:
+{ a, a, a + step, a + step, a + step * 2, a + step * 2, ...}
+  E.g. { 0, 0, 8, 8, 16, 16, ... } */
+
+  /* We want to create a pattern where value[idx] = floor (idx /
+NPATTERNS). As NPATTERNS is always a power of two we can
+rewrite this as = idx & -NPATTERNS.  */
+  /* Step 2: VID AND -NPATTERNS:
+{ 0&-4, 1&-4, 2&-4, 3 &-4, 4 &-4, 5 &-4, 6 &-4, 7 &-4, ... } */
+  rtx imm = gen_int_mode (-builder->npatterns (), builder->inner_mode ());
+  rtx tmp1 = gen_reg_rtx (builder->mode ());
+  rtx and_ops[] = {tmp1, vid, imm};
+  icode = code_for_pred_scalar (AND, builder->mode ());
+  emit_vlmax_insn (icode, BINARY_OP, and_ops);
+
+  /* Step 3: Convert to step size 1.  */
+  rtx tmp2 = gen_reg_rtx (builder->mode ());
+  /* log2 (npatterns) to get the shift amount to convert
+Eg.  { 0, 0, 0, 0, 4, 4, ... }
+into { 0, 0, 0, 0, 1, 1, ... }.  */
+  HOST_WIDE_INT shift_amt = exact_log2 (builder->npatterns ());
+  rtx shift = gen_int_mode (shift_amt, builder->inner_mode ());
+  rtx shift_ops[] = {tmp2, tmp1, shift};
+  icode = code_for_pred_scalar (ASHIFTRT, builder->mode ());
+  emit_vlmax_insn (icode, BINARY_OP, shift_ops);
+
+  /* Step 4: Multiply to step size n.  */
+  HOST_WIDE_INT step_size =
+   INTVAL (builder->elt (builder->npatterns ()))
+ - INTVAL (builder->elt (0));
+  rtx tmp3 = gen_reg_rtx (builder->mode ());
+  if (pow2p_hwi (step_size))
+   {
+ /* Power of 2 can be handled with a left shift.  */
+ HOST_WIDE_INT shift = exact_log2 (step_size);
+ rtx shift_amount = gen_int_mode (shift, Pmode);
+ insn_code icode = code_for_pred_scalar (ASHIFT, mode);
+ rtx ops[] = {tmp3, tmp2, shift_amount};
+ emit_vlmax_insn (icode, BINARY_OP, ops);
+   }
+  else
+   {
+ rtx mult_amt = gen_int_mode (step_size, builder->inner_mode ());
+ insn_code icode = code_for_pred_scalar (MULT, builder->mode ());
+ rtx ops[] = {tmp3, tmp2, mult_amt};
+ emit_vlmax_insn (icode, BINARY_OP, ops);
+   }
 
-  /* Handle variable-length vector.  */
-  unsigned int nelts_per_pattern = CONST_VECTOR_NELTS_PER_PATTERN (src);
-  unsigned int npatterns = CONST_VECTOR_NPATTERNS (src);
-  rvv_builder builder (mode, npatterns, nelts_per_pattern);
-  for 

[gcc(refs/vendors/riscv/heads/gcc-15-with-riscv-opts)] RISC-V: Extract vector stepped for expand_const_vector [NFC]

2026-01-16 Thread Jeff Law via Gcc-cvs
https://gcc.gnu.org/g:4519ab196659b74869dd6868f38cb4cb97b3094a

commit 4519ab196659b74869dd6868f38cb4cb97b3094a
Author: Pan Li 
Date:   Thu Apr 17 10:27:17 2025 +0800

RISC-V: Extract vector stepped for expand_const_vector [NFC]

Consider the expand_const_vector is quit long (about 500 lines)
and complicated, we would like to extract the different case
into different functions.  For example, the const vector stepped
will be extracted into expand_const_vector_stepped.

The below test suites are passed for this patch.
* The rv64gcv fully regression test.

gcc/ChangeLog:

* config/riscv/riscv-v.cc (expand_const_vector): Extract
const vector stepped into separated func.
(expand_const_vector_single_step_npatterns): Add new func
to take care of single step.
(expand_const_vector_interleaved_stepped_npatterns): Add new
func to take care of interleaved step.
(expand_const_vector_stepped): Add new func to take care of
const vector stepped.

Signed-off-by: Pan Li 
(cherry picked from commit ab22b8c630769330b4f37eb64d2bc285344a647a)

Diff:
---
 gcc/config/riscv/riscv-v.cc | 592 ++--
 1 file changed, 300 insertions(+), 292 deletions(-)

diff --git a/gcc/config/riscv/riscv-v.cc b/gcc/config/riscv/riscv-v.cc
index b6c906e3211a..c26158260c02 100644
--- a/gcc/config/riscv/riscv-v.cc
+++ b/gcc/config/riscv/riscv-v.cc
@@ -1340,334 +1340,342 @@ expand_const_vector_duplicate (rtx target, 
rvv_builder *builder)
 }
 
 static void
-expand_const_vector (rtx target, rtx src)
+expand_const_vector_single_step_npatterns (rtx target, rvv_builder *builder)
 {
   machine_mode mode = GET_MODE (target);
   rtx result = register_operand (target, mode) ? target : gen_reg_rtx (mode);
-  rtx elt;
 
-  if (const_vec_duplicate_p (src, &elt))
-return expand_const_vec_duplicate (target, src, elt);
+  /* Describe the case by choosing NPATTERNS = 4 as an example.  */
+  insn_code icode;
 
-  /* Support scalable const series vector.  */
-  rtx base, step;
-  if (const_vec_series_p (src, &base, &step))
-return expand_const_vec_series (target, base, step);
+  /* Step 1: Generate vid = { 0, 1, 2, 3, 4, 5, 6, 7, ... }.  */
+  rtx vid = gen_reg_rtx (builder->mode ());
+  rtx vid_ops[] = {vid};
+  icode = code_for_pred_series (builder->mode ());
+  emit_vlmax_insn (icode, NULLARY_OP, vid_ops);
+
+  if (builder->npatterns_all_equal_p ())
+{
+  /* Generate the variable-length vector following this rule:
+{ a, a, a + step, a + step, a + step * 2, a + step * 2, ...}
+  E.g. { 0, 0, 8, 8, 16, 16, ... } */
+
+  /* We want to create a pattern where value[idx] = floor (idx /
+NPATTERNS). As NPATTERNS is always a power of two we can
+rewrite this as = idx & -NPATTERNS.  */
+  /* Step 2: VID AND -NPATTERNS:
+{ 0&-4, 1&-4, 2&-4, 3 &-4, 4 &-4, 5 &-4, 6 &-4, 7 &-4, ... } */
+  rtx imm = gen_int_mode (-builder->npatterns (), builder->inner_mode ());
+  rtx tmp1 = gen_reg_rtx (builder->mode ());
+  rtx and_ops[] = {tmp1, vid, imm};
+  icode = code_for_pred_scalar (AND, builder->mode ());
+  emit_vlmax_insn (icode, BINARY_OP, and_ops);
+
+  /* Step 3: Convert to step size 1.  */
+  rtx tmp2 = gen_reg_rtx (builder->mode ());
+  /* log2 (npatterns) to get the shift amount to convert
+Eg.  { 0, 0, 0, 0, 4, 4, ... }
+into { 0, 0, 0, 0, 1, 1, ... }.  */
+  HOST_WIDE_INT shift_amt = exact_log2 (builder->npatterns ());
+  rtx shift = gen_int_mode (shift_amt, builder->inner_mode ());
+  rtx shift_ops[] = {tmp2, tmp1, shift};
+  icode = code_for_pred_scalar (ASHIFTRT, builder->mode ());
+  emit_vlmax_insn (icode, BINARY_OP, shift_ops);
+
+  /* Step 4: Multiply to step size n.  */
+  HOST_WIDE_INT step_size =
+   INTVAL (builder->elt (builder->npatterns ()))
+ - INTVAL (builder->elt (0));
+  rtx tmp3 = gen_reg_rtx (builder->mode ());
+  if (pow2p_hwi (step_size))
+   {
+ /* Power of 2 can be handled with a left shift.  */
+ HOST_WIDE_INT shift = exact_log2 (step_size);
+ rtx shift_amount = gen_int_mode (shift, Pmode);
+ insn_code icode = code_for_pred_scalar (ASHIFT, mode);
+ rtx ops[] = {tmp3, tmp2, shift_amount};
+ emit_vlmax_insn (icode, BINARY_OP, ops);
+   }
+  else
+   {
+ rtx mult_amt = gen_int_mode (step_size, builder->inner_mode ());
+ insn_code icode = code_for_pred_scalar (MULT, builder->mode ());
+ rtx ops[] = {tmp3, tmp2, mult_amt};
+ emit_vlmax_insn (icode, BINARY_OP, ops);
+   }
 
-  /* Handle variable-length vector.  */
-  unsigned int nelts_per_pattern = CONST_VECTOR_NELTS_PER_PATTERN (src);
-  unsigned int npatterns = CONST_VECTOR_NPATTERNS (src);
-  rvv_builder builder (mode, npatterns, nelts_per_pattern);
-  for 

[gcc(refs/vendors/riscv/heads/gcc-15-with-riscv-opts)] RISC-V: Extract vector stepped for expand_const_vector [NFC]

2025-11-07 Thread Jeff Law via Gcc-cvs
https://gcc.gnu.org/g:599b2330b01eaffefb7e2b7cd44f678030b7f8af

commit 599b2330b01eaffefb7e2b7cd44f678030b7f8af
Author: Pan Li 
Date:   Thu Apr 17 10:27:17 2025 +0800

RISC-V: Extract vector stepped for expand_const_vector [NFC]

Consider the expand_const_vector is quit long (about 500 lines)
and complicated, we would like to extract the different case
into different functions.  For example, the const vector stepped
will be extracted into expand_const_vector_stepped.

The below test suites are passed for this patch.
* The rv64gcv fully regression test.

gcc/ChangeLog:

* config/riscv/riscv-v.cc (expand_const_vector): Extract
const vector stepped into separated func.
(expand_const_vector_single_step_npatterns): Add new func
to take care of single step.
(expand_const_vector_interleaved_stepped_npatterns): Add new
func to take care of interleaved step.
(expand_const_vector_stepped): Add new func to take care of
const vector stepped.

Signed-off-by: Pan Li 
(cherry picked from commit ab22b8c630769330b4f37eb64d2bc285344a647a)

Diff:
---
 gcc/config/riscv/riscv-v.cc | 592 ++--
 1 file changed, 300 insertions(+), 292 deletions(-)

diff --git a/gcc/config/riscv/riscv-v.cc b/gcc/config/riscv/riscv-v.cc
index b6c906e3211a..c26158260c02 100644
--- a/gcc/config/riscv/riscv-v.cc
+++ b/gcc/config/riscv/riscv-v.cc
@@ -1340,334 +1340,342 @@ expand_const_vector_duplicate (rtx target, 
rvv_builder *builder)
 }
 
 static void
-expand_const_vector (rtx target, rtx src)
+expand_const_vector_single_step_npatterns (rtx target, rvv_builder *builder)
 {
   machine_mode mode = GET_MODE (target);
   rtx result = register_operand (target, mode) ? target : gen_reg_rtx (mode);
-  rtx elt;
 
-  if (const_vec_duplicate_p (src, &elt))
-return expand_const_vec_duplicate (target, src, elt);
+  /* Describe the case by choosing NPATTERNS = 4 as an example.  */
+  insn_code icode;
 
-  /* Support scalable const series vector.  */
-  rtx base, step;
-  if (const_vec_series_p (src, &base, &step))
-return expand_const_vec_series (target, base, step);
+  /* Step 1: Generate vid = { 0, 1, 2, 3, 4, 5, 6, 7, ... }.  */
+  rtx vid = gen_reg_rtx (builder->mode ());
+  rtx vid_ops[] = {vid};
+  icode = code_for_pred_series (builder->mode ());
+  emit_vlmax_insn (icode, NULLARY_OP, vid_ops);
+
+  if (builder->npatterns_all_equal_p ())
+{
+  /* Generate the variable-length vector following this rule:
+{ a, a, a + step, a + step, a + step * 2, a + step * 2, ...}
+  E.g. { 0, 0, 8, 8, 16, 16, ... } */
+
+  /* We want to create a pattern where value[idx] = floor (idx /
+NPATTERNS). As NPATTERNS is always a power of two we can
+rewrite this as = idx & -NPATTERNS.  */
+  /* Step 2: VID AND -NPATTERNS:
+{ 0&-4, 1&-4, 2&-4, 3 &-4, 4 &-4, 5 &-4, 6 &-4, 7 &-4, ... } */
+  rtx imm = gen_int_mode (-builder->npatterns (), builder->inner_mode ());
+  rtx tmp1 = gen_reg_rtx (builder->mode ());
+  rtx and_ops[] = {tmp1, vid, imm};
+  icode = code_for_pred_scalar (AND, builder->mode ());
+  emit_vlmax_insn (icode, BINARY_OP, and_ops);
+
+  /* Step 3: Convert to step size 1.  */
+  rtx tmp2 = gen_reg_rtx (builder->mode ());
+  /* log2 (npatterns) to get the shift amount to convert
+Eg.  { 0, 0, 0, 0, 4, 4, ... }
+into { 0, 0, 0, 0, 1, 1, ... }.  */
+  HOST_WIDE_INT shift_amt = exact_log2 (builder->npatterns ());
+  rtx shift = gen_int_mode (shift_amt, builder->inner_mode ());
+  rtx shift_ops[] = {tmp2, tmp1, shift};
+  icode = code_for_pred_scalar (ASHIFTRT, builder->mode ());
+  emit_vlmax_insn (icode, BINARY_OP, shift_ops);
+
+  /* Step 4: Multiply to step size n.  */
+  HOST_WIDE_INT step_size =
+   INTVAL (builder->elt (builder->npatterns ()))
+ - INTVAL (builder->elt (0));
+  rtx tmp3 = gen_reg_rtx (builder->mode ());
+  if (pow2p_hwi (step_size))
+   {
+ /* Power of 2 can be handled with a left shift.  */
+ HOST_WIDE_INT shift = exact_log2 (step_size);
+ rtx shift_amount = gen_int_mode (shift, Pmode);
+ insn_code icode = code_for_pred_scalar (ASHIFT, mode);
+ rtx ops[] = {tmp3, tmp2, shift_amount};
+ emit_vlmax_insn (icode, BINARY_OP, ops);
+   }
+  else
+   {
+ rtx mult_amt = gen_int_mode (step_size, builder->inner_mode ());
+ insn_code icode = code_for_pred_scalar (MULT, builder->mode ());
+ rtx ops[] = {tmp3, tmp2, mult_amt};
+ emit_vlmax_insn (icode, BINARY_OP, ops);
+   }
 
-  /* Handle variable-length vector.  */
-  unsigned int nelts_per_pattern = CONST_VECTOR_NELTS_PER_PATTERN (src);
-  unsigned int npatterns = CONST_VECTOR_NPATTERNS (src);
-  rvv_builder builder (mode, npatterns, nelts_per_pattern);
-  for 

[gcc(refs/vendors/riscv/heads/gcc-15-with-riscv-opts)] RISC-V: Extract vector stepped for expand_const_vector [NFC]

2025-11-01 Thread Jeff Law via Gcc-cvs
https://gcc.gnu.org/g:16d46b7026c89c975dd5c783c9ed40dfd8b20312

commit 16d46b7026c89c975dd5c783c9ed40dfd8b20312
Author: Pan Li 
Date:   Thu Apr 17 10:27:17 2025 +0800

RISC-V: Extract vector stepped for expand_const_vector [NFC]

Consider the expand_const_vector is quit long (about 500 lines)
and complicated, we would like to extract the different case
into different functions.  For example, the const vector stepped
will be extracted into expand_const_vector_stepped.

The below test suites are passed for this patch.
* The rv64gcv fully regression test.

gcc/ChangeLog:

* config/riscv/riscv-v.cc (expand_const_vector): Extract
const vector stepped into separated func.
(expand_const_vector_single_step_npatterns): Add new func
to take care of single step.
(expand_const_vector_interleaved_stepped_npatterns): Add new
func to take care of interleaved step.
(expand_const_vector_stepped): Add new func to take care of
const vector stepped.

Signed-off-by: Pan Li 
(cherry picked from commit ab22b8c630769330b4f37eb64d2bc285344a647a)

Diff:
---
 gcc/config/riscv/riscv-v.cc | 592 ++--
 1 file changed, 300 insertions(+), 292 deletions(-)

diff --git a/gcc/config/riscv/riscv-v.cc b/gcc/config/riscv/riscv-v.cc
index b6c906e3211a..c26158260c02 100644
--- a/gcc/config/riscv/riscv-v.cc
+++ b/gcc/config/riscv/riscv-v.cc
@@ -1340,334 +1340,342 @@ expand_const_vector_duplicate (rtx target, 
rvv_builder *builder)
 }
 
 static void
-expand_const_vector (rtx target, rtx src)
+expand_const_vector_single_step_npatterns (rtx target, rvv_builder *builder)
 {
   machine_mode mode = GET_MODE (target);
   rtx result = register_operand (target, mode) ? target : gen_reg_rtx (mode);
-  rtx elt;
 
-  if (const_vec_duplicate_p (src, &elt))
-return expand_const_vec_duplicate (target, src, elt);
+  /* Describe the case by choosing NPATTERNS = 4 as an example.  */
+  insn_code icode;
 
-  /* Support scalable const series vector.  */
-  rtx base, step;
-  if (const_vec_series_p (src, &base, &step))
-return expand_const_vec_series (target, base, step);
+  /* Step 1: Generate vid = { 0, 1, 2, 3, 4, 5, 6, 7, ... }.  */
+  rtx vid = gen_reg_rtx (builder->mode ());
+  rtx vid_ops[] = {vid};
+  icode = code_for_pred_series (builder->mode ());
+  emit_vlmax_insn (icode, NULLARY_OP, vid_ops);
+
+  if (builder->npatterns_all_equal_p ())
+{
+  /* Generate the variable-length vector following this rule:
+{ a, a, a + step, a + step, a + step * 2, a + step * 2, ...}
+  E.g. { 0, 0, 8, 8, 16, 16, ... } */
+
+  /* We want to create a pattern where value[idx] = floor (idx /
+NPATTERNS). As NPATTERNS is always a power of two we can
+rewrite this as = idx & -NPATTERNS.  */
+  /* Step 2: VID AND -NPATTERNS:
+{ 0&-4, 1&-4, 2&-4, 3 &-4, 4 &-4, 5 &-4, 6 &-4, 7 &-4, ... } */
+  rtx imm = gen_int_mode (-builder->npatterns (), builder->inner_mode ());
+  rtx tmp1 = gen_reg_rtx (builder->mode ());
+  rtx and_ops[] = {tmp1, vid, imm};
+  icode = code_for_pred_scalar (AND, builder->mode ());
+  emit_vlmax_insn (icode, BINARY_OP, and_ops);
+
+  /* Step 3: Convert to step size 1.  */
+  rtx tmp2 = gen_reg_rtx (builder->mode ());
+  /* log2 (npatterns) to get the shift amount to convert
+Eg.  { 0, 0, 0, 0, 4, 4, ... }
+into { 0, 0, 0, 0, 1, 1, ... }.  */
+  HOST_WIDE_INT shift_amt = exact_log2 (builder->npatterns ());
+  rtx shift = gen_int_mode (shift_amt, builder->inner_mode ());
+  rtx shift_ops[] = {tmp2, tmp1, shift};
+  icode = code_for_pred_scalar (ASHIFTRT, builder->mode ());
+  emit_vlmax_insn (icode, BINARY_OP, shift_ops);
+
+  /* Step 4: Multiply to step size n.  */
+  HOST_WIDE_INT step_size =
+   INTVAL (builder->elt (builder->npatterns ()))
+ - INTVAL (builder->elt (0));
+  rtx tmp3 = gen_reg_rtx (builder->mode ());
+  if (pow2p_hwi (step_size))
+   {
+ /* Power of 2 can be handled with a left shift.  */
+ HOST_WIDE_INT shift = exact_log2 (step_size);
+ rtx shift_amount = gen_int_mode (shift, Pmode);
+ insn_code icode = code_for_pred_scalar (ASHIFT, mode);
+ rtx ops[] = {tmp3, tmp2, shift_amount};
+ emit_vlmax_insn (icode, BINARY_OP, ops);
+   }
+  else
+   {
+ rtx mult_amt = gen_int_mode (step_size, builder->inner_mode ());
+ insn_code icode = code_for_pred_scalar (MULT, builder->mode ());
+ rtx ops[] = {tmp3, tmp2, mult_amt};
+ emit_vlmax_insn (icode, BINARY_OP, ops);
+   }
 
-  /* Handle variable-length vector.  */
-  unsigned int nelts_per_pattern = CONST_VECTOR_NELTS_PER_PATTERN (src);
-  unsigned int npatterns = CONST_VECTOR_NPATTERNS (src);
-  rvv_builder builder (mode, npatterns, nelts_per_pattern);
-  for 

[gcc(refs/vendors/riscv/heads/gcc-15-with-riscv-opts)] RISC-V: Extract vector stepped for expand_const_vector [NFC]

2025-10-18 Thread Jeff Law via Gcc-cvs
https://gcc.gnu.org/g:6021da781d9108c772b3587a15a75590665d7831

commit 6021da781d9108c772b3587a15a75590665d7831
Author: Pan Li 
Date:   Thu Apr 17 10:27:17 2025 +0800

RISC-V: Extract vector stepped for expand_const_vector [NFC]

Consider the expand_const_vector is quit long (about 500 lines)
and complicated, we would like to extract the different case
into different functions.  For example, the const vector stepped
will be extracted into expand_const_vector_stepped.

The below test suites are passed for this patch.
* The rv64gcv fully regression test.

gcc/ChangeLog:

* config/riscv/riscv-v.cc (expand_const_vector): Extract
const vector stepped into separated func.
(expand_const_vector_single_step_npatterns): Add new func
to take care of single step.
(expand_const_vector_interleaved_stepped_npatterns): Add new
func to take care of interleaved step.
(expand_const_vector_stepped): Add new func to take care of
const vector stepped.

Signed-off-by: Pan Li 
(cherry picked from commit ab22b8c630769330b4f37eb64d2bc285344a647a)

Diff:
---
 gcc/config/riscv/riscv-v.cc | 590 ++--
 1 file changed, 299 insertions(+), 291 deletions(-)

diff --git a/gcc/config/riscv/riscv-v.cc b/gcc/config/riscv/riscv-v.cc
index 64c09d774475..04179aa78d3c 100644
--- a/gcc/config/riscv/riscv-v.cc
+++ b/gcc/config/riscv/riscv-v.cc
@@ -1340,334 +1340,342 @@ expand_const_vector_duplicate (rtx target, 
rvv_builder *builder)
 }
 
 static void
-expand_const_vector (rtx target, rtx src)
+expand_const_vector_single_step_npatterns (rtx target, rvv_builder *builder)
 {
   machine_mode mode = GET_MODE (target);
   rtx result = register_operand (target, mode) ? target : gen_reg_rtx (mode);
-  rtx elt;
 
-  if (const_vec_duplicate_p (src, &elt))
-return expand_const_vec_duplicate (target, src, elt);
+  /* Describe the case by choosing NPATTERNS = 4 as an example.  */
+  insn_code icode;
 
-  /* Support scalable const series vector.  */
-  rtx base, step;
-  if (const_vec_series_p (src, &base, &step))
-return expand_const_vec_series (target, base, step);
+  /* Step 1: Generate vid = { 0, 1, 2, 3, 4, 5, 6, 7, ... }.  */
+  rtx vid = gen_reg_rtx (builder->mode ());
+  rtx vid_ops[] = {vid};
+  icode = code_for_pred_series (builder->mode ());
+  emit_vlmax_insn (icode, NULLARY_OP, vid_ops);
 
-  /* Handle variable-length vector.  */
-  unsigned int nelts_per_pattern = CONST_VECTOR_NELTS_PER_PATTERN (src);
-  unsigned int npatterns = CONST_VECTOR_NPATTERNS (src);
-  rvv_builder builder (mode, npatterns, nelts_per_pattern);
-  for (unsigned int i = 0; i < nelts_per_pattern; i++)
+  if (builder->npatterns_all_equal_p ())
 {
-  for (unsigned int j = 0; j < npatterns; j++)
-   builder.quick_push (CONST_VECTOR_ELT (src, i * npatterns + j));
-}
-  builder.finalize ();
+  /* Generate the variable-length vector following this rule:
+{ a, a, a + step, a + step, a + step * 2, a + step * 2, ...}
+  E.g. { 0, 0, 8, 8, 16, 16, ... } */
+
+  /* We want to create a pattern where value[idx] = floor (idx /
+NPATTERNS). As NPATTERNS is always a power of two we can
+rewrite this as = idx & -NPATTERNS.  */
+  /* Step 2: VID AND -NPATTERNS:
+{ 0&-4, 1&-4, 2&-4, 3 &-4, 4 &-4, 5 &-4, 6 &-4, 7 &-4, ... } */
+  rtx imm = gen_int_mode (-builder->npatterns (), builder->inner_mode ());
+  rtx tmp1 = gen_reg_rtx (builder->mode ());
+  rtx and_ops[] = {tmp1, vid, imm};
+  icode = code_for_pred_scalar (AND, builder->mode ());
+  emit_vlmax_insn (icode, BINARY_OP, and_ops);
+
+  /* Step 3: Convert to step size 1.  */
+  rtx tmp2 = gen_reg_rtx (builder->mode ());
+  /* log2 (npatterns) to get the shift amount to convert
+Eg.  { 0, 0, 0, 0, 4, 4, ... }
+into { 0, 0, 0, 0, 1, 1, ... }.  */
+  HOST_WIDE_INT shift_amt = exact_log2 (builder->npatterns ());
+  rtx shift = gen_int_mode (shift_amt, builder->inner_mode ());
+  rtx shift_ops[] = {tmp2, tmp1, shift};
+  icode = code_for_pred_scalar (ASHIFTRT, builder->mode ());
+  emit_vlmax_insn (icode, BINARY_OP, shift_ops);
+
+  /* Step 4: Multiply to step size n.  */
+  HOST_WIDE_INT step_size =
+   INTVAL (builder->elt (builder->npatterns ()))
+ - INTVAL (builder->elt (0));
+  rtx tmp3 = gen_reg_rtx (builder->mode ());
+  if (pow2p_hwi (step_size))
+   {
+ /* Power of 2 can be handled with a left shift.  */
+ HOST_WIDE_INT shift = exact_log2 (step_size);
+ rtx shift_amount = gen_int_mode (shift, Pmode);
+ insn_code icode = code_for_pred_scalar (ASHIFT, mode);
+ rtx ops[] = {tmp3, tmp2, shift_amount};
+ emit_vlmax_insn (icode, BINARY_OP, ops);
+   }
+  else
+   {
+ rtx mult_amt = gen_int_mode (step_size, 

[gcc(refs/vendors/riscv/heads/gcc-15-with-riscv-opts)] RISC-V: Extract vector stepped for expand_const_vector [NFC]

2025-09-20 Thread Jeff Law via Gcc-cvs
https://gcc.gnu.org/g:1e94dbcca462169b3938d8ceaf1506553ff5090d

commit 1e94dbcca462169b3938d8ceaf1506553ff5090d
Author: Pan Li 
Date:   Thu Apr 17 10:27:17 2025 +0800

RISC-V: Extract vector stepped for expand_const_vector [NFC]

Consider the expand_const_vector is quit long (about 500 lines)
and complicated, we would like to extract the different case
into different functions.  For example, the const vector stepped
will be extracted into expand_const_vector_stepped.

The below test suites are passed for this patch.
* The rv64gcv fully regression test.

gcc/ChangeLog:

* config/riscv/riscv-v.cc (expand_const_vector): Extract
const vector stepped into separated func.
(expand_const_vector_single_step_npatterns): Add new func
to take care of single step.
(expand_const_vector_interleaved_stepped_npatterns): Add new
func to take care of interleaved step.
(expand_const_vector_stepped): Add new func to take care of
const vector stepped.

Signed-off-by: Pan Li 
(cherry picked from commit ab22b8c630769330b4f37eb64d2bc285344a647a)

Diff:
---
 gcc/config/riscv/riscv-v.cc | 590 ++--
 1 file changed, 299 insertions(+), 291 deletions(-)

diff --git a/gcc/config/riscv/riscv-v.cc b/gcc/config/riscv/riscv-v.cc
index 2132216d356f..66c8b2921e26 100644
--- a/gcc/config/riscv/riscv-v.cc
+++ b/gcc/config/riscv/riscv-v.cc
@@ -1340,334 +1340,342 @@ expand_const_vector_duplicate (rtx target, 
rvv_builder *builder)
 }
 
 static void
-expand_const_vector (rtx target, rtx src)
+expand_const_vector_single_step_npatterns (rtx target, rvv_builder *builder)
 {
   machine_mode mode = GET_MODE (target);
   rtx result = register_operand (target, mode) ? target : gen_reg_rtx (mode);
-  rtx elt;
 
-  if (const_vec_duplicate_p (src, &elt))
-return expand_const_vec_duplicate (target, src, elt);
+  /* Describe the case by choosing NPATTERNS = 4 as an example.  */
+  insn_code icode;
 
-  /* Support scalable const series vector.  */
-  rtx base, step;
-  if (const_vec_series_p (src, &base, &step))
-return expand_const_vec_series (target, base, step);
+  /* Step 1: Generate vid = { 0, 1, 2, 3, 4, 5, 6, 7, ... }.  */
+  rtx vid = gen_reg_rtx (builder->mode ());
+  rtx vid_ops[] = {vid};
+  icode = code_for_pred_series (builder->mode ());
+  emit_vlmax_insn (icode, NULLARY_OP, vid_ops);
 
-  /* Handle variable-length vector.  */
-  unsigned int nelts_per_pattern = CONST_VECTOR_NELTS_PER_PATTERN (src);
-  unsigned int npatterns = CONST_VECTOR_NPATTERNS (src);
-  rvv_builder builder (mode, npatterns, nelts_per_pattern);
-  for (unsigned int i = 0; i < nelts_per_pattern; i++)
+  if (builder->npatterns_all_equal_p ())
 {
-  for (unsigned int j = 0; j < npatterns; j++)
-   builder.quick_push (CONST_VECTOR_ELT (src, i * npatterns + j));
-}
-  builder.finalize ();
+  /* Generate the variable-length vector following this rule:
+{ a, a, a + step, a + step, a + step * 2, a + step * 2, ...}
+  E.g. { 0, 0, 8, 8, 16, 16, ... } */
+
+  /* We want to create a pattern where value[idx] = floor (idx /
+NPATTERNS). As NPATTERNS is always a power of two we can
+rewrite this as = idx & -NPATTERNS.  */
+  /* Step 2: VID AND -NPATTERNS:
+{ 0&-4, 1&-4, 2&-4, 3 &-4, 4 &-4, 5 &-4, 6 &-4, 7 &-4, ... } */
+  rtx imm = gen_int_mode (-builder->npatterns (), builder->inner_mode ());
+  rtx tmp1 = gen_reg_rtx (builder->mode ());
+  rtx and_ops[] = {tmp1, vid, imm};
+  icode = code_for_pred_scalar (AND, builder->mode ());
+  emit_vlmax_insn (icode, BINARY_OP, and_ops);
+
+  /* Step 3: Convert to step size 1.  */
+  rtx tmp2 = gen_reg_rtx (builder->mode ());
+  /* log2 (npatterns) to get the shift amount to convert
+Eg.  { 0, 0, 0, 0, 4, 4, ... }
+into { 0, 0, 0, 0, 1, 1, ... }.  */
+  HOST_WIDE_INT shift_amt = exact_log2 (builder->npatterns ());
+  rtx shift = gen_int_mode (shift_amt, builder->inner_mode ());
+  rtx shift_ops[] = {tmp2, tmp1, shift};
+  icode = code_for_pred_scalar (ASHIFTRT, builder->mode ());
+  emit_vlmax_insn (icode, BINARY_OP, shift_ops);
+
+  /* Step 4: Multiply to step size n.  */
+  HOST_WIDE_INT step_size =
+   INTVAL (builder->elt (builder->npatterns ()))
+ - INTVAL (builder->elt (0));
+  rtx tmp3 = gen_reg_rtx (builder->mode ());
+  if (pow2p_hwi (step_size))
+   {
+ /* Power of 2 can be handled with a left shift.  */
+ HOST_WIDE_INT shift = exact_log2 (step_size);
+ rtx shift_amount = gen_int_mode (shift, Pmode);
+ insn_code icode = code_for_pred_scalar (ASHIFT, mode);
+ rtx ops[] = {tmp3, tmp2, shift_amount};
+ emit_vlmax_insn (icode, BINARY_OP, ops);
+   }
+  else
+   {
+ rtx mult_amt = gen_int_mode (step_size, 

[gcc(refs/vendors/riscv/heads/gcc-15-with-riscv-opts)] RISC-V: Extract vector stepped for expand_const_vector [NFC]

2025-09-07 Thread Jeff Law via Gcc-cvs
https://gcc.gnu.org/g:2ea8cc236b1b57bd61618bb9b94144f734db436a

commit 2ea8cc236b1b57bd61618bb9b94144f734db436a
Author: Pan Li 
Date:   Thu Apr 17 10:27:17 2025 +0800

RISC-V: Extract vector stepped for expand_const_vector [NFC]

Consider the expand_const_vector is quit long (about 500 lines)
and complicated, we would like to extract the different case
into different functions.  For example, the const vector stepped
will be extracted into expand_const_vector_stepped.

The below test suites are passed for this patch.
* The rv64gcv fully regression test.

gcc/ChangeLog:

* config/riscv/riscv-v.cc (expand_const_vector): Extract
const vector stepped into separated func.
(expand_const_vector_single_step_npatterns): Add new func
to take care of single step.
(expand_const_vector_interleaved_stepped_npatterns): Add new
func to take care of interleaved step.
(expand_const_vector_stepped): Add new func to take care of
const vector stepped.

Signed-off-by: Pan Li 
(cherry picked from commit ab22b8c630769330b4f37eb64d2bc285344a647a)

Diff:
---
 gcc/config/riscv/riscv-v.cc | 590 ++--
 1 file changed, 299 insertions(+), 291 deletions(-)

diff --git a/gcc/config/riscv/riscv-v.cc b/gcc/config/riscv/riscv-v.cc
index 2132216d356f..66c8b2921e26 100644
--- a/gcc/config/riscv/riscv-v.cc
+++ b/gcc/config/riscv/riscv-v.cc
@@ -1340,334 +1340,342 @@ expand_const_vector_duplicate (rtx target, 
rvv_builder *builder)
 }
 
 static void
-expand_const_vector (rtx target, rtx src)
+expand_const_vector_single_step_npatterns (rtx target, rvv_builder *builder)
 {
   machine_mode mode = GET_MODE (target);
   rtx result = register_operand (target, mode) ? target : gen_reg_rtx (mode);
-  rtx elt;
 
-  if (const_vec_duplicate_p (src, &elt))
-return expand_const_vec_duplicate (target, src, elt);
+  /* Describe the case by choosing NPATTERNS = 4 as an example.  */
+  insn_code icode;
 
-  /* Support scalable const series vector.  */
-  rtx base, step;
-  if (const_vec_series_p (src, &base, &step))
-return expand_const_vec_series (target, base, step);
+  /* Step 1: Generate vid = { 0, 1, 2, 3, 4, 5, 6, 7, ... }.  */
+  rtx vid = gen_reg_rtx (builder->mode ());
+  rtx vid_ops[] = {vid};
+  icode = code_for_pred_series (builder->mode ());
+  emit_vlmax_insn (icode, NULLARY_OP, vid_ops);
 
-  /* Handle variable-length vector.  */
-  unsigned int nelts_per_pattern = CONST_VECTOR_NELTS_PER_PATTERN (src);
-  unsigned int npatterns = CONST_VECTOR_NPATTERNS (src);
-  rvv_builder builder (mode, npatterns, nelts_per_pattern);
-  for (unsigned int i = 0; i < nelts_per_pattern; i++)
+  if (builder->npatterns_all_equal_p ())
 {
-  for (unsigned int j = 0; j < npatterns; j++)
-   builder.quick_push (CONST_VECTOR_ELT (src, i * npatterns + j));
-}
-  builder.finalize ();
+  /* Generate the variable-length vector following this rule:
+{ a, a, a + step, a + step, a + step * 2, a + step * 2, ...}
+  E.g. { 0, 0, 8, 8, 16, 16, ... } */
+
+  /* We want to create a pattern where value[idx] = floor (idx /
+NPATTERNS). As NPATTERNS is always a power of two we can
+rewrite this as = idx & -NPATTERNS.  */
+  /* Step 2: VID AND -NPATTERNS:
+{ 0&-4, 1&-4, 2&-4, 3 &-4, 4 &-4, 5 &-4, 6 &-4, 7 &-4, ... } */
+  rtx imm = gen_int_mode (-builder->npatterns (), builder->inner_mode ());
+  rtx tmp1 = gen_reg_rtx (builder->mode ());
+  rtx and_ops[] = {tmp1, vid, imm};
+  icode = code_for_pred_scalar (AND, builder->mode ());
+  emit_vlmax_insn (icode, BINARY_OP, and_ops);
+
+  /* Step 3: Convert to step size 1.  */
+  rtx tmp2 = gen_reg_rtx (builder->mode ());
+  /* log2 (npatterns) to get the shift amount to convert
+Eg.  { 0, 0, 0, 0, 4, 4, ... }
+into { 0, 0, 0, 0, 1, 1, ... }.  */
+  HOST_WIDE_INT shift_amt = exact_log2 (builder->npatterns ());
+  rtx shift = gen_int_mode (shift_amt, builder->inner_mode ());
+  rtx shift_ops[] = {tmp2, tmp1, shift};
+  icode = code_for_pred_scalar (ASHIFTRT, builder->mode ());
+  emit_vlmax_insn (icode, BINARY_OP, shift_ops);
+
+  /* Step 4: Multiply to step size n.  */
+  HOST_WIDE_INT step_size =
+   INTVAL (builder->elt (builder->npatterns ()))
+ - INTVAL (builder->elt (0));
+  rtx tmp3 = gen_reg_rtx (builder->mode ());
+  if (pow2p_hwi (step_size))
+   {
+ /* Power of 2 can be handled with a left shift.  */
+ HOST_WIDE_INT shift = exact_log2 (step_size);
+ rtx shift_amount = gen_int_mode (shift, Pmode);
+ insn_code icode = code_for_pred_scalar (ASHIFT, mode);
+ rtx ops[] = {tmp3, tmp2, shift_amount};
+ emit_vlmax_insn (icode, BINARY_OP, ops);
+   }
+  else
+   {
+ rtx mult_amt = gen_int_mode (step_size, 

[gcc(refs/vendors/riscv/heads/gcc-15-with-riscv-opts)] RISC-V: Extract vector stepped for expand_const_vector [NFC]

2025-08-25 Thread Jeff Law via Gcc-cvs
https://gcc.gnu.org/g:4dd3e80c3db9f77b15eacabb73446d443cefdad9

commit 4dd3e80c3db9f77b15eacabb73446d443cefdad9
Author: Pan Li 
Date:   Thu Apr 17 10:27:17 2025 +0800

RISC-V: Extract vector stepped for expand_const_vector [NFC]

Consider the expand_const_vector is quit long (about 500 lines)
and complicated, we would like to extract the different case
into different functions.  For example, the const vector stepped
will be extracted into expand_const_vector_stepped.

The below test suites are passed for this patch.
* The rv64gcv fully regression test.

gcc/ChangeLog:

* config/riscv/riscv-v.cc (expand_const_vector): Extract
const vector stepped into separated func.
(expand_const_vector_single_step_npatterns): Add new func
to take care of single step.
(expand_const_vector_interleaved_stepped_npatterns): Add new
func to take care of interleaved step.
(expand_const_vector_stepped): Add new func to take care of
const vector stepped.

Signed-off-by: Pan Li 
(cherry picked from commit ab22b8c630769330b4f37eb64d2bc285344a647a)

Diff:
---
 gcc/config/riscv/riscv-v.cc | 590 ++--
 1 file changed, 299 insertions(+), 291 deletions(-)

diff --git a/gcc/config/riscv/riscv-v.cc b/gcc/config/riscv/riscv-v.cc
index 2132216d356f..66c8b2921e26 100644
--- a/gcc/config/riscv/riscv-v.cc
+++ b/gcc/config/riscv/riscv-v.cc
@@ -1340,334 +1340,342 @@ expand_const_vector_duplicate (rtx target, 
rvv_builder *builder)
 }
 
 static void
-expand_const_vector (rtx target, rtx src)
+expand_const_vector_single_step_npatterns (rtx target, rvv_builder *builder)
 {
   machine_mode mode = GET_MODE (target);
   rtx result = register_operand (target, mode) ? target : gen_reg_rtx (mode);
-  rtx elt;
 
-  if (const_vec_duplicate_p (src, &elt))
-return expand_const_vec_duplicate (target, src, elt);
+  /* Describe the case by choosing NPATTERNS = 4 as an example.  */
+  insn_code icode;
 
-  /* Support scalable const series vector.  */
-  rtx base, step;
-  if (const_vec_series_p (src, &base, &step))
-return expand_const_vec_series (target, base, step);
+  /* Step 1: Generate vid = { 0, 1, 2, 3, 4, 5, 6, 7, ... }.  */
+  rtx vid = gen_reg_rtx (builder->mode ());
+  rtx vid_ops[] = {vid};
+  icode = code_for_pred_series (builder->mode ());
+  emit_vlmax_insn (icode, NULLARY_OP, vid_ops);
 
-  /* Handle variable-length vector.  */
-  unsigned int nelts_per_pattern = CONST_VECTOR_NELTS_PER_PATTERN (src);
-  unsigned int npatterns = CONST_VECTOR_NPATTERNS (src);
-  rvv_builder builder (mode, npatterns, nelts_per_pattern);
-  for (unsigned int i = 0; i < nelts_per_pattern; i++)
+  if (builder->npatterns_all_equal_p ())
 {
-  for (unsigned int j = 0; j < npatterns; j++)
-   builder.quick_push (CONST_VECTOR_ELT (src, i * npatterns + j));
-}
-  builder.finalize ();
+  /* Generate the variable-length vector following this rule:
+{ a, a, a + step, a + step, a + step * 2, a + step * 2, ...}
+  E.g. { 0, 0, 8, 8, 16, 16, ... } */
+
+  /* We want to create a pattern where value[idx] = floor (idx /
+NPATTERNS). As NPATTERNS is always a power of two we can
+rewrite this as = idx & -NPATTERNS.  */
+  /* Step 2: VID AND -NPATTERNS:
+{ 0&-4, 1&-4, 2&-4, 3 &-4, 4 &-4, 5 &-4, 6 &-4, 7 &-4, ... } */
+  rtx imm = gen_int_mode (-builder->npatterns (), builder->inner_mode ());
+  rtx tmp1 = gen_reg_rtx (builder->mode ());
+  rtx and_ops[] = {tmp1, vid, imm};
+  icode = code_for_pred_scalar (AND, builder->mode ());
+  emit_vlmax_insn (icode, BINARY_OP, and_ops);
+
+  /* Step 3: Convert to step size 1.  */
+  rtx tmp2 = gen_reg_rtx (builder->mode ());
+  /* log2 (npatterns) to get the shift amount to convert
+Eg.  { 0, 0, 0, 0, 4, 4, ... }
+into { 0, 0, 0, 0, 1, 1, ... }.  */
+  HOST_WIDE_INT shift_amt = exact_log2 (builder->npatterns ());
+  rtx shift = gen_int_mode (shift_amt, builder->inner_mode ());
+  rtx shift_ops[] = {tmp2, tmp1, shift};
+  icode = code_for_pred_scalar (ASHIFTRT, builder->mode ());
+  emit_vlmax_insn (icode, BINARY_OP, shift_ops);
+
+  /* Step 4: Multiply to step size n.  */
+  HOST_WIDE_INT step_size =
+   INTVAL (builder->elt (builder->npatterns ()))
+ - INTVAL (builder->elt (0));
+  rtx tmp3 = gen_reg_rtx (builder->mode ());
+  if (pow2p_hwi (step_size))
+   {
+ /* Power of 2 can be handled with a left shift.  */
+ HOST_WIDE_INT shift = exact_log2 (step_size);
+ rtx shift_amount = gen_int_mode (shift, Pmode);
+ insn_code icode = code_for_pred_scalar (ASHIFT, mode);
+ rtx ops[] = {tmp3, tmp2, shift_amount};
+ emit_vlmax_insn (icode, BINARY_OP, ops);
+   }
+  else
+   {
+ rtx mult_amt = gen_int_mode (step_size, 

[gcc(refs/vendors/riscv/heads/gcc-15-with-riscv-opts)] RISC-V: Extract vector stepped for expand_const_vector [NFC]

2025-07-23 Thread Jeff Law via Gcc-cvs
https://gcc.gnu.org/g:4077ce6886c52feccb5a02b523d7fdb5b8db4cc0

commit 4077ce6886c52feccb5a02b523d7fdb5b8db4cc0
Author: Pan Li 
Date:   Thu Apr 17 10:27:17 2025 +0800

RISC-V: Extract vector stepped for expand_const_vector [NFC]

Consider the expand_const_vector is quit long (about 500 lines)
and complicated, we would like to extract the different case
into different functions.  For example, the const vector stepped
will be extracted into expand_const_vector_stepped.

The below test suites are passed for this patch.
* The rv64gcv fully regression test.

gcc/ChangeLog:

* config/riscv/riscv-v.cc (expand_const_vector): Extract
const vector stepped into separated func.
(expand_const_vector_single_step_npatterns): Add new func
to take care of single step.
(expand_const_vector_interleaved_stepped_npatterns): Add new
func to take care of interleaved step.
(expand_const_vector_stepped): Add new func to take care of
const vector stepped.

Signed-off-by: Pan Li 
(cherry picked from commit ab22b8c630769330b4f37eb64d2bc285344a647a)

Diff:
---
 gcc/config/riscv/riscv-v.cc | 590 ++--
 1 file changed, 299 insertions(+), 291 deletions(-)

diff --git a/gcc/config/riscv/riscv-v.cc b/gcc/config/riscv/riscv-v.cc
index 2132216d356f..66c8b2921e26 100644
--- a/gcc/config/riscv/riscv-v.cc
+++ b/gcc/config/riscv/riscv-v.cc
@@ -1340,334 +1340,342 @@ expand_const_vector_duplicate (rtx target, 
rvv_builder *builder)
 }
 
 static void
-expand_const_vector (rtx target, rtx src)
+expand_const_vector_single_step_npatterns (rtx target, rvv_builder *builder)
 {
   machine_mode mode = GET_MODE (target);
   rtx result = register_operand (target, mode) ? target : gen_reg_rtx (mode);
-  rtx elt;
 
-  if (const_vec_duplicate_p (src, &elt))
-return expand_const_vec_duplicate (target, src, elt);
+  /* Describe the case by choosing NPATTERNS = 4 as an example.  */
+  insn_code icode;
 
-  /* Support scalable const series vector.  */
-  rtx base, step;
-  if (const_vec_series_p (src, &base, &step))
-return expand_const_vec_series (target, base, step);
+  /* Step 1: Generate vid = { 0, 1, 2, 3, 4, 5, 6, 7, ... }.  */
+  rtx vid = gen_reg_rtx (builder->mode ());
+  rtx vid_ops[] = {vid};
+  icode = code_for_pred_series (builder->mode ());
+  emit_vlmax_insn (icode, NULLARY_OP, vid_ops);
 
-  /* Handle variable-length vector.  */
-  unsigned int nelts_per_pattern = CONST_VECTOR_NELTS_PER_PATTERN (src);
-  unsigned int npatterns = CONST_VECTOR_NPATTERNS (src);
-  rvv_builder builder (mode, npatterns, nelts_per_pattern);
-  for (unsigned int i = 0; i < nelts_per_pattern; i++)
+  if (builder->npatterns_all_equal_p ())
 {
-  for (unsigned int j = 0; j < npatterns; j++)
-   builder.quick_push (CONST_VECTOR_ELT (src, i * npatterns + j));
-}
-  builder.finalize ();
+  /* Generate the variable-length vector following this rule:
+{ a, a, a + step, a + step, a + step * 2, a + step * 2, ...}
+  E.g. { 0, 0, 8, 8, 16, 16, ... } */
+
+  /* We want to create a pattern where value[idx] = floor (idx /
+NPATTERNS). As NPATTERNS is always a power of two we can
+rewrite this as = idx & -NPATTERNS.  */
+  /* Step 2: VID AND -NPATTERNS:
+{ 0&-4, 1&-4, 2&-4, 3 &-4, 4 &-4, 5 &-4, 6 &-4, 7 &-4, ... } */
+  rtx imm = gen_int_mode (-builder->npatterns (), builder->inner_mode ());
+  rtx tmp1 = gen_reg_rtx (builder->mode ());
+  rtx and_ops[] = {tmp1, vid, imm};
+  icode = code_for_pred_scalar (AND, builder->mode ());
+  emit_vlmax_insn (icode, BINARY_OP, and_ops);
+
+  /* Step 3: Convert to step size 1.  */
+  rtx tmp2 = gen_reg_rtx (builder->mode ());
+  /* log2 (npatterns) to get the shift amount to convert
+Eg.  { 0, 0, 0, 0, 4, 4, ... }
+into { 0, 0, 0, 0, 1, 1, ... }.  */
+  HOST_WIDE_INT shift_amt = exact_log2 (builder->npatterns ());
+  rtx shift = gen_int_mode (shift_amt, builder->inner_mode ());
+  rtx shift_ops[] = {tmp2, tmp1, shift};
+  icode = code_for_pred_scalar (ASHIFTRT, builder->mode ());
+  emit_vlmax_insn (icode, BINARY_OP, shift_ops);
+
+  /* Step 4: Multiply to step size n.  */
+  HOST_WIDE_INT step_size =
+   INTVAL (builder->elt (builder->npatterns ()))
+ - INTVAL (builder->elt (0));
+  rtx tmp3 = gen_reg_rtx (builder->mode ());
+  if (pow2p_hwi (step_size))
+   {
+ /* Power of 2 can be handled with a left shift.  */
+ HOST_WIDE_INT shift = exact_log2 (step_size);
+ rtx shift_amount = gen_int_mode (shift, Pmode);
+ insn_code icode = code_for_pred_scalar (ASHIFT, mode);
+ rtx ops[] = {tmp3, tmp2, shift_amount};
+ emit_vlmax_insn (icode, BINARY_OP, ops);
+   }
+  else
+   {
+ rtx mult_amt = gen_int_mode (step_size, 

[gcc(refs/vendors/riscv/heads/gcc-15-with-riscv-opts)] RISC-V: Extract vector stepped for expand_const_vector [NFC]

2025-07-05 Thread Jeff Law via Gcc-cvs
https://gcc.gnu.org/g:d79f2cfd98f2acca65b6944c1b182b05d727b5f9

commit d79f2cfd98f2acca65b6944c1b182b05d727b5f9
Author: Pan Li 
Date:   Thu Apr 17 10:27:17 2025 +0800

RISC-V: Extract vector stepped for expand_const_vector [NFC]

Consider the expand_const_vector is quit long (about 500 lines)
and complicated, we would like to extract the different case
into different functions.  For example, the const vector stepped
will be extracted into expand_const_vector_stepped.

The below test suites are passed for this patch.
* The rv64gcv fully regression test.

gcc/ChangeLog:

* config/riscv/riscv-v.cc (expand_const_vector): Extract
const vector stepped into separated func.
(expand_const_vector_single_step_npatterns): Add new func
to take care of single step.
(expand_const_vector_interleaved_stepped_npatterns): Add new
func to take care of interleaved step.
(expand_const_vector_stepped): Add new func to take care of
const vector stepped.

Signed-off-by: Pan Li 
(cherry picked from commit ab22b8c630769330b4f37eb64d2bc285344a647a)

Diff:
---
 gcc/config/riscv/riscv-v.cc | 590 ++--
 1 file changed, 299 insertions(+), 291 deletions(-)

diff --git a/gcc/config/riscv/riscv-v.cc b/gcc/config/riscv/riscv-v.cc
index 96f0b94e6140..66c8b2921e26 100644
--- a/gcc/config/riscv/riscv-v.cc
+++ b/gcc/config/riscv/riscv-v.cc
@@ -1340,334 +1340,342 @@ expand_const_vector_duplicate (rtx target, 
rvv_builder *builder)
 }
 
 static void
-expand_const_vector (rtx target, rtx src)
+expand_const_vector_single_step_npatterns (rtx target, rvv_builder *builder)
 {
   machine_mode mode = GET_MODE (target);
   rtx result = register_operand (target, mode) ? target : gen_reg_rtx (mode);
-  rtx elt;
 
-  if (const_vec_duplicate_p (src, &elt))
-return expand_const_vec_duplicate (target, src, elt);
+  /* Describe the case by choosing NPATTERNS = 4 as an example.  */
+  insn_code icode;
 
-  /* Support scalable const series vector.  */
-  rtx base, step;
-  if (const_vec_series_p (src, &base, &step))
-return expand_const_vec_series (target, base, step);
+  /* Step 1: Generate vid = { 0, 1, 2, 3, 4, 5, 6, 7, ... }.  */
+  rtx vid = gen_reg_rtx (builder->mode ());
+  rtx vid_ops[] = {vid};
+  icode = code_for_pred_series (builder->mode ());
+  emit_vlmax_insn (icode, NULLARY_OP, vid_ops);
 
-  /* Handle variable-length vector.  */
-  unsigned int nelts_per_pattern = CONST_VECTOR_NELTS_PER_PATTERN (src);
-  unsigned int npatterns = CONST_VECTOR_NPATTERNS (src);
-  rvv_builder builder (mode, npatterns, nelts_per_pattern);
-  for (unsigned int i = 0; i < nelts_per_pattern; i++)
+  if (builder->npatterns_all_equal_p ())
 {
-  for (unsigned int j = 0; j < npatterns; j++)
-   builder.quick_push (CONST_VECTOR_ELT (src, i * npatterns + j));
-}
-  builder.finalize ();
+  /* Generate the variable-length vector following this rule:
+{ a, a, a + step, a + step, a + step * 2, a + step * 2, ...}
+  E.g. { 0, 0, 8, 8, 16, 16, ... } */
+
+  /* We want to create a pattern where value[idx] = floor (idx /
+NPATTERNS). As NPATTERNS is always a power of two we can
+rewrite this as = idx & -NPATTERNS.  */
+  /* Step 2: VID AND -NPATTERNS:
+{ 0&-4, 1&-4, 2&-4, 3 &-4, 4 &-4, 5 &-4, 6 &-4, 7 &-4, ... } */
+  rtx imm = gen_int_mode (-builder->npatterns (), builder->inner_mode ());
+  rtx tmp1 = gen_reg_rtx (builder->mode ());
+  rtx and_ops[] = {tmp1, vid, imm};
+  icode = code_for_pred_scalar (AND, builder->mode ());
+  emit_vlmax_insn (icode, BINARY_OP, and_ops);
+
+  /* Step 3: Convert to step size 1.  */
+  rtx tmp2 = gen_reg_rtx (builder->mode ());
+  /* log2 (npatterns) to get the shift amount to convert
+Eg.  { 0, 0, 0, 0, 4, 4, ... }
+into { 0, 0, 0, 0, 1, 1, ... }.  */
+  HOST_WIDE_INT shift_amt = exact_log2 (builder->npatterns ());
+  rtx shift = gen_int_mode (shift_amt, builder->inner_mode ());
+  rtx shift_ops[] = {tmp2, tmp1, shift};
+  icode = code_for_pred_scalar (ASHIFTRT, builder->mode ());
+  emit_vlmax_insn (icode, BINARY_OP, shift_ops);
+
+  /* Step 4: Multiply to step size n.  */
+  HOST_WIDE_INT step_size =
+   INTVAL (builder->elt (builder->npatterns ()))
+ - INTVAL (builder->elt (0));
+  rtx tmp3 = gen_reg_rtx (builder->mode ());
+  if (pow2p_hwi (step_size))
+   {
+ /* Power of 2 can be handled with a left shift.  */
+ HOST_WIDE_INT shift = exact_log2 (step_size);
+ rtx shift_amount = gen_int_mode (shift, Pmode);
+ insn_code icode = code_for_pred_scalar (ASHIFT, mode);
+ rtx ops[] = {tmp3, tmp2, shift_amount};
+ emit_vlmax_insn (icode, BINARY_OP, ops);
+   }
+  else
+   {
+ rtx mult_amt = gen_int_mode (step_size, 

[gcc(refs/vendors/riscv/heads/gcc-15-with-riscv-opts)] RISC-V: Extract vector stepped for expand_const_vector [NFC]

2025-05-18 Thread Jeff Law via Gcc-cvs
https://gcc.gnu.org/g:f789cdaede74d5cbdb60bef631a14a6fb7025efb

commit f789cdaede74d5cbdb60bef631a14a6fb7025efb
Author: Pan Li 
Date:   Thu Apr 17 10:27:17 2025 +0800

RISC-V: Extract vector stepped for expand_const_vector [NFC]

Consider the expand_const_vector is quit long (about 500 lines)
and complicated, we would like to extract the different case
into different functions.  For example, the const vector stepped
will be extracted into expand_const_vector_stepped.

The below test suites are passed for this patch.
* The rv64gcv fully regression test.

gcc/ChangeLog:

* config/riscv/riscv-v.cc (expand_const_vector): Extract
const vector stepped into separated func.
(expand_const_vector_single_step_npatterns): Add new func
to take care of single step.
(expand_const_vector_interleaved_stepped_npatterns): Add new
func to take care of interleaved step.
(expand_const_vector_stepped): Add new func to take care of
const vector stepped.

Signed-off-by: Pan Li 
(cherry picked from commit ab22b8c630769330b4f37eb64d2bc285344a647a)

Diff:
---
 gcc/config/riscv/riscv-v.cc | 590 ++--
 1 file changed, 299 insertions(+), 291 deletions(-)

diff --git a/gcc/config/riscv/riscv-v.cc b/gcc/config/riscv/riscv-v.cc
index 96f0b94e6140..66c8b2921e26 100644
--- a/gcc/config/riscv/riscv-v.cc
+++ b/gcc/config/riscv/riscv-v.cc
@@ -1340,334 +1340,342 @@ expand_const_vector_duplicate (rtx target, 
rvv_builder *builder)
 }
 
 static void
-expand_const_vector (rtx target, rtx src)
+expand_const_vector_single_step_npatterns (rtx target, rvv_builder *builder)
 {
   machine_mode mode = GET_MODE (target);
   rtx result = register_operand (target, mode) ? target : gen_reg_rtx (mode);
-  rtx elt;
 
-  if (const_vec_duplicate_p (src, &elt))
-return expand_const_vec_duplicate (target, src, elt);
+  /* Describe the case by choosing NPATTERNS = 4 as an example.  */
+  insn_code icode;
 
-  /* Support scalable const series vector.  */
-  rtx base, step;
-  if (const_vec_series_p (src, &base, &step))
-return expand_const_vec_series (target, base, step);
+  /* Step 1: Generate vid = { 0, 1, 2, 3, 4, 5, 6, 7, ... }.  */
+  rtx vid = gen_reg_rtx (builder->mode ());
+  rtx vid_ops[] = {vid};
+  icode = code_for_pred_series (builder->mode ());
+  emit_vlmax_insn (icode, NULLARY_OP, vid_ops);
 
-  /* Handle variable-length vector.  */
-  unsigned int nelts_per_pattern = CONST_VECTOR_NELTS_PER_PATTERN (src);
-  unsigned int npatterns = CONST_VECTOR_NPATTERNS (src);
-  rvv_builder builder (mode, npatterns, nelts_per_pattern);
-  for (unsigned int i = 0; i < nelts_per_pattern; i++)
+  if (builder->npatterns_all_equal_p ())
 {
-  for (unsigned int j = 0; j < npatterns; j++)
-   builder.quick_push (CONST_VECTOR_ELT (src, i * npatterns + j));
-}
-  builder.finalize ();
+  /* Generate the variable-length vector following this rule:
+{ a, a, a + step, a + step, a + step * 2, a + step * 2, ...}
+  E.g. { 0, 0, 8, 8, 16, 16, ... } */
+
+  /* We want to create a pattern where value[idx] = floor (idx /
+NPATTERNS). As NPATTERNS is always a power of two we can
+rewrite this as = idx & -NPATTERNS.  */
+  /* Step 2: VID AND -NPATTERNS:
+{ 0&-4, 1&-4, 2&-4, 3 &-4, 4 &-4, 5 &-4, 6 &-4, 7 &-4, ... } */
+  rtx imm = gen_int_mode (-builder->npatterns (), builder->inner_mode ());
+  rtx tmp1 = gen_reg_rtx (builder->mode ());
+  rtx and_ops[] = {tmp1, vid, imm};
+  icode = code_for_pred_scalar (AND, builder->mode ());
+  emit_vlmax_insn (icode, BINARY_OP, and_ops);
+
+  /* Step 3: Convert to step size 1.  */
+  rtx tmp2 = gen_reg_rtx (builder->mode ());
+  /* log2 (npatterns) to get the shift amount to convert
+Eg.  { 0, 0, 0, 0, 4, 4, ... }
+into { 0, 0, 0, 0, 1, 1, ... }.  */
+  HOST_WIDE_INT shift_amt = exact_log2 (builder->npatterns ());
+  rtx shift = gen_int_mode (shift_amt, builder->inner_mode ());
+  rtx shift_ops[] = {tmp2, tmp1, shift};
+  icode = code_for_pred_scalar (ASHIFTRT, builder->mode ());
+  emit_vlmax_insn (icode, BINARY_OP, shift_ops);
+
+  /* Step 4: Multiply to step size n.  */
+  HOST_WIDE_INT step_size =
+   INTVAL (builder->elt (builder->npatterns ()))
+ - INTVAL (builder->elt (0));
+  rtx tmp3 = gen_reg_rtx (builder->mode ());
+  if (pow2p_hwi (step_size))
+   {
+ /* Power of 2 can be handled with a left shift.  */
+ HOST_WIDE_INT shift = exact_log2 (step_size);
+ rtx shift_amount = gen_int_mode (shift, Pmode);
+ insn_code icode = code_for_pred_scalar (ASHIFT, mode);
+ rtx ops[] = {tmp3, tmp2, shift_amount};
+ emit_vlmax_insn (icode, BINARY_OP, ops);
+   }
+  else
+   {
+ rtx mult_amt = gen_int_mode (step_size,