From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 10105 invoked by alias); 15 Jun 2011 09:54:35 -0000 Received: (qmail 10091 invoked by uid 22791); 15 Jun 2011 09:54:32 -0000 X-SWARE-Spam-Status: No, hits=-6.4 required=5.0 tests=AWL,BAYES_00,RCVD_IN_DNSWL_HI,SPF_HELO_PASS,TW_MX,TW_VP,T_RP_MATCHES_RCVD X-Spam-Check-By: sourceware.org Received: from mx1.redhat.com (HELO mx1.redhat.com) (209.132.183.28) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Wed, 15 Jun 2011 09:54:11 +0000 Received: from int-mx12.intmail.prod.int.phx2.redhat.com (int-mx12.intmail.prod.int.phx2.redhat.com [10.5.11.25]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id p5F9s94w020437 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Wed, 15 Jun 2011 05:54:09 -0400 Received: from tyan-ft48-01.lab.bos.redhat.com (tyan-ft48-01.lab.bos.redhat.com [10.16.42.4]) by int-mx12.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id p5F9s8dZ016910 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO); Wed, 15 Jun 2011 05:54:08 -0400 Received: from tyan-ft48-01.lab.bos.redhat.com (localhost.localdomain [127.0.0.1]) by tyan-ft48-01.lab.bos.redhat.com (8.14.4/8.14.4) with ESMTP id p5F9s7Cj022232; Wed, 15 Jun 2011 11:54:07 +0200 Received: (from jakub@localhost) by tyan-ft48-01.lab.bos.redhat.com (8.14.4/8.14.4/Submit) id p5F9s7eq022230; Wed, 15 Jun 2011 11:54:07 +0200 Date: Wed, 15 Jun 2011 10:26:00 -0000 From: Jakub Jelinek To: Uros Bizjak , Sebastian Pop , "Fang, Changpeng" Cc: gcc-patches@gcc.gnu.org Subject: [PATCH] Fix ICEs with -mxop __builtin_ia32_vpermil2p[sd]{,256} and __builtin_ia32_vprot[bwdq]i intrinsics (PR target/49411) Message-ID: <20110615095406.GI17079@tyan-ft48-01.lab.bos.redhat.com> Reply-To: Jakub Jelinek MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline User-Agent: Mutt/1.5.21 (2010-09-15) X-IsSubscribed: yes Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org X-SW-Source: 2011-06/txt/msg01141.txt.bz2 Hi! All of these _mm{,256}_permute2_p[sd] and _mm_roti_epi{8,16,32,64} intrinsics ICE if the last argument is constant integer, but not in the expected range. I could only find MSFT documentation for these intrinsics, where for *permute2* it says that the last argument must be 0, 1, 2 or 3, for *roti* it says that the last argument is integer rotation count, preferrably constant and that if count is negative, it performs right rotation instead of left rotation. This patch adjusts the builtins to match that, if we want to instead e.g. always mandate _mm_roti_epi* last argument is constant integer, or constant integer in the range -N+1 .. N-1 where N is the number after _mm_roti_epi, or in the range 0 .. N-1, it can be easily adjusted. Regtested on x86_64-linux {-m32,-m64}, unfortunately on a SandyBridge box, so I couldn't verify if xop-rotate[12]-int.c actually succeeds on xop capable HW. 2011-06-15 Jakub Jelinek PR target/49411 * config/i386/i386.c (ix86_expand_multi_arg_builtins): If last_arg_constant and last argument doesn't match its predicate, for xop_vpermil23 error out and for xop_rotl3 if it is CONST_INT, mask it, otherwise expand using rotl3. * gcc.target/i386/xop-vpermil2px-1.c: New test. * gcc.target/i386/xop-vpermil2px-2.c: New test. * gcc.target/i386/xop-rotate1-int.c: New test. * gcc.target/i386/xop-rotate2-int.c: New test. --- gcc/config/i386/i386.c.jj 2011-06-09 16:56:56.000000000 +0200 +++ gcc/config/i386/i386.c 2011-06-15 11:17:12.000000000 +0200 @@ -26149,16 +26149,66 @@ ix86_expand_multi_arg_builtin (enum insn int adjust = (comparison_p) ? 1 : 0; enum machine_mode mode = insn_data[icode].operand[i+adjust+1].mode; - if (last_arg_constant && i == nargs-1) + if (last_arg_constant && i == nargs - 1) { - if (!CONST_INT_P (op)) + if (!insn_data[icode].operand[i + 1].predicate (op, mode)) { - error ("last argument must be an immediate"); - return gen_reg_rtx (tmode); + enum insn_code new_icode = icode; + switch (icode) + { + case CODE_FOR_xop_vpermil2v2df3: + case CODE_FOR_xop_vpermil2v4sf3: + case CODE_FOR_xop_vpermil2v4df3: + case CODE_FOR_xop_vpermil2v8sf3: + if (!CONST_INT_P (op)) + { + error ("last argument must be an immediate"); + return gen_reg_rtx (tmode); + } + error ("last argument must be in the range 0 .. 3"); + return gen_reg_rtx (tmode); + case CODE_FOR_xop_rotlv2di3: + new_icode = CODE_FOR_rotlv2di3; + goto xop_rotl; + case CODE_FOR_xop_rotlv4si3: + new_icode = CODE_FOR_rotlv4si3; + goto xop_rotl; + case CODE_FOR_xop_rotlv8hi3: + new_icode = CODE_FOR_rotlv8hi3; + goto xop_rotl; + case CODE_FOR_xop_rotlv16qi3: + new_icode = CODE_FOR_rotlv16qi3; + xop_rotl: + if (CONST_INT_P (op)) + { + int mask = GET_MODE_BITSIZE (GET_MODE_INNER (tmode)) - 1; + op = GEN_INT (INTVAL (op) & mask); + gcc_checking_assert + (insn_data[icode].operand[i + 1].predicate (op, mode)); + } + else + { + gcc_checking_assert + (nargs == 2 + && insn_data[new_icode].operand[0].mode == tmode + && insn_data[new_icode].operand[1].mode == tmode + && insn_data[new_icode].operand[2].mode == mode + && insn_data[new_icode].operand[0].predicate + == insn_data[icode].operand[0].predicate + && insn_data[new_icode].operand[1].predicate + == insn_data[icode].operand[1].predicate); + icode = new_icode; + goto non_constant; + } + break; + default: + gcc_unreachable (); + } } } else { + non_constant: if (VECTOR_MODE_P (mode)) op = safe_vector_operand (op, mode); --- gcc/testsuite/gcc.target/i386/xop-vpermil2px-1.c.jj 2011-06-15 10:18:29.000000000 +0200 +++ gcc/testsuite/gcc.target/i386/xop-vpermil2px-1.c 2011-06-15 10:41:13.000000000 +0200 @@ -0,0 +1,25 @@ +/* PR target/49411 */ +/* { dg-do compile } */ +/* { dg-options "-O0 -mxop" } */ + +#include + +__m128d a1, a2, a3; +__m256d b1, b2, b3; +__m128 c1, c2, c3; +__m256 d1, d2, d3; +__m128i s; +__m256i t; + +void +foo (int i) +{ + a1 = _mm_permute2_pd (a2, a3, s, 3); + b1 = _mm256_permute2_pd (b2, b3, t, 3); + c1 = _mm_permute2_ps (c2, c3, s, 3); + d1 = _mm256_permute2_ps (d2, d3, t, 3); + a1 = _mm_permute2_pd (a2, a3, s, 17); /* { dg-error "last argument must be in the range 0 .. 3" } */ + b1 = _mm256_permute2_pd (b2, b3, t, 17); /* { dg-error "last argument must be in the range 0 .. 3" } */ + c1 = _mm_permute2_ps (c2, c3, s, 17); /* { dg-error "last argument must be in the range 0 .. 3" } */ + d1 = _mm256_permute2_ps (d2, d3, t, 17); /* { dg-error "last argument must be in the range 0 .. 3" } */ +} --- gcc/testsuite/gcc.target/i386/xop-vpermil2px-2.c.jj 2011-06-15 10:39:36.000000000 +0200 +++ gcc/testsuite/gcc.target/i386/xop-vpermil2px-2.c 2011-06-15 10:39:44.000000000 +0200 @@ -0,0 +1,21 @@ +/* PR target/49411 */ +/* { dg-do compile } */ +/* { dg-options "-O0 -mxop" } */ + +#include + +__m128d a1, a2, a3; +__m256d b1, b2, b3; +__m128 c1, c2, c3; +__m256 d1, d2, d3; +__m128i s; +__m256i t; + +void +foo (int i) +{ + a1 = _mm_permute2_pd (a2, a3, s, i); /* { dg-error "last argument must be an immediate" } */ + b1 = _mm256_permute2_pd (b2, b3, t, i); /* { dg-error "last argument must be an immediate" } */ + c1 = _mm_permute2_ps (c2, c3, s, i); /* { dg-error "last argument must be an immediate" } */ + d1 = _mm256_permute2_ps (d2, d3, t, i); /* { dg-error "last argument must be an immediate" } */ +} --- gcc/testsuite/gcc.target/i386/xop-rotate1-int.c.jj 2011-06-15 10:47:29.000000000 +0200 +++ gcc/testsuite/gcc.target/i386/xop-rotate1-int.c 2011-06-15 11:25:25.000000000 +0200 @@ -0,0 +1,63 @@ +/* PR target/49411 */ +/* { dg-do run } */ +/* { dg-require-effective-target xop } */ +/* { dg-options "-O2 -mxop" } */ + +#include "xop-check.h" + +#include + +extern void abort (void); + +union +{ + __m128i v; + unsigned char c[16]; + unsigned short s[8]; + unsigned int i[4]; + unsigned long long l[2]; +} a, b, c, d; + +#define TEST1(F, N, S, SS) \ +do { \ + for (i = 0; i < sizeof (a.F) / sizeof (a.F[0]); i++) \ + a.F[i] = i * 17; \ + s = _mm_set1_epi##SS (N); \ + b.v = _mm_roti_epi##S (a.v, N); \ + c.v = _mm_rot_epi##S (a.v, s); \ + for (i = 0; i < sizeof (a.F) / sizeof (a.F[0]); i++) \ + { \ + int mask = __CHAR_BIT__ * sizeof (a.F[i]) - 1; \ + d.F[i] = a.F[i] << (N & mask); \ + if (N & mask) \ + d.F[i] |= a.F[i] >> (mask + 1 - (N & mask)); \ + if (b.F[i] != c.F[i] || b.F[i] != d.F[i]) \ + abort (); \ + } \ +} while (0) +#define TEST(N) \ + TEST1 (c, N, 8, 8); \ + TEST1 (s, N, 16, 16); \ + TEST1 (i, N, 32, 32); \ + TEST1 (l, N, 64, 64x) + +volatile int n; + +static void +xop_test (void) +{ + unsigned int i; + __m128i s; + +#ifndef NON_CONST + TEST (5); + TEST (-5); + TEST (0); + TEST (31); +#else + n = 5; TEST (n); + n = -5; TEST (n); + n = 0; TEST (n); + n = 31; TEST (n); +#endif +} --- gcc/testsuite/gcc.target/i386/xop-rotate2-int.c.jj 2011-06-15 11:25:42.000000000 +0200 +++ gcc/testsuite/gcc.target/i386/xop-rotate2-int.c 2011-06-15 11:26:03.000000000 +0200 @@ -0,0 +1,7 @@ +/* PR target/49411 */ +/* { dg-do run } */ +/* { dg-require-effective-target xop } */ +/* { dg-options "-O2 -mxop" } */ + +#define NON_CONST 1 +#include "xop-rotate1-int.c" Jakub