We couldn't generate EXTR for AArch64 ... until now! This patch includes the pattern and a test.
Full regression testing for Linux and bare-metal passed. OK for trunk stage-1? Thanks, Ian 2013-03-14 Ian Bolton <ian.bol...@arm.com> gcc/ * config/aarch64/aarch64.md (*extr<mode>5_insn): New pattern. (*extrsi5_insn_uxtw): Likewise. testsuite/ * gcc.target/aarch64/extr.c: New test.
diff --git a/gcc/config/aarch64/aarch64.md b/gcc/config/aarch64/aarch64.md index 73d86a7..ef1c0f3 100644 --- a/gcc/config/aarch64/aarch64.md +++ b/gcc/config/aarch64/aarch64.md @@ -2703,6 +2703,34 @@ (set_attr "mode" "<MODE>")] ) +(define_insn "*extr<mode>5_insn" + [(set (match_operand:GPI 0 "register_operand" "=r") + (ior:GPI (ashift:GPI (match_operand:GPI 1 "register_operand" "r") + (match_operand 3 "const_int_operand" "n")) + (lshiftrt:GPI (match_operand:GPI 2 "register_operand" "r") + (match_operand 4 "const_int_operand" "n"))))] + "UINTVAL (operands[3]) < GET_MODE_BITSIZE (<MODE>mode) && + (UINTVAL (operands[3]) + UINTVAL (operands[4]) == GET_MODE_BITSIZE (<MODE>mode))" + "extr\\t%<w>0, %<w>1, %<w>2, %4" + [(set_attr "v8type" "shift") + (set_attr "mode" "<MODE>")] +) + +;; zero_extend version of the above +(define_insn "*extrsi5_insn_uxtw" + [(set (match_operand:DI 0 "register_operand" "=r") + (zero_extend:DI + (ior:SI (ashift:SI (match_operand:SI 1 "register_operand" "r") + (match_operand 3 "const_int_operand" "n")) + (lshiftrt:SI (match_operand:SI 2 "register_operand" "r") + (match_operand 4 "const_int_operand" "n")))))] + "UINTVAL (operands[3]) < 32 && + (UINTVAL (operands[3]) + UINTVAL (operands[4]) == 32)" + "extr\\t%w0, %w1, %w2, %4" + [(set_attr "v8type" "shift") + (set_attr "mode" "SI")] +) + (define_insn "*<ANY_EXTEND:optab><GPI:mode>_ashl<SHORT:mode>" [(set (match_operand:GPI 0 "register_operand" "=r") (ANY_EXTEND:GPI diff --git a/gcc/testsuite/gcc.target/aarch64/extr.c b/gcc/testsuite/gcc.target/aarch64/extr.c new file mode 100644 index 0000000..a78dd8d --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/extr.c @@ -0,0 +1,34 @@ +/* { dg-options "-O2 --save-temps" } */ +/* { dg-do run } */ + +extern void abort (void); + +int +test_si (int a, int b) +{ + /* { dg-final { scan-assembler "extr\tw\[0-9\]+, w\[0-9\]+, w\[0-9\]+, 27\n" } } */ + return (a << 5) | ((unsigned int) b >> 27); +} + +long long +test_di (long long a, long long b) +{ + /* { dg-final { scan-assembler "extr\tx\[0-9\]+, x\[0-9\]+, x\[0-9\]+, 45\n" } } */ + return (a << 19) | ((unsigned long long) b >> 45); +} + +int +main () +{ + int v; + long long w; + v = test_si (0x00000004, 0x30000000); + if (v != 0x00000086) + abort(); + w = test_di (0x0001040040040004ll, 0x0070050066666666ll); + if (w != 0x2002002000200380ll) + abort(); + return 0; +} + +/* { dg-final { cleanup-saved-temps } } */