From patchwork Thu Oct 4 16:31:01 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jakub Jelinek X-Patchwork-Id: 189203 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 A729C2C0479 for ; Fri, 5 Oct 2012 02:31:33 +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=1349973095; h=Comment: DomainKey-Signature:Received:Received:Received:Received:Received: Received:Received:Date:From:To:Subject:Message-ID:Reply-To: MIME-Version:Content-Type:Content-Disposition:User-Agent: Mailing-List:Precedence:List-Id:List-Unsubscribe:List-Archive: List-Post:List-Help:Sender:Delivered-To; bh=T4KJ9HVml+K6zxugv48p zG+AfKg=; b=fr+EnBOSk//nCfg9DAxo8RnSCHdEbIY+ebg/nDCpMWGquMy3Y0HQ b7IR8tKnN6ho7MUw5Pivnjzd1JcYOUqbcu5RBDhfOwBuAC5kYDFgt94c6NGrHzA7 KtMn7wsE6USy3fmO1+9DGRsiDGa1LvGa0/PuxulH8H1orIvAfq3H0qA= 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:Received:Received:Date:From:To:Subject:Message-ID:Reply-To:MIME-Version:Content-Type:Content-Disposition:User-Agent:X-IsSubscribed:Mailing-List:Precedence:List-Id:List-Unsubscribe:List-Archive:List-Post:List-Help:Sender:Delivered-To; b=CWyuUSm+yklJ0U6i2zdZRhVdQ3/VQZTx9fVDJRuxVGEewvioO8y3wb8XcFi9Tg SJjx9bFmkU4u5fxCd1uspQNuc8c9IP3Xo/Z+vt4qAEUlgX0H7ALL6BAPW8rfiliP jSO3Q6rPzp3JGumPLDq1k2zmsVeLozwge5Po1hU6ikFhM=; Received: (qmail 10059 invoked by alias); 4 Oct 2012 16:31:22 -0000 Received: (qmail 10043 invoked by uid 22791); 4 Oct 2012 16:31:18 -0000 X-SWARE-Spam-Status: No, hits=-7.3 required=5.0 tests=AWL, BAYES_00, KHOP_RCVD_UNTRUST, KHOP_SPAMHAUS_DROP, RCVD_IN_DNSWL_HI, RCVD_IN_HOSTKARMA_W, RP_MATCHES_RCVD, SPF_HELO_PASS, TW_TM, T_FILL_THIS_FORM_SHORT 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; Thu, 04 Oct 2012 16:31:05 +0000 Received: from int-mx02.intmail.prod.int.phx2.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id q94GV5ct030173 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK) for ; Thu, 4 Oct 2012 12:31:05 -0400 Received: from zalov.redhat.com (vpn1-5-185.ams2.redhat.com [10.36.5.185]) by int-mx02.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id q94GV28t005179 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO) for ; Thu, 4 Oct 2012 12:31:04 -0400 Received: from zalov.cz (localhost [127.0.0.1]) by zalov.redhat.com (8.14.5/8.14.5) with ESMTP id q94GV2x2012083 for ; Thu, 4 Oct 2012 18:31:02 +0200 Received: (from jakub@localhost) by zalov.cz (8.14.5/8.14.5/Submit) id q94GV16j012082 for gcc-patches@gcc.gnu.org; Thu, 4 Oct 2012 18:31:01 +0200 Date: Thu, 4 Oct 2012 18:31:01 +0200 From: Jakub Jelinek To: gcc-patches@gcc.gnu.org Subject: [PATCH] Teach VRP to handle if ((unsigned_narrowing_cast) x != 0) similarly to if ((x & 0xffff) != 0) (PR tree-optimization/54810) Message-ID: <20121004163101.GB1787@tucnak.redhat.com> Reply-To: Jakub Jelinek MIME-Version: 1.0 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-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org Hi! This patch handles unsigned narrowing casts the same as BIT_AND_EXPR with the unsigned narrow type's max value. Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk? 2012-10-04 Jakub Jelinek PR tree-optimization/54810 * tree-vrp.c (register_edge_assert_for_2): Handle NAME = (unsigned) NAME2; if (NAME cmp CST) for narrowing casts to unsigned integral type like NAME = NAME2 & CST2; if (NAME cmp CST) where CST2 is the max value of the unsigned integral type. Jakub --- gcc/tree-vrp.c.jj 2012-09-25 14:45:48.000000000 +0200 +++ gcc/tree-vrp.c 2012-10-04 11:43:32.334988401 +0200 @@ -4712,6 +4712,11 @@ register_edge_assert_for_2 (tree name, e tree val2 = NULL_TREE; double_int mask = double_int_zero; unsigned int prec = TYPE_PRECISION (TREE_TYPE (val)); + unsigned int nprec = prec; + enum tree_code rhs_code = ERROR_MARK; + + if (is_gimple_assign (def_stmt)) + rhs_code = gimple_assign_rhs_code (def_stmt); /* Add asserts for NAME cmp CST and NAME being defined as NAME = (int) NAME2. */ @@ -4721,7 +4726,7 @@ register_edge_assert_for_2 (tree name, e && gimple_assign_cast_p (def_stmt)) { name2 = gimple_assign_rhs1 (def_stmt); - if (CONVERT_EXPR_CODE_P (gimple_assign_rhs_code (def_stmt)) + if (CONVERT_EXPR_CODE_P (rhs_code) && INTEGRAL_TYPE_P (TREE_TYPE (name2)) && TYPE_UNSIGNED (TREE_TYPE (name2)) && prec == TYPE_PRECISION (TREE_TYPE (name2)) @@ -4767,8 +4772,7 @@ register_edge_assert_for_2 (tree name, e NAME = NAME2 >> CST2. Extract CST2 from the right shift. */ - if (is_gimple_assign (def_stmt) - && gimple_assign_rhs_code (def_stmt) == RSHIFT_EXPR) + if (rhs_code == RSHIFT_EXPR) { name2 = gimple_assign_rhs1 (def_stmt); cst2 = gimple_assign_rhs2 (def_stmt); @@ -4840,21 +4844,37 @@ register_edge_assert_for_2 (tree name, e /* Add asserts for NAME cmp CST and NAME being defined as NAME = NAME2 & CST2. - Extract CST2 from the and. */ + Extract CST2 from the and. + + Also handle + NAME = (unsigned) NAME2; + casts where NAME's type is unsigned and has smaller precision + than NAME2's type as if it was NAME = NAME2 & MASK. */ names[0] = NULL_TREE; names[1] = NULL_TREE; cst2 = NULL_TREE; - if (is_gimple_assign (def_stmt) - && gimple_assign_rhs_code (def_stmt) == BIT_AND_EXPR) + if (rhs_code == BIT_AND_EXPR + || (CONVERT_EXPR_CODE_P (rhs_code) + && TREE_CODE (TREE_TYPE (val)) == INTEGER_TYPE + && TYPE_UNSIGNED (TREE_TYPE (val)) + && TYPE_PRECISION (TREE_TYPE (gimple_assign_rhs1 (def_stmt))) + > prec + && !retval)) { name2 = gimple_assign_rhs1 (def_stmt); - cst2 = gimple_assign_rhs2 (def_stmt); + if (rhs_code == BIT_AND_EXPR) + cst2 = gimple_assign_rhs2 (def_stmt); + else + { + cst2 = TYPE_MAX_VALUE (TREE_TYPE (val)); + nprec = TYPE_PRECISION (TREE_TYPE (name2)); + } if (TREE_CODE (name2) == SSA_NAME && INTEGRAL_TYPE_P (TREE_TYPE (name2)) && TREE_CODE (cst2) == INTEGER_CST && !integer_zerop (cst2) - && prec <= HOST_BITS_PER_DOUBLE_INT - && (prec > 1 + && nprec <= HOST_BITS_PER_DOUBLE_INT + && (nprec > 1 || TYPE_UNSIGNED (TREE_TYPE (val)))) { gimple def_stmt2 = SSA_NAME_DEF_STMT (name2); @@ -4881,12 +4901,12 @@ register_edge_assert_for_2 (tree name, e bool valid_p = false, valn = false, cst2n = false; enum tree_code ccode = comp_code; - valv = tree_to_double_int (val).zext (prec); - cst2v = tree_to_double_int (cst2).zext (prec); + valv = tree_to_double_int (val).zext (nprec); + cst2v = tree_to_double_int (cst2).zext (nprec); if (!TYPE_UNSIGNED (TREE_TYPE (val))) { - valn = valv.sext (prec).is_negative (); - cst2n = cst2v.sext (prec).is_negative (); + valn = valv.sext (nprec).is_negative (); + cst2n = cst2v.sext (nprec).is_negative (); } /* If CST2 doesn't have most significant bit set, but VAL is negative, we have comparison like @@ -4894,7 +4914,7 @@ register_edge_assert_for_2 (tree name, e if (!cst2n && valn) ccode = ERROR_MARK; if (cst2n) - sgnbit = double_int_one.llshift (prec - 1, prec).zext (prec); + sgnbit = double_int_one.llshift (nprec - 1, nprec).zext (nprec); else sgnbit = double_int_zero; minv = valv & cst2v; @@ -4906,12 +4926,12 @@ register_edge_assert_for_2 (tree name, e have folded the comparison into false) and maximum unsigned value is VAL | ~CST2. */ maxv = valv | ~cst2v; - maxv = maxv.zext (prec); + maxv = maxv.zext (nprec); valid_p = true; break; case NE_EXPR: tem = valv | ~cst2v; - tem = tem.zext (prec); + tem = tem.zext (nprec); /* If VAL is 0, handle (X & CST2) != 0 as (X & CST2) > 0U. */ if (valv.is_zero ()) { @@ -4921,7 +4941,7 @@ register_edge_assert_for_2 (tree name, e } /* If (VAL | ~CST2) is all ones, handle it as (X & CST2) < VAL. */ - if (tem == double_int::mask (prec)) + if (tem == double_int::mask (nprec)) { cst2n = false; valn = false; @@ -4929,8 +4949,9 @@ register_edge_assert_for_2 (tree name, e goto lt_expr; } if (!cst2n - && cst2v.sext (prec).is_negative ()) - sgnbit = double_int_one.llshift (prec - 1, prec).zext (prec); + && cst2v.sext (nprec).is_negative ()) + sgnbit + = double_int_one.llshift (nprec - 1, nprec).zext (nprec); if (!sgnbit.is_zero ()) { if (valv == sgnbit) @@ -4939,7 +4960,7 @@ register_edge_assert_for_2 (tree name, e valn = true; goto gt_expr; } - if (tem == double_int::mask (prec - 1)) + if (tem == double_int::mask (nprec - 1)) { cst2n = true; goto lt_expr; @@ -4958,22 +4979,22 @@ register_edge_assert_for_2 (tree name, e { /* If (VAL & CST2) != VAL, X & CST2 can't be equal to VAL. */ - minv = masked_increment (valv, cst2v, sgnbit, prec); + minv = masked_increment (valv, cst2v, sgnbit, nprec); if (minv == valv) break; } - maxv = double_int::mask (prec - (cst2n ? 1 : 0)); + maxv = double_int::mask (nprec - (cst2n ? 1 : 0)); valid_p = true; break; case GT_EXPR: gt_expr: /* Find out smallest MINV where MINV > VAL && (MINV & CST2) == MINV, if any. If VAL is signed and - CST2 has MSB set, compute it biased by 1 << (prec - 1). */ - minv = masked_increment (valv, cst2v, sgnbit, prec); + CST2 has MSB set, compute it biased by 1 << (nprec - 1). */ + minv = masked_increment (valv, cst2v, sgnbit, nprec); if (minv == valv) break; - maxv = double_int::mask (prec - (cst2n ? 1 : 0)); + maxv = double_int::mask (nprec - (cst2n ? 1 : 0)); valid_p = true; break; case LE_EXPR: @@ -4989,13 +5010,13 @@ register_edge_assert_for_2 (tree name, e maxv = valv; else { - maxv = masked_increment (valv, cst2v, sgnbit, prec); + maxv = masked_increment (valv, cst2v, sgnbit, nprec); if (maxv == valv) break; maxv -= double_int_one; } maxv |= ~cst2v; - maxv = maxv.zext (prec); + maxv = maxv.zext (nprec); minv = sgnbit; valid_p = true; break; @@ -5017,13 +5038,13 @@ register_edge_assert_for_2 (tree name, e } else { - maxv = masked_increment (valv, cst2v, sgnbit, prec); + maxv = masked_increment (valv, cst2v, sgnbit, nprec); if (maxv == valv) break; } maxv -= double_int_one; maxv |= ~cst2v; - maxv = maxv.zext (prec); + maxv = maxv.zext (nprec); minv = sgnbit; valid_p = true; break; @@ -5031,7 +5052,7 @@ register_edge_assert_for_2 (tree name, e break; } if (valid_p - && (maxv - minv).zext (prec) != double_int::mask (prec)) + && (maxv - minv).zext (nprec) != double_int::mask (nprec)) { tree tmp, new_val, type; int i; @@ -5044,7 +5065,7 @@ register_edge_assert_for_2 (tree name, e type = TREE_TYPE (names[i]); if (!TYPE_UNSIGNED (type)) { - type = build_nonstandard_integer_type (prec, 1); + type = build_nonstandard_integer_type (nprec, 1); tmp = build1 (NOP_EXPR, type, names[i]); } if (!minv.is_zero ()) --- gcc/testsuite/gcc.dg/tree-ssa/vrp85.c.jj 2012-10-04 11:32:18.787781121 +0200 +++ gcc/testsuite/gcc.dg/tree-ssa/vrp85.c 2012-10-04 11:49:18.128031124 +0200 @@ -0,0 +1,40 @@ +/* PR tree-optimization/54810 */ +/* { dg-do link } */ +/* { dg-options "-O2 -fdump-tree-vrp1" } */ + +extern void link_error (void); + +#define T(n, ntype, wtype) \ +void \ +f##n (wtype s) \ +{ \ + if ((ntype) s == 0) \ + return; \ + if (s == 0) \ + link_error (); \ +} + +T(1, unsigned char, unsigned char) +T(2, unsigned char, unsigned short) +T(3, unsigned char, unsigned int) +T(4, unsigned char, unsigned long int) +T(5, unsigned char, unsigned long long int) +T(6, unsigned short int, unsigned short int) +T(7, unsigned short int, unsigned int) +T(8, unsigned short int, unsigned long int) +T(9, unsigned short int, unsigned long long int) +T(10, unsigned int, unsigned int) +T(11, unsigned int, unsigned long int) +T(12, unsigned int, unsigned long long int) +T(13, unsigned long int, unsigned long int) +T(14, unsigned long int, unsigned long long int) +T(15, unsigned long long int, unsigned long long int) + +int +main () +{ + return 0; +} + +/* { dg-final { scan-tree-dump-not "link_error" "vrp1"} } */ +/* { dg-final { cleanup-tree-dump "vrp1" } } */