This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH, i386]: Fix PR target/30970, take 2


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;
 }


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]