diff options
author | Xi Ruoyao <xry111@xry111.site> | 2023-12-17 05:38:20 +0800 |
---|---|---|
committer | Xi Ruoyao <xry111@xry111.site> | 2023-12-27 19:02:03 +0800 |
commit | 80b8f1e53502a398248bbf10bf59f7d5b0f1c861 (patch) | |
tree | bd6970443b831035424a800454342266cb6f0427 | |
parent | c4ac073d4fc7474e29d085bbd10971138ee7478e (diff) | |
download | gcc-80b8f1e53502a398248bbf10bf59f7d5b0f1c861.zip gcc-80b8f1e53502a398248bbf10bf59f7d5b0f1c861.tar.gz gcc-80b8f1e53502a398248bbf10bf59f7d5b0f1c861.tar.bz2 |
LoongArch: Expand left rotate to right rotate with negated amount
gcc/ChangeLog:
* config/loongarch/loongarch.md (rotl<mode>3):
New define_expand.
* config/loongarch/simd.md (vrotl<mode>3): Likewise.
(rotl<mode>3): Likewise.
gcc/testsuite/ChangeLog:
* gcc.target/loongarch/rotl-with-rotr.c: New test.
* gcc.target/loongarch/rotl-with-vrotr-b.c: New test.
* gcc.target/loongarch/rotl-with-vrotr-h.c: New test.
* gcc.target/loongarch/rotl-with-vrotr-w.c: New test.
* gcc.target/loongarch/rotl-with-vrotr-d.c: New test.
* gcc.target/loongarch/rotl-with-xvrotr-b.c: New test.
* gcc.target/loongarch/rotl-with-xvrotr-h.c: New test.
* gcc.target/loongarch/rotl-with-xvrotr-w.c: New test.
* gcc.target/loongarch/rotl-with-xvrotr-d.c: New test.
11 files changed, 127 insertions, 0 deletions
diff --git a/gcc/config/loongarch/loongarch.md b/gcc/config/loongarch/loongarch.md index 2b0609f..e56ea71 100644 --- a/gcc/config/loongarch/loongarch.md +++ b/gcc/config/loongarch/loongarch.md @@ -2903,6 +2903,18 @@ [(set_attr "type" "shift,shift") (set_attr "mode" "SI")]) +;; Expand left rotate to right rotate. +(define_expand "rotl<mode>3" + [(set (match_dup 3) + (neg:SI (match_operand:SI 2 "register_operand"))) + (set (match_operand:GPR 0 "register_operand") + (rotatert:GPR (match_operand:GPR 1 "register_operand") + (match_dup 3)))] + "" + { + operands[3] = gen_reg_rtx (SImode); + }); + ;; The following templates were added to generate "bstrpick.d + alsl.d" ;; instruction pairs. ;; It is required that the values of const_immalsl_operand and diff --git a/gcc/config/loongarch/simd.md b/gcc/config/loongarch/simd.md index 13202f7..93fb39a 100644 --- a/gcc/config/loongarch/simd.md +++ b/gcc/config/loongarch/simd.md @@ -268,6 +268,35 @@ [(set_attr "type" "simd_int_arith") (set_attr "mode" "<MODE>")]) +;; Expand left rotate to right rotate. +(define_expand "vrotl<mode>3" + [(set (match_dup 3) + (neg:IVEC (match_operand:IVEC 2 "register_operand"))) + (set (match_operand:IVEC 0 "register_operand") + (rotatert:IVEC (match_operand:IVEC 1 "register_operand") + (match_dup 3)))] + "" + { + operands[3] = gen_reg_rtx (<MODE>mode); + }); + +;; Expand left rotate with a scalar amount to right rotate: negate the +;; scalar before broadcasting it because scalar negation is cheaper than +;; vector negation. +(define_expand "rotl<mode>3" + [(set (match_dup 3) + (neg:SI (match_operand:SI 2 "register_operand"))) + (set (match_dup 4) + (vec_duplicate:IVEC (subreg:<IVEC:UNITMODE> (match_dup 3) 0))) + (set (match_operand:IVEC 0 "register_operand") + (rotatert:IVEC (match_operand:IVEC 1 "register_operand") + (match_dup 4)))] + "" + { + operands[3] = gen_reg_rtx (SImode); + operands[4] = gen_reg_rtx (<MODE>mode); + }); + ;; <x>vrotri.{b/h/w/d} (define_insn "rotr<mode>3" diff --git a/gcc/testsuite/gcc.target/loongarch/rotl-with-rotr.c b/gcc/testsuite/gcc.target/loongarch/rotl-with-rotr.c new file mode 100644 index 0000000..84cc53c --- /dev/null +++ b/gcc/testsuite/gcc.target/loongarch/rotl-with-rotr.c @@ -0,0 +1,9 @@ +/* { dg-do compile } */ +/* { dg-options "-O2" } */ +/* { dg-final { scan-assembler "rotr\\.w" } } */ + +unsigned +t (unsigned a, unsigned b) +{ + return a << b | a >> (32 - b); +} diff --git a/gcc/testsuite/gcc.target/loongarch/rotl-with-vrotr-b.c b/gcc/testsuite/gcc.target/loongarch/rotl-with-vrotr-b.c new file mode 100644 index 0000000..14298bf --- /dev/null +++ b/gcc/testsuite/gcc.target/loongarch/rotl-with-vrotr-b.c @@ -0,0 +1,7 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -mlsx -fno-vect-cost-model" } */ +/* { dg-final { scan-assembler-times "vrotr\\.b" 2 } } */ +/* { dg-final { scan-assembler-times "vneg\\.b" 1 } } */ + +#define TYPE char +#include "rotl-with-vrotr-w.c" diff --git a/gcc/testsuite/gcc.target/loongarch/rotl-with-vrotr-d.c b/gcc/testsuite/gcc.target/loongarch/rotl-with-vrotr-d.c new file mode 100644 index 0000000..0e971b3 --- /dev/null +++ b/gcc/testsuite/gcc.target/loongarch/rotl-with-vrotr-d.c @@ -0,0 +1,7 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -mlsx -fno-vect-cost-model" } */ +/* { dg-final { scan-assembler-times "vrotr\\.d" 2 } } */ +/* { dg-final { scan-assembler-times "vneg\\.d" 1 } } */ + +#define TYPE long long +#include "rotl-with-vrotr-w.c" diff --git a/gcc/testsuite/gcc.target/loongarch/rotl-with-vrotr-h.c b/gcc/testsuite/gcc.target/loongarch/rotl-with-vrotr-h.c new file mode 100644 index 0000000..93216eb --- /dev/null +++ b/gcc/testsuite/gcc.target/loongarch/rotl-with-vrotr-h.c @@ -0,0 +1,7 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -mlsx -fno-vect-cost-model" } */ +/* { dg-final { scan-assembler-times "vrotr\\.h" 2 } } */ +/* { dg-final { scan-assembler-times "vneg\\.h" 1 } } */ + +#define TYPE short +#include "rotl-with-vrotr-w.c" diff --git a/gcc/testsuite/gcc.target/loongarch/rotl-with-vrotr-w.c b/gcc/testsuite/gcc.target/loongarch/rotl-with-vrotr-w.c new file mode 100644 index 0000000..d05b86f --- /dev/null +++ b/gcc/testsuite/gcc.target/loongarch/rotl-with-vrotr-w.c @@ -0,0 +1,28 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -mlsx -fno-vect-cost-model" } */ +/* { dg-final { scan-assembler-times "vrotr\\.w" 2 } } */ +/* { dg-final { scan-assembler-times "vneg\\.w" 1 } } */ + +#ifndef VLEN +#define VLEN 16 +#endif + +#ifndef TYPE +#define TYPE int +#endif + +typedef unsigned TYPE V __attribute__ ((vector_size (VLEN))); +V a, b, c; + +void +test (int x) +{ + b = a << x | a >> ((int)sizeof (TYPE) * __CHAR_BIT__ - x); +} + +void +test2 (void) +{ + for (int i = 0; i < VLEN / sizeof (TYPE); i++) + c[i] = a[i] << b[i] | a[i] >> ((int)sizeof (TYPE) * __CHAR_BIT__ - b[i]); +} diff --git a/gcc/testsuite/gcc.target/loongarch/rotl-with-xvrotr-b.c b/gcc/testsuite/gcc.target/loongarch/rotl-with-xvrotr-b.c new file mode 100644 index 0000000..2674b1b --- /dev/null +++ b/gcc/testsuite/gcc.target/loongarch/rotl-with-xvrotr-b.c @@ -0,0 +1,7 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -mlasx -fno-vect-cost-model" } */ +/* { dg-final { scan-assembler-times "xvrotr\\.b" 2 } } */ +/* { dg-final { scan-assembler-times "xvneg\\.b" 1 } } */ + +#define VLEN 32 +#include "rotl-with-vrotr-b.c" diff --git a/gcc/testsuite/gcc.target/loongarch/rotl-with-xvrotr-d.c b/gcc/testsuite/gcc.target/loongarch/rotl-with-xvrotr-d.c new file mode 100644 index 0000000..e944033 --- /dev/null +++ b/gcc/testsuite/gcc.target/loongarch/rotl-with-xvrotr-d.c @@ -0,0 +1,7 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -mlasx -fno-vect-cost-model" } */ +/* { dg-final { scan-assembler-times "xvrotr\\.d" 2 } } */ +/* { dg-final { scan-assembler-times "xvneg\\.d" 1 } } */ + +#define VLEN 32 +#include "rotl-with-vrotr-d.c" diff --git a/gcc/testsuite/gcc.target/loongarch/rotl-with-xvrotr-h.c b/gcc/testsuite/gcc.target/loongarch/rotl-with-xvrotr-h.c new file mode 100644 index 0000000..3d99894 --- /dev/null +++ b/gcc/testsuite/gcc.target/loongarch/rotl-with-xvrotr-h.c @@ -0,0 +1,7 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -mlasx -fno-vect-cost-model" } */ +/* { dg-final { scan-assembler-times "xvrotr\\.h" 2 } } */ +/* { dg-final { scan-assembler-times "xvneg\\.h" 1 } } */ + +#define VLEN 32 +#include "rotl-with-vrotr-h.c" diff --git a/gcc/testsuite/gcc.target/loongarch/rotl-with-xvrotr-w.c b/gcc/testsuite/gcc.target/loongarch/rotl-with-xvrotr-w.c new file mode 100644 index 0000000..ca6aa7b --- /dev/null +++ b/gcc/testsuite/gcc.target/loongarch/rotl-with-xvrotr-w.c @@ -0,0 +1,7 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -mlasx -fno-vect-cost-model" } */ +/* { dg-final { scan-assembler-times "xvrotr\\.w" 2 } } */ +/* { dg-final { scan-assembler-times "xvneg\\.w" 1 } } */ + +#define VLEN 32 +#include "rotl-with-vrotr-w.c" |