diff mbox

[i386] : Fix PR 61423, incorrect conversion from unsigned int to floating point

Message ID CAFULd4bk6UL4Qwt=GKrbosQC-p5EoEYu8JND_P0SNnQgx=ALXg@mail.gmail.com
State New
Headers show

Commit Message

Uros Bizjak June 6, 2014, 5:52 p.m. UTC
Hello!

Attached patch fixes PR 61423. The problem was that splitters omitted
apparently necessary zero extension, and left garbage in the highpart
of the register.

2014-06-06  Uros Bizjak  <ubizjak@gmail.com>

    PR target/61423
    * config/i386/i386.md (*floatunssi<mode>2_i387_with_xmm): New
    define_insn_and_split pattern, merged from *floatunssi<mode>2_1
    and corresponding splitters.  Zero extend general register
    or memory input operand to XMM temporary.  Enable for
    TARGET_SSE2 and TARGET_INTER_UNIT_MOVES_TO_VEC only.
    (floatunssi<mode>2): Update expander predicate.

testsuite/ChangeLog:

2014-06-06  Uros Bizjak  <ubizjak@gmail.com>

    PR target/61423
    * gcc.target/i386/pr61423.c: New test.

The patch was bootstrapped and regression tested on
x86_64-pc-linux-gnu {,-m32} and committed to mainline SVN.

Please note that the patch breaks bootstrap when gcc is configured
with "--with-arch=core-avx-i --with-cpu=core-avx-i" due to an
unrelated problem in REE pass. The failing preprocessed source from
the libgcc is attached to the PR.

Uros.
diff mbox

Patch

Index: config/i386/i386.md
===================================================================
--- config/i386/i386.md	(revision 211316)
+++ config/i386/i386.md	(working copy)
@@ -4943,66 +4943,37 @@ 
 
 ;; Avoid store forwarding (partial memory) stall penalty by extending
 ;; SImode value to DImode through XMM register instead of pushing two
-;; SImode values to stack. Note that even !TARGET_INTER_UNIT_MOVES_TO_VEC
-;; targets benefit from this optimization. Also note that fild
-;; loads from memory only.
+;; SImode values to stack. Also note that fild loads from memory only.
 
-(define_insn "*floatunssi<mode>2_1"
-  [(set (match_operand:X87MODEF 0 "register_operand" "=f,f")
+(define_insn_and_split "*floatunssi<mode>2_i387_with_xmm"
+  [(set (match_operand:X87MODEF 0 "register_operand" "=f")
 	(unsigned_float:X87MODEF
-	  (match_operand:SI 1 "nonimmediate_operand" "x,m")))
-   (clobber (match_operand:DI 2 "memory_operand" "=m,m"))
-   (clobber (match_scratch:SI 3 "=X,x"))]
+	  (match_operand:SI 1 "nonimmediate_operand" "rm")))
+   (clobber (match_scratch:DI 3 "=x"))
+   (clobber (match_operand:DI 2 "memory_operand" "=m"))]
   "!TARGET_64BIT
    && TARGET_80387 && X87_ENABLE_FLOAT (<X87MODEF:MODE>mode, DImode)
-   && TARGET_SSE"
+   && TARGET_SSE2 && TARGET_INTER_UNIT_MOVES_TO_VEC"
   "#"
+  "&& reload_completed"
+  [(set (match_dup 3) (zero_extend:DI (match_dup 1)))
+   (set (match_dup 2) (match_dup 3))
+   (set (match_dup 0)
+	(float:X87MODEF (match_dup 2)))]
+  ""
   [(set_attr "type" "multi")
    (set_attr "mode" "<MODE>")])
 
-(define_split
-  [(set (match_operand:X87MODEF 0 "register_operand")
-	(unsigned_float:X87MODEF
-	  (match_operand:SI 1 "register_operand")))
-   (clobber (match_operand:DI 2 "memory_operand"))
-   (clobber (match_scratch:SI 3))]
-  "!TARGET_64BIT
-   && TARGET_80387 && X87_ENABLE_FLOAT (<X87MODEF:MODE>mode, DImode)
-   && TARGET_SSE
-   && reload_completed"
-  [(set (match_dup 2) (match_dup 1))
-   (set (match_dup 0)
-	(float:X87MODEF (match_dup 2)))]
-  "operands[1] = simplify_gen_subreg (DImode, operands[1], SImode, 0);")
-
-(define_split
-  [(set (match_operand:X87MODEF 0 "register_operand")
-	(unsigned_float:X87MODEF
-	  (match_operand:SI 1 "memory_operand")))
-   (clobber (match_operand:DI 2 "memory_operand"))
-   (clobber (match_scratch:SI 3))]
-  "!TARGET_64BIT
-   && TARGET_80387 && X87_ENABLE_FLOAT (<X87MODEF:MODE>mode, DImode)
-   && TARGET_SSE
-   && reload_completed"
-  [(set (match_dup 2) (match_dup 3))
-   (set (match_dup 0)
-	(float:X87MODEF (match_dup 2)))]
-{
-  emit_move_insn (operands[3], operands[1]);
-  operands[3] = simplify_gen_subreg (DImode, operands[3], SImode, 0);
-})
-
 (define_expand "floatunssi<mode>2"
   [(parallel
      [(set (match_operand:X87MODEF 0 "register_operand")
 	   (unsigned_float:X87MODEF
 	     (match_operand:SI 1 "nonimmediate_operand")))
-      (clobber (match_dup 2))
-      (clobber (match_scratch:SI 3))])]
+      (clobber (match_scratch:DI 3))
+      (clobber (match_dup 2))])]
   "!TARGET_64BIT
    && ((TARGET_80387 && X87_ENABLE_FLOAT (<X87MODEF:MODE>mode, DImode)
-	&& TARGET_SSE)
+	&& TARGET_SSE2 && TARGET_INTER_UNIT_MOVES_TO_VEC)
        || (SSE_FLOAT_MODE_P (<MODE>mode) && TARGET_SSE_MATH))"
 {
   if (SSE_FLOAT_MODE_P (<MODE>mode) && TARGET_SSE_MATH)
Index: testsuite/gcc.target/i386/pr61423.c
===================================================================
--- testsuite/gcc.target/i386/pr61423.c	(revision 0)
+++ testsuite/gcc.target/i386/pr61423.c	(working copy)
@@ -0,0 +1,38 @@ 
+/* PR target/61423 */
+/* { dg-do run { target ia32 } } */
+/* { dg-options "-O1 -ftree-vectorize -msse2 -mfpmath=387 -mtune=core2" } */
+
+#define N 1024
+static unsigned int A[N];
+
+double
+__attribute__((noinline))
+func (void)
+{
+  unsigned int sum = 0;
+  unsigned i;
+  double t;
+
+  for (i = 0; i < N; i++)
+    sum += A[i];
+
+  t = sum;
+  return t;
+}
+
+int
+main ()
+{
+  unsigned i;
+  double d;
+
+  for(i = 0; i < N; i++)
+    A[i] = 1;
+
+  d = func();
+
+  if (d != 1024.0)
+    __builtin_abort ();
+
+  return 0;
+}