From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 23391 invoked by alias); 8 Jul 2011 09:36:14 -0000 Received: (qmail 22988 invoked by uid 22791); 8 Jul 2011 09:36:10 -0000 X-SWARE-Spam-Status: No, hits=-2.3 required=5.0 tests=AWL,BAYES_00,DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FROM,RCVD_IN_DNSWL_LOW,TW_TM X-Spam-Check-By: sourceware.org Received: from mail-wy0-f175.google.com (HELO mail-wy0-f175.google.com) (74.125.82.175) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Fri, 08 Jul 2011 09:35:54 +0000 Received: by wyg30 with SMTP id 30so1467247wyg.20 for ; Fri, 08 Jul 2011 02:35:53 -0700 (PDT) MIME-Version: 1.0 Received: by 10.227.55.66 with SMTP id t2mr1578689wbg.109.1310117753221; Fri, 08 Jul 2011 02:35:53 -0700 (PDT) Received: by 10.227.36.212 with HTTP; Fri, 8 Jul 2011 02:35:53 -0700 (PDT) In-Reply-To: References: Date: Fri, 08 Jul 2011 09:39:00 -0000 Message-ID: Subject: Re: [patch tree-optimization]: [3 of 3]: Boolify compares & more From: Richard Guenther To: Kai Tietz Cc: GCC Patches Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: quoted-printable X-IsSubscribed: yes Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org X-SW-Source: 2011-07/txt/msg00603.txt.bz2 On Thu, Jul 7, 2011 at 6:07 PM, Kai Tietz wrote: > Hello, > > This patch - third of series - fixes vrp to handle bitwise one-bit > precision typed operations. > And it introduces a second - limitted to non-switch-statement range - vrp= pass. Err - please split this patch. I agree with Paolo, this 2nd substitute_and_fold call is bogus. More comments inline. > > Bootstrapped and regression tested for all standard-languages (plus > Ada and Obj-C++) on host x86_64-pc-linux-gnu. > > Ok for apply? > > Regards, > Kai > > ChangeLog > > 2011-07-07 =A0Kai Tietz =A0 > > =A0 =A0 =A0 =A0* tree-vrp.c (in_second_pass): New static variable. > =A0 =A0 =A0 =A0(extract_range_from_binary_expr): Add handling for > =A0 =A0 =A0 =A0BIT_IOR_EXPR, BIT_AND_EXPR, and BIT_NOT_EXPR. > =A0 =A0 =A0 =A0(register_edge_assert_for_1): Add handling for 1-bit > =A0 =A0 =A0 =A0BIT_IOR_EXPR and BIT_NOT_EXPR. > =A0 =A0 =A0 =A0(register_edge_assert_for): Add handling for 1-bit > =A0 =A0 =A0 =A0BIT_IOR_EXPR. > =A0 =A0 =A0 =A0(ssa_name_get_inner_ssa_name_p): New helper function. > =A0 =A0 =A0 =A0(ssa_name_get_cast_to_p): New helper function. > =A0 =A0 =A0 =A0(simplify_truth_ops_using_ranges): Handle prefixed > =A0 =A0 =A0 =A0cast instruction for result, and add support for one > =A0 =A0 =A0 =A0bit precision BIT_IOR_EXPR, BIT_AND_EXPR, BIT_XOR_EXPR, > =A0 =A0 =A0 =A0, and BIT_NOT_EXPR. > =A0 =A0 =A0 =A0(simplify_stmt_using_ranges): Add handling for one bit > =A0 =A0 =A0 =A0precision BIT_IOR_EXPR, BIT_AND_EXPR, BIT_XOR_EXPR, > =A0 =A0 =A0 =A0and BIT_NOT_EXPR. > =A0 =A0 =A0 =A0(vrp_finalize): Do substitute and fold pass a second > =A0 =A0 =A0 =A0time for vrp_stmt and preserve switch-edge simplification > =A0 =A0 =A0 =A0on second run. > =A0 =A0 =A0 =A0(simplify_switch_using_ranges): Preserve rerun of function > =A0 =A0 =A0 =A0in second pass. > > Index: gcc-head/gcc/tree-vrp.c > =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D > --- gcc-head.orig/gcc/tree-vrp.c > +++ gcc-head/gcc/tree-vrp.c > @@ -74,6 +74,9 @@ struct value_range_d > > =A0typedef struct value_range_d value_range_t; > > +/* This flag indicates that we are doing a second pass of VRP. =A0*/ > +static bool in_second_pass =3D false; > + > =A0/* Set of SSA names found live during the RPO traversal of the function > =A0 =A0for still active basic-blocks. =A0*/ > =A0static sbitmap *live; > @@ -2232,6 +2235,7 @@ extract_range_from_binary_expr (value_ra > =A0 =A0 =A0some cases. =A0*/ > =A0 if (code !=3D BIT_AND_EXPR > =A0 =A0 =A0 && code !=3D TRUTH_AND_EXPR > + =A0 =A0 =A0&& code !=3D BIT_IOR_EXPR Huh? So how would VARYING | x ever produce something better than VARYING? > =A0 =A0 =A0 && code !=3D TRUTH_OR_EXPR > =A0 =A0 =A0 && code !=3D TRUNC_DIV_EXPR > =A0 =A0 =A0 && code !=3D FLOOR_DIV_EXPR > @@ -2291,6 +2295,8 @@ extract_range_from_binary_expr (value_ra > =A0 =A0 =A0 =A0 =A0else > =A0 =A0 =A0 =A0 =A0 =A0set_value_range_to_varying (vr); > =A0 =A0 =A0 =A0} > + =A0 =A0 =A0else if (code =3D=3D BIT_IOR_EXPR) > + =A0 =A0 =A0 =A0set_value_range_to_varying (vr); err - BIT_IOR_EXPR on pointers? > =A0 =A0 =A0 else > =A0 =A0 =A0 =A0gcc_unreachable (); > > @@ -2300,11 +2306,13 @@ extract_range_from_binary_expr (value_ra > =A0 /* For integer ranges, apply the operation to each end of the > =A0 =A0 =A0range and see what we end up with. =A0*/ > =A0 if (code =3D=3D TRUTH_AND_EXPR > - =A0 =A0 =A0|| code =3D=3D TRUTH_OR_EXPR) > + =A0 =A0 =A0|| code =3D=3D TRUTH_OR_EXPR > + =A0 =A0 =A0|| ((code =3D=3D BIT_AND_EXPR || code =3D=3D BIT_IOR_EXPR) > + =A0 =A0 =A0 =A0 =A0&& TYPE_PRECISION (TREE_TYPE (op1)) =3D=3D 1)) Rather than adding code to handle BIT_*_EXPR this patch should transform the TRUTH_*_EXPR handling to appropriate BIT_*_EXPR handling as we no longer have TRUTH_*_EXPR in our IL. In fact I would say the existing BIT_*_EXPR handling should already cover all the TRUTH_*_CASES, so this patch patches the wrong spot if it is necessary at all. > =A0 =A0 { > =A0 =A0 =A0 /* If one of the operands is zero, we know that the whole > =A0 =A0 =A0 =A0 expression evaluates zero. =A0*/ > - =A0 =A0 =A0if (code =3D=3D TRUTH_AND_EXPR > + =A0 =A0 =A0if ((code =3D=3D TRUTH_AND_EXPR || code =3D=3D BIT_AND_EXPR) > =A0 =A0 =A0 =A0 =A0&& ((vr0.type =3D=3D VR_RANGE > =A0 =A0 =A0 =A0 =A0 =A0 =A0 && integer_zerop (vr0.min) > =A0 =A0 =A0 =A0 =A0 =A0 =A0 && integer_zerop (vr0.max)) > @@ -2317,7 +2325,7 @@ extract_range_from_binary_expr (value_ra > =A0 =A0 =A0 =A0} > =A0 =A0 =A0 /* If one of the operands is one, we know that the whole > =A0 =A0 =A0 =A0 expression evaluates one. =A0*/ > - =A0 =A0 =A0else if (code =3D=3D TRUTH_OR_EXPR > + =A0 =A0 =A0else if ((code =3D=3D TRUTH_OR_EXPR || code =3D=3D BIT_IOR_E= XPR) > =A0 =A0 =A0 =A0 =A0 =A0 =A0 && ((vr0.type =3D=3D VR_RANGE > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0&& integer_onep (vr0.min) > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0&& integer_onep (vr0.max)) > @@ -2809,7 +2817,7 @@ extract_range_from_unary_expr (value_ran > =A0 =A0 =A0cannot easily determine a resulting range. =A0*/ > =A0 if (code =3D=3D FIX_TRUNC_EXPR > =A0 =A0 =A0 || code =3D=3D FLOAT_EXPR > - =A0 =A0 =A0|| code =3D=3D BIT_NOT_EXPR > + =A0 =A0 =A0|| (code =3D=3D BIT_NOT_EXPR && TYPE_PRECISION (type) !=3D 1) > =A0 =A0 =A0 || code =3D=3D CONJ_EXPR) > =A0 =A0 { > =A0 =A0 =A0 /* We can still do constant propagation here. =A0*/ > @@ -3976,7 +3984,9 @@ build_assert_expr_for (tree cond, tree v > =A0 =A0 =A0 tree a =3D build2 (ASSERT_EXPR, TREE_TYPE (v), v, cond); > =A0 =A0 =A0 assertion =3D gimple_build_assign (n, a); > =A0 =A0 } > - =A0else if (TREE_CODE (cond) =3D=3D TRUTH_NOT_EXPR) > + =A0else if (TREE_CODE (cond) =3D=3D TRUTH_NOT_EXPR > + =A0 =A0 =A0 =A0 =A0|| (TREE_CODE (cond) =3D=3D BIT_NOT_EXPR > + =A0 =A0 =A0 =A0 =A0 =A0 =A0&& TYPE_PRECISION (TREE_TYPE (cond)) =3D=3D = 1)) > =A0 =A0 { > =A0 =A0 =A0 /* Given !V, build the assignment N =3D false. =A0*/ > =A0 =A0 =A0 tree op0 =3D TREE_OPERAND (cond, 0); > @@ -4531,7 +4541,9 @@ register_edge_assert_for_1 (tree op, enu > =A0 =A0 =A0 retval |=3D register_edge_assert_for_1 (gimple_assign_rhs2 (o= p_def), > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 = =A0 =A0 =A0 =A0code, e, bsi); > =A0 =A0 } > - =A0else if (gimple_assign_rhs_code (op_def) =3D=3D TRUTH_NOT_EXPR) > + =A0else if (gimple_assign_rhs_code (op_def) =3D=3D TRUTH_NOT_EXPR > + =A0 =A0 =A0 =A0 =A0|| (gimple_assign_rhs_code (op_def) =3D=3D BIT_NOT_E= XPR > + =A0 =A0 =A0 =A0 =A0 =A0 =A0&& TYPE_PRECISION (TREE_TYPE (op)) =3D=3D 1)) > =A0 =A0 { > =A0 =A0 =A0 /* Recurse, flipping CODE. =A0*/ > =A0 =A0 =A0 code =3D invert_tree_comparison (code, false); > @@ -4617,6 +4629,9 @@ register_edge_assert_for (tree name, edg > > =A0 =A0 =A0 if (is_gimple_assign (def_stmt) > =A0 =A0 =A0 =A0 =A0&& (gimple_assign_rhs_code (def_stmt) =3D=3D TRUTH_OR_= EXPR > + =A0 =A0 =A0 =A0 =A0 =A0 || (gimple_assign_rhs_code (def_stmt) =3D=3D BI= T_IOR_EXPR > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 && INTEGRAL_TYPE_P (TREE_TYPE (name)) > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 && TYPE_PRECISION (TREE_TYPE (name)) = =3D=3D 1) > =A0 =A0 =A0 =A0 =A0 =A0 =A0/* For BIT_IOR_EXPR only if NAME =3D=3D 0 both= operands have > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 necessarily zero value. =A0*/ > =A0 =A0 =A0 =A0 =A0 =A0 =A0|| (comp_code =3D=3D EQ_EXPR > @@ -6747,19 +6762,96 @@ varying: > =A0 return SSA_PROP_VARYING; > =A0} > > +/* Returns operand1 of ssa-name with SSA_NAME as code, Otherwise it > + =A0 returns NULL_TREE. =A0*/ ? Why would you want to look through a single copy? > +static tree > +ssa_name_get_inner_ssa_name_p (tree op) > +{ > + =A0gimple stmt; > + > + =A0if (TREE_CODE (op) !=3D SSA_NAME > + =A0 =A0 =A0|| !is_gimple_assign (SSA_NAME_DEF_STMT (op))) > + =A0 =A0return NULL_TREE; > + =A0stmt =3D SSA_NAME_DEF_STMT (op); > + =A0if (gimple_assign_rhs_code (stmt) !=3D SSA_NAME) > + =A0 =A0return NULL_TREE; > + =A0return gimple_assign_rhs1 (stmt); > +} > + > +/* Returns operand of cast operation, if OP is a type-conversion. Otherw= ise > + =A0 return NULL_TREE. =A0*/ > +static tree > +ssa_name_get_cast_to_p (tree op) > +{ > + =A0gimple stmt; > + > + =A0if (TREE_CODE (op) !=3D SSA_NAME > + =A0 =A0 =A0|| !is_gimple_assign (SSA_NAME_DEF_STMT (op))) > + =A0 =A0return NULL_TREE; > + =A0stmt =3D SSA_NAME_DEF_STMT (op); > + =A0if (!CONVERT_EXPR_CODE_P (gimple_assign_rhs_code (stmt))) > + =A0 =A0return NULL_TREE; > + =A0return gimple_assign_rhs1 (stmt); > +} > + > =A0/* Simplify boolean operations if the source is known > =A0 =A0to be already a boolean. =A0*/ > =A0static bool > =A0simplify_truth_ops_using_ranges (gimple_stmt_iterator *gsi, gimple stm= t) > =A0{ > =A0 enum tree_code rhs_code =3D gimple_assign_rhs_code (stmt); > + =A0gimple stmt2 =3D stmt; > =A0 tree val =3D NULL; > - =A0tree op0, op1; > + =A0tree op0, op1, cop0, cop1; > =A0 value_range_t *vr; > =A0 bool sop =3D false; > =A0 bool need_conversion; > + =A0location_t loc =3D gimple_location (stmt); > > =A0 op0 =3D gimple_assign_rhs1 (stmt); > + =A0op1 =3D NULL_TREE; > + > + =A0/* Handle cases with prefixed type-cast. =A0*/ What cases? This code lacks comments. > + =A0if (CONVERT_EXPR_CODE_P (rhs_code) So this simplifies conversions, not truth ops. > + =A0 =A0 =A0&& INTEGRAL_TYPE_P (TREE_TYPE (op0)) > + =A0 =A0 =A0&& TREE_CODE (op0) =3D=3D SSA_NAME > + =A0 =A0 =A0&& is_gimple_assign (SSA_NAME_DEF_STMT (op0)) > + =A0 =A0 =A0&& INTEGRAL_TYPE_P (TREE_TYPE (gimple_assign_lhs (stmt)))) > + =A0 =A0{ > + =A0 =A0 =A0stmt2 =3D SSA_NAME_DEF_STMT (op0); > + =A0 =A0 =A0op0 =3D gimple_assign_rhs1 (stmt2); > + =A0 =A0 =A0if (!INTEGRAL_TYPE_P (TREE_TYPE (op0))) > + =A0 =A0 =A0 return false; > + =A0 =A0 =A0rhs_code =3D gimple_assign_rhs_code (stmt2); > + =A0 =A0 =A0if (rhs_code !=3D BIT_NOT_EXPR && rhs_code !=3D TRUTH_NOT_EX= PR > + =A0 =A0 =A0 =A0 && rhs_code !=3D TRUTH_AND_EXPR && rhs_code !=3D BIT_AN= D_EXPR > + =A0 =A0 =A0 =A0 && rhs_code !=3D TRUTH_OR_EXPR && rhs_code !=3D BIT_IOR= _EXPR > + =A0 =A0 =A0 =A0 && rhs_code !=3D TRUTH_XOR_EXPR && rhs_code !=3D BIT_XO= R_EXPR > + =A0 =A0 =A0 =A0 && rhs_code !=3D NE_EXPR && rhs_code !=3D EQ_EXPR) > + =A0 =A0 =A0 return false; > + =A0 =A0 =A0if (rhs_code =3D=3D BIT_AND_EXPR || rhs_code =3D=3D BIT_IOR_= EXPR > + =A0 =A0 =A0 =A0 || rhs_code =3D=3D BIT_XOR_EXPR || rhs_code =3D=3D TRUT= H_AND_EXPR > + =A0 =A0 =A0 =A0 || rhs_code =3D=3D TRUTH_OR_EXPR || rhs_code =3D=3D TRU= TH_XOR_EXPR > + =A0 =A0 =A0 =A0 || rhs_code =3D=3D NE_EXPR || rhs_code =3D=3D EQ_EXPR) > + =A0 =A0 =A0 op1 =3D gimple_assign_rhs2 (stmt2); > + =A0 =A0 =A0if (gimple_has_location (stmt2)) > + =A0 =A0 =A0 =A0loc =3D gimple_location (stmt2); > + =A0 =A0} > + =A0else if (CONVERT_EXPR_CODE_P (rhs_code)) > + =A0 =A0return false; That's funny control flow. > + =A0else if (rhs_code =3D=3D BIT_AND_EXPR || rhs_code =3D=3D BIT_IOR_EXPR > + =A0 =A0 =A0|| rhs_code =3D=3D BIT_XOR_EXPR || rhs_code =3D=3D TRUTH_AND= _EXPR > + =A0 =A0 =A0|| rhs_code =3D=3D TRUTH_OR_EXPR || rhs_code =3D=3D TRUTH_XO= R_EXPR > + =A0 =A0 =A0|| rhs_code =3D=3D NE_EXPR || rhs_code =3D=3D EQ_EXPR) > + =A0 =A0op1 =3D gimple_assign_rhs2 (stmt); > + > + =A0/* ~X is only equivalent of !X, if type-precision is one and X has > + =A0 =A0 an integral type. =A0*/ > + =A0if (rhs_code =3D=3D BIT_NOT_EXPR > + =A0 =A0 =A0&& (!INTEGRAL_TYPE_P (TREE_TYPE (op0)) > + =A0 =A0 =A0 =A0 || TYPE_PRECISION (TREE_TYPE (op0)) !=3D 1)) > + =A0 =A0return false; > + > =A0 if (TYPE_PRECISION (TREE_TYPE (op0)) !=3D 1) > =A0 =A0 { > =A0 =A0 =A0 if (TREE_CODE (op0) !=3D SSA_NAME) > @@ -6775,22 +6867,100 @@ simplify_truth_ops_using_ranges (gimple_ > =A0 =A0 =A0 =A0 return false; > =A0 =A0 } > > - =A0if (rhs_code =3D=3D TRUTH_NOT_EXPR) > + =A0if (op1 && TREE_CODE (op1) !=3D INTEGER_CST > + =A0 =A0 =A0&& TYPE_PRECISION (TREE_TYPE (op1)) !=3D 1) > + =A0 =A0{ > + =A0 =A0 =A0vr =3D get_value_range (op1); > + =A0 =A0 =A0val =3D compare_range_with_value (GE_EXPR, vr, integer_zero_= node, &sop); > + =A0 =A0 =A0if (!val || !integer_onep (val)) > + =A0 =A0 =A0 return false; > + > + =A0 =A0 =A0val =3D compare_range_with_value (LE_EXPR, vr, integer_one_n= ode, &sop); > + =A0 =A0 =A0if (!val || !integer_onep (val)) > + =A0 =A0 =A0 return false; > + =A0 =A0} > + > + =A0need_conversion =3D > + =A0 =A0!useless_type_conversion_p (TREE_TYPE (gimple_assign_lhs (stmt)), > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 TREE_TYPE (= op0)); > + > + =A0/* As comparisons X !=3D 0 getting folded by prior pass to (bool) X, > + =A0 =A0 but X =3D=3D 0 might be not folded for none boolean type of X > + =A0 =A0 to (bool) (X ^ 1). > + =A0 =A0 So for bitwise-binary operations we have three cases to handle: > + =A0 =A0 a) ((bool) X) op ((bool) Y) > + =A0 =A0 b) ((bool) X) op (Y =3D=3D 0) OR (X =3D=3D 0) op ((bool) Y) > + =A0 =A0 c) (X =3D=3D 0) op (Y =3D=3D 0) > + =A0 =A0 The later two cases can't be handled for now, as vr tables > + =A0 =A0 would need to be adjusted. =A0*/ > + =A0if (need_conversion > + =A0 =A0 =A0&& (rhs_code =3D=3D BIT_XOR_EXPR > + =A0 =A0 =A0 =A0 || rhs_code =3D=3D BIT_AND_EXPR > + =A0 =A0 =A0 =A0 || rhs_code =3D=3D BIT_IOR_EXPR) > + =A0 =A0 =A0&& TREE_CODE (op1) =3D=3D SSA_NAME && TREE_CODE (op0) =3D=3D= SSA_NAME) > + =A0 =A0{ > + =A0 =A0 =A0cop0 =3D ssa_name_get_cast_to_p (op0); > + =A0 =A0 =A0cop1 =3D ssa_name_get_cast_to_p (op1); > + =A0 =A0 =A0if (!cop0 || !cop1) > + =A0 =A0 =A0 =A0/* We would need an new statment for cases b and c, and = we can't > + =A0 =A0 =A0 =A0 =A0 due vr table, so bail out. =A0*/ > + =A0 =A0 =A0 =A0return false; > + > + =A0 =A0 =A0if (!INTEGRAL_TYPE_P (TREE_TYPE (cop0)) > + =A0 =A0 =A0 =A0 || !types_compatible_p (TREE_TYPE (cop0), TREE_TYPE (co= p1))) > + =A0 =A0 =A0 return false; > + =A0 =A0 =A0need_conversion =3D > + =A0 =A0 =A0 !useless_type_conversion_p (TREE_TYPE (gimple_assign_lhs (s= tmt)), > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 TRE= E_TYPE (cop0)); > + =A0 =A0 =A0if (need_conversion) > + =A0 =A0 =A0 return false; > + =A0 =A0 =A0op0 =3D cop0; > + =A0 =A0 =A0op1 =3D cop1; > + > + =A0 =A0 =A0/* We need to re-check if value ranges for new operands > + =A0 =A0 =A0 =A0 for 1-bit precision/range. =A0*/ > + =A0 =A0 =A0if (TYPE_PRECISION (TREE_TYPE (op0)) !=3D 1) > + =A0 =A0 =A0 { > + =A0 =A0 =A0 =A0 if (TREE_CODE (op0) !=3D SSA_NAME) > + =A0 =A0 =A0 =A0 =A0 return false; > + =A0 =A0 =A0 =A0 vr =3D get_value_range (op0); > + > + =A0 =A0 =A0 =A0 val =3D compare_range_with_value (GE_EXPR, vr, integer_= zero_node, &sop); > + =A0 =A0 =A0 =A0 if (!val || !integer_onep (val)) > + =A0 =A0 =A0 =A0 =A0 return false; > + > + =A0 =A0 =A0 =A0 val =3D compare_range_with_value (LE_EXPR, vr, integer_= one_node, &sop); > + =A0 =A0 =A0 =A0 if (!val || !integer_onep (val)) > + =A0 =A0 =A0 =A0 =A0 return false; > + =A0 =A0 =A0 } > + > + =A0 =A0 =A0if (op1 && TYPE_PRECISION (TREE_TYPE (op1)) !=3D 1) > + =A0 =A0 =A0 { > + =A0 =A0 =A0 =A0 vr =3D get_value_range (op1); > + =A0 =A0 =A0 =A0 val =3D compare_range_with_value (GE_EXPR, vr, integer_= zero_node, &sop); > + =A0 =A0 =A0 =A0 if (!val || !integer_onep (val)) > + =A0 =A0 =A0 =A0 =A0 return false; > + > + =A0 =A0 =A0 =A0 val =3D compare_range_with_value (LE_EXPR, vr, integer_= one_node, &sop); > + =A0 =A0 =A0 =A0 if (!val || !integer_onep (val)) > + =A0 =A0 =A0 =A0 =A0 return false; > + =A0 =A0 =A0 } > + =A0 =A0} > + =A0else if (rhs_code =3D=3D TRUTH_NOT_EXPR || rhs_code =3D=3D BIT_NOT_E= XPR) > =A0 =A0 { > =A0 =A0 =A0 rhs_code =3D NE_EXPR; > =A0 =A0 =A0 op1 =3D build_int_cst (TREE_TYPE (op0), 1); > =A0 =A0 } > =A0 else > =A0 =A0 { > - =A0 =A0 =A0op1 =3D gimple_assign_rhs2 (stmt); > - > =A0 =A0 =A0 /* Reduce number of cases to handle. =A0*/ > =A0 =A0 =A0 if (is_gimple_min_invariant (op1)) > =A0 =A0 =A0 =A0{ > =A0 =A0 =A0 =A0 =A0 /* Exclude anything that should have been already fol= ded. =A0*/ > =A0 =A0 =A0 =A0 =A0if (rhs_code !=3D EQ_EXPR > =A0 =A0 =A0 =A0 =A0 =A0 =A0&& rhs_code !=3D NE_EXPR > - =A0 =A0 =A0 =A0 =A0 =A0 && rhs_code !=3D TRUTH_XOR_EXPR) > + =A0 =A0 =A0 =A0 =A0 =A0 && rhs_code !=3D TRUTH_XOR_EXPR > + =A0 =A0 =A0 =A0 =A0 =A0 && rhs_code !=3D BIT_XOR_EXPR) > =A0 =A0 =A0 =A0 =A0 =A0return false; > > =A0 =A0 =A0 =A0 =A0if (!integer_zerop (op1) > @@ -6810,18 +6980,6 @@ simplify_truth_ops_using_ranges (gimple_ > =A0 =A0 =A0 =A0 =A0/* Punt on A =3D=3D B as there is no BIT_XNOR_EXPR. = =A0*/ > =A0 =A0 =A0 =A0 =A0if (rhs_code =3D=3D EQ_EXPR) > =A0 =A0 =A0 =A0 =A0 =A0return false; > - > - =A0 =A0 =A0 =A0 if (TYPE_PRECISION (TREE_TYPE (op1)) !=3D 1) > - =A0 =A0 =A0 =A0 =A0 { > - =A0 =A0 =A0 =A0 =A0 =A0 vr =3D get_value_range (op1); > - =A0 =A0 =A0 =A0 =A0 =A0 val =3D compare_range_with_value (GE_EXPR, vr, = integer_zero_node, &sop); > - =A0 =A0 =A0 =A0 =A0 =A0 if (!val || !integer_onep (val)) > - =A0 =A0 =A0 =A0 =A0 =A0 =A0 return false; > - > - =A0 =A0 =A0 =A0 =A0 =A0 val =3D compare_range_with_value (LE_EXPR, vr, = integer_one_node, &sop); > - =A0 =A0 =A0 =A0 =A0 =A0 if (!val || !integer_onep (val)) > - =A0 =A0 =A0 =A0 =A0 =A0 =A0 return false; > - =A0 =A0 =A0 =A0 =A0 } > =A0 =A0 =A0 =A0} > =A0 =A0 } > > @@ -6838,7 +6996,8 @@ simplify_truth_ops_using_ranges (gimple_ > =A0 =A0 =A0 =A0 warning_at (location, OPT_Wstrict_overflow, > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0_("assuming signed overflow does n= ot occur when " > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0"simplifying && or || to & or = |")); > - =A0 =A0 =A0else > + =A0 =A0 =A0else if (rhs_code !=3D BIT_AND_EXPR && rhs_code !=3D BIT_IOR= _EXPR > + =A0 =A0 =A0 =A0 =A0 =A0 =A0&& rhs_code !=3D BIT_XOR_EXPR) > =A0 =A0 =A0 =A0 warning_at (location, OPT_Wstrict_overflow, > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0_("assuming signed overflow does n= ot occur when " > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0"simplifying =3D=3D, !=3D or != to identity or ^")); > @@ -6859,16 +7018,21 @@ simplify_truth_ops_using_ranges (gimple_ > =A0 =A0 case TRUTH_AND_EXPR: > =A0 =A0 =A0 rhs_code =3D BIT_AND_EXPR; > =A0 =A0 =A0 break; > + =A0 =A0case BIT_AND_EXPR: > + =A0 =A0 =A0break; > =A0 =A0 case TRUTH_OR_EXPR: > =A0 =A0 =A0 rhs_code =3D BIT_IOR_EXPR; > + =A0 =A0case BIT_IOR_EXPR: > =A0 =A0 =A0 break; > =A0 =A0 case TRUTH_XOR_EXPR: > + =A0 =A0case BIT_XOR_EXPR: > =A0 =A0 case NE_EXPR: > =A0 =A0 =A0 if (integer_zerop (op1)) > =A0 =A0 =A0 =A0{ > =A0 =A0 =A0 =A0 =A0gimple_assign_set_rhs_with_ops (gsi, > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 = =A0 =A0 =A0need_conversion ? NOP_EXPR : SSA_NAME, > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 = =A0 =A0 =A0op0, NULL); > + =A0 =A0 =A0 =A0 gimple_set_location (stmt, loc); > =A0 =A0 =A0 =A0 =A0update_stmt (gsi_stmt (*gsi)); > =A0 =A0 =A0 =A0 =A0return true; > =A0 =A0 =A0 =A0} > @@ -6879,10 +7043,20 @@ simplify_truth_ops_using_ranges (gimple_ > =A0 =A0 =A0 gcc_unreachable (); > =A0 =A0 } > > + =A0/* We can't insert here new expression as otherwise > + =A0 =A0 tracked vr tables getting out of bounds. =A0*/ > =A0 if (need_conversion) > =A0 =A0 return false; > > + =A0/* Reduce here SSA_NAME -> SSA_NAME. =A0*/ > + =A0while ((cop0 =3D ssa_name_get_inner_ssa_name_p (op0)) !=3D NULL_TREE) > + =A0 =A0op0 =3D cop0; > + > + =A0while ((cop1 =3D ssa_name_get_inner_ssa_name_p (op1)) !=3D NULL_TREE) > + =A0 =A0op1 =3D cop1; > + > =A0 gimple_assign_set_rhs_with_ops (gsi, rhs_code, op0, op1); > + =A0gimple_set_location (stmt, loc); > =A0 update_stmt (gsi_stmt (*gsi)); > =A0 return true; > =A0} > @@ -7263,6 +7437,9 @@ simplify_switch_using_ranges (gimple stm > =A0 tree vec2; > =A0 switch_update su; > > + =A0if (in_second_pass) > + =A0 =A0return false; > + > =A0 if (TREE_CODE (op) =3D=3D SSA_NAME) > =A0 =A0 { > =A0 =A0 =A0 vr =3D get_value_range (op); > @@ -7390,6 +7567,7 @@ simplify_stmt_using_ranges (gimple_stmt_ > =A0 =A0 =A0 =A0{ > =A0 =A0 =A0 =A0case EQ_EXPR: > =A0 =A0 =A0 =A0case NE_EXPR: > + =A0 =A0 =A0 case BIT_NOT_EXPR: > =A0 =A0 =A0 =A0case TRUTH_NOT_EXPR: > =A0 =A0 =A0 =A0case TRUTH_AND_EXPR: > =A0 =A0 =A0 =A0case TRUTH_OR_EXPR: > @@ -7425,13 +7603,21 @@ simplify_stmt_using_ranges (gimple_stmt_ > =A0 =A0 =A0 =A0 =A0 =A0 if all the bits being cleared are already cleared= or > =A0 =A0 =A0 =A0 =A0 =A0 all the bits being set are already set. =A0*/ > =A0 =A0 =A0 =A0 =A0if (INTEGRAL_TYPE_P (TREE_TYPE (rhs1))) > - =A0 =A0 =A0 =A0 =A0 return simplify_bit_ops_using_ranges (gsi, stmt); > + =A0 =A0 =A0 =A0 =A0 { > + =A0 =A0 =A0 =A0 =A0 =A0 if (simplify_truth_ops_using_ranges (gsi, stmt)) > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 return true; > + =A0 =A0 =A0 =A0 =A0 =A0 return simplify_bit_ops_using_ranges (gsi, stmt= ); > + =A0 =A0 =A0 =A0 =A0 } > =A0 =A0 =A0 =A0 =A0break; > > =A0 =A0 =A0 =A0CASE_CONVERT: > =A0 =A0 =A0 =A0 =A0if (TREE_CODE (rhs1) =3D=3D SSA_NAME > =A0 =A0 =A0 =A0 =A0 =A0 =A0&& INTEGRAL_TYPE_P (TREE_TYPE (rhs1))) > - =A0 =A0 =A0 =A0 =A0 return simplify_conversion_using_ranges (stmt); > + =A0 =A0 =A0 =A0 =A0 { > + =A0 =A0 =A0 =A0 =A0 =A0 if (simplify_truth_ops_using_ranges (gsi, stmt)) > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 return true; > + =A0 =A0 =A0 =A0 =A0 =A0 return simplify_conversion_using_ranges (stmt); > + =A0 =A0 =A0 =A0 =A0 } > =A0 =A0 =A0 =A0 =A0break; > > =A0 =A0 =A0 =A0default: > @@ -7685,8 +7870,16 @@ vrp_finalize (void) > =A0 =A0 =A0 fprintf (dump_file, "\n"); > =A0 =A0 } > > + =A0/* We redo folding here one time for allowing to inspect more > + =A0 =A0 complex reductions. =A0*/ > + =A0substitute_and_fold (op_with_constant_singleton_value_range, > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0vrp_fold_stmt, false); > + =A0/* We need to mark this second pass to avoid re-entering of same > + =A0 =A0 edges for switch statments. =A0*/ > + =A0in_second_pass =3D true; > =A0 substitute_and_fold (op_with_constant_singleton_value_range, > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 vrp_fold_stmt, false); > + =A0in_second_pass =3D false; If at all you only want to re-call vrp_fold_stmt on all stmts in the function, not do a full-blown substitute_and_fold. Richard. > =A0 if (warn_array_bounds) > =A0 =A0 check_all_array_refs (); >