diff options
author | Eric Botcazou <ebotcazou@adacore.com> | 2013-05-24 06:46:11 +0000 |
---|---|---|
committer | Eric Botcazou <ebotcazou@gcc.gnu.org> | 2013-05-24 06:46:11 +0000 |
commit | b17c024fa920895a860c675836e98fc49c01e9ce (patch) | |
tree | 76784853bcad116d42b13a68d164909e4c2f1ad4 /gcc | |
parent | d0c70325c9ee2767b87cf7f104ab34ba8e316a4e (diff) | |
download | gcc-b17c024fa920895a860c675836e98fc49c01e9ce.zip gcc-b17c024fa920895a860c675836e98fc49c01e9ce.tar.gz gcc-b17c024fa920895a860c675836e98fc49c01e9ce.tar.bz2 |
re PR tree-optimization/55177 (missed optimizations with __builtin_bswap)
PR rtl-optimization/55177
* simplify-rtx.c (simplify_unary_operation_1) <NOT>: Deal with BSWAP.
(simplify_byte_swapping_operation): New.
(simplify_binary_operation_1): Call it for AND, IOR and XOR.
(simplify_relational_operation_1): Deal with BSWAP.
From-SVN: r199278
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 8 | ||||
-rw-r--r-- | gcc/simplify-rtx.c | 66 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 7 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/builtin-bswap-6.c | 38 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/builtin-bswap-7.c | 39 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/builtin-bswap-8.c | 45 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/builtin-bswap-9.c | 46 |
7 files changed, 247 insertions, 2 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 51e7b9e..ae1d9b5 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,11 @@ +2013-05-24 Eric Botcazou <ebotcazou@adacore.com> + + PR rtl-optimization/55177 + * simplify-rtx.c (simplify_unary_operation_1) <NOT>: Deal with BSWAP. + (simplify_byte_swapping_operation): New. + (simplify_binary_operation_1): Call it for AND, IOR and XOR. + (simplify_relational_operation_1): Deal with BSWAP. + 2013-05-23 Richard Henderson <rth@redhat.com> PR target/56742 diff --git a/gcc/simplify-rtx.c b/gcc/simplify-rtx.c index 865d37d..5c1dd25 100644 --- a/gcc/simplify-rtx.c +++ b/gcc/simplify-rtx.c @@ -858,7 +858,6 @@ simplify_unary_operation_1 (enum rtx_code code, enum machine_mode mode, rtx op) /* (not (ashiftrt foo C)) where C is the number of bits in FOO minus 1 is (ge foo (const_int 0)) if STORE_FLAG_VALUE is -1, so we can perform the above simplification. */ - if (STORE_FLAG_VALUE == -1 && GET_CODE (op) == ASHIFTRT && GET_CODE (XEXP (op, 1)) @@ -890,7 +889,6 @@ simplify_unary_operation_1 (enum rtx_code code, enum machine_mode mode, rtx op) with negating logical insns (and-not, nand, etc.). If result has only one NOT, put it first, since that is how the patterns are coded. */ - if (GET_CODE (op) == IOR || GET_CODE (op) == AND) { rtx in1 = XEXP (op, 0), in2 = XEXP (op, 1); @@ -913,6 +911,13 @@ simplify_unary_operation_1 (enum rtx_code code, enum machine_mode mode, rtx op) return gen_rtx_fmt_ee (GET_CODE (op) == IOR ? AND : IOR, mode, in1, in2); } + + /* (not (bswap x)) -> (bswap (not x)). */ + if (GET_CODE (op) == BSWAP) + { + rtx x = simplify_gen_unary (NOT, mode, XEXP (op, 0), mode); + return simplify_gen_unary (BSWAP, mode, x, mode); + } break; case NEG: @@ -2050,6 +2055,36 @@ simplify_const_unary_operation (enum rtx_code code, enum machine_mode mode, return NULL_RTX; } +/* Subroutine of simplify_binary_operation to simplify a binary operation + CODE that can commute with byte swapping, with result mode MODE and + operating on OP0 and OP1. CODE is currently one of AND, IOR or XOR. + Return zero if no simplification or canonicalization is possible. */ + +static rtx +simplify_byte_swapping_operation (enum rtx_code code, enum machine_mode mode, + rtx op0, rtx op1) +{ + rtx tem; + + /* (op (bswap x) C1)) -> (bswap (op x C2)) with C2 swapped. */ + if (GET_CODE (op0) == BSWAP + && (CONST_INT_P (op1) || CONST_DOUBLE_AS_INT_P (op1))) + { + tem = simplify_gen_binary (code, mode, XEXP (op0, 0), + simplify_gen_unary (BSWAP, mode, op1, mode)); + return simplify_gen_unary (BSWAP, mode, tem, mode); + } + + /* (op (bswap x) (bswap y)) -> (bswap (op x y)). */ + if (GET_CODE (op0) == BSWAP && GET_CODE (op1) == BSWAP) + { + tem = simplify_gen_binary (code, mode, XEXP (op0, 0), XEXP (op1, 0)); + return simplify_gen_unary (BSWAP, mode, tem, mode); + } + + return NULL_RTX; +} + /* Subroutine of simplify_binary_operation to simplify a commutative, associative binary operation CODE with result mode MODE, operating on OP0 and OP1. CODE is currently one of PLUS, MULT, AND, IOR, XOR, @@ -2791,6 +2826,10 @@ simplify_binary_operation_1 (enum rtx_code code, enum machine_mode mode, XEXP (op0, 1)); } + tem = simplify_byte_swapping_operation (code, mode, op0, op1); + if (tem) + return tem; + tem = simplify_associative_operation (code, mode, op0, op1); if (tem) return tem; @@ -2934,6 +2973,10 @@ simplify_binary_operation_1 (enum rtx_code code, enum machine_mode mode, && (reversed = reversed_comparison (op0, mode))) return reversed; + tem = simplify_byte_swapping_operation (code, mode, op0, op1); + if (tem) + return tem; + tem = simplify_associative_operation (code, mode, op0, op1); if (tem) return tem; @@ -3116,6 +3159,10 @@ simplify_binary_operation_1 (enum rtx_code code, enum machine_mode mode, && op1 == XEXP (XEXP (op0, 0), 0)) return simplify_gen_binary (AND, mode, op1, XEXP (op0, 1)); + tem = simplify_byte_swapping_operation (code, mode, op0, op1); + if (tem) + return tem; + tem = simplify_associative_operation (code, mode, op0, op1); if (tem) return tem; @@ -4764,6 +4811,21 @@ simplify_relational_operation_1 (enum rtx_code code, enum machine_mode mode, simplify_gen_binary (XOR, cmp_mode, XEXP (op0, 1), op1)); + /* (eq/ne (bswap x) C1) simplifies to (eq/ne x C2) with C2 swapped. */ + if ((code == EQ || code == NE) + && GET_CODE (op0) == BSWAP + && (CONST_INT_P (op1) || CONST_DOUBLE_AS_INT_P (op1))) + return simplify_gen_relational (code, mode, cmp_mode, XEXP (op0, 0), + simplify_gen_unary (BSWAP, cmp_mode, + op1, cmp_mode)); + + /* (eq/ne (bswap x) (bswap y)) simplifies to (eq/ne x y). */ + if ((code == EQ || code == NE) + && GET_CODE (op0) == BSWAP + && GET_CODE (op1) == BSWAP) + return simplify_gen_relational (code, mode, cmp_mode, + XEXP (op0, 0), XEXP (op1, 0)); + if (op0code == POPCOUNT && op1 == const0_rtx) switch (code) { diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index b1895fb..521873c 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,10 @@ +2013-05-24 Eric Botcazou <ebotcazou@adacore.com> + + * gcc.dg/builtin-bswap-6.c: New test. + * gcc.dg/builtin-bswap-7.c: Likewise. + * gcc.dg/builtin-bswap-8.c: Likewise. + * gcc.dg/builtin-bswap-9.c: Likewise. + 2013-05-23 Christian Bruel <christian.bruel@st.com> PR debug/57351 diff --git a/gcc/testsuite/gcc.dg/builtin-bswap-6.c b/gcc/testsuite/gcc.dg/builtin-bswap-6.c new file mode 100644 index 0000000..544f26e --- /dev/null +++ b/gcc/testsuite/gcc.dg/builtin-bswap-6.c @@ -0,0 +1,38 @@ +/* { dg-do compile { target arm*-*-* alpha*-*-* ia64*-*-* x86_64-*-* s390x-*-* powerpc*-*-* rs6000-*-* } } */ +/* { dg-require-effective-target stdint_types } */ +/* { dg-options "-O -fdump-rtl-combine" } */ + +#include <stdint.h> + +#define BS(X) __builtin_bswap32(X) + +int foo1 (uint32_t a) +{ + if (BS (a) == 0xA0000) + return 1; + return 0; +} + +int foo2 (uint32_t a) +{ + if (BS (a) != 0xA0000) + return 1; + return 0; +} + +int foo3 (uint32_t a, uint32_t b) +{ + if (BS (a) == BS (b)) + return 1; + return 0; +} + +int foo4 (uint32_t a, uint32_t b) +{ + if (BS (a) != BS (b)) + return 1; + return 0; +} + +/* { dg-final { scan-rtl-dump-not "bswapsi" "combine" } } */ +/* { dg-final { cleanup-rtl-dump "combine" } } */ diff --git a/gcc/testsuite/gcc.dg/builtin-bswap-7.c b/gcc/testsuite/gcc.dg/builtin-bswap-7.c new file mode 100644 index 0000000..399b825 --- /dev/null +++ b/gcc/testsuite/gcc.dg/builtin-bswap-7.c @@ -0,0 +1,39 @@ +/* { dg-do compile { target arm*-*-* alpha*-*-* ia64*-*-* x86_64-*-* s390x-*-* powerpc*-*-* rs6000-*-* } } */ +/* { dg-require-effective-target stdint_types } */ +/* { dg-require-effective-target lp64 } */ +/* { dg-options "-O -fdump-rtl-combine" } */ + +#include <stdint.h> + +#define BS(X) __builtin_bswap64(X) + +int foo1 (uint64_t a) +{ + if (BS (a) == 0xA00000000) + return 1; + return 0; +} + +int foo2 (uint64_t a) +{ + if (BS (a) != 0xA00000000) + return 1; + return 0; +} + +int foo3 (uint64_t a, uint64_t b) +{ + if (BS (a) == BS (b)) + return 1; + return 0; +} + +int foo4 (uint64_t a, uint64_t b) +{ + if (BS (a) != BS (b)) + return 1; + return 0; +} + +/* { dg-final { scan-rtl-dump-not "bswapdi" "combine" } } */ +/* { dg-final { cleanup-rtl-dump "combine" } } */ diff --git a/gcc/testsuite/gcc.dg/builtin-bswap-8.c b/gcc/testsuite/gcc.dg/builtin-bswap-8.c new file mode 100644 index 0000000..db75021 --- /dev/null +++ b/gcc/testsuite/gcc.dg/builtin-bswap-8.c @@ -0,0 +1,45 @@ +/* { dg-do compile { target arm*-*-* alpha*-*-* ia64*-*-* x86_64-*-* s390x-*-* powerpc*-*-* rs6000-*-* } } */ +/* { dg-require-effective-target stdint_types } */ +/* { dg-options "-O -fdump-rtl-combine" } */ + +#include <stdint.h> + +#define BS(X) __builtin_bswap32(X) + +uint32_t foo1 (uint32_t a) +{ + return BS (~ BS (a)); +} + +uint32_t foo2 (uint32_t a) +{ + return BS (BS (a) & 0xA0000); +} + +uint32_t foo3 (uint32_t a) +{ + return BS (BS (a) | 0xA0000); +} + +uint32_t foo4 (uint32_t a) +{ + return BS (BS (a) ^ 0xA0000); +} + +uint32_t foo5 (uint32_t a, uint32_t b) +{ + return BS (BS (a) & BS (b)); +} + +uint32_t foo6 (uint32_t a, uint32_t b) +{ + return BS (BS (a) | BS (b)); +} + +uint32_t foo7 (uint32_t a, uint32_t b) +{ + return BS (BS (a) ^ BS (b)); +} + +/* { dg-final { scan-rtl-dump-not "bswapsi" "combine" } } */ +/* { dg-final { cleanup-rtl-dump "combine" } } */ diff --git a/gcc/testsuite/gcc.dg/builtin-bswap-9.c b/gcc/testsuite/gcc.dg/builtin-bswap-9.c new file mode 100644 index 0000000..632dddf --- /dev/null +++ b/gcc/testsuite/gcc.dg/builtin-bswap-9.c @@ -0,0 +1,46 @@ +/* { dg-do compile { target arm*-*-* alpha*-*-* ia64*-*-* x86_64-*-* s390x-*-* powerpc*-*-* rs6000-*-* } } */ +/* { dg-require-effective-target stdint_types } */ +/* { dg-require-effective-target lp64 } */ +/* { dg-options "-O -fdump-rtl-combine" } */ + +#include <stdint.h> + +#define BS(X) __builtin_bswap64(X) + +uint64_t foo1 (uint64_t a) +{ + return BS (~ BS (a)); +} + +uint64_t foo2 (uint64_t a) +{ + return BS (BS (a) & 0xA00000000); +} + +uint64_t foo3 (uint64_t a) +{ + return BS (BS (a) | 0xA00000000); +} + +uint64_t foo4 (uint64_t a) +{ + return BS (BS (a) ^ 0xA00000000); +} + +uint64_t foo5 (uint64_t a, uint64_t b) +{ + return BS (BS (a) & BS (b)); +} + +uint64_t foo6 (uint64_t a, uint64_t b) +{ + return BS (BS (a) | BS (b)); +} + +uint64_t foo7 (uint64_t a, uint64_t b) +{ + return BS (BS (a) ^ BS (b)); +} + +/* { dg-final { scan-rtl-dump-not "bswapdi" "combine" } } */ +/* { dg-final { cleanup-rtl-dump "combine" } } */ |