From patchwork Sun Jul 1 08:05:07 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Aldy Hernandez X-Patchwork-Id: 937510 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-480803-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="Yi69jbKg"; 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 41JNGv0qpWz9s1b for ; Sun, 1 Jul 2018 18:05:23 +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:to :from:subject:message-id:date:mime-version:content-type; q=dns; s=default; b=fCohjuMCSQq0LiZhtqZ8kjeX9XIqZXpDBIUWkJIT+595wjcKz8 DHCV/TxY330Hh58qlbOGpzmjoWJGADsYF4WyN33bxdph6fkEkmJzoS2g+FT3dopk jcF3DG8TeD788/dtIvqwyzKbzDJh4ZIHCalwl025DxTr11oYZh38vu9fQ= 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:to :from:subject:message-id:date:mime-version:content-type; s= default; bh=CzNMCG25RuAuSFnVNRsvRY6zYsI=; b=Yi69jbKgEVyhpIqsfjGz HBZrzjGfhZ1ls85ti8ERo1TvcvThd8QW4fmHyqawh041DQyE3/VJa06rfr3jRlwn XjZrCiE0s/fVkBkN9CvjGuNbVAsTgGxXvbTlgP96EbdN9L7W22KJ+CXTAyAWJjOc U6BWWYDgfIZHZMBFrAEsVso= Received: (qmail 57788 invoked by alias); 1 Jul 2018 08:05:15 -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 57779 invoked by uid 89); 1 Jul 2018 08:05:14 -0000 Authentication-Results: sourceware.org; auth=none X-Spam-SWARE-Status: No, score=-24.0 required=5.0 tests=GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, KAM_LAZY_DOMAIN_SECURITY, RCVD_IN_DNSWL_NONE autolearn=unavailable version=3.3.2 spammy= X-HELO: mail-wm0-f46.google.com Received: from mail-wm0-f46.google.com (HELO mail-wm0-f46.google.com) (74.125.82.46) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Sun, 01 Jul 2018 08:05:12 +0000 Received: by mail-wm0-f46.google.com with SMTP id v25-v6so5012426wmc.0 for ; Sun, 01 Jul 2018 01:05:12 -0700 (PDT) Received: from abulafia.quesejoda.com (247.red-79-147-188.dynamicip.rima-tde.net. [79.147.188.247]) by smtp.gmail.com with ESMTPSA id h193-v6sm10104939wmd.25.2018.07.01.01.05.08 for (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Sun, 01 Jul 2018 01:05:09 -0700 (PDT) To: gcc-patches From: Aldy Hernandez Subject: abstract ABS_EXPR code for ranges into separate function Message-ID: <10061ca8-17c2-4ffe-ed44-d7a06db8bfb4@redhat.com> Date: Sun, 1 Jul 2018 04:05:07 -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 Boy those extract_range_from_*_expr functions are huge. OK to move the ABS_EXPR code into its own function? Tested on x86-64 Linux. Aldy commit 1e0dd52b909722e9387a34ef546fc308c68dac23 Author: Aldy Hernandez Date: Fri Jun 29 20:12:36 2018 +0200 * tree-vrp.c (extract_range_from_unary_expr): Abstract ABS_EXPR code... (extract_range_from_abs_expr): ...here. diff --git a/gcc/ChangeLog b/gcc/ChangeLog index d1bb6f54d4a..ddbbdd1253e 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,9 @@ +2018-06-29 Aldy Hernandez + + * tree-vrp.c (extract_range_from_unary_expr): Abstract ABS_EXPR + code... + (extract_range_from_abs_expr): ...here. + 2018-06-29 Aldy Hernandez * tree-vrp.c (extract_range_from_binary_expr_1): Abstract a lot of the diff --git a/gcc/tree-vrp.c b/gcc/tree-vrp.c index ee112bb1826..c966334acbc 100644 --- a/gcc/tree-vrp.c +++ b/gcc/tree-vrp.c @@ -2365,6 +2365,85 @@ extract_range_from_binary_expr_1 (value_range *vr, set_value_range (vr, type, min, max, NULL); } +/* Calculates the absolute value of a range and puts the result in VR. + VR0 is the input range. TYPE is the type of the resulting + range. */ + +static void +extract_range_from_abs_expr (value_range &vr, tree type, value_range &vr0) +{ + /* Pass through vr0 in the easy cases. */ + if (TYPE_UNSIGNED (type) + || value_range_nonnegative_p (&vr0)) + { + copy_value_range (&vr, &vr0); + return; + } + + /* For the remaining varying or symbolic ranges we can't do anything + useful. */ + if (vr0.type == VR_VARYING + || symbolic_range_p (&vr0)) + { + set_value_range_to_varying (&vr); + return; + } + + /* -TYPE_MIN_VALUE = TYPE_MIN_VALUE with flag_wrapv so we can't get a + useful range. */ + if (!TYPE_OVERFLOW_UNDEFINED (type) + && ((vr0.type == VR_RANGE + && vrp_val_is_min (vr0.min)) + || (vr0.type == VR_ANTI_RANGE + && !vrp_val_is_min (vr0.min)))) + { + set_value_range_to_varying (&vr); + return; + } + + /* ABS_EXPR may flip the range around, if the original range + included negative values. */ + tree min, max; + if (!vrp_val_is_min (vr0.min)) + min = fold_unary_to_constant (ABS_EXPR, type, vr0.min); + else + min = TYPE_MAX_VALUE (type); + + if (!vrp_val_is_min (vr0.max)) + max = fold_unary_to_constant (ABS_EXPR, type, vr0.max); + else + max = TYPE_MAX_VALUE (type); + + int cmp = compare_values (min, max); + gcc_assert (vr0.type != VR_ANTI_RANGE); + + /* If the range contains zero then we know that the minimum value in the + range will be zero. */ + if (range_includes_zero_p (vr0.min, vr0.max) == 1) + { + if (cmp == 1) + max = min; + min = build_int_cst (type, 0); + } + else + { + /* If the range was reversed, swap MIN and MAX. */ + if (cmp == 1) + std::swap (min, max); + } + + cmp = compare_values (min, max); + if (cmp == -2 || cmp == 1) + { + /* If the new range has its limits swapped around (MIN > MAX), + then the operation caused one of them to wrap around, mark + the new range VARYING. */ + set_value_range_to_varying (&vr); + } + else + set_value_range (&vr, vr0.type, min, max, NULL); +} + /* Extract range information from a unary operation CODE based on the range of its operand *VR0 with type OP0_TYPE with resulting type TYPE. The resulting range is stored in *VR. */ @@ -2495,117 +2574,7 @@ extract_range_from_unary_expr (value_range *vr, return; } else if (code == ABS_EXPR) - { - tree min, max; - int cmp; - - /* Pass through vr0 in the easy cases. */ - if (TYPE_UNSIGNED (type) - || value_range_nonnegative_p (&vr0)) - { - copy_value_range (vr, &vr0); - return; - } - - /* For the remaining varying or symbolic ranges we can't do anything - useful. */ - if (vr0.type == VR_VARYING - || symbolic_range_p (&vr0)) - { - set_value_range_to_varying (vr); - return; - } - - /* -TYPE_MIN_VALUE = TYPE_MIN_VALUE with flag_wrapv so we can't get a - useful range. */ - if (!TYPE_OVERFLOW_UNDEFINED (type) - && ((vr0.type == VR_RANGE - && vrp_val_is_min (vr0.min)) - || (vr0.type == VR_ANTI_RANGE - && !vrp_val_is_min (vr0.min)))) - { - set_value_range_to_varying (vr); - return; - } - - /* ABS_EXPR may flip the range around, if the original range - included negative values. */ - if (!vrp_val_is_min (vr0.min)) - min = fold_unary_to_constant (code, type, vr0.min); - else - min = TYPE_MAX_VALUE (type); - - if (!vrp_val_is_min (vr0.max)) - max = fold_unary_to_constant (code, type, vr0.max); - else - max = TYPE_MAX_VALUE (type); - - cmp = compare_values (min, max); - - /* If a VR_ANTI_RANGEs contains zero, then we have - ~[-INF, min(MIN, MAX)]. */ - if (vr0.type == VR_ANTI_RANGE) - { - if (range_includes_zero_p (vr0.min, vr0.max) == 1) - { - /* Take the lower of the two values. */ - if (cmp != 1) - max = min; - - /* Create ~[-INF, min (abs(MIN), abs(MAX))] - or ~[-INF + 1, min (abs(MIN), abs(MAX))] when - flag_wrapv is set and the original anti-range doesn't include - TYPE_MIN_VALUE, remember -TYPE_MIN_VALUE = TYPE_MIN_VALUE. */ - if (TYPE_OVERFLOW_WRAPS (type)) - { - tree type_min_value = TYPE_MIN_VALUE (type); - - min = (vr0.min != type_min_value - ? int_const_binop (PLUS_EXPR, type_min_value, - build_int_cst (TREE_TYPE (type_min_value), 1)) - : type_min_value); - } - else - min = TYPE_MIN_VALUE (type); - } - else - { - /* All else has failed, so create the range [0, INF], even for - flag_wrapv since TYPE_MIN_VALUE is in the original - anti-range. */ - vr0.type = VR_RANGE; - min = build_int_cst (type, 0); - max = TYPE_MAX_VALUE (type); - } - } - - /* If the range contains zero then we know that the minimum value in the - range will be zero. */ - else if (range_includes_zero_p (vr0.min, vr0.max) == 1) - { - if (cmp == 1) - max = min; - min = build_int_cst (type, 0); - } - else - { - /* If the range was reversed, swap MIN and MAX. */ - if (cmp == 1) - std::swap (min, max); - } - - cmp = compare_values (min, max); - if (cmp == -2 || cmp == 1) - { - /* If the new range has its limits swapped around (MIN > MAX), - then the operation caused one of them to wrap around, mark - the new range VARYING. */ - set_value_range_to_varying (vr); - } - else - set_value_range (vr, vr0.type, min, max, NULL); - return; - } + return extract_range_from_abs_expr (*vr, type, vr0); /* For unhandled operations fall back to varying. */ set_value_range_to_varying (vr);