From patchwork Fri Sep 14 13:59:13 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Marc Glisse X-Patchwork-Id: 183939 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) by ozlabs.org (Postfix) with SMTP id 98E1A2C0096 for ; Fri, 14 Sep 2012 23:59:47 +1000 (EST) Comment: DKIM? See http://www.dkim.org DKIM-Signature: v=1; a=rsa-sha1; c=relaxed/relaxed; d=gcc.gnu.org; s=default; x=1348235987; h=Comment: DomainKey-Signature:Received:Received:Received:Received:Received: Date:From:To:cc:Subject:In-Reply-To:Message-ID:References: User-Agent:MIME-Version:Content-Type:Mailing-List:Precedence: List-Id:List-Unsubscribe:List-Archive:List-Post:List-Help:Sender: Delivered-To; bh=8cmgFysXZreNvQp6F3Xdscsxqug=; b=iiwhjBWfScYeleW PqTlChBpH8VnSduFsPGn8vWcD7u+y7ZlExbjpVW96vFHLisuMkiT/VkY16J+6MrZ c3+0Rk54Jhx+tXksmY3n1p94VzzqMyUAIVTLu47603+DPNF0hRJOxlMKgDCDeCNL lt+H3LZDPpxhcBEGqULlDKix0Jso= Comment: DomainKeys? See http://antispam.yahoo.com/domainkeys DomainKey-Signature: a=rsa-sha1; q=dns; c=nofws; s=default; d=gcc.gnu.org; h=Received:Received:X-SWARE-Spam-Status:X-Spam-Check-By:Received:Received:Received:Date:From:To:cc:Subject:In-Reply-To:Message-ID:References:User-Agent:MIME-Version:Content-Type:Mailing-List:Precedence:List-Id:List-Unsubscribe:List-Archive:List-Post:List-Help:Sender:Delivered-To; b=bDoPUDi+yAaZ5+V2PVjSDOVHqwWWlxwrf36F/8K3Z2ei9OOQ1bpwCx25+es7rr 4esxr24AQnSvcS+Qgcv1ubPrTuJM+9dQgJhUyhpHeJ0H8w+8AJ94ycwZSJuErE1b /sm38SLjw3bACe3EiLoTW40G0FgR3jnpPZoiPem9XvloM=; Received: (qmail 27968 invoked by alias); 14 Sep 2012 13:59:39 -0000 Received: (qmail 27944 invoked by uid 22791); 14 Sep 2012 13:59:34 -0000 X-SWARE-Spam-Status: No, hits=-7.9 required=5.0 tests=AWL, BAYES_00, KHOP_RCVD_UNTRUST, KHOP_THREADED, RCVD_IN_DNSWL_HI, RCVD_IN_HOSTKARMA_W, RP_MATCHES_RCVD, TW_VF X-Spam-Check-By: sourceware.org Received: from mail1-relais-roc.national.inria.fr (HELO mail1-relais-roc.national.inria.fr) (192.134.164.82) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Fri, 14 Sep 2012 13:59:16 +0000 Received: from stedding.saclay.inria.fr ([193.55.250.194]) by mail1-relais-roc.national.inria.fr with ESMTP/TLS/DHE-RSA-AES128-SHA; 14 Sep 2012 15:59:13 +0200 Received: from glisse (helo=localhost) by stedding.saclay.inria.fr with local-esmtp (Exim 4.80) (envelope-from ) id 1TCWQL-0001cE-40; Fri, 14 Sep 2012 15:59:13 +0200 Date: Fri, 14 Sep 2012 15:59:13 +0200 (CEST) From: Marc Glisse To: Jason Merrill cc: gcc-patches@gcc.gnu.org Subject: Re: vector comparisons in C++ In-Reply-To: <50532E69.9090209@redhat.com> Message-ID: References: <5051EFEE.5000804@redhat.com> <50524AD4.3080706@redhat.com> <50532E69.9090209@redhat.com> User-Agent: Alpine 2.02 (DEB 1266 2009-07-14) MIME-Version: 1.0 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org Here is the patch I just tested. Changes compared to the previous patch include: * same_type_ignoring_top_level_qualifiers_p * build_vector_type: don't use an opaque vector for the return type of operator< (not sure what the point was of making it opaque?) * Disable BIT_AND -> TRUTH_AND optimization for vectors * Disable (type)(a (a a<=b, use a vector type, not boolean * 2 more testcases (through which I discovered the issues) I am sure there are other optimizations that do weird things, but I should stop increasing the size of this patch... I'll update the doc in a later patch. Ok? 2012-09-14 Marc Glisse PR c++/54427 gcc/ChangeLog * fold-const.c (fold_unary_loc): Disable for VECTOR_TYPE. (fold_binary_loc): Likewise. * gimple-fold.c (and_comparisons_1): Handle VECTOR_TYPE. (or_comparisons_1): Likewise. gcc/cp/ChangeLog * typeck.c (cp_build_binary_op) [LSHIFT_EXPR, RSHIFT_EXPR, EQ_EXPR, NE_EXPR, LE_EXPR, GE_EXPR, LT_EXPR, GT_EXPR]: Handle VECTOR_TYPE. gcc/testsuite/ChangeLog * g++.dg/other/vector-compare.C: New testcase. * gcc/testsuite/c-c++-common/vector-compare-3.c: New testcase. * gcc.dg/vector-shift.c: Move ... * c-c++-common/vector-shift.c: ... here. * gcc.dg/vector-shift1.c: Move ... * c-c++-common/vector-shift1.c: ... here. * gcc.dg/vector-shift3.c: Move ... * c-c++-common/vector-shift3.c: ... here. * gcc.dg/vector-compare-1.c: Move ... * c-c++-common/vector-compare-1.c: ... here. * gcc.dg/vector-compare-2.c: Move ... * c-c++-common/vector-compare-2.c: ... here. * gcc.c-torture/execute/vector-compare-1.c: Move ... * c-c++-common/torture/vector-compare-1.c: ... here. * gcc.c-torture/execute/vector-compare-2.x: Delete. * gcc.c-torture/execute/vector-compare-2.c: Move ... * c-c++-common/torture/vector-compare-2.c: ... here. * gcc.c-torture/execute/vector-shift.c: Move ... * c-c++-common/torture/vector-shift.c: ... here. * gcc.c-torture/execute/vector-shift2.c: Move ... * c-c++-common/torture/vector-shift2.c: ... here. * gcc.c-torture/execute/vector-subscript-1.c: Move ... * c-c++-common/torture/vector-subscript-1.c: ... here. * gcc.c-torture/execute/vector-subscript-2.c: Move ... * c-c++-common/torture/vector-subscript-2.c: ... here. * gcc.c-torture/execute/vector-subscript-3.c: Move ... * c-c++-common/torture/vector-subscript-3.c: ... here. Index: gcc/testsuite/g++.dg/other/vector-compare.C =================================================================== --- gcc/testsuite/g++.dg/other/vector-compare.C (revision 0) +++ gcc/testsuite/g++.dg/other/vector-compare.C (revision 0) @@ -0,0 +1,38 @@ +/* { dg-do compile } */ +/* { dg-options "-std=gnu++11 -Wall" } */ + +// Check that we can compare vector types that really are the same through +// typedefs. + +typedef float v4f __attribute__((vector_size(4*sizeof(float)))); + +template void eat (T&&) {} + +template +struct Vec +{ + typedef T type __attribute__((vector_size(4*sizeof(T)))); + + template + static void fun (type const& t, U& u) { eat (t > u); } +}; + +long long +f (v4f *x, v4f const *y) +{ + return ((*x < *y) | (*x <= *y))[2]; +} + +int main () +{ + v4f x = {0,1,2,3}; + typedef decltype (x < x) v4i; + v4i y = {4,5,6,7}; // v4i is not opaque + Vec::type f = {-1,5,2,3.1}; + v4i c = (x == f) == y; + eat (c); + Vec::fun (f, x); + Vec::fun (x, f); + Vec::fun (f, f); + Vec::fun (x, x); +} Property changes on: gcc/testsuite/g++.dg/other/vector-compare.C ___________________________________________________________________ Added: svn:keywords + Author Date Id Revision URL Added: svn:eol-style + native Index: gcc/testsuite/c-c++-common/vector-compare-3.c =================================================================== --- gcc/testsuite/c-c++-common/vector-compare-3.c (revision 0) +++ gcc/testsuite/c-c++-common/vector-compare-3.c (revision 0) @@ -0,0 +1,25 @@ +/* { dg-do compile } */ +/* { dg-options "-O2" } */ + +typedef int v4i __attribute__((vector_size(4*sizeof(int)))); + +// fold should not turn (vec_other)(x *y; +} + Property changes on: gcc/testsuite/c-c++-common/vector-compare-3.c ___________________________________________________________________ Added: svn:eol-style + native Added: svn:keywords + Author Date Id Revision URL Index: gcc/testsuite/c-c++-common/vector-shift.c =================================================================== --- gcc/testsuite/c-c++-common/vector-shift.c (revision 190834) +++ gcc/testsuite/c-c++-common/vector-shift.c (working copy) @@ -1,11 +1,12 @@ /* { dg-do compile } */ +/* { dg-prune-output "in evaluation of" } */ #define vector(elcount, type) \ __attribute__((vector_size((elcount)*sizeof(type)))) type int main (int argc, char *argv[]) { vector(4,char) vchar = {1,2,3,4}; vector(4, int) vint = {1,1,1,1}; vint <<= vchar; /* { dg-error "nvalid operands to binary <<" } */ vchar >>= vint; /* { dg-error "nvalid operands to binary >>" } */ Index: gcc/testsuite/c-c++-common/torture/vector-subscript-1.c =================================================================== --- gcc/testsuite/c-c++-common/torture/vector-subscript-1.c (revision 190838) +++ gcc/testsuite/c-c++-common/torture/vector-subscript-1.c (working copy) @@ -1,11 +1,11 @@ -/* dg-do run */ +/* { dg-do run } */ #define vector __attribute__((vector_size(sizeof(int)*4) )) /* Check to make sure that we extract and insert the vector at the same location for vector subscripting and that vectors layout are the same as arrays. */ struct TV4 { vector int v; }; Index: gcc/testsuite/c-c++-common/torture/vector-subscript-2.c =================================================================== --- gcc/testsuite/c-c++-common/torture/vector-subscript-2.c (revision 190838) +++ gcc/testsuite/c-c++-common/torture/vector-subscript-2.c (working copy) @@ -1,10 +1,11 @@ +/* { dg-do run } */ #define vector __attribute__((vector_size(sizeof(int)*4) )) /* Check to make sure that we extract and insert the vector at the same location for vector subscripting (with constant indexes) and that vectors layout are the same as arrays. */ struct TV4 { vector int v; }; Index: gcc/testsuite/c-c++-common/torture/vector-shift.c =================================================================== --- gcc/testsuite/c-c++-common/torture/vector-shift.c (revision 190838) +++ gcc/testsuite/c-c++-common/torture/vector-shift.c (working copy) @@ -1,29 +1,30 @@ +/* { dg-do run } */ #define vector __attribute__((vector_size(sizeof(int)*4) )) static vector int allones = {1, 1, 1, 1}; static vector int allzeros = {0, 0, 0, 0}; static vector int numbers = {0, 1, 2, 3}; static vector int numbersleftshiftallones = {0, 2, 4, 6}; static vector int numbersrightshiftallones = {0, 0, 1, 1}; static vector unsigned int uallones = {1, 1, 1, 1}; static vector unsigned int uallzeros = {0, 0, 0, 0}; static vector unsigned int unumbers = {0, 1, 2, 3}; static vector unsigned int unumbersleftshiftallones = {0, 2, 4, 6}; static vector unsigned int unumbersrightshiftallones = {0, 0, 1, 1}; #define TEST(result, expected) \ do { \ - typeof(result) result1 = result; \ + __typeof__(result) result1 = result; \ if(sizeof (result1) != sizeof (expected)) \ __builtin_abort (); \ if (__builtin_memcmp (&result1, &expected, sizeof(result1)) != 0) \ __builtin_abort (); \ }while (0); int main(void) { vector int result; TEST ((numbers << allzeros), numbers); Index: gcc/testsuite/c-c++-common/torture/vector-subscript-3.c =================================================================== --- gcc/testsuite/c-c++-common/torture/vector-subscript-3.c (revision 190838) +++ gcc/testsuite/c-c++-common/torture/vector-subscript-3.c (working copy) @@ -1,11 +1,11 @@ -/* dg-do run */ +/* { dg-do run } */ #define vector __attribute__((vector_size(16) )) /* Check whether register declaration of vector type still allow us to subscript this type. */ typedef vector short myvec_t; struct vec_s { vector short member; }; Index: gcc/testsuite/c-c++-common/torture/vector-compare-1.c =================================================================== --- gcc/testsuite/c-c++-common/torture/vector-compare-1.c (revision 190838) +++ gcc/testsuite/c-c++-common/torture/vector-compare-1.c (working copy) @@ -1,10 +1,11 @@ +/* { dg-do run } */ #define vector(elcount, type) \ __attribute__((vector_size((elcount)*sizeof(type)))) type #define check_compare(count, res, i0, i1, op, fmt) \ do { \ int __i; \ for (__i = 0; __i < count; __i ++) { \ if ((res)[__i] != ((i0)[__i] op (i1)[__i] ? -1 : 0)) \ { \ __builtin_printf ("%i != ((" fmt " " #op " " fmt " ? -1 : 0) ", \ @@ -31,76 +32,76 @@ do { \ } while (0) int main (int argc, char *argv[]) { #define INT int vector (4, INT) i0; vector (4, INT) i1; vector (4, int) ires; int i; - i0 = (vector (4, INT)){argc, 1, 2, 10}; + i0 = (vector (4, INT)){(INT)argc, 1, 2, 10}; i1 = (vector (4, INT)){0, 3, 2, (INT)-23}; test (4, i0, i1, ires, "%i"); #undef INT #define INT unsigned int vector (4, int) ures; vector (4, INT) u0; vector (4, INT) u1; - u0 = (vector (4, INT)){argc, 1, 2, 10}; + u0 = (vector (4, INT)){(INT)argc, 1, 2, 10}; u1 = (vector (4, INT)){0, 3, 2, (INT)-23}; test (4, u0, u1, ures, "%u"); #undef INT #define SHORT short vector (8, SHORT) s0; vector (8, SHORT) s1; vector (8, short) sres; - s0 = (vector (8, SHORT)){argc, 1, 2, 10, 6, 87, (SHORT)-5, 2}; + s0 = (vector (8, SHORT)){(SHORT)argc, 1, 2, 10, 6, 87, (SHORT)-5, 2}; s1 = (vector (8, SHORT)){0, 3, 2, (SHORT)-23, 12, 10, (SHORT)-2, 0}; test (8, s0, s1, sres, "%i"); #undef SHORT #define SHORT unsigned short vector (8, SHORT) us0; vector (8, SHORT) us1; vector (8, short) usres; - us0 = (vector (8, SHORT)){argc, 1, 2, 10, 6, 87, (SHORT)-5, 2}; + us0 = (vector (8, SHORT)){(SHORT)argc, 1, 2, 10, 6, 87, (SHORT)-5, 2}; us1 = (vector (8, SHORT)){0, 3, 2, (SHORT)-23, 12, 10, (SHORT)-2, 0}; test (8, us0, us1, usres, "%u"); #undef SHORT #define CHAR signed char vector (16, CHAR) c0; vector (16, CHAR) c1; vector (16, signed char) cres; - c0 = (vector (16, CHAR)){argc, 1, 2, 10, 6, 87, (CHAR)-5, 2, \ - argc, 1, 2, 10, 6, 87, (CHAR)-5, 2 }; + c0 = (vector (16, CHAR)){(CHAR)argc, 1, 2, 10, 6, 87, (CHAR)-5, 2, \ + (CHAR)argc, 1, 2, 10, 6, 87, (CHAR)-5, 2 }; c1 = (vector (16, CHAR)){0, 3, 2, (CHAR)-23, 12, 10, (CHAR)-2, 0, \ 0, 3, 2, (CHAR)-23, 12, 10, (CHAR)-2, 0}; test (16, c0, c1, cres, "%i"); #undef CHAR #define CHAR unsigned char vector (16, CHAR) uc0; vector (16, CHAR) uc1; vector (16, signed char) ucres; - uc0 = (vector (16, CHAR)){argc, 1, 2, 10, 6, 87, (CHAR)-5, 2, \ - argc, 1, 2, 10, 6, 87, (CHAR)-5, 2 }; + uc0 = (vector (16, CHAR)){(CHAR)argc, 1, 2, 10, 6, 87, (CHAR)-5, 2, \ + (CHAR)argc, 1, 2, 10, 6, 87, (CHAR)-5, 2 }; uc1 = (vector (16, CHAR)){0, 3, 2, (CHAR)-23, 12, 10, (CHAR)-2, 0, \ 0, 3, 2, (CHAR)-23, 12, 10, (CHAR)-2, 0}; test (16, uc0, uc1, ucres, "%u"); #undef CHAR /* Float comparison. */ vector (4, float) f0; vector (4, float) f1; __typeof (f0 == f1) ifres; Index: gcc/testsuite/c-c++-common/torture/vector-compare-2.c =================================================================== --- gcc/testsuite/c-c++-common/torture/vector-compare-2.c (revision 190838) +++ gcc/testsuite/c-c++-common/torture/vector-compare-2.c (working copy) @@ -1,10 +1,12 @@ +/* { dg-do run } */ +/* { dg-options "-Wno-psabi" } */ #define vector(elcount, type) \ __attribute__((vector_size((elcount)*sizeof(type)))) type /* Check that constant folding in these simple cases works. */ vector (4, int) foo (vector (4, int) x) { return (x == x) + (x != x) + (x > x) + (x < x) + (x >= x) + (x <= x); Index: gcc/testsuite/c-c++-common/torture/vector-shift2.c =================================================================== --- gcc/testsuite/c-c++-common/torture/vector-shift2.c (revision 190838) +++ gcc/testsuite/c-c++-common/torture/vector-shift2.c (working copy) @@ -1,10 +1,11 @@ +/* { dg-do run } */ #define vector(elcount, type) \ __attribute__((vector_size((elcount)*sizeof(type)))) type #define vidx(type, vec, idx) (*((type *) &(vec) + idx)) #define uint unsigned int int main (int argc, char *argv[]) { vector(4, uint) vuint = { 1, 2, 3, 4}; vector(4, int) vint0 = { 1, 1, 1, 1}; vector(4, int) vint1 = {-1, -1, -1, -1}; Index: gcc/testsuite/c-c++-common/vector-shift1.c =================================================================== --- gcc/testsuite/c-c++-common/vector-shift1.c (revision 190834) +++ gcc/testsuite/c-c++-common/vector-shift1.c (working copy) @@ -1,18 +1,19 @@ /* { dg-do compile } */ +/* { dg-prune-output "in evaluation of" } */ #define vector(elcount, type) \ __attribute__((vector_size((elcount)*sizeof(type)))) type int main (int argc, char *argv[]) { vector(4, float) vfloat0 = {1., 2., 3., 4.}; vector(4, float) vfloat1 = {1., 2., 3., 4.}; vector(4, int) vint = {1, 1, 1, 1 }; vint <<= vfloat0; /* { dg-error "nvalid operands to binary <<" } */ vfloat0 >>= vint; /* { dg-error "nvalid operands to binary >>" } */ - vfloat0 <<= vfloat1; /* { dg-error "nvalid operands to binary <<" } */ + vfloat0 <<= vfloat1; /* { dg-error "nvalid operands" } */ return 0; } Index: gcc/testsuite/c-c++-common/vector-shift3.c =================================================================== --- gcc/testsuite/c-c++-common/vector-shift3.c (revision 190834) +++ gcc/testsuite/c-c++-common/vector-shift3.c (working copy) @@ -1,16 +1,16 @@ /* { dg-do compile } */ #define vector(elcount, type) \ __attribute__((vector_size((elcount)*sizeof(type)))) type int main (int argc, char *argv[]) { - vector(8, short) v0 = {argc,2,3,4,5,6,7}; + vector(8, short) v0 = {(short)argc,2,3,4,5,6,7}; short sc; - scalar1 <<= v0; /* { dg-error ".*scalar1.*undeclared" } */ + scalar1 <<= v0; /* { dg-error "scalar1.*(undeclared|was not declared)" } */ return 0; } Index: gcc/testsuite/c-c++-common/vector-compare-1.c =================================================================== --- gcc/testsuite/c-c++-common/vector-compare-1.c (revision 190834) +++ gcc/testsuite/c-c++-common/vector-compare-1.c (working copy) @@ -7,13 +7,13 @@ __attribute__((vector_size((elcount)*siz void foo (vector (4, int) x, vector (4, float) y) { vector (4, int) p4; vector (4, int) r4; vector (4, unsigned int) q4; vector (8, int) r8; vector (4, float) f4; r4 = x > y; /* { dg-error "comparing vectors with different element types" } */ - r8 = (x != p4); /* { dg-error "incompatible types when assigning to type" } */ + r8 = (x != p4); /* { dg-error "incompatible types when assigning to type|cannot convert" } */ r8 == r4; /* { dg-error "comparing vectors with different number of elements" } */ } Index: gcc/fold-const.c =================================================================== --- gcc/fold-const.c (revision 191291) +++ gcc/fold-const.c (working copy) @@ -7764,21 +7764,21 @@ fold_unary_loc (location_t loc, enum tre /* If we have (type) (a CMP b) and type is an integral type, return new expression involving the new type. Canonicalize (type) (a CMP b) to (a CMP b) ? (type) true : (type) false for non-integral type. Do not fold the result as that would not simplify further, also folding again results in recursions. */ if (TREE_CODE (type) == BOOLEAN_TYPE) return build2_loc (loc, TREE_CODE (op0), type, TREE_OPERAND (op0, 0), TREE_OPERAND (op0, 1)); - else if (!INTEGRAL_TYPE_P (type)) + else if (!INTEGRAL_TYPE_P (type) && TREE_CODE (type) != VECTOR_TYPE) return build3_loc (loc, COND_EXPR, type, op0, constant_boolean_node (true, type), constant_boolean_node (false, type)); } /* Handle cases of two conversions in a row. */ if (CONVERT_EXPR_P (op0)) { tree inside_type = TREE_TYPE (TREE_OPERAND (op0, 0)); tree inter_type = TREE_TYPE (op0); @@ -9822,20 +9822,21 @@ fold_binary_loc (location_t loc, Before we do that, see if this is a BIT_AND_EXPR or a BIT_IOR_EXPR, one of the operands is a comparison and the other is a comparison, a BIT_AND_EXPR with the constant 1, or a truth value. In that case, the code below would make the expression more complex. Change it to a TRUTH_{AND,OR}_EXPR. Likewise, convert a similar NE_EXPR to TRUTH_XOR_EXPR and an EQ_EXPR to the inversion of a TRUTH_XOR_EXPR. */ if ((code == BIT_AND_EXPR || code == BIT_IOR_EXPR || code == EQ_EXPR || code == NE_EXPR) + && TREE_CODE (type) != VECTOR_TYPE && ((truth_value_p (TREE_CODE (arg0)) && (truth_value_p (TREE_CODE (arg1)) || (TREE_CODE (arg1) == BIT_AND_EXPR && integer_onep (TREE_OPERAND (arg1, 1))))) || (truth_value_p (TREE_CODE (arg1)) && (truth_value_p (TREE_CODE (arg0)) || (TREE_CODE (arg0) == BIT_AND_EXPR && integer_onep (TREE_OPERAND (arg0, 1))))))) { tem = fold_build2_loc (loc, code == BIT_AND_EXPR ? TRUTH_AND_EXPR Index: gcc/gimple-fold.c =================================================================== --- gcc/gimple-fold.c (revision 191291) +++ gcc/gimple-fold.c (working copy) @@ -23,20 +23,21 @@ along with GCC; see the file COPYING3. #include "coretypes.h" #include "tm.h" #include "tree.h" #include "flags.h" #include "function.h" #include "dumpfile.h" #include "tree-flow.h" #include "tree-ssa-propagate.h" #include "target.h" #include "gimple-fold.h" +#include "langhooks.h" /* Return true when DECL can be referenced from current unit. FROM_DECL (if non-null) specify constructor of variable DECL was taken from. We can get declarations that are not possible to reference for various reasons: 1) When analyzing C++ virtual tables. C++ virtual tables do have known constructors even when they are keyed to other compilation unit. Those tables can contain pointers to methods and vars @@ -1685,41 +1686,51 @@ and_var_with_comparison_1 (gimple stmt, (OP1A CODE1 OP1B) and (OP2A CODE2 OP2B), respectively. If this can be done without constructing an intermediate value, return the resulting tree; otherwise NULL_TREE is returned. This function is deliberately asymmetric as it recurses on SSA_DEFs in the first comparison but not the second. */ static tree and_comparisons_1 (enum tree_code code1, tree op1a, tree op1b, enum tree_code code2, tree op2a, tree op2b) { + tree truth_type = boolean_type_node; + if (TREE_CODE (TREE_TYPE (op1a)) == VECTOR_TYPE) + { + tree vec_type = TREE_TYPE (op1a); + tree elem = lang_hooks.types.type_for_size + (GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (vec_type))), 0); + truth_type = build_opaque_vector_type (elem, + TYPE_VECTOR_SUBPARTS (vec_type)); + } + /* First check for ((x CODE1 y) AND (x CODE2 y)). */ if (operand_equal_p (op1a, op2a, 0) && operand_equal_p (op1b, op2b, 0)) { /* Result will be either NULL_TREE, or a combined comparison. */ tree t = combine_comparisons (UNKNOWN_LOCATION, TRUTH_ANDIF_EXPR, code1, code2, - boolean_type_node, op1a, op1b); + truth_type, op1a, op1b); if (t) return t; } /* Likewise the swapped case of the above. */ if (operand_equal_p (op1a, op2b, 0) && operand_equal_p (op1b, op2a, 0)) { /* Result will be either NULL_TREE, or a combined comparison. */ tree t = combine_comparisons (UNKNOWN_LOCATION, TRUTH_ANDIF_EXPR, code1, swap_tree_comparison (code2), - boolean_type_node, op1a, op1b); + truth_type, op1a, op1b); if (t) return t; } /* If both comparisons are of the same value against constants, we might be able to merge them. */ if (operand_equal_p (op1a, op2a, 0) && TREE_CODE (op1b) == INTEGER_CST && TREE_CODE (op2b) == INTEGER_CST) { @@ -2147,41 +2158,51 @@ or_var_with_comparison_1 (gimple stmt, (OP1A CODE1 OP1B) and (OP2A CODE2 OP2B), respectively. If this can be done without constructing an intermediate value, return the resulting tree; otherwise NULL_TREE is returned. This function is deliberately asymmetric as it recurses on SSA_DEFs in the first comparison but not the second. */ static tree or_comparisons_1 (enum tree_code code1, tree op1a, tree op1b, enum tree_code code2, tree op2a, tree op2b) { + tree truth_type = boolean_type_node; + if (TREE_CODE (TREE_TYPE (op1a)) == VECTOR_TYPE) + { + tree vec_type = TREE_TYPE (op1a); + tree elem = lang_hooks.types.type_for_size + (GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (vec_type))), 0); + truth_type = build_vector_type (elem, + TYPE_VECTOR_SUBPARTS (vec_type)); + } + /* First check for ((x CODE1 y) OR (x CODE2 y)). */ if (operand_equal_p (op1a, op2a, 0) && operand_equal_p (op1b, op2b, 0)) { /* Result will be either NULL_TREE, or a combined comparison. */ tree t = combine_comparisons (UNKNOWN_LOCATION, TRUTH_ORIF_EXPR, code1, code2, - boolean_type_node, op1a, op1b); + truth_type, op1a, op1b); if (t) return t; } /* Likewise the swapped case of the above. */ if (operand_equal_p (op1a, op2b, 0) && operand_equal_p (op1b, op2a, 0)) { /* Result will be either NULL_TREE, or a combined comparison. */ tree t = combine_comparisons (UNKNOWN_LOCATION, TRUTH_ORIF_EXPR, code1, swap_tree_comparison (code2), - boolean_type_node, op1a, op1b); + truth_type, op1a, op1b); if (t) return t; } /* If both comparisons are of the same value against constants, we might be able to merge them. */ if (operand_equal_p (op1a, op2a, 0) && TREE_CODE (op1b) == INTEGER_CST && TREE_CODE (op2b) == INTEGER_CST) { Index: gcc/cp/typeck.c =================================================================== --- gcc/cp/typeck.c (revision 191291) +++ gcc/cp/typeck.c (working copy) @@ -3978,21 +3978,29 @@ cp_build_binary_op (location_t location, case TRUTH_AND_EXPR: case TRUTH_OR_EXPR: result_type = boolean_type_node; break; /* Shift operations: result has same type as first operand; always convert second operand to int. Also set SHORT_SHIFT if shifting rightward. */ case RSHIFT_EXPR: - if (code0 == INTEGER_TYPE && code1 == INTEGER_TYPE) + if (code0 == VECTOR_TYPE && code1 == VECTOR_TYPE + && TREE_CODE (TREE_TYPE (type0)) == INTEGER_TYPE + && TREE_CODE (TREE_TYPE (type1)) == INTEGER_TYPE + && TYPE_VECTOR_SUBPARTS (type0) == TYPE_VECTOR_SUBPARTS (type1)) + { + result_type = type0; + converted = 1; + } + else if (code0 == INTEGER_TYPE && code1 == INTEGER_TYPE) { result_type = type0; if (TREE_CODE (op1) == INTEGER_CST) { if (tree_int_cst_lt (op1, integer_zero_node)) { if ((complain & tf_warning) && c_inhibit_evaluation_warnings == 0) warning (0, "right shift count is negative"); } @@ -4007,21 +4015,29 @@ cp_build_binary_op (location_t location, /* Convert the shift-count to an integer, regardless of size of value being shifted. */ if (TYPE_MAIN_VARIANT (TREE_TYPE (op1)) != integer_type_node) op1 = cp_convert (integer_type_node, op1, complain); /* Avoid converting op1 to result_type later. */ converted = 1; } break; case LSHIFT_EXPR: - if (code0 == INTEGER_TYPE && code1 == INTEGER_TYPE) + if (code0 == VECTOR_TYPE && code1 == VECTOR_TYPE + && TREE_CODE (TREE_TYPE (type0)) == INTEGER_TYPE + && TREE_CODE (TREE_TYPE (type1)) == INTEGER_TYPE + && TYPE_VECTOR_SUBPARTS (type0) == TYPE_VECTOR_SUBPARTS (type1)) + { + result_type = type0; + converted = 1; + } + else if (code0 == INTEGER_TYPE && code1 == INTEGER_TYPE) { result_type = type0; if (TREE_CODE (op1) == INTEGER_CST) { if (tree_int_cst_lt (op1, integer_zero_node)) { if ((complain & tf_warning) && c_inhibit_evaluation_warnings == 0) warning (0, "left shift count is negative"); } @@ -4065,20 +4081,22 @@ cp_build_binary_op (location_t location, } /* Convert the shift-count to an integer, regardless of size of value being shifted. */ if (TYPE_MAIN_VARIANT (TREE_TYPE (op1)) != integer_type_node) op1 = cp_convert (integer_type_node, op1, complain); } break; case EQ_EXPR: case NE_EXPR: + if (code0 == VECTOR_TYPE && code1 == VECTOR_TYPE) + goto vector_compare; if ((complain & tf_warning) && (FLOAT_TYPE_P (type0) || FLOAT_TYPE_P (type1))) warning (OPT_Wfloat_equal, "comparing floating point with == or != is unsafe"); if ((complain & tf_warning) && ((TREE_CODE (orig_op0) == STRING_CST && !integer_zerop (op1)) || (TREE_CODE (orig_op1) == STRING_CST && !integer_zerop (op0)))) warning (OPT_Waddress, "comparison with string literal results in unspecified behaviour"); build_type = boolean_type_node; @@ -4307,20 +4325,47 @@ cp_build_binary_op (location_t location, case GE_EXPR: case LT_EXPR: case GT_EXPR: if (TREE_CODE (orig_op0) == STRING_CST || TREE_CODE (orig_op1) == STRING_CST) { if (complain & tf_warning) warning (OPT_Waddress, "comparison with string literal results in unspecified behaviour"); } + if (code0 == VECTOR_TYPE && code1 == VECTOR_TYPE) + { + vector_compare: + tree intt; + if (!same_type_ignoring_top_level_qualifiers_p (TREE_TYPE (type0), + TREE_TYPE (type1))) + { + error_at (location, "comparing vectors with different " + "element types"); + return error_mark_node; + } + + if (TYPE_VECTOR_SUBPARTS (type0) != TYPE_VECTOR_SUBPARTS (type1)) + { + error_at (location, "comparing vectors with different " + "number of elements"); + return error_mark_node; + } + + /* Always construct signed integer vector type. */ + intt = c_common_type_for_size (GET_MODE_BITSIZE + (TYPE_MODE (TREE_TYPE (type0))), 0); + result_type = build_vector_type (intt, + TYPE_VECTOR_SUBPARTS (type0)); + converted = 1; + break; + } build_type = boolean_type_node; if ((code0 == INTEGER_TYPE || code0 == REAL_TYPE || code0 == ENUMERAL_TYPE) && (code1 == INTEGER_TYPE || code1 == REAL_TYPE || code1 == ENUMERAL_TYPE)) short_compare = 1; else if (code0 == POINTER_TYPE && code1 == POINTER_TYPE) result_type = composite_pointer_type (type0, type1, op0, op1, CPO_COMPARISON, complain); else if (code0 == POINTER_TYPE && null_ptr_cst_p (op1))