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.c: New test. * gcc.target/loongarch/rotl-with-xvrotr.c: New test. --- Bootstrapped and regtested on loongarch64-linux-gnu. Ok for trunk? gcc/config/loongarch/loongarch.md | 12 ++++++++ gcc/config/loongarch/simd.md | 29 +++++++++++++++++++ .../gcc.target/loongarch/rotl-with-rotr.c | 9 ++++++ .../gcc.target/loongarch/rotl-with-vrotr.c | 24 +++++++++++++++ .../gcc.target/loongarch/rotl-with-xvrotr.c | 7 +++++ 5 files changed, 81 insertions(+) create mode 100644 gcc/testsuite/gcc.target/loongarch/rotl-with-rotr.c create mode 100644 gcc/testsuite/gcc.target/loongarch/rotl-with-vrotr.c create mode 100644 gcc/testsuite/gcc.target/loongarch/rotl-with-xvrotr.c diff --git a/gcc/config/loongarch/loongarch.md b/gcc/config/loongarch/loongarch.md index 30025bf1908..939432b83e0 100644 --- a/gcc/config/loongarch/loongarch.md +++ b/gcc/config/loongarch/loongarch.md @@ -2903,6 +2903,18 @@ (define_insn "rotrsi3_extend" [(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 13202f79bee..a42e20eb8fc 100644 --- a/gcc/config/loongarch/simd.md +++ b/gcc/config/loongarch/simd.md @@ -268,6 +268,35 @@ (define_insn "vrotr<mode>3" [(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 (match_dup 3))) + (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 00000000000..84cc53cecaf --- /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.c b/gcc/testsuite/gcc.target/loongarch/rotl-with-vrotr.c new file mode 100644 index 00000000000..3ebf7e3c083 --- /dev/null +++ b/gcc/testsuite/gcc.target/loongarch/rotl-with-vrotr.c @@ -0,0 +1,24 @@ +/* { 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 + +typedef unsigned int V __attribute__((vector_size(VLEN))); +V a, b, c; + +void +test (int x) +{ + b = a << x | a >> (32 - x); +} + +void +test2 (void) +{ + for (int i = 0; i < VLEN / sizeof (int); i++) + c[i] = a[i] << b[i] | a[i] >> (32 - b[i]); +} diff --git a/gcc/testsuite/gcc.target/loongarch/rotl-with-xvrotr.c b/gcc/testsuite/gcc.target/loongarch/rotl-with-xvrotr.c new file mode 100644 index 00000000000..833e041b2e2 --- /dev/null +++ b/gcc/testsuite/gcc.target/loongarch/rotl-with-xvrotr.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.c" -- 2.43.0