This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH, i386]: Fix PR target/30970, take 2
- From: Uros Bizjak <ubizjak at gmail dot com>
- To: GCC Patches <gcc-patches at gcc dot gnu dot org>
- Cc: Richard Henderson <rth at redhat dot com>, Ian Lance Taylor <iant at google dot com>
- Date: Tue, 27 Feb 2007 14:05:07 +0100
- Subject: [PATCH, i386]: Fix PR target/30970, take 2
- Dkim-signature: a=rsa-sha1; c=relaxed/relaxed; d=gmail.com; s=beta; h=domainkey-signature:received:received:message-id:date:from:user-agent:mime-version:to:cc:subject:content-type; b=kE3ghVb9uBTE90t4lRjmQBZMwOpRava1sYmJi+orgIlq5NLppiMqldeyqwjFm3MgFBd3UmfmEV4EKqfmY6sjebkgo/ZuTpOsrfTe5Cbtx8JtkLG0pUufQPjNwxBYuPxpkWW0GVF6QBSphBWwAAVL8bQn6i0mNm3rhT94Xrd9xe4=
Hello!
The addition to this patch is corrected MODES_TIEABLE_P functionality
for i386 targets. The problem is, that lower-subreg pass checks
MODES_TIEABLE_P if the XMM register can be splitted into word_mode
(DImode) _without_copying_.
Current ix86_modes_tieable_p() allows splitting of all SSE modes into
DImode word_mode. This causes following testsuite failures
FAIL: gcc.target/i386/sse-1.c scan-assembler-not movaps
FAIL: gcc.target/i386/vecinit-1.c scan-assembler-not movaps
These failures (i.e. vecinit-1.c):
vector float f1(void) { return (vector float){ a, 0.0, 0.0, 0.0}; }
are causes because gcc compiles above example for x86_64 target into
following horror:
f1:
.LFB2:
movss a(%rip), %xmm0
movaps %xmm0, -24(%rsp)
movq -24(%rsp), %rax
movq -16(%rsp), %rdx
movq %rax, -40(%rsp)
movq %rdx, -32(%rsp)
movaps -40(%rsp), %xmm0
ret
With attached patch, the code is "much" better:
f1:
.LFB2:
movss a(%rip), %xmm0
ret
The solution is to allow tying only modes, where both of them are 128bit
for SSE registers and when both modes are 64bit for MMX registers. This
effectively suppresses compiler creativity in the area of various
strange move sequences.
2007-02-27 Uros Bizjak <ubizjak@gmail.com>
PR target/30970
* config/i386/sse.md (*mov<mode>_internal, *movv4sf_internal,
*movv2df_internal): Enable pattern only for valid operand
combinations.
* config/i386/i386.c (ix86_modes_tieable_p): For SSE registers,
tie only 128bit modes. For MMX registers, tie only 64bit modes.
testsuite/ChangeLog:
2007-02-27 Uros Bizjak <ubizjak@gmail.com>
PR target/30970
* gcc.target/i386/gfortran.dg/pr30970.c: New test.
Patch was bootstrapped on x86_64-pc-linux-gnu and regression tested for
all default languages.
Uros.
Index: testsuite/gcc.target/i386/pr30970.c
===================================================================
--- testsuite/gcc.target/i386/pr30970.c (revision 0)
+++ testsuite/gcc.target/i386/pr30970.c (revision 0)
@@ -0,0 +1,15 @@
+/* { dg-do compile { target i?86-*-* x86_64-*-* } }
+/* { dg-options "-msse2 -O2 -ftree-vectorize" } */
+
+#define N 256
+int b[N];
+
+void test()
+{
+ int i;
+
+ for (i = 0; i < N; i++)
+ b[i] = 0;
+}
+
+/* { dg-final { scan-assembler-times "pxor" 1 } } */
Index: config/i386/sse.md
===================================================================
--- config/i386/sse.md (revision 122336)
+++ config/i386/sse.md (working copy)
@@ -60,7 +60,9 @@
(define_insn "*mov<mode>_internal"
[(set (match_operand:SSEMODEI 0 "nonimmediate_operand" "=x,x ,m")
(match_operand:SSEMODEI 1 "nonimmediate_or_sse_const_operand" "C ,xm,x"))]
- "TARGET_SSE && !(MEM_P (operands[0]) && MEM_P (operands[1]))"
+ "TARGET_SSE
+ && !(MEM_P (operands[0])
+ && (MEM_P (operands[1]) || standard_sse_constant_p (operands[1]) > 0))"
{
switch (which_alternative)
{
@@ -140,7 +142,9 @@
(define_insn "*movv4sf_internal"
[(set (match_operand:V4SF 0 "nonimmediate_operand" "=x,x,m")
(match_operand:V4SF 1 "nonimmediate_or_sse_const_operand" "C,xm,x"))]
- "TARGET_SSE"
+ "TARGET_SSE
+ && !(MEM_P (operands[0])
+ && (MEM_P (operands[1]) || standard_sse_constant_p (operands[1]) > 0))"
{
switch (which_alternative)
{
@@ -182,7 +186,9 @@
(define_insn "*movv2df_internal"
[(set (match_operand:V2DF 0 "nonimmediate_operand" "=x,x,m")
(match_operand:V2DF 1 "nonimmediate_or_sse_const_operand" "C,xm,x"))]
- "TARGET_SSE && !(MEM_P (operands[0]) && MEM_P (operands[1]))"
+ "TARGET_SSE
+ && !(MEM_P (operands[0])
+ && (MEM_P (operands[1]) || standard_sse_constant_p (operands[1]) > 0))"
{
switch (which_alternative)
{
Index: config/i386/i386.c
===================================================================
--- config/i386/i386.c (revision 122336)
+++ config/i386/i386.c (working copy)
@@ -18783,15 +18783,17 @@
/* If MODE2 is only appropriate for an SSE register, then tie with
any other mode acceptable to SSE registers. */
- if (GET_MODE_SIZE (mode2) >= 8
+ if (GET_MODE_SIZE (mode2) == 16
&& ix86_hard_regno_mode_ok (FIRST_SSE_REG, mode2))
- return ix86_hard_regno_mode_ok (FIRST_SSE_REG, mode1);
+ return (GET_MODE_SIZE (mode1) == 16
+ && ix86_hard_regno_mode_ok (FIRST_SSE_REG, mode1));
- /* If MODE2 is appropriate for an MMX (or SSE) register, then tie
+ /* If MODE2 is appropriate for an MMX register, then tie
with any other mode acceptable to MMX registers. */
if (GET_MODE_SIZE (mode2) == 8
&& ix86_hard_regno_mode_ok (FIRST_MMX_REG, mode2))
- return ix86_hard_regno_mode_ok (FIRST_MMX_REG, mode1);
+ return (GET_MODE_SIZE (mode2) == 8
+ && ix86_hard_regno_mode_ok (FIRST_MMX_REG, mode1));
return false;
}