From patchwork Fri Apr 12 09:03:04 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Marc Glisse X-Patchwork-Id: 235994 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]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (Client CN "localhost", Issuer "www.qmailtoaster.com" (not verified)) by ozlabs.org (Postfix) with ESMTPS id CB60E2C00B2 for ; Fri, 12 Apr 2013 19:03:16 +1000 (EST) DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:date :from:to:cc:subject:message-id:mime-version:content-type; q=dns; s=default; b=aKvpRV5TZ/KhrN81kvxKfpIyymntX6lw60P54xe3ijqkZ14GHf e/+efOrREW480bIwJ+Y7oQOuv0yDBumSwHE+6zmqrSElTh0v05V0VOS5UNdJRpoH udqgneU7SzRRa7uBJGN4TzMFzx8L1eXKo9WB6o5FRXilUX+WKpm8zN+e8= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:date :from:to:cc:subject:message-id:mime-version:content-type; s= default; bh=K+MGfSVNB++K0VbLwEcWFFK5fhQ=; b=X7A0qmPQD1hrVXYk8k3u weiFnNNeASQHPywAIgmOD8PNu1umWzgCfsRujy5LyTvAHZCMuGU5RyWazLbOPw2n XUn3zLYAy5zO3yV1GBkKqc5e4WTDqvgzfHLpfahYgzmmZWs6r9Xqq45Tz6Hq0hiO np25LWYRuJtf4WoorXeddj4= Received: (qmail 7239 invoked by alias); 12 Apr 2013 09:03:10 -0000 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 Received: (qmail 7223 invoked by uid 89); 12 Apr 2013 09:03:09 -0000 X-Spam-SWARE-Status: No, score=-8.2 required=5.0 tests=AWL, BAYES_00, KHOP_RCVD_UNTRUST, RCVD_IN_DNSWL_HI, RP_MATCHES_RCVD autolearn=ham version=3.3.1 X-Spam-User: qpsmtpd, 2 recipients Received: from mail3-relais-sop.national.inria.fr (HELO mail3-relais-sop.national.inria.fr) (192.134.164.104) by sourceware.org (qpsmtpd/0.84/v0.84-167-ge50287c) with ESMTP; Fri, 12 Apr 2013 09:03:07 +0000 Received: from stedding.saclay.inria.fr ([193.55.250.194]) by mail3-relais-sop.national.inria.fr with ESMTP/TLS/DHE-RSA-AES128-SHA; 12 Apr 2013 11:03:04 +0200 Received: from glisse (helo=localhost) by stedding.saclay.inria.fr with local-esmtp (Exim 4.80) (envelope-from ) id 1UQZsu-00014i-DA; Fri, 12 Apr 2013 11:03:04 +0200 Date: Fri, 12 Apr 2013 11:03:04 +0200 (CEST) From: Marc Glisse To: gcc-patches@gcc.gnu.org cc: jason@gcc.gnu.org Subject: Logic operators ! && || for vectors Message-ID: User-Agent: Alpine 2.02 (DEB 1266 2009-07-14) MIME-Version: 1.0 X-Virus-Found: No Hello, this adds support for vector !, && and ||. In the long run, I think it would be good to be able to use TRUTH_*_EXPR with vectors, but that's probably a lot of work. It currently restricts && and || to vector-vector operations. I'd like to also support mixed scalar-vector later, but it is a bit more complicated. With vectors, && evaluates both sides. For scal && vec, we have the choice of making it short-circuit: cond_expr((bool)scal, vec!=0, {0}) or do a vector and. For vec && scal, it seems clear we have to evaluate both operands, but then we can also make it a cond_expr instead of a BIT_AND_EXPR (technically, I think I can achieve that with save_expr and a compound_expr, I don't know if there is a better way to add statements). The missing save_expr before build_vector_from_val are a bug I introduced when I adapted the code from the C front-end. This bit (and the vector-scalar-2.c testcase that goes with it) should probably be backported to 4.8. The code we generate for these examples is not very good, but that's a different issue. Bootstrap+testsuite on x86_64-linux-gnu. 2013-04-12 Marc Glisse gcc/cp/ * typeck.c (cp_build_binary_op): Call save_expr before build_vector_from_val. : Handle vectors. (cp_build_unary_op) : Likewise. gcc/c-family/ * c-common.c (warn_logical_operator): Give up for vectors. gcc/testsuite/ * c-c++-common/vector-scalar-2.c: New testcase. * g++.dg/ext/vector22.C: Likewise. * g++.dg/ext/vector23.C: Likewise. * g++.dg/ext/vector9.C: Adapt. * g++.dg/other/error23.C: Adapt. Index: gcc/c-family/c-common.c =================================================================== --- gcc/c-family/c-common.c (revision 197846) +++ gcc/c-family/c-common.c (working copy) @@ -1624,20 +1624,24 @@ warn_logical_operator (location_t locati if (CONSTANT_CLASS_P (op_left) || CONSTANT_CLASS_P (op_right)) return; /* This warning only makes sense with logical operands. */ if (!(truth_value_p (TREE_CODE (op_left)) || INTEGRAL_TYPE_P (TREE_TYPE (op_left))) || !(truth_value_p (TREE_CODE (op_right)) || INTEGRAL_TYPE_P (TREE_TYPE (op_right)))) return; + /* The range computations only work with scalars. */ + if (VECTOR_TYPE_P (TREE_TYPE (op_left)) + || VECTOR_TYPE_P (TREE_TYPE (op_right))) + return; /* We first test whether either side separately is trivially true (with OR) or trivially false (with AND). If so, do not warn. This is a common idiom for testing ranges of data types in portable code. */ lhs = make_range (op_left, &in0_p, &low0, &high0, &strict_overflow_p); if (!lhs) return; if (TREE_CODE (lhs) == C_MAYBE_CONST_EXPR) lhs = C_MAYBE_CONST_EXPR_EXPR (lhs); Index: gcc/cp/typeck.c =================================================================== --- gcc/cp/typeck.c (revision 197846) +++ gcc/cp/typeck.c (working copy) @@ -3970,30 +3970,30 @@ cp_build_binary_op (location_t location, { enum stv_conv convert_flag = scalar_to_vector (location, code, op0, op1, complain & tf_error); switch (convert_flag) { case stv_error: return error_mark_node; case stv_firstarg: { - op0 = convert (TREE_TYPE (type1), op0); + op0 = save_expr (convert (TREE_TYPE (type1), op0)); op0 = build_vector_from_val (type1, op0); type0 = TREE_TYPE (op0); code0 = TREE_CODE (type0); converted = 1; break; } case stv_secondarg: { - op1 = convert (TREE_TYPE (type0), op1); + op1 = save_expr (convert (TREE_TYPE (type0), op1)); op1 = build_vector_from_val (type0, op1); type1 = TREE_TYPE (op1); code1 = TREE_CODE (type1); converted = 1; break; } default: break; } } @@ -4111,20 +4111,43 @@ cp_build_binary_op (location_t location, || (TREE_CODE (op1) == INTEGER_CST && ! integer_all_onesp (op1))); common = 1; } break; case TRUTH_ANDIF_EXPR: case TRUTH_ORIF_EXPR: case TRUTH_AND_EXPR: case TRUTH_OR_EXPR: + if (VECTOR_TYPE_P (type0) != VECTOR_TYPE_P (type1)) + { + if (complain & tf_error) + sorry ("%<&&%> or %<||%> with a vector and a scalar"); + return error_mark_node; + } + if (VECTOR_TYPE_P (type0) && VECTOR_TYPE_P (type1)) + { + if (!COMPARISON_CLASS_P (op0)) + op0 = cp_build_binary_op (EXPR_LOCATION (op0), NE_EXPR, op0, + build_zero_cst (type0), complain); + if (!COMPARISON_CLASS_P (op1)) + op1 = cp_build_binary_op (EXPR_LOCATION (op1), NE_EXPR, op1, + build_zero_cst (type1), complain); + + if (code == TRUTH_ANDIF_EXPR || code == TRUTH_AND_EXPR) + code = BIT_AND_EXPR; + else /* if (code == TRUTH_ORIF_EXPR || code == TRUTH_OR_EXPR) */ + code = BIT_IOR_EXPR; + + return cp_build_binary_op (location, code, op0, op1, complain); + } + 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 == VECTOR_TYPE && code1 == INTEGER_TYPE && TREE_CODE (TREE_TYPE (type0)) == INTEGER_TYPE) @@ -5476,20 +5499,23 @@ cp_build_unary_op (enum tree_code code, errstring = _("wrong type argument to conjugation"); else if (!noconvert) { arg = cp_default_conversion (arg, complain); if (arg == error_mark_node) return error_mark_node; } break; case TRUTH_NOT_EXPR: + if (VECTOR_INTEGER_TYPE_P (TREE_TYPE (arg))) + return cp_build_binary_op (input_location, EQ_EXPR, arg, + build_zero_cst (TREE_TYPE (arg)), complain); arg = perform_implicit_conversion (boolean_type_node, arg, complain); val = invert_truthvalue_loc (input_location, arg); if (arg != error_mark_node) return val; errstring = _("in argument to unary !"); break; case NOP_EXPR: break; Index: gcc/testsuite/g++.dg/ext/vector22.C =================================================================== --- gcc/testsuite/g++.dg/ext/vector22.C (revision 0) +++ gcc/testsuite/g++.dg/ext/vector22.C (revision 0) @@ -0,0 +1,13 @@ +/* { dg-do compile } */ + +typedef int veci __attribute__ ((vector_size (4 * sizeof (int)))); +typedef float vecf __attribute__ ((vector_size (4 * sizeof (float)))); + +void f (veci *a, veci *b, int c) +{ + *a = !*a || *b < ++c; +} +void g (vecf *a, vecf *b) +{ + *a = (*a < 1 && !(*b > 2)) ? *a + *b : 3; +} Property changes on: gcc/testsuite/g++.dg/ext/vector22.C ___________________________________________________________________ Added: svn:eol-style + native Added: svn:keywords + Author Date Id Revision URL Index: gcc/testsuite/g++.dg/ext/vector23.C =================================================================== --- gcc/testsuite/g++.dg/ext/vector23.C (revision 0) +++ gcc/testsuite/g++.dg/ext/vector23.C (revision 0) @@ -0,0 +1,9 @@ +/* { dg-do compile } */ + +typedef int veci __attribute__ ((vector_size (4 * sizeof (int)))); +typedef float vecf __attribute__ ((vector_size (4 * sizeof (float)))); + +void f (veci *a, veci *b, int c) +{ + *a = *a || c; /* { dg-message "a vector and a scalar" } */ +} Property changes on: gcc/testsuite/g++.dg/ext/vector23.C ___________________________________________________________________ Added: svn:keywords + Author Date Id Revision URL Added: svn:eol-style + native Index: gcc/testsuite/g++.dg/ext/vector9.C =================================================================== --- gcc/testsuite/g++.dg/ext/vector9.C (revision 197846) +++ gcc/testsuite/g++.dg/ext/vector9.C (working copy) @@ -1,10 +1,10 @@ // PR c++/34891 typedef float v4f __attribute__((vector_size(8))); typedef int v4i __attribute__((vector_size(8))); void foo() { v4f v; - !(v4i)v; // { dg-error "v4i|argument" } + !(v4i)v; } Index: gcc/testsuite/g++.dg/other/error23.C =================================================================== --- gcc/testsuite/g++.dg/other/error23.C (revision 197846) +++ gcc/testsuite/g++.dg/other/error23.C (working copy) @@ -1,5 +1,5 @@ // PR c++/34918 // { dg-do compile } int v __attribute ((vector_size (8))); -bool b = !(v - v); // { dg-error "could not convert .\\(__vector.2. int\\)\\{0, 0\\}. from .__vector.2. int. to .bool.|in argument to unary" } +bool b = !(v - v); // { dg-error "not convert .__vector.2. int. to .bool. in initialization" } Index: gcc/testsuite/c-c++-common/vector-scalar-2.c =================================================================== --- gcc/testsuite/c-c++-common/vector-scalar-2.c (revision 0) +++ gcc/testsuite/c-c++-common/vector-scalar-2.c (revision 0) @@ -0,0 +1,14 @@ +/* { dg-do compile } */ +/* { dg-options "-fdump-tree-gimple" } */ + +typedef int veci __attribute__ ((vector_size (4 * sizeof (int)))); + +int c; + +void f (veci *a) +{ + *a = *a + ++c; +} + +/* { dg-final { scan-tree-dump-times " \\\+ 1" 1 "gimple" } } */ +/* { dg-final { cleanup-tree-dump "gimple" } } */