bpf: add define_insn for bswap

The eBPF architecture provides 'end[be,le]' instructions for endianness
swapping. Add a define_insn for bswap<mode>2 to use them instaed of
falling back on a libcall.

gcc/

	* config/bpf/bpf.md (bswap<mode>2): New define_insn.

gcc/testsuite/

	* gcc.target/bpf/bswap-1.c: New test.
This commit is contained in:
David Faust 2022-12-08 10:08:22 -08:00
parent bd0485f20f
commit 5ddfe79440
2 changed files with 40 additions and 0 deletions

View File

@ -341,6 +341,23 @@
"rsh<msuffix>\t%0,%2"
[(set_attr "type" "<mtype>")])
;;;; Endianness conversion
(define_mode_iterator BSM [HI SI DI])
(define_mode_attr endmode [(HI "16") (SI "32") (DI "64")])
(define_insn "bswap<BSM:mode>2"
[(set (match_operand:BSM 0 "register_operand" "=r")
(bswap:BSM (match_operand:BSM 1 "register_operand" " r")))]
""
{
if (TARGET_BIG_ENDIAN)
return "endle\t%0, <endmode>";
else
return "endbe\t%0, <endmode>";
}
[(set_attr "type" "end")])
;;;; Conditional branches
;; The eBPF jump instructions use 64-bit arithmetic when evaluating

View File

@ -0,0 +1,23 @@
/* { dg-do compile } */
/* { dg-options "-mlittle-endian" } */
unsigned short in16 = 0x1234U;
unsigned int in32 = 0x12345678U;
unsigned long in64 = 0x123456789abcdef0ULL;
unsigned short out16 = 0;
unsigned int out32 = 0;
unsigned long out64 = 0;
int foo (void)
{
out16 = __builtin_bswap16 (in16);
out32 = __builtin_bswap32 (in32);
out64 = __builtin_bswap64 (in64);
return 0;
}
/* { dg-final { scan-assembler "endbe\t%r., 16" } } */
/* { dg-final { scan-assembler "endbe\t%r., 32" } } */
/* { dg-final { scan-assembler "endbe\t%r., 64" } } */