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]

[3.4 only?] PR target/18582: ICE on SSE load builtins


PR target/18582 (a 3.4-only regression) is about an ICE on:

    xs[0] = __builtin_ia32_loadupd (x2);

The problem is that the builtin expander creates a MEM->MEM "load",
the source being (mem x2) and the destination being (mem xs).
The MOVU define_insn condition only allows one operand to be
a MEM and so the insn fails to match.

The SSE(1) patterns avoid this by using separate define_expands
and define_insns.  However, rather than do that for all other
affected insns, I thought it would be tidier (and safer) to change
the builtin expansion code instead.

As far as I can tell, (a) all affected builtins go through
ix86_expand_unop_builtin() with "do_load" set to 1 and (b)
no pattern that calls i_x_u_b() with "do_load" set to 1
allows both the source and destination to be MEMs.
The patch therefore forces ix86_expand_unop_builtin() to
use a temporary target if the original target was a MEM
and if "do_load" is true.

The attached testcase is supposed to test all unary builtins that are
expanded with "do_load" set to true.  Many of these builtins were removed
in 4.0 and 4.1, and those that remain work as-is.  4.x compilers don't
pass a MEM target any more.

Bootstrapped & regression tested on i686-pc-linux-gnu.  OK for 3.4?

If so, would the patch be useful for mainline, despite the lack of a
failing testcase?  Or is the target guaranteed to be a register now?

Richard


	PR target/18582
	* config/i386/i386.c (ix86_expand_unop_builtin): Force the target
	to be a register if do_load is true.

testsuite/
	PR target/18582
	* testsuite/gcc.dg/torture/pr18582-1.c: New test.

Index: config/i386/i386.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/i386/i386.c,v
retrieving revision 1.635.2.21
diff -c -p -F^\([(a-zA-Z0-9_]\|#define\) -r1.635.2.21 i386.c
*** config/i386/i386.c 9 Jul 2005 08:54:18 -0000 1.635.2.21
--- config/i386/i386.c 2 Aug 2005 15:43:41 -0000
*************** ix86_expand_unop_builtin (enum insn_code
*** 13956,13961 ****
--- 13956,13962 ----
  
    if (! target
        || GET_MODE (target) != tmode
+       || (do_load && GET_CODE (target) == MEM)
        || ! (*insn_data[icode].operand[0].predicate) (target, tmode))
      target = gen_reg_rtx (tmode);
    if (do_load)
diff -c /dev/null testsuite/gcc.dg/torture/pr18582-1.c
*** /dev/null	2005-06-16 22:49:09.000000000 +0100
--- testsuite/gcc.dg/torture/pr18582-1.c	2005-08-02 16:39:41.000000000 +0100
***************
*** 0 ****
--- 1,37 ----
+ /* { dg-do compile { target i?86-*-* } } */
+ /* { dg-options "-msse3" } */
+ typedef char v16qi __attribute__((vector_size (16)));
+ typedef int v4si __attribute__((vector_size (16)));
+ typedef float v4sf __attribute__((vector_size (16)));
+ typedef double v2df __attribute__((vector_size (16)));
+ 
+ extern char ca[];
+ extern int ia[];
+ extern float fa[];
+ extern double da[];
+ 
+ extern v16qi cva[];
+ extern v4si iva[];
+ extern v4sf fva[];
+ extern v2df dva[];
+ 
+ void
+ foo (void)
+ {
+   cva[0] = __builtin_ia32_loaddqa (ca);
+   cva[0] = __builtin_ia32_loaddqu (ca);
+   cva[0] = __builtin_ia32_lddqu (ca);
+ 
+   iva[0] = __builtin_ia32_loadd (ia);
+ 
+   fva[0] = __builtin_ia32_loadaps (fa);
+   fva[0] = __builtin_ia32_loadups (fa);
+   fva[0] = __builtin_ia32_loadss (fa);
+ 
+   dva[0] = __builtin_ia32_loadapd (da);
+   dva[0] = __builtin_ia32_loadupd (da);
+   dva[0] = __builtin_ia32_loadsd (da);
+   dva[0] = __builtin_ia32_loadpd1 (da);
+   dva[0] = __builtin_ia32_loadrpd (da);
+   dva[0] = __builtin_ia32_loadddup (da);
+ }


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