From patchwork Mon Aug 27 12:24:33 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Aldy Hernandez X-Patchwork-Id: 962496 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=gcc.gnu.org (client-ip=209.132.180.131; helo=sourceware.org; envelope-from=gcc-patches-return-484494-incoming=patchwork.ozlabs.org@gcc.gnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=redhat.com Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.b="xr0/cmLA"; dkim-atps=neutral Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 41zWL41gkMz9s1x for ; Mon, 27 Aug 2018 22:24:58 +1000 (AEST) DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:from :subject:to:message-id:date:mime-version:content-type; q=dns; s= default; b=eNW2+qkSEaGzPH0EotgvY+QIpNGSKnVC0QghL5vGmLvoc6OsgNG0q kzqD2IgaIupKc2YaWCTa3dHJMKBcJ6VDmV7lWE5BXo/Dbhox10oP+j5pa1CWZvAM FnDUKWGjaAvoWs/oYiDh67mG9RY/Q0eujMV5+jNXAGwbM1rgFKmLlc= 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:from :subject:to:message-id:date:mime-version:content-type; s= default; bh=rVqcWra+HtE1HqkfxLexh6vI8nk=; b=xr0/cmLArwZ7b4qUDWoi SqgDfoLj9W8CLGpsX17Uc2/PqYb7022DbsP+rwNYM0O27EEJgYQg7Q1c6bncnFq1 2NHogJktlmdn4JLxkW+D8pWrFWNkCKv4hO8fVWF4Iqr9BvRIH+OCdw1/iTdc1S2u UgqaPeOyQbHdo1UT0hA+xuc= Received: (qmail 61300 invoked by alias); 27 Aug 2018 12:24:49 -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 61181 invoked by uid 89); 27 Aug 2018 12:24:40 -0000 Authentication-Results: sourceware.org; auth=none X-Spam-SWARE-Status: No, score=-24.0 required=5.0 tests=BAYES_40, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, KAM_LAZY_DOMAIN_SECURITY, RCVD_IN_DNSWL_NONE autolearn=ham version=3.3.2 spammy=brought, choosing, 996, regtest X-HELO: mail-wr1-f45.google.com Received: from mail-wr1-f45.google.com (HELO mail-wr1-f45.google.com) (209.85.221.45) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Mon, 27 Aug 2018 12:24:37 +0000 Received: by mail-wr1-f45.google.com with SMTP id a108-v6so13421457wrc.13 for ; Mon, 27 Aug 2018 05:24:36 -0700 (PDT) Received: from abulafia.quesejoda.com (131.107.133.37.dynamic.jazztel.es. [37.133.107.131]) by smtp.gmail.com with ESMTPSA id z11-v6sm14611302wrm.94.2018.08.27.05.24.33 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 27 Aug 2018 05:24:34 -0700 (PDT) From: Aldy Hernandez Subject: VRP: abstract out wide int CONVERT_EXPR_P code To: Richard Biener , gcc-patches Message-ID: Date: Mon, 27 Aug 2018 08:24:33 -0400 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:52.0) Gecko/20100101 Thunderbird/52.8.0 MIME-Version: 1.0 X-IsSubscribed: yes Howdy! Phew, I think this is the last abstraction. This handles the unary CONVERT_EXPR_P code. It's the usual story-- normalize the symbolics to [-MIN,+MAX] and handle everything generically. Normalizing the symbolics brought about some nice surprises. We now handle a few things we were punting on before, which I've documented in the patch, but can remove if so desired. I wrote them mainly for myself: /* NOTES: Previously we were returning VARYING for all symbolics, but we can do better by treating them as [-MIN, +MAX]. For example, converting [SYM, SYM] from INT to LONG UNSIGNED, we can return: ~[0x8000000, 0xffffffff7fffffff]. We were also failing to convert ~[0,0] from char* to unsigned, instead choosing to return VR_VARYING. Now we return ~[0,0]. */ Tested on x86-64 by the usual bootstrap and regtest gymnastics, including --enable-languages=all, because my past sins are still haunting me. OK? gcc/ * wide-int-range.cc (wide_int_range_convert_tree): New. * wide-int-range.h (wide_int_range_convert_tree): New. * tree-vrp.c (extract_range_from_unary_expr): Abstract wide int code into wide_int_range_convert_tree. (extract_range_into_wide_ints): Do not munge anti range constants into the entire domain. Just return the range back. diff --git a/gcc/tree-vrp.c b/gcc/tree-vrp.c index f20730a85ba..89fbbffcd2e 100644 --- a/gcc/tree-vrp.c +++ b/gcc/tree-vrp.c @@ -995,7 +995,7 @@ ranges_from_anti_range (value_range *ar, /* Extract the components of a value range into a pair of wide ints in [WMIN, WMAX]. - If the value range is anything but a VR_RANGE of constants, the + If the value range is anything but a VR_*RANGE of constants, the resulting wide ints are set to [-MIN, +MAX] for the type. */ static void inline @@ -1003,7 +1003,10 @@ extract_range_into_wide_ints (value_range *vr, signop sign, unsigned prec, wide_int &wmin, wide_int &wmax) { - if (range_int_cst_p (vr)) + if ((vr->type == VR_RANGE + || vr->type == VR_ANTI_RANGE) + && TREE_CODE (vr->min) == INTEGER_CST + && TREE_CODE (vr->max) == INTEGER_CST) { wmin = wi::to_wide (vr->min); wmax = wi::to_wide (vr->max); @@ -1894,44 +1897,35 @@ extract_range_from_unary_expr (value_range *vr, return; } - /* If VR0 is varying and we increase the type precision, assume - a full range for the following transformation. */ - if (vr0.type == VR_VARYING - && INTEGRAL_TYPE_P (inner_type) - && TYPE_PRECISION (inner_type) < TYPE_PRECISION (outer_type)) - { - vr0.type = VR_RANGE; - vr0.min = TYPE_MIN_VALUE (inner_type); - vr0.max = TYPE_MAX_VALUE (inner_type); - } - - /* If VR0 is a constant range or anti-range and the conversion is - not truncating we can convert the min and max values and - canonicalize the resulting range. Otherwise we can do the - conversion if the size of the range is less than what the - precision of the target type can represent and the range is - not an anti-range. */ - if ((vr0.type == VR_RANGE - || vr0.type == VR_ANTI_RANGE) + /* We normalize everything to a VR_RANGE, but for constant + anti-ranges we must handle them by leaving the final result + as an anti range. This allows us to convert things like + ~[0,5] seamlessly. */ + value_range_type vr_type = VR_RANGE; + if (vr0.type == VR_ANTI_RANGE && TREE_CODE (vr0.min) == INTEGER_CST - && TREE_CODE (vr0.max) == INTEGER_CST - && (TYPE_PRECISION (outer_type) >= TYPE_PRECISION (inner_type) - || (vr0.type == VR_RANGE - && integer_zerop (int_const_binop (RSHIFT_EXPR, - int_const_binop (MINUS_EXPR, vr0.max, vr0.min), - size_int (TYPE_PRECISION (outer_type))))))) - { - tree new_min, new_max; - new_min = force_fit_type (outer_type, wi::to_widest (vr0.min), - 0, false); - new_max = force_fit_type (outer_type, wi::to_widest (vr0.max), - 0, false); - set_and_canonicalize_value_range (vr, vr0.type, - new_min, new_max, NULL); - return; - } + && TREE_CODE (vr0.max) == INTEGER_CST) + vr_type = VR_ANTI_RANGE; - set_value_range_to_varying (vr); + /* NOTES: Previously we were returning VARYING for all symbolics, but + we can do better by treating them as [-MIN, +MAX]. For + example, converting [SYM, SYM] from INT to LONG UNSIGNED, + we can return: ~[0x8000000, 0xffffffff7fffffff]. + + We were also failing to convert ~[0,0] from char* to unsigned, + instead choosing to return VR_VARYING. Now we return ~[0,0]. */ + wide_int vr0_min, vr0_max; + signop inner_sign = TYPE_SIGN (inner_type); + unsigned inner_prec = TYPE_PRECISION (inner_type); + tree tmin, tmax; + extract_range_into_wide_ints (&vr0, inner_sign, inner_prec, + vr0_min, vr0_max); + if (wide_int_range_convert_tree (tmin, tmax, outer_type, + inner_sign, inner_prec, + vr0_min, vr0_max)) + set_and_canonicalize_value_range (vr, vr_type, tmin, tmax, NULL); + else + set_value_range_to_varying (vr); return; } else if (code == ABS_EXPR) diff --git a/gcc/wide-int-range.cc b/gcc/wide-int-range.cc index 3cdcede04cd..d3e1424e77f 100644 --- a/gcc/wide-int-range.cc +++ b/gcc/wide-int-range.cc @@ -665,6 +665,42 @@ wide_int_range_abs (wide_int &min, wide_int &max, return true; } +/* Convert range in VR0 to OUTER_TYPE and store the result in a pair of + trees [TMIN, TMAX]. + + Return TRUE if we were able to successfully calculate the new range. + + Caller is responsible for canonicalizing the resulting range. */ + +bool +wide_int_range_convert_tree (tree &tmin, tree &tmax, + tree outer_type, + signop inner_sign, + unsigned inner_prec, + const wide_int &vr0_min, + const wide_int &vr0_max) +{ + /* If the conversion is not truncating we can convert the min and + max values and canonicalize the resulting range. Otherwise we + can do the conversion if the size of the range is less than what + the precision of the target type can represent. */ + if (TYPE_PRECISION (outer_type) >= inner_prec + || wi::rshift (wi::sub (vr0_max, vr0_min), + wi::uhwi (TYPE_PRECISION (outer_type), inner_prec), + inner_sign) == 0) + { + signop outer_sign = TYPE_SIGN (outer_type); + outer_sign = inner_sign; + tmin = force_fit_type (outer_type, + widest_int::from (vr0_min, outer_sign), 0, false); + tmax = force_fit_type (outer_type, + widest_int::from (vr0_max, outer_sign), 0, false); + return (!operand_equal_p (tmin, TYPE_MIN_VALUE (outer_type), 0) + || !operand_equal_p (tmax, TYPE_MAX_VALUE (outer_type), 0)); + } + return false; +} + /* Calculate a division operation on two ranges and store the result in [WMIN, WMAX] U [EXTRA_MIN, EXTRA_MAX]. diff --git a/gcc/wide-int-range.h b/gcc/wide-int-range.h index 427ef34c6b4..6aa0b76b6e3 100644 --- a/gcc/wide-int-range.h +++ b/gcc/wide-int-range.h @@ -99,6 +99,12 @@ extern bool wide_int_range_abs (wide_int &min, wide_int &max, const wide_int &vr0_min, const wide_int &vr0_max, bool overflow_undefined); +extern bool wide_int_range_convert_tree (tree &tmin, tree &tmax, + tree outer_type, + signop inner_sign, + unsigned inner_prec, + const wide_int &vr0_min, + const wide_int &vr0_max); extern bool wide_int_range_div (wide_int &wmin, wide_int &wmax, enum tree_code code, signop sign, unsigned prec,