In order to support vectorization of loops with multiple exits, this
patch adds the implementation of the conditional branch optab for
LoongArch LSX/LASX instructions.

This patch causes the gen-vect-{2,25}.c tests to fail.  This is because
the support for vectorizing loops with multiple exits has vectorized
the loop checking the results.  The failure is due to an issue in the
test case's own implementation.

gcc/ChangeLog:

        * config/loongarch/lasx.md (cbranch<mode>4): New expander.
        * config/loongarch/lsx.md (cbranch<mode>4): New expander.

gcc/testsuite/ChangeLog:

        * lib/target-supports.exp (check_effective_target_vect_early_break_hw,
        check_effective_target_vect_early_break): Support LoongArch LSX.
        * gcc.target/loongarch/vector/lasx/lasx-vseteqz.c: New test.
        * gcc.target/loongarch/vector/lsx/lsx-vseteqz.c: New test.

Co-authored-by: Deng Jianbo <dengjia...@loongson.cn>
---
 gcc/config/loongarch/lasx.md                  | 29 +++++++++++++++++++
 gcc/config/loongarch/lsx.md                   | 29 +++++++++++++++++++
 .../loongarch/vector/lasx/lasx-vseteqz.c      | 14 +++++++++
 .../loongarch/vector/lsx/lsx-vseteqz.c        | 15 ++++++++++
 gcc/testsuite/lib/target-supports.exp         |  2 ++
 5 files changed, 89 insertions(+)
 create mode 100644 
gcc/testsuite/gcc.target/loongarch/vector/lasx/lasx-vseteqz.c
 create mode 100644 gcc/testsuite/gcc.target/loongarch/vector/lsx/lsx-vseteqz.c

diff --git a/gcc/config/loongarch/lasx.md b/gcc/config/loongarch/lasx.md
index 2f485de8a65..87e47ff479d 100644
--- a/gcc/config/loongarch/lasx.md
+++ b/gcc/config/loongarch/lasx.md
@@ -4952,3 +4952,32 @@
   emit_insn (gen_addv8si3 (operands[0], t3, operands[3]));
   DONE;
 })
+
+(define_expand "cbranch<mode>4"
+ [(set (pc)
+       (if_then_else
+         (match_operator 0 "equality_operator"
+           [(match_operand:ILASX 1 "register_operand")
+            (match_operand:ILASX 2 "reg_or_vector_same_val_operand")])
+         (label_ref (match_operand 3 ""))
+         (pc)))]
+ "ISA_HAS_LASX"
+{
+  RTX_CODE code = GET_CODE (operands[0]);
+  rtx tmp = operands[1];
+  rtx const0 = CONST0_RTX (SImode);
+
+  /* If comparing against a non-zero vector we have to do a comparison first
+    so we can have a != 0 comparison with the result.  */
+  if (operands[2] != CONST0_RTX (<MODE>mode))
+    {
+      rtx tmp = gen_reg_rtx (<MODE>mode);
+      emit_insn (gen_xor<mode>3 (tmp, operands[1], operands[2]));
+    }
+
+  if (code == NE)
+    emit_jump_insn (gen_lasx_xbnz_v_b (operands[3], tmp, const0));
+  else
+    emit_jump_insn (gen_lasx_xbz_v_b (operands[3], tmp, const0));
+  DONE;
+})
diff --git a/gcc/config/loongarch/lsx.md b/gcc/config/loongarch/lsx.md
index e51bd18d511..36d817be463 100644
--- a/gcc/config/loongarch/lsx.md
+++ b/gcc/config/loongarch/lsx.md
@@ -4298,3 +4298,32 @@
   [(set (match_dup 0)
        (vec_duplicate:V2DI (match_dup 1)))]
   "")
+
+(define_expand "cbranch<mode>4"
+ [(set (pc)
+       (if_then_else
+         (match_operator 0 "equality_operator"
+           [(match_operand:ILSX 1 "register_operand")
+            (match_operand:ILSX 2 "reg_or_vector_same_val_operand")])
+         (label_ref (match_operand 3 ""))
+         (pc)))]
+ "ISA_HAS_LSX"
+{
+  RTX_CODE code = GET_CODE (operands[0]);
+  rtx tmp = operands[1];
+  rtx const0 = CONST0_RTX (SImode);
+
+  /* If comparing against a non-zero vector we have to do a comparison first
+    so we can have a != 0 comparison with the result.  */
+  if (operands[2] != CONST0_RTX (<MODE>mode))
+    {
+      tmp = gen_reg_rtx (<MODE>mode);
+      emit_insn (gen_xor<mode>3 (tmp, operands[1], operands[2]));
+    }
+
+  if (code == NE)
+    emit_jump_insn (gen_lsx_bnz_v_b (operands[3], tmp, const0));
+  else
+    emit_jump_insn (gen_lsx_bz_v_b (operands[3], tmp, const0));
+  DONE;
+})
diff --git a/gcc/testsuite/gcc.target/loongarch/vector/lasx/lasx-vseteqz.c 
b/gcc/testsuite/gcc.target/loongarch/vector/lasx/lasx-vseteqz.c
new file mode 100644
index 00000000000..1f69a80a784
--- /dev/null
+++ b/gcc/testsuite/gcc.target/loongarch/vector/lasx/lasx-vseteqz.c
@@ -0,0 +1,14 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -mlasx" } */
+/* { dg-final { scan-assembler "\txvset.*.v\t" } } */
+/* { dg-final { scan-assembler  "bcnez" } } */
+
+int
+foo (int N)
+{
+  for (int i = 0; i <= N; i++)
+    if (i * i == N)
+      return i;
+  return -1;
+}
+
diff --git a/gcc/testsuite/gcc.target/loongarch/vector/lsx/lsx-vseteqz.c 
b/gcc/testsuite/gcc.target/loongarch/vector/lsx/lsx-vseteqz.c
new file mode 100644
index 00000000000..2536bb7945e
--- /dev/null
+++ b/gcc/testsuite/gcc.target/loongarch/vector/lsx/lsx-vseteqz.c
@@ -0,0 +1,15 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -mlsx" } */
+/* { dg-final { scan-assembler "\tvset.*.v\t" } } */
+/* { dg-final { scan-assembler  "bcnez" } } */
+
+int
+foo (int N)
+{
+  for (int i = 0; i <= N; i++)
+    if (i * i == N)
+      return i;
+
+  return -1;
+}
+
diff --git a/gcc/testsuite/lib/target-supports.exp 
b/gcc/testsuite/lib/target-supports.exp
index fe2970e024b..cb9c23d8a94 100644
--- a/gcc/testsuite/lib/target-supports.exp
+++ b/gcc/testsuite/lib/target-supports.exp
@@ -4431,6 +4431,7 @@ proc check_effective_target_vect_early_break { } {
        || [check_effective_target_sse4]
        || [istarget amdgcn-*-*]
        || [check_effective_target_riscv_v]
+       || [check_effective_target_loongarch_sx]
        }}]
 }
 
@@ -4447,6 +4448,7 @@ proc check_effective_target_vect_early_break_hw { } {
        || [check_sse4_hw_available]
        || [istarget amdgcn-*-*]
        || [check_effective_target_riscv_v_ok]
+       || [check_effective_target_loongarch_sx_hw]
        }}]
 }
 
-- 
2.20.1

Reply via email to