From eb5f081c16bde273f0b3c24b5929c822ae502a4f Mon Sep 17 00:00:00 2001 From: Michael Meissner Date: Fri, 7 Aug 2020 01:03:22 -0400 Subject: [PATCH] Power10: Add BRD, BRW, and BRH support. This patch adds support for the ISA 3.1 (power10) instructions that does a byte swap of values in GPR registers. gcc/ 2020-08-07 Michael Meissner * config/rs6000/rs6000.md (bswaphi2_reg): Add ISA 3.1 support. (bswapsi2_reg): Add ISA 3.1 support. (bswapdi2): Rename bswapdi2_xxbrd to bswapdi2_brd. (bswapdi2_brd,bswapdi2_xxbrd): Rename. Add ISA 3.1 support. gcc/testsuite/ 2020-08-07 Michael Meissner * gcc.target/powerpc/bswap-brd.c: New test. * gcc.target/powerpc/bswap-brw.c: New test. * gcc.target/powerpc/bswap-brh.c: New test. --- gcc/config/rs6000/rs6000.md | 44 +++++++++++--------- gcc/testsuite/gcc.target/powerpc/bswap-brd.c | 23 ++++++++++ gcc/testsuite/gcc.target/powerpc/bswap-brh.c | 11 +++++ gcc/testsuite/gcc.target/powerpc/bswap-brw.c | 22 ++++++++++ 4 files changed, 80 insertions(+), 20 deletions(-) create mode 100644 gcc/testsuite/gcc.target/powerpc/bswap-brd.c create mode 100644 gcc/testsuite/gcc.target/powerpc/bswap-brh.c create mode 100644 gcc/testsuite/gcc.target/powerpc/bswap-brw.c diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md index 48f1f1c6876..43b620ae1c0 100644 --- a/gcc/config/rs6000/rs6000.md +++ b/gcc/config/rs6000/rs6000.md @@ -2591,15 +2591,16 @@ [(set_attr "type" "store")]) (define_insn_and_split "bswaphi2_reg" - [(set (match_operand:HI 0 "gpc_reg_operand" "=&r,wa") + [(set (match_operand:HI 0 "gpc_reg_operand" "=r,&r,wa") (bswap:HI - (match_operand:HI 1 "gpc_reg_operand" "r,wa"))) - (clobber (match_scratch:SI 2 "=&r,X"))] + (match_operand:HI 1 "gpc_reg_operand" "r,r,wa"))) + (clobber (match_scratch:SI 2 "=X,&r,X"))] "" "@ + brh %0,%1 # xxbrh %x0,%x1" - "reload_completed && int_reg_operand (operands[0], HImode)" + "reload_completed && !TARGET_POWER10 && int_reg_operand (operands[0], HImode)" [(set (match_dup 3) (and:SI (lshiftrt:SI (match_dup 4) (const_int 8)) @@ -2615,21 +2616,22 @@ operands[3] = simplify_gen_subreg (SImode, operands[0], HImode, 0); operands[4] = simplify_gen_subreg (SImode, operands[1], HImode, 0); } - [(set_attr "length" "12,4") - (set_attr "type" "*,vecperm") - (set_attr "isa" "*,p9v")]) + [(set_attr "length" "*,12,*") + (set_attr "type" "shift,*,vecperm") + (set_attr "isa" "p10,*,p9v")]) ;; We are always BITS_BIG_ENDIAN, so the bit positions below in ;; zero_extract insns do not change for -mlittle. (define_insn_and_split "bswapsi2_reg" - [(set (match_operand:SI 0 "gpc_reg_operand" "=&r,wa") + [(set (match_operand:SI 0 "gpc_reg_operand" "=r,&r,wa") (bswap:SI - (match_operand:SI 1 "gpc_reg_operand" "r,wa")))] + (match_operand:SI 1 "gpc_reg_operand" "r,r,wa")))] "" "@ + brw %0,%1 # xxbrw %x0,%x1" - "reload_completed && int_reg_operand (operands[0], SImode)" + "reload_completed && !TARGET_POWER10 && int_reg_operand (operands[0], SImode)" [(set (match_dup 0) ; DABC (rotate:SI (match_dup 1) (const_int 24))) @@ -2646,9 +2648,9 @@ (and:SI (match_dup 0) (const_int -256))))] "" - [(set_attr "length" "12,4") - (set_attr "type" "*,vecperm") - (set_attr "isa" "*,p9v")]) + [(set_attr "length" "4,12,4") + (set_attr "type" "shift,*,vecperm") + (set_attr "isa" "p10,*,p9v")]) ;; On systems with LDBRX/STDBRX generate the loads/stores directly, just like ;; we do for L{H,W}BRX and ST{H,W}BRX above. If not, we have to generate more @@ -2681,7 +2683,7 @@ emit_insn (gen_bswapdi2_store (dest, src)); } else if (TARGET_P9_VECTOR) - emit_insn (gen_bswapdi2_xxbrd (dest, src)); + emit_insn (gen_bswapdi2_brd (dest, src)); else emit_insn (gen_bswapdi2_reg (dest, src)); DONE; @@ -2712,13 +2714,15 @@ "stdbrx %1,%y0" [(set_attr "type" "store")]) -(define_insn "bswapdi2_xxbrd" - [(set (match_operand:DI 0 "gpc_reg_operand" "=wa") - (bswap:DI (match_operand:DI 1 "gpc_reg_operand" "wa")))] +(define_insn "bswapdi2_brd" + [(set (match_operand:DI 0 "gpc_reg_operand" "=r,wa") + (bswap:DI (match_operand:DI 1 "gpc_reg_operand" "r,wa")))] "TARGET_P9_VECTOR" - "xxbrd %x0,%x1" - [(set_attr "type" "vecperm") - (set_attr "isa" "p9v")]) + "@ + brd %0,%1 + xxbrd %x0,%x1" + [(set_attr "type" "shift,vecperm") + (set_attr "isa" "p10,p9v")]) (define_insn "bswapdi2_reg" [(set (match_operand:DI 0 "gpc_reg_operand" "=&r") diff --git a/gcc/testsuite/gcc.target/powerpc/bswap-brd.c b/gcc/testsuite/gcc.target/powerpc/bswap-brd.c new file mode 100644 index 00000000000..876129eb633 --- /dev/null +++ b/gcc/testsuite/gcc.target/powerpc/bswap-brd.c @@ -0,0 +1,23 @@ +/* { dg-do compile { target { lp64 } } } */ +/* { dg-require-effective-target power10_ok } */ +/* { dg-options "-O2 -mdejagnu-cpu=power10" } */ + +/* This tests whether GCC generates the ISA 3.1 BRW byte swap instruction for + GPR data, but generates XXBRW for data in a vector register. */ + +unsigned long long +bswap_ll (unsigned long long a) +{ + return __builtin_bswap64 (a); /* { dg-final { scan-assembler {\mbrd\M} } } */ +} + +double +bswap_ll_dbl (unsigned long long a) +{ + unsigned int b = a; + /* Force the value to be loaded into a vector register. */ + __asm__ (" # %x0" : "+wa" (b)); + + /* { dg-final { scan-assembler {\mxxbrd\M} } } */ + return (double) __builtin_bswap64 (b); +} diff --git a/gcc/testsuite/gcc.target/powerpc/bswap-brh.c b/gcc/testsuite/gcc.target/powerpc/bswap-brh.c new file mode 100644 index 00000000000..4dbab12891b --- /dev/null +++ b/gcc/testsuite/gcc.target/powerpc/bswap-brh.c @@ -0,0 +1,11 @@ +/* { dg-require-effective-target power10_ok } */ +/* { dg-options "-O2 -mdejagnu-cpu=power10" } */ + +/* This tests whether GCC generates the ISA 3.1 16-bit byte swap + instruction BRH. */ + +unsigned short +bswap_short (unsigned short a) +{ + return __builtin_bswap16 (a); /* { dg-final { scan-assembler {\mbrh\M} } } */ +} diff --git a/gcc/testsuite/gcc.target/powerpc/bswap-brw.c b/gcc/testsuite/gcc.target/powerpc/bswap-brw.c new file mode 100644 index 00000000000..b3f923eea84 --- /dev/null +++ b/gcc/testsuite/gcc.target/powerpc/bswap-brw.c @@ -0,0 +1,22 @@ +/* { dg-require-effective-target power10_ok } */ +/* { dg-options "-O2 -mdejagnu-cpu=power10" } */ + +/* This tests whether GCC generates the ISA 3.1 BRW byte swap instruction for + GPR data, but generates XXBRW for data in a vector register. */ + +unsigned int +bswap_int (unsigned int a) +{ + return __builtin_bswap32 (a); /* { dg-final { scan-assembler {\mbrw\M} } } */ +} + +double +bswap_int_dbl (unsigned int a) +{ + unsigned int b = a; + /* Force the value to be loaded into a vector register. */ + __asm__ (" # %x0" : "+wa" (b)); + + /* { dg-final { scan-assembler {\mxxbrw\M} } } */ + return (double) __builtin_bswap32 (b); +} -- 2.30.2