During the if-convert process, it was discovered that due to the lack of
standard mask{load/store} in the backend, vectorization conversion could
not be performed. After adding the suppoprt, it is possible to successfully
slp vectorize the ifcvt loop.
Among the various test items, there were performance improvements. For
instance, 450 and 481 were able to increase by 2% and 4.3% respectively.
//test.c
float cond_arr[1024];
float data_a[1024];
float data_b[1024];
float data_c[1024];
float data_d[1024];
void foo3(float * restrict p0) {
float s0 = 0.0f;
for (int i = 0; i < 1024; i++) {
if (cond_arr[i] > 0.0f)
s0 +=data_a[i];
}
*p0 = s0;
}
before asm:
...
.L4:
fld.s $f0,$r12,0
addi.d $r12,$r12,4
fcmp.sgt.s $fcc0,$f0,$f2
bceqz $fcc0,.L2
fld.s $f0,$r13,0
fadd.s $f1,$f1,$f0
.align 3
.L2:
addi.d $r13,$r13,4
bne $r12,$r14,.L4
fst.s $f1,$r4,0
jr $r1
after asm:
...
.L2:
xvld $xr3,$r12,0
xvld $xr2,$r12,32
xvld $xr1,$r12,64
xvld $xr0,$r12,96
addi.d $r12,$r12,128
xvld $xr12,$r13,0
xvld $xr11,$r13,32
xvld $xr10,$r13,64
xvld $xr9,$r13,96
xvfcmp.slt.s $xr3,$xr4,$xr3
xvfcmp.slt.s $xr2,$xr4,$xr2
xvfcmp.slt.s $xr1,$xr4,$xr1
xvfcmp.slt.s $xr0,$xr4,$xr0
xvand.v $xr3,$xr3,$xr12
xvand.v $xr2,$xr2,$xr11
xvand.v $xr1,$xr1,$xr10
xvand.v $xr0,$xr0,$xr9
addi.d $r13,$r13,128
xvfadd.s $xr7,$xr7,$xr3
xvfadd.s $xr8,$xr8,$xr2
xvfadd.s $xr5,$xr5,$xr1
xvfadd.s $xr6,$xr6,$xr0
bne $r12,$r14,.L2
...
gcc/ChangeLog:
* config/loongarch/simd.md (@simd_vbitsel<mode>): Add new
template.
(maskload<mode><allmode_i>): Dito.
(maskstore<mode><allmode_i>): Dito.
gcc/testsuite/ChangeLog:
* gcc.dg/tree-ssa/gen-vect-34.c: Add loongarch test support.
* gcc.dg/vect/tsvc/vect-tsvc-vif.c: Dito.
* lib/target-supports.exp: Add test support for loongarch architecture
vect_mask{load/store}.
* gcc.target/loongarch/vector/lasx/vect-slp-reduc-maskload-float.c: New
test.
* gcc.target/loongarch/vector/lasx/vect-slp-reduc-maskload-int.c: New
test.
* gcc.target/loongarch/vector/lasx/vect-slp-reduc-maskstore-float.c:
New test.
* gcc.target/loongarch/vector/lasx/vect-slp-reduc-maskstore-int.c: New
test.
* gcc.target/loongarch/vector/lsx/vect-slp-reduc-maskload-char.c: New
test.
* gcc.target/loongarch/vector/lsx/vect-slp-reduc-maskload-short.c: New
test.
* gcc.target/loongarch/vector/lsx/vect-slp-reduc-maskstore-char.c: New
test.
* gcc.target/loongarch/vector/lsx/vect-slp-reduc-maskstore-short.c: New
test.
---
gcc/config/loongarch/simd.md | 74 ++++++++++++++++++-
gcc/testsuite/gcc.dg/tree-ssa/gen-vect-34.c | 1 +
.../gcc.dg/vect/tsvc/vect-tsvc-vif.c | 2 +-
.../lasx/vect-slp-reduc-maskload-float.c | 30 ++++++++
.../vector/lasx/vect-slp-reduc-maskload-int.c | 30 ++++++++
.../lasx/vect-slp-reduc-maskstore-float.c | 25 +++++++
.../lasx/vect-slp-reduc-maskstore-int.c | 25 +++++++
.../vector/lsx/vect-slp-reduc-maskload-char.c | 30 ++++++++
.../lsx/vect-slp-reduc-maskload-short.c | 30 ++++++++
.../lsx/vect-slp-reduc-maskstore-char.c | 23 ++++++
.../lsx/vect-slp-reduc-maskstore-short.c | 23 ++++++
gcc/testsuite/lib/target-supports.exp | 6 +-
12 files changed, 295 insertions(+), 4 deletions(-)
create mode 100644
gcc/testsuite/gcc.target/loongarch/vector/lasx/vect-slp-reduc-maskload-float.c
create mode 100644
gcc/testsuite/gcc.target/loongarch/vector/lasx/vect-slp-reduc-maskload-int.c
create mode 100644
gcc/testsuite/gcc.target/loongarch/vector/lasx/vect-slp-reduc-maskstore-float.c
create mode 100644
gcc/testsuite/gcc.target/loongarch/vector/lasx/vect-slp-reduc-maskstore-int.c
create mode 100644
gcc/testsuite/gcc.target/loongarch/vector/lsx/vect-slp-reduc-maskload-char.c
create mode 100644
gcc/testsuite/gcc.target/loongarch/vector/lsx/vect-slp-reduc-maskload-short.c
create mode 100644
gcc/testsuite/gcc.target/loongarch/vector/lsx/vect-slp-reduc-maskstore-char.c
create mode 100644
gcc/testsuite/gcc.target/loongarch/vector/lsx/vect-slp-reduc-maskstore-short.c
diff --git a/gcc/config/loongarch/simd.md b/gcc/config/loongarch/simd.md
index 09e746c56e7..8e21d06b731 100644
--- a/gcc/config/loongarch/simd.md
+++ b/gcc/config/loongarch/simd.md
@@ -264,7 +264,9 @@ (define_c_enum "unspec"
UNSPEC_SIMD_FRINT
UNSPEC_SIMD_FRINTRM
UNSPEC_SIMD_FRINTRNE
- UNSPEC_SIMD_VSHUF])
+ UNSPEC_SIMD_VSHUF
+ UNSPEC_MASKLOAD
+ UNSPEC_MASKSTORE])
(define_int_iterator SIMD_FRINT
[UNSPEC_SIMD_FRINTRP
@@ -1224,6 +1226,76 @@ (define_insn "@simd_vshuf_<mode>"
[(set_attr "type" "simd_sld")
(set_attr "mode" "<MODE>")])
+(define_insn "@simd_vbitsel<mode>"
+ [(set (match_operand:ALLVEC 0 "register_operand" "=f")
+ (ior:ALLVEC
+ (and:ALLVEC
+ (not:ALLVEC (match_operand:ALLVEC 3 "register_operand" "f"))
+ (match_operand:ALLVEC 1 "register_operand" "f"))
+ (and:ALLVEC (match_dup 3)
+ (match_operand:ALLVEC 2 "register_operand" "f"))))]
+ ""
+ "<x>vbitsel.v\t%<wu>0,%<wu>1,%<wu>2,%<wu>3"
+ [(set_attr "type" "simd_bitmov")
+ (set_attr "mode" "<MODE>")])
+
+;; implement maskload.
+(define_expand "maskload<mode><allmode_i>"
+ [(set (match_operand:ALLVEC 0 "register_operand")
+ (unspec:ALLVEC
+ [(match_operand:<VIMODE> 2 "register_operand")
+ (match_operand:ALLVEC 1 "memory_operand")
+ (match_operand:ALLVEC 3 "const_0_operand")]
+ UNSPEC_MASKLOAD))]
+ ""
+ {
+ rtx else_val = gen_reg_rtx (<VIMODE>mode);
+ rtx load_data = gen_reg_rtx (<VIMODE>mode);
+ rtx dest_int = gen_reg_rtx (<VIMODE>mode);
+
+ emit_move_insn ( else_val,
+ simplify_gen_subreg (<VIMODE>mode, operands[3],
+ <MODE>mode, 0));
+
+ emit_move_insn (load_data,
+ simplify_gen_subreg (<VIMODE>mode, operands[1],
+ <MODE>mode, 0));
+
+ emit_insn (gen_simd_vbitsel (<VIMODE>mode, dest_int, else_val,
+ load_data, operands[2]));
+
+ emit_move_insn (operands[0],
+ simplify_gen_subreg (<MODE>mode, dest_int,
+ <VIMODE>mode, 0));
+ DONE;
+ }
+)
+;; implement maskstore.
+(define_expand "maskstore<mode><allmode_i>"
+ [(set (match_operand:ALLVEC 0 "memory_operand")
+ (unspec:ALLVEC
+ [(match_operand:<VIMODE> 2 "register_operand")
+ (match_operand:ALLVEC 1 "register_operand")
+ (match_dup 0)]
+ UNSPEC_MASKSTORE))]
+ ""
+ {
+ rtx mem_init = adjust_address (operands[0], <VIMODE>mode, 0);
+ rtx op0_data = force_reg (<VIMODE>mode, mem_init);
+ rtx store_data = gen_reg_rtx (<VIMODE>mode);
+ rtx dest_int = gen_reg_rtx (<VIMODE>mode);
+
+ emit_move_insn (store_data,
+ simplify_gen_subreg (<VIMODE>mode, operands[1], <MODE>mode, 0));
+
+ emit_insn (gen_simd_vbitsel (<VIMODE>mode, dest_int, op0_data, store_data,
+ operands[2]));
+ emit_move_insn (operands[0], simplify_gen_subreg (<MODE>mode,
+ dest_int, <VIMODE>mode, 0));
+ DONE;
+ }
+)
+
;; Backward compatibility wrapper. New code should use simd_vshuf
;; directly instead: gen_simd_vshuf (mode, ...) can often significantly
;; simplify the logic.
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/gen-vect-34.c
b/gcc/testsuite/gcc.dg/tree-ssa/gen-vect-34.c
index c2e5dfea35f..84e125461e6 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/gen-vect-34.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/gen-vect-34.c
@@ -1,6 +1,7 @@
/* { dg-do compile } */
/* { dg-options "-Ofast -fdump-tree-vect-details" } */
/* { dg-additional-options "-mavx2" { target { x86_64-*-* i?86-*-* } } } */
+/* { dg-additional-options "-mlasx" { target { loongarch64-*-* } } } */
float summul(int n, float *arg1, float *arg2)
{
diff --git a/gcc/testsuite/gcc.dg/vect/tsvc/vect-tsvc-vif.c
b/gcc/testsuite/gcc.dg/vect/tsvc/vect-tsvc-vif.c
index 6eba46403b4..199690289a1 100644
--- a/gcc/testsuite/gcc.dg/vect/tsvc/vect-tsvc-vif.c
+++ b/gcc/testsuite/gcc.dg/vect/tsvc/vect-tsvc-vif.c
@@ -38,4 +38,4 @@ int main (int argc, char **argv)
return 0;
}
-/* { dg-final { scan-tree-dump "vectorized 1 loops" "vect" { xfail { { !
aarch64_sve } && { ! riscv_v } } } } } */
+/* { dg-final { scan-tree-dump "vectorized 1 loops" "vect" { xfail { { { !
aarch64_sve } && { ! riscv_v } } && { ! loongarch_sx } } } } } */
diff --git
a/gcc/testsuite/gcc.target/loongarch/vector/lasx/vect-slp-reduc-maskload-float.c
b/gcc/testsuite/gcc.target/loongarch/vector/lasx/vect-slp-reduc-maskload-float.c
new file mode 100644
index 00000000000..08baf2ab258
--- /dev/null
+++
b/gcc/testsuite/gcc.target/loongarch/vector/lasx/vect-slp-reduc-maskload-float.c
@@ -0,0 +1,30 @@
+/* { dg-do compile { target { loongarch64*-*-* } } } */
+/* { dg-options "-mabi=lp64d -Ofast -mlasx
-fdump-tree-ifcvt-stats-blocks-details" } */
+
+float cond_arr[1024];
+float data_a[1024];
+float data_b[1024];
+float data_c[1024];
+float data_d[1024];
+
+void foo(float * restrict p0, float * restrict p1,
+ float * restrict p2, float * restrict p3) {
+ float s0 = 0.0f, s1 = 0.0f, s2 = 0.0f, s3 = 0.0f;
+
+ for (int i = 0; i < 1024; i++) {
+ if (cond_arr[i] > 0.0f) {
+ s0 += data_a[i];
+ s1 += data_b[i];
+ s2 += data_c[i];
+ s3 += data_d[i];
+ }
+ }
+
+ *p0 = s0;
+ *p1 = s1;
+ *p2 = s2;
+ *p3 = s3;
+}
+
+/* { dg-final { scan-tree-dump-times "Applying if-conversion" 1 "ifcvt" } } */
+/* { dg-final { scan-tree-dump-times "LOOP_VECTORIZED" 1 "ifcvt" } } */
diff --git
a/gcc/testsuite/gcc.target/loongarch/vector/lasx/vect-slp-reduc-maskload-int.c
b/gcc/testsuite/gcc.target/loongarch/vector/lasx/vect-slp-reduc-maskload-int.c
new file mode 100644
index 00000000000..801e8afcfaf
--- /dev/null
+++
b/gcc/testsuite/gcc.target/loongarch/vector/lasx/vect-slp-reduc-maskload-int.c
@@ -0,0 +1,30 @@
+/* { dg-do compile { target { loongarch64*-*-* } } } */
+/* { dg-options "-mabi=lp64d -Ofast -mlasx
-fdump-tree-ifcvt-stats-blocks-details" } */
+
+int cond_arr[1024];
+int data_a[1024];
+int data_b[1024];
+int data_c[1024];
+int data_d[1024];
+
+void foo(int * restrict p0, int * restrict p1,
+ int * restrict p2, int * restrict p3) {
+ int s0 = 0, s1 = 0, s2 = 0, s3 = 0;
+
+ for (int i = 0; i < 1024; i++) {
+ if (cond_arr[i] > 0) {
+ s0 += data_a[i];
+ s1 += data_b[i];
+ s2 += data_c[i];
+ s3 += data_d[i];
+ }
+ }
+
+ *p0 = s0;
+ *p1 = s1;
+ *p2 = s2;
+ *p3 = s3;
+}
+
+/* { dg-final { scan-tree-dump-times "Applying if-conversion" 1 "ifcvt" } } */
+/* { dg-final { scan-tree-dump-times "LOOP_VECTORIZED" 1 "ifcvt" } } */
diff --git
a/gcc/testsuite/gcc.target/loongarch/vector/lasx/vect-slp-reduc-maskstore-float.c
b/gcc/testsuite/gcc.target/loongarch/vector/lasx/vect-slp-reduc-maskstore-float.c
new file mode 100644
index 00000000000..fbbc35450eb
--- /dev/null
+++
b/gcc/testsuite/gcc.target/loongarch/vector/lasx/vect-slp-reduc-maskstore-float.c
@@ -0,0 +1,25 @@
+/* { dg-do compile { target { loongarch64*-*-* } } } */
+/* { dg-options "-mabi=lp64d -Ofast -mlasx
-fdump-tree-ifcvt-stats-blocks-details" } */
+
+float cond_arr[1024];
+float data_a[1024];
+float data_b[1024];
+float data_c[1024];
+float data_d[1024];
+
+void foo(float * restrict p0, float * restrict p1,
+ float * restrict p2, float * restrict p3) {
+
+ for (int i = 0; i < 1024; i++) {
+ if (cond_arr[i] > 0) {
+ p0[i] += data_a[i];
+ p1[i] += data_b[i];
+ p2[i] += data_c[i];
+ p3[i] += data_d[i];
+ }
+ }
+
+}
+
+/* { dg-final { scan-tree-dump-times "Applying if-conversion" 1 "ifcvt" } } */
+/* { dg-final { scan-tree-dump-times "LOOP_VECTORIZED" 1 "ifcvt" } } */
diff --git
a/gcc/testsuite/gcc.target/loongarch/vector/lasx/vect-slp-reduc-maskstore-int.c
b/gcc/testsuite/gcc.target/loongarch/vector/lasx/vect-slp-reduc-maskstore-int.c
new file mode 100644
index 00000000000..9c5d7775859
--- /dev/null
+++
b/gcc/testsuite/gcc.target/loongarch/vector/lasx/vect-slp-reduc-maskstore-int.c
@@ -0,0 +1,25 @@
+/* { dg-do compile { target { loongarch64*-*-* } } } */
+/* { dg-options "-mabi=lp64d -Ofast -mlasx
-fdump-tree-ifcvt-stats-blocks-details" } */
+
+int cond_arr[1024];
+int data_a[1024];
+int data_b[1024];
+int data_c[1024];
+int data_d[1024];
+
+void foo(int * restrict p0, int * restrict p1,
+ int * restrict p2, int * restrict p3) {
+
+ for (int i = 0; i < 1024; i++) {
+ if (cond_arr[i] > 0) {
+ p0[i] += data_a[i];
+ p1[i] += data_b[i];
+ p2[i] += data_c[i];
+ p3[i] += data_d[i];
+ }
+ }
+
+}
+
+/* { dg-final { scan-tree-dump-times "Applying if-conversion" 1 "ifcvt" } } */
+/* { dg-final { scan-tree-dump-times "LOOP_VECTORIZED" 1 "ifcvt" } } */
diff --git
a/gcc/testsuite/gcc.target/loongarch/vector/lsx/vect-slp-reduc-maskload-char.c
b/gcc/testsuite/gcc.target/loongarch/vector/lsx/vect-slp-reduc-maskload-char.c
new file mode 100644
index 00000000000..d4f7a0df366
--- /dev/null
+++
b/gcc/testsuite/gcc.target/loongarch/vector/lsx/vect-slp-reduc-maskload-char.c
@@ -0,0 +1,30 @@
+/* { dg-do compile { target { loongarch64*-*-* } } } */
+/* { dg-options "-mabi=lp64d -Ofast -mlsx
-fdump-tree-ifcvt-stats-blocks-details" } */
+
+char cond_arr[1024];
+char data_a[1024];
+char data_b[1024];
+char data_c[1024];
+char data_d[1024];
+
+void foo(char * restrict p0, int * restrict p1,
+ char * restrict p2, int * restrict p3) {
+ char s0 = 0, s1 = 0, s2 = 0, s3 = 0;
+
+ for (int i = 0; i < 1024; i++) {
+ if (cond_arr[i] > 0) {
+ s0 += data_a[i];
+ s1 += data_b[i];
+ s2 += data_c[i];
+ s3 += data_d[i];
+ }
+ }
+
+ *p0 = s0;
+ *p1 = s1;
+ *p2 = s2;
+ *p3 = s3;
+}
+
+/* { dg-final { scan-tree-dump-times "Applying if-conversion" 1 "ifcvt" } } */
+/* { dg-final { scan-tree-dump-times "LOOP_VECTORIZED" 1 "ifcvt" } } */
diff --git
a/gcc/testsuite/gcc.target/loongarch/vector/lsx/vect-slp-reduc-maskload-short.c
b/gcc/testsuite/gcc.target/loongarch/vector/lsx/vect-slp-reduc-maskload-short.c
new file mode 100644
index 00000000000..a78bde6a8b0
--- /dev/null
+++
b/gcc/testsuite/gcc.target/loongarch/vector/lsx/vect-slp-reduc-maskload-short.c
@@ -0,0 +1,30 @@
+/* { dg-do compile { target { loongarch64*-*-* } } } */
+/* { dg-options "-mabi=lp64d -Ofast -mlsx
-fdump-tree-ifcvt-stats-blocks-details" } */
+
+short cond_arr[1024];
+short data_a[1024];
+short data_b[1024];
+short data_c[1024];
+short data_d[1024];
+
+void foo(short * restrict p0, short * restrict p1,
+ short * restrict p2, short * restrict p3) {
+ short s0 = 0, s1 = 0, s2 = 0, s3 = 0;
+
+ for (int i = 0; i < 1024; i++) {
+ if (cond_arr[i] > 0) {
+ s0 += data_a[i];
+ s1 += data_b[i];
+ s2 += data_c[i];
+ s3 += data_d[i];
+ }
+ }
+
+ *p0 = s0;
+ *p1 = s1;
+ *p2 = s2;
+ *p3 = s3;
+}
+
+/* { dg-final { scan-tree-dump-times "Applying if-conversion" 1 "ifcvt" } } */
+/* { dg-final { scan-tree-dump-times "LOOP_VECTORIZED" 1 "ifcvt" } } */
diff --git
a/gcc/testsuite/gcc.target/loongarch/vector/lsx/vect-slp-reduc-maskstore-char.c
b/gcc/testsuite/gcc.target/loongarch/vector/lsx/vect-slp-reduc-maskstore-char.c
new file mode 100644
index 00000000000..a6a1639379e
--- /dev/null
+++
b/gcc/testsuite/gcc.target/loongarch/vector/lsx/vect-slp-reduc-maskstore-char.c
@@ -0,0 +1,23 @@
+/* { dg-do compile { target { loongarch64*-*-* } } } */
+/* { dg-options "-mabi=lp64d -Ofast -mlsx
-fdump-tree-ifcvt-stats-blocks-details" } */
+
+char cond_arr[1024];
+char data_a[1024];
+char data_b[1024];
+char data_c[1024];
+char data_d[1024];
+
+void foo(char * restrict p0, int * restrict p1,
+ char * restrict p2, int * restrict p3) {
+ for (int i = 0; i < 1024; i++) {
+ if (cond_arr[i] > 0) {
+ p0[i] += data_a[i];
+ p1[i] += data_b[i];
+ p2[i] += data_c[i];
+ p3[i] += data_d[i];
+ }
+ }
+}
+
+/* { dg-final { scan-tree-dump-times "Applying if-conversion" 1 "ifcvt" } } */
+/* { dg-final { scan-tree-dump-times "LOOP_VECTORIZED" 1 "ifcvt" } } */
diff --git
a/gcc/testsuite/gcc.target/loongarch/vector/lsx/vect-slp-reduc-maskstore-short.c
b/gcc/testsuite/gcc.target/loongarch/vector/lsx/vect-slp-reduc-maskstore-short.c
new file mode 100644
index 00000000000..b133ce2f4a2
--- /dev/null
+++
b/gcc/testsuite/gcc.target/loongarch/vector/lsx/vect-slp-reduc-maskstore-short.c
@@ -0,0 +1,23 @@
+/* { dg-do compile { target { loongarch64*-*-* } } } */
+/* { dg-options "-mabi=lp64d -Ofast -mlsx
-fdump-tree-ifcvt-stats-blocks-details" } */
+
+short cond_arr[1024];
+short data_a[1024];
+short data_b[1024];
+short data_c[1024];
+short data_d[1024];
+
+void foo(short * restrict p0, short * restrict p1,
+ short * restrict p2, short * restrict p3) {
+ for (int i = 0; i < 1024; i++) {
+ if (cond_arr[i] > 0) {
+ p0[i] += data_a[i];
+ p1[i] += data_b[i];
+ p2[i] += data_c[i];
+ p3[i] += data_d[i];
+ }
+ }
+}
+
+/* { dg-final { scan-tree-dump-times "Applying if-conversion" 1 "ifcvt" } } */
+/* { dg-final { scan-tree-dump-times "LOOP_VECTORIZED" 1 "ifcvt" } } */
diff --git a/gcc/testsuite/lib/target-supports.exp
b/gcc/testsuite/lib/target-supports.exp
index 3ce06189d2e..b9ecbaf171f 100644
--- a/gcc/testsuite/lib/target-supports.exp
+++ b/gcc/testsuite/lib/target-supports.exp
@@ -10295,7 +10295,8 @@ proc check_effective_target_vect_masked_load { } {
return [expr { [check_avx_available]
|| [check_effective_target_aarch64_sve]
|| [istarget amdgcn*-*-*]
- || [check_effective_target_riscv_v] } ]
+ || [check_effective_target_riscv_v]
+ || [check_effective_target_loongarch_sx] } ]
}
# Return 1 if the target supports vector masked stores.
@@ -10304,7 +10305,8 @@ proc check_effective_target_vect_masked_store { } {
return [expr { [check_avx_available]
|| [check_effective_target_aarch64_sve]
|| [istarget amdgcn*-*-*]
- || [check_effective_target_riscv_v] }]
+ || [check_effective_target_riscv_v]
+ || [check_effective_target_loongarch_sx] }]
}
# Return 1 if the target supports vector gather loads via internal functions.
--
2.20.1