aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIlya Enkovich <enkovich.gnu@gmail.com>2016-01-15 11:04:25 +0000
committerIlya Enkovich <ienkovich@gcc.gnu.org>2016-01-15 11:04:25 +0000
commit94f373957092bf7c3ed8a83d00e5c4f21e7ffd35 (patch)
tree4c4a300804c52a464ec6172b32753fad35b86a8b
parent0f6176e67c84ffe19978aaad568d5e9996890fb3 (diff)
downloadgcc-94f373957092bf7c3ed8a83d00e5c4f21e7ffd35.zip
gcc-94f373957092bf7c3ed8a83d00e5c4f21e7ffd35.tar.gz
gcc-94f373957092bf7c3ed8a83d00e5c4f21e7ffd35.tar.bz2
i386.c (ix86_expand_branch): Don't split DI mode xor instruction to SI mode.
gcc/ * config/i386/i386.c (ix86_expand_branch): Don't split DI mode xor instruction to SI mode. gcc/testsuite/ * gcc.target/i386/pr65105-5.c: New test. From-SVN: r232413
-rw-r--r--gcc/ChangeLog5
-rw-r--r--gcc/config/i386/i386.c13
-rw-r--r--gcc/testsuite/ChangeLog4
-rw-r--r--gcc/testsuite/gcc.target/i386/pr65105-5.c22
4 files changed, 44 insertions, 0 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index ac14805..bd05295 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,8 @@
+2016-01-15 Ilya Enkovich <enkovich.gnu@gmail.com>
+
+ * config/i386/i386.c (ix86_expand_branch): Don't split
+ DI mode xor instruction to SI mode.
+
2016-01-15 Jan Hubicka <hubicka@ucw.cz>
PR ipa/68148
diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
index 996913b..92f3a41 100644
--- a/gcc/config/i386/i386.c
+++ b/gcc/config/i386/i386.c
@@ -21699,6 +21699,19 @@ ix86_expand_branch (enum rtx_code code, rtx op0, rtx op1, rtx label)
case DImode:
if (TARGET_64BIT)
goto simple;
+ /* For 32-bit target DI comparison may be performed on
+ SSE registers. To allow this we should avoid split
+ to SI mode which is achieved by doing xor in DI mode
+ and then comparing with zero (which is recognized by
+ STV pass). We don't compare using xor when optimizing
+ for size. */
+ if (!optimize_insn_for_size_p ()
+ && TARGET_STV
+ && (code == EQ || code == NE))
+ {
+ op0 = force_reg (mode, gen_rtx_XOR (mode, op0, op1));
+ op1 = const0_rtx;
+ }
case TImode:
/* Expand DImode branch into multiple compare+branch. */
{
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index d949b83..456edf2 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,7 @@
+2016-01-15 Ilya Enkovich <enkovich.gnu@gmail.com>
+
+ * gcc.target/i386/pr65105-5.c: New test.
+
2016-01-15 Jan Hubicka <hubicka@ucw.cz>
* gcc.c-torture/execute/alias-4.c: New testcase.
diff --git a/gcc/testsuite/gcc.target/i386/pr65105-5.c b/gcc/testsuite/gcc.target/i386/pr65105-5.c
new file mode 100644
index 0000000..5818c1c
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr65105-5.c
@@ -0,0 +1,22 @@
+/* PR target/pr65105 */
+/* { dg-do compile { target { ia32 } } } */
+/* { dg-options "-O2 -march=core-avx2" } */
+/* { dg-final { scan-assembler "pand" } } */
+/* { dg-final { scan-assembler "pxor" } } */
+/* { dg-final { scan-assembler "ptest" } } */
+
+struct S1
+{
+ unsigned long long a;
+ unsigned long long b;
+};
+
+void
+test (int p1, unsigned long long p2, int p3, struct S1 *p4)
+{
+ int i;
+
+ for (i = 0; i < p1; i++)
+ if ((p4[i].a & p2) != p2)
+ p4[i].a ^= (1ULL << p3);
+}