From patchwork Sat Jan 17 02:09:31 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kugan Vivekanandarajah X-Patchwork-Id: 43264 Return-Path: X-Original-To: linaro@patches.linaro.org Delivered-To: linaro@patches.linaro.org Received: from mail-lb0-f200.google.com (mail-lb0-f200.google.com [209.85.217.200]) by ip-10-151-82-157.ec2.internal (Postfix) with ESMTPS id B5386240BA for ; Sat, 17 Jan 2015 02:10:36 +0000 (UTC) Received: by mail-lb0-f200.google.com with SMTP id u14sf12722102lbd.3 for ; Fri, 16 Jan 2015 18:10:35 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:delivered-to:mailing-list:precedence:list-id :list-unsubscribe:list-archive:list-post:list-help:sender :delivered-to:message-id:date:from:user-agent:mime-version:to:cc :subject:references:in-reply-to:content-type:x-original-sender :x-original-authentication-results; bh=NOwvfaAn/2H5Z4S1dI6tc0L6Au50nn/n/HNMG5o1Mo4=; b=NY9cVgngDr2uAAWXsaMqXAZjllNr/ljIY3QrCvwQ1x2mfuBWUFunWSe3q2gRmlQPrd ZXMEOIb1AzL1MV5Y3JvkEn7sAOXxsfoGAETph9xDEpVeZ0Od0yOGyAqwtNRGAXJt5NBf Ku8Qn6KS3SPdYgjdieacqWLlRk+Yf7eRrMTeahrKBCOQNvF9tMstKBqfqDgkhidUHiG3 XSJS/m/wGAB0RvijeN3IbZAYHML3VWxhOcwdRfXPNMRRYQcNuoH42/aLr5B33oj3c+1Z 5anZHIKfIUs/O8xJK3lkXSK4fC8ORcBofyjKx0mkfv5ImncxYJPPIBhMTijrjMt7iB5v 3OOw== X-Gm-Message-State: ALoCoQkm8w6w18wm17oJ+bu+Qtgpag12rHvWiszUJ5hapqgzuz70HdbnG6SJKgrt2cEJCFfodBW1 X-Received: by 10.180.89.211 with SMTP id bq19mr786309wib.4.1421460635236; Fri, 16 Jan 2015 18:10:35 -0800 (PST) X-BeenThere: patchwork-forward@linaro.org Received: by 10.152.206.70 with SMTP id lm6ls419885lac.41.gmail; Fri, 16 Jan 2015 18:10:35 -0800 (PST) X-Received: by 10.112.160.33 with SMTP id xh1mr18823630lbb.60.1421460635049; Fri, 16 Jan 2015 18:10:35 -0800 (PST) Received: from mail-la0-x22f.google.com (mail-la0-x22f.google.com. [2a00:1450:4010:c03::22f]) by mx.google.com with ESMTPS id u2si5857028lae.110.2015.01.16.18.10.34 for (version=TLSv1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Fri, 16 Jan 2015 18:10:34 -0800 (PST) Received-SPF: pass (google.com: domain of patch+caf_=patchwork-forward=linaro.org@linaro.org designates 2a00:1450:4010:c03::22f as permitted sender) client-ip=2a00:1450:4010:c03::22f; Received: by mail-la0-f47.google.com with SMTP id hz20so21720098lab.6 for ; Fri, 16 Jan 2015 18:10:34 -0800 (PST) X-Received: by 10.152.27.8 with SMTP id p8mr11826875lag.69.1421460634593; Fri, 16 Jan 2015 18:10:34 -0800 (PST) X-Forwarded-To: patchwork-forward@linaro.org X-Forwarded-For: patch@linaro.org patchwork-forward@linaro.org Delivered-To: patch@linaro.org Received: by 10.112.9.200 with SMTP id c8csp485417lbb; Fri, 16 Jan 2015 18:10:32 -0800 (PST) X-Received: by 10.70.103.197 with SMTP id fy5mr27351867pdb.131.1421460631889; Fri, 16 Jan 2015 18:10:31 -0800 (PST) Received: from sourceware.org (server1.sourceware.org. [209.132.180.131]) by mx.google.com with ESMTPS id rk11si7594161pab.99.2015.01.16.18.10.30 for (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Fri, 16 Jan 2015 18:10:31 -0800 (PST) Received-SPF: pass (google.com: domain of gcc-patches-return-389687-patch=linaro.org@gcc.gnu.org designates 209.132.180.131 as permitted sender) client-ip=209.132.180.131; Received: (qmail 7929 invoked by alias); 17 Jan 2015 02:10:11 -0000 Mailing-List: list patchwork-forward@linaro.org; contact patchwork-forward+owners@linaro.org Precedence: list 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 7874 invoked by uid 89); 17 Jan 2015 02:10:02 -0000 X-Virus-Found: No X-Spam-SWARE-Status: No, score=-2.6 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_LOW, SPF_PASS autolearn=ham version=3.3.2 X-HELO: mail-pa0-f49.google.com Received: from mail-pa0-f49.google.com (HELO mail-pa0-f49.google.com) (209.85.220.49) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with (AES128-SHA encrypted) ESMTPS; Sat, 17 Jan 2015 02:09:46 +0000 Received: by mail-pa0-f49.google.com with SMTP id eu11so27579309pac.8 for ; Fri, 16 Jan 2015 18:09:41 -0800 (PST) X-Received: by 10.70.47.6 with SMTP id z6mr17303751pdm.82.1421460581483; Fri, 16 Jan 2015 18:09:41 -0800 (PST) Received: from [192.168.1.6] ([112.134.156.250]) by mx.google.com with ESMTPSA id x10sm5253464pas.18.2015.01.16.18.09.38 (version=TLSv1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Fri, 16 Jan 2015 18:09:40 -0800 (PST) Message-ID: <54B9C45B.3010704@linaro.org> Date: Sat, 17 Jan 2015 13:09:31 +1100 From: Kugan User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Thunderbird/24.2.0 MIME-Version: 1.0 To: "gcc-patches@gcc.gnu.org" CC: Richard Biener , Jakub Jelinek , Jeff Law Subject: [RFC][PATCH 2/3] Propagate and save value ranges wrapped information References: <54B9C2EE.4050100@linaro.org> In-Reply-To: <54B9C2EE.4050100@linaro.org> X-IsSubscribed: yes X-Original-Sender: kugan.vivekanandarajah@linaro.org X-Original-Authentication-Results: mx.google.com; spf=pass (google.com: domain of patch+caf_=patchwork-forward=linaro.org@linaro.org designates 2a00:1450:4010:c03::22f as permitted sender) smtp.mail=patch+caf_=patchwork-forward=linaro.org@linaro.org; dkim=pass header.i=@gcc.gnu.org X-Google-Group-Id: 836684582541 This patch propagate value range wrapps attribute and save this to SSA_NAME. Thanks, Kugan gcc/ChangeLog: 2015-01-16 Kugan Vivekanandarajah * builtins.c (determine_block_size): Use new definition of get_range_info. * gimple-pretty-print.c (dump_ssaname_info): Dump new wrapped info. * internal-fn.c (get_range_pos_neg): Use new definition of get_range_info. (get_min_precision): Likewise. * tree-ssa-copy.c (fini_copy_prop): Use new definition of duplicate_ssa_range_info. * tree-ssa-loop-im.c (move_computations_dom_walker::before_dom_children): Likewise. * tree-ssa-pre.c (eliminate_dom_walker::before_dom_children): Likewise. * tree-ssa-loop-niter.c (determine_value_range): Use new definition. * tree-ssanames.c (set_range_info): Save wrapped information. (get_range_info): Retrive wrapped information. (set_nonzero_bits): Set wrapped info. (duplicate_ssa_name_range_info): Likewise. (duplicate_ssa_name_fn): Likewise. * tree-ssanames.h: (set_range_info): Update definition. (get_range_info): Ditto. * tree-vect-patterns.c (vect_recog_divmod_pattern): Use new declaration get_range_info. * tree-vrp.c (struct value_range_d): Add wrapped field. (set_value_range): Calculate and add wrapped field. (set_and_canonicalize_value_range): Likewise. (copy_value_range): Likewise. (set_value_range_to_value): Likewise. (set_value_range_to_nonnegative): Likewise. (set_value_range_to_nonnull): Likewise. (set_value_range_to_truthvalue): Likewise. (abs_extent_range): Likewise. (get_value_range): Return wrapped info. (update_value_range): Save wrapped info. (extract_range_from_assert): Extract and update wrapped info. (extract_range_from_ssa_name): Likewise. (vrp_int_const_binop): Likewise. (extract_range_from_multiplicative_op_1): Likewise. (extract_range_from_binary_expr_1): Likewise. (extract_range_from_binary_expr): Likewise. (extract_range_from_unary_expr_1): Likewise. (extract_range_from_comparison): Likewise. (extract_range_basic): Likewise. (adjust_range_with_scev): Likewise. (dump_value_range): Dump wrapped info. (remove_range_assertions): Update parameters. (vrp_intersect_ranges_1): Propagate wrapped info. (vrp_meet_1): Likewise. (vrp_visit_phi_node): Save wrapped info to SSA. (vrp_finalize): Likewise. * tree.h (SSA_NAME_ANTI_RANGE_P): Remove. (SSA_NAME_RANGE_OVF_P): New. gcc/testsuite/ChangeLog: 2015-01-16 Kugan Vivekanandarajah * gcc.dg/tree-ssa/vrp92.c: Update scanned pattern. diff --git a/gcc/builtins.c b/gcc/builtins.c index 9280704..83a0882 100644 --- a/gcc/builtins.c +++ b/gcc/builtins.c @@ -3150,7 +3150,7 @@ determine_block_size (tree len, rtx len_rtx, *probable_max_size = *max_size = GET_MODE_MASK (GET_MODE (len_rtx)); if (TREE_CODE (len) == SSA_NAME) - range_type = get_range_info (len, &min, &max); + range_type = get_range_info (len, &min, &max, NULL); if (range_type == VR_RANGE) { if (wi::fits_uhwi_p (min) && *min_size < min.to_uhwi ()) diff --git a/gcc/gimple-pretty-print.c b/gcc/gimple-pretty-print.c index 21e98c6..4d41bca 100644 --- a/gcc/gimple-pretty-print.c +++ b/gcc/gimple-pretty-print.c @@ -1812,13 +1812,15 @@ dump_ssaname_info (pretty_printer *buffer, tree node, int spc) && SSA_NAME_RANGE_INFO (node)) { wide_int min, max, nonzero_bits; - value_range_type range_type = get_range_info (node, &min, &max); + bool wrapped; + value_range_type range_type = get_range_info (node, &min, &max, &wrapped); if (range_type == VR_VARYING) pp_printf (buffer, "# RANGE VR_VARYING"); else if (range_type == VR_RANGE || range_type == VR_ANTI_RANGE) { pp_printf (buffer, "# RANGE "); + pp_printf (buffer, "WRAPPED = %s ", wrapped ? "true" : "false"); pp_printf (buffer, "%s[", range_type == VR_RANGE ? "" : "~"); pp_wide_int (buffer, min, TYPE_SIGN (TREE_TYPE (node))); pp_printf (buffer, ", "); diff --git a/gcc/internal-fn.c b/gcc/internal-fn.c index 07a9ec5..8955bb8 100644 --- a/gcc/internal-fn.c +++ b/gcc/internal-fn.c @@ -262,7 +262,7 @@ get_range_pos_neg (tree arg) if (TREE_CODE (arg) != SSA_NAME) return 3; wide_int arg_min, arg_max; - while (get_range_info (arg, &arg_min, &arg_max) != VR_RANGE) + while (get_range_info (arg, &arg_min, &arg_max, NULL) != VR_RANGE) { gimple g = SSA_NAME_DEF_STMT (arg); if (is_gimple_assign (g) @@ -344,7 +344,7 @@ get_min_precision (tree arg, signop sign) if (TREE_CODE (arg) != SSA_NAME) return prec + (orig_sign != sign); wide_int arg_min, arg_max; - while (get_range_info (arg, &arg_min, &arg_max) != VR_RANGE) + while (get_range_info (arg, &arg_min, &arg_max, NULL) != VR_RANGE) { gimple g = SSA_NAME_DEF_STMT (arg); if (is_gimple_assign (g) diff --git a/gcc/testsuite/gcc.dg/tree-ssa/vrp92.c b/gcc/testsuite/gcc.dg/tree-ssa/vrp92.c index a84ba8e..67a2afc 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/vrp92.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/vrp92.c @@ -18,6 +18,6 @@ int foo (int i, int j) return j; } -/* { dg-final { scan-tree-dump "res_.: \\\[1, 1\\\]" "vrp1" } } */ +/* { dg-final { scan-tree-dump "res_.: NOWRAPP \\\[1, 1\\\]" "vrp1" } } */ /* { dg-final { scan-tree-dump-not "Threaded" "vrp1" } } */ /* { dg-final { cleanup-tree-dump "vrp1" } } */ diff --git a/gcc/tree-ssa-copy.c b/gcc/tree-ssa-copy.c index 5ae8e6c..637588c 100644 --- a/gcc/tree-ssa-copy.c +++ b/gcc/tree-ssa-copy.c @@ -574,8 +574,8 @@ fini_copy_prop (void) && !SSA_NAME_RANGE_INFO (copy_of[i].value) && var_bb == copy_of_bb) duplicate_ssa_name_range_info (copy_of[i].value, - SSA_NAME_RANGE_TYPE (var), - SSA_NAME_RANGE_INFO (var)); + SSA_NAME_RANGE_INFO (var), + SSA_NAME_RANGE_WRAPPED_P (var)); } } diff --git a/gcc/tree-ssa-loop-im.c b/gcc/tree-ssa-loop-im.c index 9aba79b..3c97fb2 100644 --- a/gcc/tree-ssa-loop-im.c +++ b/gcc/tree-ssa-loop-im.c @@ -1245,7 +1245,6 @@ move_computations_dom_walker::before_dom_children (basic_block bb) { tree lhs = gimple_assign_lhs (new_stmt); SSA_NAME_RANGE_INFO (lhs) = NULL; - SSA_NAME_ANTI_RANGE_P (lhs) = 0; } gsi_insert_on_edge (loop_preheader_edge (level), new_stmt); remove_phi_node (&bsi, false); @@ -1315,7 +1314,6 @@ move_computations_dom_walker::before_dom_children (basic_block bb) { tree lhs = gimple_get_lhs (stmt); SSA_NAME_RANGE_INFO (lhs) = NULL; - SSA_NAME_ANTI_RANGE_P (lhs) = 0; } /* In case this is a stmt that is not unconditionally executed when the target loop header is executed and the stmt may diff --git a/gcc/tree-ssa-loop-niter.c b/gcc/tree-ssa-loop-niter.c index 7b0313a..5655e06 100644 --- a/gcc/tree-ssa-loop-niter.c +++ b/gcc/tree-ssa-loop-niter.c @@ -165,7 +165,7 @@ determine_value_range (struct loop *loop, tree type, tree var, mpz_t off, gphi_iterator gsi; /* Either for VAR itself... */ - rtype = get_range_info (var, &minv, &maxv); + rtype = get_range_info (var, &minv, &maxv, NULL); /* Or for PHI results in loop->header where VAR is used as PHI argument from the loop preheader edge. */ for (gsi = gsi_start_phis (loop->header); !gsi_end_p (gsi); gsi_next (&gsi)) @@ -173,7 +173,7 @@ determine_value_range (struct loop *loop, tree type, tree var, mpz_t off, gphi *phi = gsi.phi (); wide_int minc, maxc; if (PHI_ARG_DEF_FROM_EDGE (phi, e) == var - && (get_range_info (gimple_phi_result (phi), &minc, &maxc) + && (get_range_info (gimple_phi_result (phi), &minc, &maxc, NULL) == VR_RANGE)) { if (rtype != VR_RANGE) @@ -192,7 +192,7 @@ determine_value_range (struct loop *loop, tree type, tree var, mpz_t off, involved. */ if (wi::gt_p (minv, maxv, sgn)) { - rtype = get_range_info (var, &minv, &maxv); + rtype = get_range_info (var, &minv, &maxv, NULL); break; } } diff --git a/gcc/tree-ssa-pre.c b/gcc/tree-ssa-pre.c index 497890f..6a61232 100644 --- a/gcc/tree-ssa-pre.c +++ b/gcc/tree-ssa-pre.c @@ -4107,8 +4107,8 @@ eliminate_dom_walker::before_dom_children (basic_block b) && !SSA_NAME_RANGE_INFO (sprime) && b == sprime_b) duplicate_ssa_name_range_info (sprime, - SSA_NAME_RANGE_TYPE (lhs), - SSA_NAME_RANGE_INFO (lhs)); + SSA_NAME_RANGE_INFO (lhs), + SSA_NAME_RANGE_WRAPPED_P (lhs)); } /* Inhibit the use of an inserted PHI on a loop header when diff --git a/gcc/tree-ssanames.c b/gcc/tree-ssanames.c index 744dc43..6e49616 100644 --- a/gcc/tree-ssanames.c +++ b/gcc/tree-ssanames.c @@ -201,7 +201,7 @@ make_ssa_name_fn (struct function *fn, tree var, gimple stmt) void set_range_info (tree name, - const wide_int_ref &min, const wide_int_ref &max) + const wide_int_ref &min, const wide_int_ref &max, bool is_wrapped) { gcc_assert (!POINTER_TYPE_P (TREE_TYPE (name))); range_info_def *ri = SSA_NAME_RANGE_INFO (name); @@ -221,6 +221,7 @@ set_range_info (tree name, /* Set the values. */ ri->set_min (min); ri->set_max (max); + SSA_NAME_RANGE_WRAPPED_P (name) = is_wrapped; /* If it is a range, try to improve nonzero_bits from the min/max. */ if (wi::cmp (min, max, TYPE_SIGN (TREE_TYPE (name))) < 0) @@ -238,7 +239,7 @@ set_range_info (tree name, is used to determine if MIN and MAX are valid values. */ enum value_range_type -get_range_info (const_tree name, wide_int *min, wide_int *max) +get_range_info (const_tree name, wide_int *min, wide_int *max, bool *is_wrapped) { gcc_assert (!POINTER_TYPE_P (TREE_TYPE (name))); gcc_assert (min && max); @@ -266,6 +267,8 @@ get_range_info (const_tree name, wide_int *min, wide_int *max) *min = ri->get_min (); *max = ri->get_max (); } + if (is_wrapped) + *is_wrapped = SSA_NAME_RANGE_WRAPPED_P (name); return range_type; } @@ -278,7 +281,8 @@ set_nonzero_bits (tree name, const wide_int_ref &mask) if (SSA_NAME_RANGE_INFO (name) == NULL) set_range_info (name, TYPE_MIN_VALUE (TREE_TYPE (name)), - TYPE_MAX_VALUE (TREE_TYPE (name))); + TYPE_MAX_VALUE (TREE_TYPE (name)), + false); range_info_def *ri = SSA_NAME_RANGE_INFO (name); ri->set_nonzero_bits (mask); } @@ -505,14 +509,13 @@ duplicate_ssa_name_ptr_info (tree name, struct ptr_info_def *ptr_info) RANGE_TYPE for use by the SSA name NAME. */ void duplicate_ssa_name_range_info (tree name, - enum value_range_type range_type ATTRIBUTE_UNUSED, - struct range_info_def *range_info) + struct range_info_def *range_info, + bool is_wrapped) { struct range_info_def *new_range_info; gcc_assert (!POINTER_TYPE_P (TREE_TYPE (name))); gcc_assert (!SSA_NAME_RANGE_INFO (name)); - gcc_assert (!SSA_NAME_ANTI_RANGE_P (name)); if (!range_info) return; @@ -523,6 +526,7 @@ duplicate_ssa_name_range_info (tree name, new_range_info = static_cast (ggc_internal_alloc (size)); memcpy (new_range_info, range_info, size); + SSA_NAME_RANGE_WRAPPED_P (name) = is_wrapped; SSA_NAME_RANGE_INFO (name) = new_range_info; } @@ -547,8 +551,9 @@ duplicate_ssa_name_fn (struct function *fn, tree name, gimple stmt) struct range_info_def *old_range_info = SSA_NAME_RANGE_INFO (name); if (old_range_info) - duplicate_ssa_name_range_info (new_name, SSA_NAME_RANGE_TYPE (name), - old_range_info); + duplicate_ssa_name_range_info (new_name, + old_range_info, + SSA_NAME_RANGE_WRAPPED_P (name)); } return new_name; diff --git a/gcc/tree-ssanames.h b/gcc/tree-ssanames.h index 0d4b212..7bb33db 100644 --- a/gcc/tree-ssanames.h +++ b/gcc/tree-ssanames.h @@ -69,10 +69,10 @@ enum value_range_type { VR_UNDEFINED, VR_RANGE, VR_ANTI_RANGE, VR_VARYING }; /* Sets the value range to SSA. */ extern void set_range_info (tree, const wide_int_ref &, - const wide_int_ref &); + const wide_int_ref &, bool); /* Gets the value range from SSA. */ extern enum value_range_type get_range_info (const_tree, wide_int *, - wide_int *); + wide_int *, bool *); extern void set_nonzero_bits (tree, const wide_int_ref &); extern wide_int get_nonzero_bits (const_tree); extern void init_ssanames (struct function *, int); @@ -92,8 +92,9 @@ extern struct ptr_info_def *get_ptr_info (tree); extern tree copy_ssa_name_fn (struct function *, tree, gimple); extern void duplicate_ssa_name_ptr_info (tree, struct ptr_info_def *); extern tree duplicate_ssa_name_fn (struct function *, tree, gimple); -extern void duplicate_ssa_name_range_info (tree, enum value_range_type, - struct range_info_def *); +extern void duplicate_ssa_name_range_info (tree, + struct range_info_def *, + bool); extern void release_defs (gimple); extern void replace_ssa_name_symbol (tree, tree); diff --git a/gcc/tree-vect-patterns.c b/gcc/tree-vect-patterns.c index 814222b..09ca14d 100644 --- a/gcc/tree-vect-patterns.c +++ b/gcc/tree-vect-patterns.c @@ -2553,7 +2553,7 @@ vect_recog_divmod_pattern (vec *stmts, wide_int oprnd0_min, oprnd0_max; int msb = 1; - if (get_range_info (oprnd0, &oprnd0_min, &oprnd0_max) == VR_RANGE) + if (get_range_info (oprnd0, &oprnd0_min, &oprnd0_max, NULL) == VR_RANGE) { if (!wi::neg_p (oprnd0_min, TYPE_SIGN (itype))) msb = 0; diff --git a/gcc/tree-vrp.c b/gcc/tree-vrp.c index 9b7695d..832c35d 100644 --- a/gcc/tree-vrp.c +++ b/gcc/tree-vrp.c @@ -103,6 +103,9 @@ struct value_range_d tree min; tree max; + /* Set to true if values in this value range could wrapp. */ + bool is_wrapped; + /* Set of SSA names whose value ranges are equivalent to this one. This set is only valid when TYPE is VR_RANGE or VR_ANTI_RANGE. */ bitmap equiv; @@ -110,7 +113,7 @@ struct value_range_d typedef struct value_range_d value_range_t; -#define VR_INITIALIZER { VR_UNDEFINED, NULL_TREE, NULL_TREE, NULL } +#define VR_INITIALIZER { VR_UNDEFINED, NULL_TREE, NULL_TREE, false, NULL } /* Set of SSA names found live during the RPO traversal of the function for still active basic-blocks. */ @@ -447,7 +450,7 @@ set_value_range_to_varying (value_range_t *vr) static void set_value_range (value_range_t *vr, enum value_range_type t, tree min, - tree max, bitmap equiv) + tree max, bool is_wrapped, bitmap equiv) { #if defined ENABLE_CHECKING /* Check the validity of the range. */ @@ -481,6 +484,7 @@ set_value_range (value_range_t *vr, enum value_range_type t, tree min, vr->type = t; vr->min = min; vr->max = max; + vr->is_wrapped = is_wrapped; /* Since updating the equivalence set involves deep copying the bitmaps, only do it if absolutely necessary. */ @@ -509,7 +513,7 @@ set_value_range (value_range_t *vr, enum value_range_type t, tree min, static void set_and_canonicalize_value_range (value_range_t *vr, enum value_range_type t, - tree min, tree max, bitmap equiv) + tree min, tree max, bool is_wrapped, bitmap equiv) { /* Use the canonical setters for VR_UNDEFINED and VR_VARYING. */ if (t == VR_UNDEFINED) @@ -527,7 +531,7 @@ set_and_canonicalize_value_range (value_range_t *vr, enum value_range_type t, if (TREE_CODE (min) != INTEGER_CST || TREE_CODE (max) != INTEGER_CST) { - set_value_range (vr, t, min, max, equiv); + set_value_range (vr, t, min, max, is_wrapped, equiv); return; } @@ -615,7 +619,7 @@ set_and_canonicalize_value_range (value_range_t *vr, enum value_range_type t, return; } - set_value_range (vr, t, min, max, equiv); + set_value_range (vr, t, min, max, is_wrapped, equiv); } /* Copy value range FROM into value range TO. */ @@ -623,7 +627,8 @@ set_and_canonicalize_value_range (value_range_t *vr, enum value_range_type t, static inline void copy_value_range (value_range_t *to, value_range_t *from) { - set_value_range (to, from->type, from->min, from->max, from->equiv); + set_value_range (to, from->type, from->min, from->max, + from->is_wrapped, from->equiv); } /* Set value range VR to a single value. This function is only called @@ -637,7 +642,7 @@ set_value_range_to_value (value_range_t *vr, tree val, bitmap equiv) gcc_assert (is_gimple_min_invariant (val)); if (TREE_OVERFLOW_P (val)) val = drop_tree_overflow (val); - set_value_range (vr, VR_RANGE, val, val, equiv); + set_value_range (vr, VR_RANGE, val, val, false, equiv); } /* Set value range VR to a non-negative range of type TYPE. @@ -663,6 +668,7 @@ set_value_range_to_nonnegative (value_range_t *vr, tree type, (overflow_infinity ? positive_overflow_infinity (type) : TYPE_MAX_VALUE (type)), + false, vr->equiv); } @@ -672,7 +678,7 @@ static inline void set_value_range_to_nonnull (value_range_t *vr, tree type) { tree zero = build_int_cst (type, 0); - set_value_range (vr, VR_ANTI_RANGE, zero, zero, vr->equiv); + set_value_range (vr, VR_ANTI_RANGE, zero, zero, false, vr->equiv); } @@ -695,6 +701,7 @@ set_value_range_to_truthvalue (value_range_t *vr, tree type) else set_value_range (vr, VR_RANGE, build_int_cst (type, 0), build_int_cst (type, 1), + false, vr->equiv); } @@ -731,7 +738,7 @@ abs_extent_range (value_range_t *vr, tree min, tree max) set_value_range_to_varying (vr); return; } - set_and_canonicalize_value_range (vr, VR_RANGE, min, max, NULL); + set_and_canonicalize_value_range (vr, VR_RANGE, min, max, false, NULL); } @@ -744,7 +751,7 @@ static value_range_t * get_value_range (const_tree var) { static const struct value_range_d vr_const_varying - = { VR_VARYING, NULL_TREE, NULL_TREE, NULL }; + = { VR_VARYING, NULL_TREE, NULL_TREE, false, NULL }; value_range_t *vr; tree sym; unsigned ver = SSA_NAME_VERSION (var); @@ -842,6 +849,7 @@ update_value_range (const_tree var, value_range_t *new_vr) is_new = old_vr->type != new_vr->type || !vrp_operand_equal_p (old_vr->min, new_vr->min) || !vrp_operand_equal_p (old_vr->max, new_vr->max) + || old_vr->is_wrapped != new_vr->is_wrapped || !vrp_bitmap_equal_p (old_vr->equiv, new_vr->equiv); if (is_new) @@ -856,6 +864,7 @@ update_value_range (const_tree var, value_range_t *new_vr) set_value_range_to_varying (old_vr); else set_value_range (old_vr, new_vr->type, new_vr->min, new_vr->max, + new_vr->is_wrapped, new_vr->equiv); } @@ -1745,10 +1754,10 @@ extract_range_from_assert (value_range_t *vr_p, tree expr) this for us. */ if (cond_code == LE_EXPR) set_and_canonicalize_value_range (vr_p, VR_RANGE, - min, max, vr_p->equiv); + min, max, false, vr_p->equiv); else if (cond_code == GT_EXPR) set_and_canonicalize_value_range (vr_p, VR_ANTI_RANGE, - min, max, vr_p->equiv); + min, max, false, vr_p->equiv); else gcc_unreachable (); } @@ -1769,7 +1778,7 @@ extract_range_from_assert (value_range_t *vr_p, tree expr) max = limit; } - set_value_range (vr_p, range_type, min, max, vr_p->equiv); + set_value_range (vr_p, range_type, min, max, false, vr_p->equiv); /* When asserting the equality VAR == LIMIT and LIMIT is another SSA name, the new range will also inherit the equivalence set @@ -1821,7 +1830,7 @@ extract_range_from_assert (value_range_t *vr_p, tree expr) min = max = limit; set_and_canonicalize_value_range (vr_p, VR_ANTI_RANGE, - min, max, vr_p->equiv); + min, max, false, vr_p->equiv); } else if (cond_code == LE_EXPR || cond_code == LT_EXPR) { @@ -1860,7 +1869,7 @@ extract_range_from_assert (value_range_t *vr_p, tree expr) TREE_NO_WARNING (max) = 1; } - set_value_range (vr_p, VR_RANGE, min, max, vr_p->equiv); + set_value_range (vr_p, VR_RANGE, min, max, false, vr_p->equiv); } } else if (cond_code == GE_EXPR || cond_code == GT_EXPR) @@ -1900,7 +1909,7 @@ extract_range_from_assert (value_range_t *vr_p, tree expr) TREE_NO_WARNING (min) = 1; } - set_value_range (vr_p, VR_RANGE, min, max, vr_p->equiv); + set_value_range (vr_p, VR_RANGE, min, max, false, vr_p->equiv); } } else @@ -1932,7 +1941,7 @@ extract_range_from_ssa_name (value_range_t *vr, tree var) if (var_vr->type != VR_VARYING) copy_value_range (vr, var_vr); else - set_value_range (vr, VR_RANGE, var, var, NULL); + set_value_range (vr, VR_RANGE, var, var, false, NULL); add_equivalence (&vr->equiv, var); } @@ -1945,11 +1954,13 @@ extract_range_from_ssa_name (value_range_t *vr, tree var) the type does not support it. */ static tree -vrp_int_const_binop (enum tree_code code, tree val1, tree val2) +vrp_int_const_binop (enum tree_code code, tree val1, tree val2, bool *is_wrapped) { tree res; res = int_const_binop (code, val1, val2); + if (is_wrapped) + *is_wrapped = false; /* If we are using unsigned arithmetic, operate symbolically on -INF and +INF as int_const_binop only handles signed overflow. */ @@ -1993,7 +2004,10 @@ vrp_int_const_binop (enum tree_code code, tree val1, tree val2) else if (TYPE_OVERFLOW_WRAPS (TREE_TYPE (val1))) /* If the singed operation wraps then int_const_binop has done everything we want. */ - ; + { + if (is_wrapped) + *is_wrapped = true; + } /* Signed division of -1/0 overflows and by the time it gets here returns NULL_TREE. */ else if (!res) @@ -2187,6 +2201,8 @@ extract_range_from_multiplicative_op_1 (value_range_t *vr, tree min, max; bool sop; int cmp; + bool is_wrapped = false; + bool t_is_wrapped = false; /* Multiplications, divisions and shifts are a bit tricky to handle, depending on the mix of signs we have in the two ranges, we @@ -2216,35 +2232,43 @@ extract_range_from_multiplicative_op_1 (value_range_t *vr, /* Compute the 4 cross operations. */ sop = false; - val[0] = vrp_int_const_binop (code, vr0->min, vr1->min); + val[0] = vrp_int_const_binop (code, vr0->min, vr1->min, &t_is_wrapped); if (val[0] == NULL_TREE) sop = true; + if (t_is_wrapped) + is_wrapped = true; if (vr1->max == vr1->min) val[1] = NULL_TREE; else { - val[1] = vrp_int_const_binop (code, vr0->min, vr1->max); + val[1] = vrp_int_const_binop (code, vr0->min, vr1->max, &t_is_wrapped); if (val[1] == NULL_TREE) sop = true; + if (t_is_wrapped) + is_wrapped = true; } if (vr0->max == vr0->min) val[2] = NULL_TREE; else { - val[2] = vrp_int_const_binop (code, vr0->max, vr1->min); + val[2] = vrp_int_const_binop (code, vr0->max, vr1->min, &t_is_wrapped); if (val[2] == NULL_TREE) sop = true; + if (t_is_wrapped) + is_wrapped = true; } if (vr0->min == vr0->max || vr1->min == vr1->max) val[3] = NULL_TREE; else { - val[3] = vrp_int_const_binop (code, vr0->max, vr1->max); + val[3] = vrp_int_const_binop (code, vr0->max, vr1->max, &t_is_wrapped); if (val[3] == NULL_TREE) sop = true; + if (t_is_wrapped) + is_wrapped = true; } if (sop) @@ -2324,7 +2348,7 @@ extract_range_from_multiplicative_op_1 (value_range_t *vr, set_value_range_to_varying (vr); } else - set_value_range (vr, type, min, max, NULL); + set_value_range (vr, type, min, max, is_wrapped, NULL); } /* Extract range information from a binary operation CODE based on @@ -2341,6 +2365,7 @@ extract_range_from_binary_expr_1 (value_range_t *vr, enum value_range_type type; tree min = NULL_TREE, max = NULL_TREE; int cmp; + bool vr_is_wrapped = false; if (!INTEGRAL_TYPE_P (expr_type) && !POINTER_TYPE_P (expr_type)) @@ -2640,6 +2665,7 @@ extract_range_from_binary_expr_1 (value_range_t *vr, range kind and bounds appropriately. */ wide_int tmin = wide_int::from (wmin, prec, sgn); wide_int tmax = wide_int::from (wmax, prec, sgn); + vr_is_wrapped = true; if (min_ovf == max_ovf) { /* No overflow or both overflow or underflow. The @@ -2792,8 +2818,8 @@ extract_range_from_binary_expr_1 (value_range_t *vr, /* For operations that make the resulting range directly proportional to the original ranges, apply the operation to the same end of each range. */ - min = vrp_int_const_binop (code, vr0.min, vr1.min); - max = vrp_int_const_binop (code, vr0.max, vr1.max); + min = vrp_int_const_binop (code, vr0.min, vr1.min, NULL); + max = vrp_int_const_binop (code, vr0.max, vr1.max, NULL); } else if (code == MIN_EXPR) { @@ -2917,9 +2943,10 @@ extract_range_from_binary_expr_1 (value_range_t *vr, /* The following should handle the wrapping and selecting VR_ANTI_RANGE for us. */ + vr_is_wrapped = true; min = wide_int_to_tree (expr_type, prod0); max = wide_int_to_tree (expr_type, prod3); - set_and_canonicalize_value_range (vr, VR_RANGE, min, max, NULL); + set_and_canonicalize_value_range (vr, VR_RANGE, min, max, vr_is_wrapped, NULL); return; } @@ -3287,7 +3314,7 @@ extract_range_from_binary_expr_1 (value_range_t *vr, set_value_range_to_varying (vr); } else - set_value_range (vr, type, min, max, NULL); + set_value_range (vr, type, min, max, vr_is_wrapped, NULL); } /* Extract range information from a binary expression OP0 CODE OP1 based on @@ -3336,15 +3363,15 @@ extract_range_from_binary_expr (value_range_t *vr, /* Try with VR0 and [-INF, OP1]. */ if (is_gimple_min_invariant (minus_p ? vr0.max : vr0.min)) - set_value_range (&n_vr1, VR_RANGE, vrp_val_min (expr_type), op1, NULL); + set_value_range (&n_vr1, VR_RANGE, vrp_val_min (expr_type), op1, false, NULL); /* Try with VR0 and [OP1, +INF]. */ else if (is_gimple_min_invariant (minus_p ? vr0.min : vr0.max)) - set_value_range (&n_vr1, VR_RANGE, op1, vrp_val_max (expr_type), NULL); + set_value_range (&n_vr1, VR_RANGE, op1, vrp_val_max (expr_type), false, NULL); /* Try with VR0 and [OP1, OP1]. */ else - set_value_range (&n_vr1, VR_RANGE, op1, op1, NULL); + set_value_range (&n_vr1, VR_RANGE, op1, op1, false, NULL); extract_range_from_binary_expr_1 (vr, code, expr_type, &vr0, &n_vr1); } @@ -3360,15 +3387,15 @@ extract_range_from_binary_expr (value_range_t *vr, /* Try with [-INF, OP0] and VR1. */ if (is_gimple_min_invariant (minus_p ? vr1.max : vr1.min)) - set_value_range (&n_vr0, VR_RANGE, vrp_val_min (expr_type), op0, NULL); + set_value_range (&n_vr0, VR_RANGE, vrp_val_min (expr_type), op0, false, NULL); /* Try with [OP0, +INF] and VR1. */ else if (is_gimple_min_invariant (minus_p ? vr1.min : vr1.max)) - set_value_range (&n_vr0, VR_RANGE, op0, vrp_val_max (expr_type), NULL); + set_value_range (&n_vr0, VR_RANGE, op0, vrp_val_max (expr_type), false, NULL); /* Try with [OP0, OP0] and VR1. */ else - set_value_range (&n_vr0, VR_RANGE, op0, op0, NULL); + set_value_range (&n_vr0, VR_RANGE, op0, op0, false, NULL); extract_range_from_binary_expr_1 (vr, code, expr_type, &n_vr0, &vr1); } @@ -3384,6 +3411,7 @@ extract_range_from_unary_expr_1 (value_range_t *vr, value_range_t *vr0_, tree op0_type) { value_range_t vr0 = *vr0_, vrtem0 = VR_INITIALIZER, vrtem1 = VR_INITIALIZER; + bool vr_is_wrapped = false; /* VRP only operates on integral and pointer types. */ if (!(INTEGRAL_TYPE_P (op0_type) @@ -3504,15 +3532,23 @@ extract_range_from_unary_expr_1 (value_range_t *vr, if (is_overflow_infinity (vr0.min)) new_min = negative_overflow_infinity (outer_type); else - new_min = force_fit_type (outer_type, wi::to_widest (vr0.min), - 0, false); + { + if (!int_fits_type_p (vr0.min, outer_type)) + vr_is_wrapped = true; + new_min = force_fit_type (outer_type, wi::to_widest (vr0.min), + 0, false); + } if (is_overflow_infinity (vr0.max)) new_max = positive_overflow_infinity (outer_type); else - new_max = force_fit_type (outer_type, wi::to_widest (vr0.max), - 0, false); + { + if (!int_fits_type_p (vr0.max, outer_type)) + vr_is_wrapped = true; + 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); + new_min, new_max, vr_is_wrapped, NULL); return; } @@ -3626,6 +3662,7 @@ extract_range_from_unary_expr_1 (value_range_t *vr, anti-range. */ vr0.type = VR_RANGE; min = build_int_cst (type, 0); + vr_is_wrapped = true; if (needs_overflow_infinity (type)) { if (supports_overflow_infinity (type)) @@ -3669,7 +3706,7 @@ extract_range_from_unary_expr_1 (value_range_t *vr, set_value_range_to_varying (vr); } else - set_value_range (vr, vr0.type, min, max, NULL); + set_value_range (vr, vr0.type, min, max, vr_is_wrapped, NULL); return; } @@ -3763,7 +3800,7 @@ extract_range_from_comparison (value_range_t *vr, enum tree_code code, if (is_gimple_min_invariant (val)) set_value_range_to_value (vr, val, vr->equiv); else - set_value_range (vr, VR_RANGE, val, val, vr->equiv); + set_value_range (vr, VR_RANGE, val, val, false, vr->equiv); } else /* The result of a comparison is always true or false. */ @@ -4060,7 +4097,7 @@ extract_range_basic (value_range_t *vr, gimple stmt) goto bitop_builtin; bitop_builtin: set_value_range (vr, VR_RANGE, build_int_cst (type, mini), - build_int_cst (type, maxi), NULL); + build_int_cst (type, maxi), false, NULL); return; default: break; @@ -4150,7 +4187,7 @@ extract_range_basic (value_range_t *vr, gimple stmt) NULL); else set_value_range (vr, VR_RANGE, build_int_cst (type, 0), - build_int_cst (type, 1), NULL); + build_int_cst (type, 1), false, NULL); } else if (types_compatible_p (type, TREE_TYPE (op0)) && types_compatible_p (type, TREE_TYPE (op1))) @@ -4244,6 +4281,7 @@ adjust_range_with_scev (value_range_t *vr, struct loop *loop, { tree init, step, chrec, tmin, tmax, min, max, type, tem; enum ev_direction dir; + bool t_is_wrapped = false, is_wrapped = false; /* TODO. Don't adjust anti-ranges. An anti-range may provide better opportunities than a regular range, but I'm not sure. */ @@ -4339,6 +4377,7 @@ adjust_range_with_scev (value_range_t *vr, struct loop *loop, /* Likewise if the addition did. */ if (maxvr.type == VR_RANGE) { + t_is_wrapped = maxvr.is_wrapped; tmin = maxvr.min; tmax = maxvr.max; } @@ -4350,6 +4389,7 @@ adjust_range_with_scev (value_range_t *vr, struct loop *loop, { min = tmin; max = tmax; + is_wrapped = t_is_wrapped; /* For VARYING or UNDEFINED ranges, just about anything we get from scalar evolutions should be better. */ @@ -4403,7 +4443,7 @@ adjust_range_with_scev (value_range_t *vr, struct loop *loop, && is_positive_overflow_infinity (max))) return; - set_value_range (vr, VR_RANGE, min, max, vr->equiv); + set_value_range (vr, VR_RANGE, min, max, is_wrapped, vr->equiv); } @@ -4722,7 +4762,8 @@ dump_value_range (FILE *file, value_range_t *vr) { tree type = TREE_TYPE (vr->min); - fprintf (file, "%s[", (vr->type == VR_ANTI_RANGE) ? "~" : ""); + fprintf (file, "%s %s[", vr->is_wrapped ? "WRAPP" : "NOWRAPP", + (vr->type == VR_ANTI_RANGE) ? "~" : ""); if (is_negative_overflow_infinity (vr->min)) fprintf (file, "-INF(OVF)"); @@ -6917,7 +6958,8 @@ remove_range_assertions (void) { set_range_info (var, SSA_NAME_RANGE_INFO (lhs)->get_min (), - SSA_NAME_RANGE_INFO (lhs)->get_max ()); + SSA_NAME_RANGE_INFO (lhs)->get_max (), + SSA_NAME_RANGE_WRAPPED_P (lhs)); maybe_set_nonzero_bits (bb, var); } } @@ -8584,7 +8626,9 @@ vrp_intersect_ranges_1 (value_range_t *vr0, value_range_t *vr1) /* Make sure to canonicalize the result though as the inversion of a VR_RANGE can still be a VR_RANGE. */ set_and_canonicalize_value_range (vr0, vr0->type, - vr0->min, vr0->max, vr0->equiv); + vr0->min, vr0->max, + vr0->is_wrapped && vr1->is_wrapped, + vr0->equiv); /* If that failed, use the saved original VR0. */ if (vr0->type == VR_VARYING) { @@ -8635,7 +8679,7 @@ vrp_meet_1 (value_range_t *vr0, value_range_t *vr1) if (vr0->type == VR_UNDEFINED) { - set_value_range (vr0, vr1->type, vr1->min, vr1->max, vr1->equiv); + set_value_range (vr0, vr1->type, vr1->min, vr1->max, vr1->is_wrapped, vr1->equiv); return; } @@ -8689,6 +8733,7 @@ vrp_meet_1 (value_range_t *vr0, value_range_t *vr1) return; } set_and_canonicalize_value_range (vr0, vr0->type, vr0->min, vr0->max, + vr0->is_wrapped && vr1->is_wrapped, vr0->equiv); if (vr0->type == VR_VARYING) return; @@ -8747,6 +8792,7 @@ vrp_visit_phi_node (gphi *phi) for (i = 0; i < gimple_phi_num_args (phi); i++) { edge e = gimple_phi_arg_edge (phi, i); + bool is_wrapped = false; if (dump_file && (dump_flags & TDF_DETAILS)) { @@ -8792,6 +8838,7 @@ vrp_visit_phi_node (gphi *phi) vr_arg.type = VR_RANGE; vr_arg.min = arg; vr_arg.max = arg; + vr_arg.is_wrapped = is_wrapped; vr_arg.equiv = NULL; } } @@ -8804,6 +8851,7 @@ vrp_visit_phi_node (gphi *phi) vr_arg.type = VR_RANGE; vr_arg.min = arg; vr_arg.max = arg; + vr_arg.is_wrapped = is_wrapped; vr_arg.equiv = NULL; } @@ -10244,7 +10292,7 @@ vrp_finalize (void) || vr_value[i]->type == VR_ANTI_RANGE)) { if (vr_value[i]->type == VR_RANGE) - set_range_info (name, vr_value[i]->min, vr_value[i]->max); + set_range_info (name, vr_value[i]->min, vr_value[i]->max, vr_value[i]->is_wrapped); else if (vr_value[i]->type == VR_ANTI_RANGE) { /* VR_ANTI_RANGE @@ -10259,11 +10307,13 @@ vrp_finalize (void) /* ~[0,0] anti-range is represented as range. */ set_range_info (name, build_int_cst (TREE_TYPE (name), 1), - TYPE_MAXVAL (TREE_TYPE (name))); + TYPE_MAXVAL (TREE_TYPE (name)), + vr_value[i]->is_wrapped); else set_range_info (name, wi::add (vr_value[i]->max, 1), - wi::sub (vr_value[i]->min, 1)); + wi::sub (vr_value[i]->min, 1), + vr_value[i]->is_wrapped); } } diff --git a/gcc/tree.h b/gcc/tree.h index ac27268..946321a 100644 --- a/gcc/tree.h +++ b/gcc/tree.h @@ -1467,7 +1467,7 @@ extern void protected_set_expr_location (tree, location_t); SSA_NAME_CHECK (N)->ssa_name.info.ptr_info /* True if SSA_NAME_RANGE_INFO describes an anti-range. */ -#define SSA_NAME_ANTI_RANGE_P(N) \ +#define SSA_NAME_RANGE_WRAPPED_P(N) \ SSA_NAME_CHECK (N)->base.static_flag /* The type of range described by SSA_NAME_RANGE_INFO. */