From patchwork Sat Nov 26 09:17:33 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Joern Rennecke X-Patchwork-Id: 127774 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 65CFE1007D1 for ; Sat, 26 Nov 2011 20:17:55 +1100 (EST) Received: (qmail 24654 invoked by alias); 26 Nov 2011 09:17:52 -0000 Received: (qmail 24644 invoked by uid 22791); 26 Nov 2011 09:17:50 -0000 X-SWARE-Spam-Status: No, hits=-1.4 required=5.0 tests=AWL, BAYES_00, MIME_QP_LONG_LINE X-Spam-Check-By: sourceware.org Received: from c60.cesmail.net (HELO c60.cesmail.net) (216.154.195.49) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Sat, 26 Nov 2011 09:17:34 +0000 Received: from unknown (HELO delta2) ([192.168.1.50]) by c60.cesmail.net with ESMTP; 26 Nov 2011 04:17:34 -0500 Received: from host-92-29-210-76.as13285.net (host-92-29-210-76.as13285.net [92.29.210.76]) by webmail.spamcop.net (Horde MIME library) with HTTP; Sat, 26 Nov 2011 04:17:33 -0500 Message-ID: <20111126041733.6e6dc6mxw0cs0kwo-nzlynne@webmail.spamcop.net> Date: Sat, 26 Nov 2011 04:17:33 -0500 From: Joern Rennecke To: gcc-patches@gcc.gnu.org Subject: RFA: Fix PR tree-optimization/50802 MIME-Version: 1.0 User-Agent: Internet Messaging Program (IMP) H3 (4.1.4) 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 With this rewrite of simplify_conversion_using_ranges we go back to the original problem of considering if a single conversion is sufficient considering the known input range. Bootstrapped and regtested on i686-pc-linux-gnu. 2011-11-18 Joern Rennecke PR tree-optimization/50802 * tree-vrp.c (simplify_conversion_using_ranges): Rewrite test considering what happens to ranges during sign changes and/or intermediate narrowing conversions. Index: tree-vrp.c =================================================================== --- tree-vrp.c (revision 2195) +++ tree-vrp.c (working copy) @@ -7254,7 +7254,9 @@ simplify_conversion_using_ranges (gimple tree innerop, middleop, finaltype; gimple def_stmt; value_range_t *innervr; - double_int innermin, innermax, middlemin, middlemax; + bool inner_unsigned_p, middle_unsigned_p, final_unsigned_p; + unsigned inner_prec, middle_prec, final_prec; + double_int innermin, innermed, innermax, middlemin, middlemed, middlemax; finaltype = TREE_TYPE (gimple_assign_lhs (stmt)); if (!INTEGRAL_TYPE_P (finaltype)) @@ -7279,33 +7281,49 @@ simplify_conversion_using_ranges (gimple the middle conversion is removed. */ innermin = tree_to_double_int (innervr->min); innermax = tree_to_double_int (innervr->max); - middlemin = double_int_ext (innermin, TYPE_PRECISION (TREE_TYPE (middleop)), - TYPE_UNSIGNED (TREE_TYPE (middleop))); - middlemax = double_int_ext (innermax, TYPE_PRECISION (TREE_TYPE (middleop)), - TYPE_UNSIGNED (TREE_TYPE (middleop))); - /* If the middle values are not equal to the original values fail. - But only if the inner cast truncates (thus we ignore differences - in extension to handle the case going from a range to an anti-range - and back). */ - if ((TYPE_PRECISION (TREE_TYPE (innerop)) - > TYPE_PRECISION (TREE_TYPE (middleop))) - && (!double_int_equal_p (innermin, middlemin) - || !double_int_equal_p (innermax, middlemax))) - return false; + + inner_prec = TYPE_PRECISION (TREE_TYPE (innerop)); + middle_prec = TYPE_PRECISION (TREE_TYPE (middleop)); + final_prec = TYPE_PRECISION (finaltype); + + /* If the first conversion is not injective, the second must not + be widening. */ + if (double_int_cmp (double_int_sub (innermax, innermin), + double_int_mask (middle_prec), true) > 0 + && middle_prec < final_prec) + return false; + /* We also want a medium value so that we can track the effect that + narrowing conversions with sign change have. */ + inner_unsigned_p = TYPE_UNSIGNED (TREE_TYPE (innerop)); + if (inner_unsigned_p) + innermed = double_int_rshift (double_int_mask (inner_prec), + 1, inner_prec, false); + else + innermed = double_int_zero; + if (double_int_cmp (innermin, innermed, inner_unsigned_p) >= 0 + || double_int_cmp (innermed, innermax, inner_unsigned_p) >= 0) + innermed = innermin; + + middle_unsigned_p = TYPE_UNSIGNED (TREE_TYPE (middleop)); + middlemin = double_int_ext (innermin, middle_prec, middle_unsigned_p); + middlemed = double_int_ext (innermed, middle_prec, middle_unsigned_p); + middlemax = double_int_ext (innermax, middle_prec, middle_unsigned_p); + /* Require that the final conversion applied to both the original and the intermediate range produces the same result. */ + final_unsigned_p = TYPE_UNSIGNED (finaltype); if (!double_int_equal_p (double_int_ext (middlemin, - TYPE_PRECISION (finaltype), - TYPE_UNSIGNED (finaltype)), + final_prec, final_unsigned_p), double_int_ext (innermin, - TYPE_PRECISION (finaltype), - TYPE_UNSIGNED (finaltype))) + final_prec, final_unsigned_p)) + || !double_int_equal_p (double_int_ext (middlemed, + final_prec, final_unsigned_p), + double_int_ext (innermed, + final_prec, final_unsigned_p)) || !double_int_equal_p (double_int_ext (middlemax, - TYPE_PRECISION (finaltype), - TYPE_UNSIGNED (finaltype)), + final_prec, final_unsigned_p), double_int_ext (innermax, - TYPE_PRECISION (finaltype), - TYPE_UNSIGNED (finaltype)))) + final_prec, final_unsigned_p))) return false; gimple_assign_set_rhs1 (stmt, innerop);