aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorEric Botcazou <ebotcazou@adacore.com>2013-05-24 06:46:11 +0000
committerEric Botcazou <ebotcazou@gcc.gnu.org>2013-05-24 06:46:11 +0000
commitb17c024fa920895a860c675836e98fc49c01e9ce (patch)
tree76784853bcad116d42b13a68d164909e4c2f1ad4 /gcc
parentd0c70325c9ee2767b87cf7f104ab34ba8e316a4e (diff)
downloadgcc-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/ChangeLog8
-rw-r--r--gcc/simplify-rtx.c66
-rw-r--r--gcc/testsuite/ChangeLog7
-rw-r--r--gcc/testsuite/gcc.dg/builtin-bswap-6.c38
-rw-r--r--gcc/testsuite/gcc.dg/builtin-bswap-7.c39
-rw-r--r--gcc/testsuite/gcc.dg/builtin-bswap-8.c45
-rw-r--r--gcc/testsuite/gcc.dg/builtin-bswap-9.c46
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" } } */