This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[3.4 only?] PR target/18582: ICE on SSE load builtins
- From: Richard Sandiford <richard at codesourcery dot com>
- To: gcc-patches at gcc dot gnu dot org
- Date: Tue, 02 Aug 2005 18:09:33 +0100
- Subject: [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);
+ }