From patchwork Wed Aug 17 02:27:37 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kugan Vivekanandarajah X-Patchwork-Id: 74047 Delivered-To: patch@linaro.org Received: by 10.140.29.52 with SMTP id a49csp2289028qga; Tue, 16 Aug 2016 19:28:13 -0700 (PDT) X-Received: by 10.67.7.229 with SMTP id df5mr18814681pad.6.1471400893237; Tue, 16 Aug 2016 19:28:13 -0700 (PDT) Return-Path: Received: from sourceware.org (server1.sourceware.org. [209.132.180.131]) by mx.google.com with ESMTPS id h63si35027350pfd.38.2016.08.16.19.28.12 for (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 16 Aug 2016 19:28:13 -0700 (PDT) Received-SPF: pass (google.com: domain of gcc-patches-return-434102-patch=linaro.org@gcc.gnu.org designates 209.132.180.131 as permitted sender) client-ip=209.132.180.131; Authentication-Results: mx.google.com; dkim=pass header.i=@gcc.gnu.org; spf=pass (google.com: domain of gcc-patches-return-434102-patch=linaro.org@gcc.gnu.org designates 209.132.180.131 as permitted sender) smtp.mailfrom=gcc-patches-return-434102-patch=linaro.org@gcc.gnu.org; dmarc=fail (p=NONE dis=NONE) header.from=linaro.org DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender :subject:to:references:cc:from:message-id:date:mime-version :in-reply-to:content-type; q=dns; s=default; b=ZjASvUpn+olN3/MEl h9O0n2PVtxnZrcdX0cqcFTUaEnjIgR0CWrTaLAYpnM+kkQ0sTyB8CpOa4krQpNmL 2SI5P9MGRucco0Nu3Cay55x2ys8hPDATYKkzKd/O+5IZCQ2y9GhXMcHdFmvzX5nm c+S5Jy91J/8O0Ar++IORKRkS0U= 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 :subject:to:references:cc:from:message-id:date:mime-version :in-reply-to:content-type; s=default; bh=d+Q4fPGmbvuyHboPVaQL/Db U274=; b=uGo8AL6yhSyRrf5m1fI7++UQ/njZLHqQDtIj/XRO5atKaNwHA2UFf/4 msJS8AbJ5R5RZIkWssk66kzXW1YXDAVTh5nf9eefShSyKw7CIVPfAVOZyGRNxrpz QVV3SCs6+OssACEaIHsPpl7tbb7om0gduV7WQCJ0INqZPVJVLkQY= Received: (qmail 121384 invoked by alias); 17 Aug 2016 02:27:57 -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 120728 invoked by uid 89); 17 Aug 2016 02:27:56 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-2.6 required=5.0 tests=AWL, BAYES_00, RCVD_IN_DNSWL_LOW, SPF_PASS autolearn=ham version=3.3.2 spammy=_Complex, _complex, ongoing, 76298 X-HELO: mail-pa0-f51.google.com Received: from mail-pa0-f51.google.com (HELO mail-pa0-f51.google.com) (209.85.220.51) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Wed, 17 Aug 2016 02:27:45 +0000 Received: by mail-pa0-f51.google.com with SMTP id ti13so31869085pac.0 for ; Tue, 16 Aug 2016 19:27:45 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:subject:to:references:cc:from:message-id:date :user-agent:mime-version:in-reply-to; bh=auH/i1IlejfvkRVmk3x0w7OJ7A8UUEOyhav5TFEEbrQ=; b=ZuSPYneDEcqWpH5mocOar5sNgMU5QuD01y6KOAL/mtmsvHFNLPW0VR7ut/wYNhSfIG I64re1xrIpVtFr+p21gYFKnOlMswTevZgZID3K32ZfzlFHw2mmm3sqBqxGYz8Kv9ounQ Vapj17h+zjGDR9h3T1lU1XO5BMj07tEUxGQNVBDzR/ZwoTp8B23ASSZtjsY37OWbD4br tH8XM6BmLn0jWO0gwYJ9+KyxrHPVEXF++8tvFhQMq2AnrAD/t3ywMoc1ou9Z2ahwBsrK ZJnj2obVcVAFUvRFQOgmDV1EsOTCaSdlN+zEE+1zraan9IWhVBaX8b/1k2i9CeYJoRNZ FYCA== X-Gm-Message-State: AEkoouub8Hujtgso4DUPFRxp6gcjEKhGDudPP8uOX98wGYysfD2PoM6z8pzlXxyFblt6W2Wn X-Received: by 10.66.127.38 with SMTP id nd6mr11070868pab.74.1471400864052; Tue, 16 Aug 2016 19:27:44 -0700 (PDT) Received: from [10.1.1.3] (58-6-183-210.dyn.iinet.net.au. [58.6.183.210]) by smtp.gmail.com with ESMTPSA id h86sm42355993pfh.46.2016.08.16.19.27.40 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 16 Aug 2016 19:27:43 -0700 (PDT) Subject: Re: [RFC][IPA-VRP] splits out the update_value_range calls from vrp_visit_stmt To: Richard Biener References: <57886949.8010300@linaro.org> <57886A71.6030103@linaro.org> <57888BD6.6070200@linaro.org> <578891C8.7090609@linaro.org> <19ff8188-aed7-0f9e-cc0b-0603698787ff@linaro.org> <48e42d0c-057c-312a-4e41-cd78c8b38b5e@linaro.org> <3a581e5d-921a-18ef-5c3d-e1d1158ec40c@linaro.org> Cc: Andrew Pinski , "gcc-patches@gcc.gnu.org" , Jan Hubicka , Martin Jambor From: kugan Message-ID: <98dd7d66-d220-a7f0-46c4-4e5ca0af9d28@linaro.org> Date: Wed, 17 Aug 2016 12:27:37 +1000 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:45.0) Gecko/20100101 Thunderbird/45.2.0 MIME-Version: 1.0 In-Reply-To: X-IsSubscribed: yes Hi, On 16/08/16 20:58, Richard Biener wrote: > On Tue, Aug 16, 2016 at 9:39 AM, kugan > wrote: >> Hi, >> >>> as said the refactoring that would be appreciated is to split out the >>> update_value_range calls >>> from the worker functions so you can call the respective functions >>> from the DOM implementations. >>> That they are globbed in vrp_visit_stmt currently is due to the API of >>> the SSA propagator. >> >> >> Here is a patch that just splits out the update_value_range calls >> visit_stmts. Bootstrapped and regression tested on x86_64-linux with no new >> regressions. >> >> I also verified few random fdump-tree-vrp1-details from stage2 to make sure >> they are same. >> >> Is this OK for trunk? > > For vrp_visit_assignment_or_call please defer the question whether the update > is interesting (for the internal call stuff) to the caller and always > return new_vr. > > Also do not perform the "not handled stmt" handling here but make the return > value reflect whether we handled the stmt or not and put > > /* Every other statement produces no useful ranges. */ > FOR_EACH_SSA_TREE_OPERAND (def, stmt, iter, SSA_OP_DEF) > set_value_range_to_varying (get_value_range (def)); > > into the caller (as that's also a lattice-updating thing). > > +static enum ssa_prop_result > +vrp_visit_stmt (gimple *stmt, edge *taken_edge_p, tree *output_p) > +{ > + value_range vr = VR_INITIALIZER; > + tree lhs = gimple_get_lhs (stmt); > + bool vr_found = vrp_visit_stmt_worker (stmt, taken_edge_p, > + output_p, &vr); > + > + if (lhs) > + { > + if (vr_found > + && update_value_range (lhs, &vr)) > + { > + *output_p = lhs; > > I think rather than computing LHS here you should use *output_p. > > Otherwise this looks good though I'd rename the _worker variants > to extract_range_from_phi_node, extract_range_from_stmt and > extract_range_from_assignment_or_call. > Please find the patch attached which addresses the comments above. Bootstrap and regression testing is ongoing. Is this of if there is no new regressions? Thanks, Kugan gcc/ChangeLog: 2016-08-17 Kugan Vivekanandarajah * tree-vrp.c (vrp_visit_assignment_or_call): Changed to Return VR. (vrp_visit_cond_stmt): Just sets TAKEN_EDGE_P. (vrp_visit_switch_stmt): Likewise. (extract_range_from_stmt): Factored out from vrp_visit_stmt. (extract_range_from_phi_node): Factored out from vrp_visit_phi_stmt. (vrp_visit_stmt): Use extract_range_from_stmt. (vrp_visit_phi_node): Use extract_range_from_phi_node. >From 78c6fd33b9440c6748e32216b1c205015f276b49 Mon Sep 17 00:00:00 2001 From: Kugan Vivekanandarajah Date: Tue, 16 Aug 2016 13:48:21 +1000 Subject: [PATCH 2/5] Refactor vrp_visit_stmt --- gcc/tree-vrp.c | 335 ++++++++++++++++++++++++++++++--------------------------- 1 file changed, 175 insertions(+), 160 deletions(-) diff --git a/gcc/tree-vrp.c b/gcc/tree-vrp.c index ccfccef..89b1e7a 100644 --- a/gcc/tree-vrp.c +++ b/gcc/tree-vrp.c @@ -7030,15 +7030,15 @@ vrp_valueize_1 (tree name) } /* Visit assignment STMT. If it produces an interesting range, record - the SSA name in *OUTPUT_P. */ + the range in VR and set LHS to OUTPUT_P. */ -static enum ssa_prop_result -vrp_visit_assignment_or_call (gimple *stmt, tree *output_p) +static void +vrp_visit_assignment_or_call (gimple *stmt, tree *output_p, value_range *vr) { - tree def, lhs; - ssa_op_iter iter; + tree lhs; enum gimple_code code = gimple_code (stmt); lhs = gimple_get_lhs (stmt); + *output_p = NULL_TREE; /* We only keep track of ranges in integral and pointer types. */ if (TREE_CODE (lhs) == SSA_NAME @@ -7049,114 +7049,18 @@ vrp_visit_assignment_or_call (gimple *stmt, tree *output_p) && TYPE_MAX_VALUE (TREE_TYPE (lhs))) || POINTER_TYPE_P (TREE_TYPE (lhs)))) { - value_range new_vr = VR_INITIALIZER; - /* Try folding the statement to a constant first. */ tree tem = gimple_fold_stmt_to_constant_1 (stmt, vrp_valueize, vrp_valueize_1); if (tem && is_gimple_min_invariant (tem)) - set_value_range_to_value (&new_vr, tem, NULL); + set_value_range_to_value (vr, tem, NULL); /* Then dispatch to value-range extracting functions. */ else if (code == GIMPLE_CALL) - extract_range_basic (&new_vr, stmt); + extract_range_basic (vr, stmt); else - extract_range_from_assignment (&new_vr, as_a (stmt)); - - if (update_value_range (lhs, &new_vr)) - { - *output_p = lhs; - - if (dump_file && (dump_flags & TDF_DETAILS)) - { - fprintf (dump_file, "Found new range for "); - print_generic_expr (dump_file, lhs, 0); - fprintf (dump_file, ": "); - dump_value_range (dump_file, &new_vr); - fprintf (dump_file, "\n"); - } - - if (new_vr.type == VR_VARYING) - return SSA_PROP_VARYING; - - return SSA_PROP_INTERESTING; - } - - return SSA_PROP_NOT_INTERESTING; + extract_range_from_assignment (vr, as_a (stmt)); + *output_p = lhs; } - else if (is_gimple_call (stmt) && gimple_call_internal_p (stmt)) - switch (gimple_call_internal_fn (stmt)) - { - case IFN_ADD_OVERFLOW: - case IFN_SUB_OVERFLOW: - case IFN_MUL_OVERFLOW: - /* These internal calls return _Complex integer type, - which VRP does not track, but the immediate uses - thereof might be interesting. */ - if (lhs && TREE_CODE (lhs) == SSA_NAME) - { - imm_use_iterator iter; - use_operand_p use_p; - enum ssa_prop_result res = SSA_PROP_VARYING; - - set_value_range_to_varying (get_value_range (lhs)); - - FOR_EACH_IMM_USE_FAST (use_p, iter, lhs) - { - gimple *use_stmt = USE_STMT (use_p); - if (!is_gimple_assign (use_stmt)) - continue; - enum tree_code rhs_code = gimple_assign_rhs_code (use_stmt); - if (rhs_code != REALPART_EXPR && rhs_code != IMAGPART_EXPR) - continue; - tree rhs1 = gimple_assign_rhs1 (use_stmt); - tree use_lhs = gimple_assign_lhs (use_stmt); - if (TREE_CODE (rhs1) != rhs_code - || TREE_OPERAND (rhs1, 0) != lhs - || TREE_CODE (use_lhs) != SSA_NAME - || !stmt_interesting_for_vrp (use_stmt) - || (!INTEGRAL_TYPE_P (TREE_TYPE (use_lhs)) - || !TYPE_MIN_VALUE (TREE_TYPE (use_lhs)) - || !TYPE_MAX_VALUE (TREE_TYPE (use_lhs)))) - continue; - - /* If there is a change in the value range for any of the - REALPART_EXPR/IMAGPART_EXPR immediate uses, return - SSA_PROP_INTERESTING. If there are any REALPART_EXPR - or IMAGPART_EXPR immediate uses, but none of them have - a change in their value ranges, return - SSA_PROP_NOT_INTERESTING. If there are no - {REAL,IMAG}PART_EXPR uses at all, - return SSA_PROP_VARYING. */ - value_range new_vr = VR_INITIALIZER; - extract_range_basic (&new_vr, use_stmt); - value_range *old_vr = get_value_range (use_lhs); - if (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) - || !vrp_bitmap_equal_p (old_vr->equiv, new_vr.equiv)) - res = SSA_PROP_INTERESTING; - else - res = SSA_PROP_NOT_INTERESTING; - BITMAP_FREE (new_vr.equiv); - if (res == SSA_PROP_INTERESTING) - { - *output_p = lhs; - return res; - } - } - - return res; - } - break; - default: - break; - } - - /* Every other statement produces no useful ranges. */ - FOR_EACH_SSA_TREE_OPERAND (def, stmt, iter, SSA_OP_DEF) - set_value_range_to_varying (get_value_range (def)); - - return SSA_PROP_VARYING; } /* Helper that gets the value range of the SSA_NAME with version I @@ -7528,10 +7432,9 @@ vrp_evaluate_conditional (tree_code code, tree op0, tree op1, gimple *stmt) /* Visit conditional statement STMT. If we can determine which edge will be taken out of STMT's basic block, record it in - *TAKEN_EDGE_P and return SSA_PROP_INTERESTING. Otherwise, return - SSA_PROP_VARYING. */ + *TAKEN_EDGE_P. Otherwise, set *TAKEN_EDGE_P to NULL. */ -static enum ssa_prop_result +static void vrp_visit_cond_stmt (gcond *stmt, edge *taken_edge_p) { tree val; @@ -7629,8 +7532,6 @@ vrp_visit_cond_stmt (gcond *stmt, edge *taken_edge_p) else print_generic_stmt (dump_file, val, 0); } - - return (*taken_edge_p) ? SSA_PROP_INTERESTING : SSA_PROP_VARYING; } /* Searches the case label vector VEC for the index *IDX of the CASE_LABEL @@ -7827,10 +7728,9 @@ find_case_label_ranges (gswitch *stmt, value_range *vr, size_t *min_idx1, /* Visit switch statement STMT. If we can determine which edge will be taken out of STMT's basic block, record it in - *TAKEN_EDGE_P and return SSA_PROP_INTERESTING. Otherwise, return - SSA_PROP_VARYING. */ + *TAKEN_EDGE_P. Otherwise, *TAKEN_EDGE_P set to NULL. */ -static enum ssa_prop_result +static void vrp_visit_switch_stmt (gswitch *stmt, edge *taken_edge_p) { tree op, val; @@ -7841,7 +7741,7 @@ vrp_visit_switch_stmt (gswitch *stmt, edge *taken_edge_p) *taken_edge_p = NULL; op = gimple_switch_index (stmt); if (TREE_CODE (op) != SSA_NAME) - return SSA_PROP_VARYING; + return; vr = get_value_range (op); if (dump_file && (dump_flags & TDF_DETAILS)) @@ -7856,7 +7756,7 @@ vrp_visit_switch_stmt (gswitch *stmt, edge *taken_edge_p) if ((vr->type != VR_RANGE && vr->type != VR_ANTI_RANGE) || symbolic_range_p (vr)) - return SSA_PROP_VARYING; + return; /* Find the single edge that is taken from the switch expression. */ take_default = !find_case_label_ranges (stmt, vr, &i, &j, &k, &l); @@ -7881,7 +7781,7 @@ vrp_visit_switch_stmt (gswitch *stmt, edge *taken_edge_p) if (dump_file && (dump_flags & TDF_DETAILS)) fprintf (dump_file, " not a single destination for this " "range\n"); - return SSA_PROP_VARYING; + return; } for (++i; i <= j; ++i) { @@ -7890,7 +7790,7 @@ vrp_visit_switch_stmt (gswitch *stmt, edge *taken_edge_p) if (dump_file && (dump_flags & TDF_DETAILS)) fprintf (dump_file, " not a single destination for this " "range\n"); - return SSA_PROP_VARYING; + return; } } for (; k <= l; ++k) @@ -7900,7 +7800,7 @@ vrp_visit_switch_stmt (gswitch *stmt, edge *taken_edge_p) if (dump_file && (dump_flags & TDF_DETAILS)) fprintf (dump_file, " not a single destination for this " "range\n"); - return SSA_PROP_VARYING; + return; } } } @@ -7913,12 +7813,37 @@ vrp_visit_switch_stmt (gswitch *stmt, edge *taken_edge_p) fprintf (dump_file, " will take edge to "); print_generic_stmt (dump_file, CASE_LABEL (val), 0); } - - return SSA_PROP_INTERESTING; } /* Evaluate statement STMT. If the statement produces a useful range, + set VR and corepsponding OUTPUT_P. + + If STMT is a conditional branch and we can determine its truth + value, the taken edge is recorded in *TAKEN_EDGE_P. */ + +static void +extract_range_from_stmt (gimple *stmt, edge *taken_edge_p, + tree *output_p, value_range *vr) +{ + + if (dump_file && (dump_flags & TDF_DETAILS)) + { + fprintf (dump_file, "\nVisiting statement:\n"); + print_gimple_stmt (dump_file, stmt, 0, dump_flags); + } + + if (!stmt_interesting_for_vrp (stmt)) + gcc_assert (stmt_ends_bb_p (stmt)); + else if (is_gimple_assign (stmt) || is_gimple_call (stmt)) + vrp_visit_assignment_or_call (stmt, output_p, vr); + else if (gimple_code (stmt) == GIMPLE_COND) + vrp_visit_cond_stmt (as_a (stmt), taken_edge_p); + else if (gimple_code (stmt) == GIMPLE_SWITCH) + vrp_visit_switch_stmt (as_a (stmt), taken_edge_p); +} + +/* Evaluate statement STMT. If the statement produces a useful range, return SSA_PROP_INTERESTING and record the SSA name with the interesting range into *OUTPUT_P. @@ -7930,30 +7855,108 @@ vrp_visit_switch_stmt (gswitch *stmt, edge *taken_edge_p) static enum ssa_prop_result vrp_visit_stmt (gimple *stmt, edge *taken_edge_p, tree *output_p) { + value_range vr = VR_INITIALIZER; + tree lhs = gimple_get_lhs (stmt); tree def; ssa_op_iter iter; + extract_range_from_stmt (stmt, taken_edge_p, output_p, &vr); - if (dump_file && (dump_flags & TDF_DETAILS)) + if (*output_p) { - fprintf (dump_file, "\nVisiting statement:\n"); - print_gimple_stmt (dump_file, stmt, 0, dump_flags); + if (update_value_range (*output_p, &vr)) + { + if (dump_file && (dump_flags & TDF_DETAILS)) + { + fprintf (dump_file, "Found new range for "); + print_generic_expr (dump_file, *output_p, 0); + fprintf (dump_file, ": "); + dump_value_range (dump_file, &vr); + fprintf (dump_file, "\n"); + } + + if (vr.type == VR_VARYING) + return SSA_PROP_VARYING; + + return SSA_PROP_INTERESTING; + } + return SSA_PROP_NOT_INTERESTING; } - if (!stmt_interesting_for_vrp (stmt)) - gcc_assert (stmt_ends_bb_p (stmt)); - else if (is_gimple_assign (stmt) || is_gimple_call (stmt)) - return vrp_visit_assignment_or_call (stmt, output_p); - else if (gimple_code (stmt) == GIMPLE_COND) - return vrp_visit_cond_stmt (as_a (stmt), taken_edge_p); - else if (gimple_code (stmt) == GIMPLE_SWITCH) - return vrp_visit_switch_stmt (as_a (stmt), taken_edge_p); + if (is_gimple_call (stmt) && gimple_call_internal_p (stmt)) + switch (gimple_call_internal_fn (stmt)) + { + case IFN_ADD_OVERFLOW: + case IFN_SUB_OVERFLOW: + case IFN_MUL_OVERFLOW: + /* These internal calls return _Complex integer type, + which VRP does not track, but the immediate uses + thereof might be interesting. */ + if (lhs && TREE_CODE (lhs) == SSA_NAME) + { + imm_use_iterator iter; + use_operand_p use_p; + enum ssa_prop_result res = SSA_PROP_VARYING; + + set_value_range_to_varying (get_value_range (lhs)); + + FOR_EACH_IMM_USE_FAST (use_p, iter, lhs) + { + gimple *use_stmt = USE_STMT (use_p); + if (!is_gimple_assign (use_stmt)) + continue; + enum tree_code rhs_code = gimple_assign_rhs_code (use_stmt); + if (rhs_code != REALPART_EXPR && rhs_code != IMAGPART_EXPR) + continue; + tree rhs1 = gimple_assign_rhs1 (use_stmt); + tree use_lhs = gimple_assign_lhs (use_stmt); + if (TREE_CODE (rhs1) != rhs_code + || TREE_OPERAND (rhs1, 0) != lhs + || TREE_CODE (use_lhs) != SSA_NAME + || !stmt_interesting_for_vrp (use_stmt) + || (!INTEGRAL_TYPE_P (TREE_TYPE (use_lhs)) + || !TYPE_MIN_VALUE (TREE_TYPE (use_lhs)) + || !TYPE_MAX_VALUE (TREE_TYPE (use_lhs)))) + continue; + + /* If there is a change in the value range for any of the + REALPART_EXPR/IMAGPART_EXPR immediate uses, return + SSA_PROP_INTERESTING. If there are any REALPART_EXPR + or IMAGPART_EXPR immediate uses, but none of them have + a change in their value ranges, return + SSA_PROP_NOT_INTERESTING. If there are no + {REAL,IMAG}PART_EXPR uses at all, + return SSA_PROP_VARYING. */ + value_range new_vr = VR_INITIALIZER; + extract_range_basic (&new_vr, use_stmt); + value_range *old_vr = get_value_range (use_lhs); + if (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) + || !vrp_bitmap_equal_p (old_vr->equiv, new_vr.equiv)) + res = SSA_PROP_INTERESTING; + else + res = SSA_PROP_NOT_INTERESTING; + BITMAP_FREE (new_vr.equiv); + if (res == SSA_PROP_INTERESTING) + { + *output_p = lhs; + return res; + } + } + + return res; + } + break; + default: + break; + } /* All other statements produce nothing of interest for VRP, so mark their outputs varying and prevent further simulation. */ FOR_EACH_SSA_TREE_OPERAND (def, stmt, iter, SSA_OP_DEF) set_value_range_to_varying (get_value_range (def)); - return SSA_PROP_VARYING; + return (*taken_edge_p) ? SSA_PROP_INTERESTING : SSA_PROP_VARYING; } /* Union the two value-ranges { *VR0TYPE, *VR0MIN, *VR0MAX } and @@ -8678,15 +8681,14 @@ vrp_meet (value_range *vr0, const value_range *vr1) /* Visit all arguments for PHI node PHI that flow through executable edges. If a valid value range can be derived from all the incoming - value ranges, set a new range for the LHS of PHI. */ + value ranges, set a new range in VR_RESULT. */ -static enum ssa_prop_result -vrp_visit_phi_node (gphi *phi) +static void +extract_range_from_phi_node (gphi *phi, value_range *vr_result) { size_t i; tree lhs = PHI_RESULT (phi); value_range *lhs_vr = get_value_range (lhs); - value_range vr_result = VR_INITIALIZER; bool first = true; int edges, old_edges; struct loop *l; @@ -8778,19 +8780,19 @@ vrp_visit_phi_node (gphi *phi) } if (first) - copy_value_range (&vr_result, &vr_arg); + copy_value_range (vr_result, &vr_arg); else - vrp_meet (&vr_result, &vr_arg); + vrp_meet (vr_result, &vr_arg); first = false; - if (vr_result.type == VR_VARYING) + if (vr_result->type == VR_VARYING) break; } } - if (vr_result.type == VR_VARYING) + if (vr_result->type == VR_VARYING) goto varying; - else if (vr_result.type == VR_UNDEFINED) + else if (vr_result->type == VR_UNDEFINED) goto update_range; old_edges = vr_phi_edge_counts[SSA_NAME_VERSION (lhs)]; @@ -8812,16 +8814,16 @@ vrp_visit_phi_node (gphi *phi) { /* Compare old and new ranges, fall back to varying if the values are not comparable. */ - int cmp_min = compare_values (lhs_vr->min, vr_result.min); + int cmp_min = compare_values (lhs_vr->min, vr_result->min); if (cmp_min == -2) goto varying; - int cmp_max = compare_values (lhs_vr->max, vr_result.max); + int cmp_max = compare_values (lhs_vr->max, vr_result->max); if (cmp_max == -2) goto varying; /* For non VR_RANGE or for pointers fall back to varying if the range changed. */ - if ((lhs_vr->type != VR_RANGE || vr_result.type != VR_RANGE + if ((lhs_vr->type != VR_RANGE || vr_result->type != VR_RANGE || POINTER_TYPE_P (TREE_TYPE (lhs))) && (cmp_min != 0 || cmp_max != 0)) goto varying; @@ -8835,23 +8837,23 @@ vrp_visit_phi_node (gphi *phi) iteration compute whether there will be any overflow, at the expense of one additional iteration. */ if (cmp_min < 0) - vr_result.min = lhs_vr->min; + vr_result->min = lhs_vr->min; else if (cmp_min > 0 - && !vrp_val_is_min (vr_result.min)) - vr_result.min + && !vrp_val_is_min (vr_result->min)) + vr_result->min = int_const_binop (PLUS_EXPR, - vrp_val_min (TREE_TYPE (vr_result.min)), - build_int_cst (TREE_TYPE (vr_result.min), 1)); + vrp_val_min (TREE_TYPE (vr_result->min)), + build_int_cst (TREE_TYPE (vr_result->min), 1)); /* Similarly for the maximum value. */ if (cmp_max > 0) - vr_result.max = lhs_vr->max; + vr_result->max = lhs_vr->max; else if (cmp_max < 0 - && !vrp_val_is_max (vr_result.max)) - vr_result.max + && !vrp_val_is_max (vr_result->max)) + vr_result->max = int_const_binop (MINUS_EXPR, - vrp_val_max (TREE_TYPE (vr_result.min)), - build_int_cst (TREE_TYPE (vr_result.min), 1)); + vrp_val_max (TREE_TYPE (vr_result->min)), + build_int_cst (TREE_TYPE (vr_result->min), 1)); /* If we dropped either bound to +-INF then if this is a loop PHI node SCEV may known more about its value-range. */ @@ -8865,7 +8867,7 @@ vrp_visit_phi_node (gphi *phi) goto update_range; varying: - set_value_range_to_varying (&vr_result); + set_value_range_to_varying (vr_result); scev_check: /* If this is a loop PHI node SCEV may known more about its value-range. @@ -8874,22 +8876,35 @@ scev_check: avoid infinite simulation. */ if ((l = loop_containing_stmt (phi)) && l->header == gimple_bb (phi)) - adjust_range_with_scev (&vr_result, l, phi, lhs); + adjust_range_with_scev (vr_result, l, phi, lhs); infinite_check: /* If we will end up with a (-INF, +INF) range, set it to VARYING. Same if the previous max value was invalid for the type and we end up with vr_result.min > vr_result.max. */ - if ((vr_result.type == VR_RANGE || vr_result.type == VR_ANTI_RANGE) - && !((vrp_val_is_max (vr_result.max) && vrp_val_is_min (vr_result.min)) - || compare_values (vr_result.min, vr_result.max) > 0)) + if ((vr_result->type == VR_RANGE || vr_result->type == VR_ANTI_RANGE) + && !((vrp_val_is_max (vr_result->max) && vrp_val_is_min (vr_result->min)) + || compare_values (vr_result->min, vr_result->max) > 0)) ; else - set_value_range_to_varying (&vr_result); + set_value_range_to_varying (vr_result); /* If the new range is different than the previous value, keep iterating. */ update_range: + return; +} + +/* Visit all arguments for PHI node PHI that flow through executable + edges. If a valid value range can be derived from all the incoming + value ranges, set a new range for the LHS of PHI. */ + +static enum ssa_prop_result +vrp_visit_phi_node (gphi *phi) +{ + tree lhs = PHI_RESULT (phi); + value_range vr_result = VR_INITIALIZER; + extract_range_from_phi_node (phi, &vr_result); if (update_value_range (lhs, &vr_result)) { if (dump_file && (dump_flags & TDF_DETAILS)) -- 2.7.4