[patch] Fix wrong code for boolean negation in condition at -O

Jeff Law law@redhat.com
Tue Mar 19 17:54:00 GMT 2019


On 2/25/19 2:07 AM, Eric Botcazou wrote:
> Hi,
> 
> this is a regression present on the mainline and 8 branch, introduced by the 
> new code in edge_info::derive_equivalences dealing with BIT_AND_EXPR for SSA 
> names with boolean range:
> 
> 	      /* If either operand has a boolean range, then we
> 		 know its value must be one, otherwise we just know it
> 		 is nonzero.  The former is clearly useful, I haven't
> 		 seen cases where the latter is helpful yet.  */
> 	      if (TREE_CODE (rhs1) == SSA_NAME)
> 		{
> 		  if (ssa_name_has_boolean_range (rhs1))
> 		    {
> 		      value = build_one_cst (TREE_TYPE (rhs1));
> 		      derive_equivalences (rhs1, value, recursion_limit - 1);
> 		    }
> 		}
> 	      if (TREE_CODE (rhs2) == SSA_NAME)
> 		{
> 		  if (ssa_name_has_boolean_range (rhs2))
> 		    {
> 		      value = build_one_cst (TREE_TYPE (rhs2));
> 		      derive_equivalences (rhs2, value, recursion_limit - 1);
> 		    }
> 		}
> 
> and visible on the attached Ada testcase at -O1 or above.
> 
> The sequence of events is as follows: for boolean types with precision > 1 
> (the normal boolean types in Ada), the gimplifier turns a TRUTH_NOT_EXPR into 
> a BIT_XOR_EXPR with 1 in order to preserve the 0-or-1-value invariant:
> 
> 	    /* The parsers are careful to generate TRUTH_NOT_EXPR
> 	       only with operands that are always zero or one.
> 	       We do not fold here but handle the only interesting case
> 	       manually, as fold may re-introduce the TRUTH_NOT_EXPR.  */
> 	    *expr_p = gimple_boolify (*expr_p);
> 	    if (TYPE_PRECISION (TREE_TYPE (*expr_p)) == 1)
> 	      *expr_p = build1_loc (input_location, BIT_NOT_EXPR,
> 				    TREE_TYPE (*expr_p),
> 				    TREE_OPERAND (*expr_p, 0));
> 	    else
> 	      *expr_p = build2_loc (input_location, BIT_XOR_EXPR,
> 				    TREE_TYPE (*expr_p),
> 				    TREE_OPERAND (*expr_p, 0),
> 				    build_int_cst (TREE_TYPE (*expr_p), 1));
> 
> Now this TRUTH_NOT_EXPR is part of a conjunction which has been turned into a 
> BIT_AND_EXPR by the folder, so this gives BIT_AND_EXPR <BIT_XOR_EXPR <X, 1>>.
> 
> After some optimization passes, the second operand of the BIT_AND_EXPR is also 
> folded into 1 and, consequently, the following match.pd pattern kicks in:
> 
> /* Fold (X & Y) ^ Y and (X ^ Y) & Y as ~X & Y.  */
> (for opo (bit_and bit_xor)
>      opi (bit_xor bit_and)
>  (simplify
>   (opo:c (opi:c @0 @1) @1) 
>   (bit_and (bit_not @0) @1)))
> 
> and yields BIT_AND_EXPR <BIT_NOT_EXPR, 1>.  This is still correct, in the 
> sense that the 0-or-1-value invariant is preserved.
> 
> Then the new code in edge_info::derive_equivalences above deduces from this 
> that the BIT_NOT_EXPR has value 1 on one of the edges.  But the same function 
> also handles the BIT_NOT_EXPR itself and further deduces that its operand has 
> value ~1 or 254 (the precision of boolean types is 8) on this edge, which 
> breaks the 0-or-1-value invariant and leads to wrong code downstream.
> 
> Given the new code for BIT_AND_EXPR in edge_info::derive_equivalences for 
> boolean types, I think that the same special treatment must be added for 
> boolean types in the BIT_NOT_EXPR case to preserve the 0-or-1-value invariant.
> 
> Bootstrapped/regtested on x86_64-suse-linux, OK for mainline and 8 branch?
> 
> 
> 2019-02-25  Eric Botcazou  <ebotcazou@adacore.com>
> 
> 	* tree-ssa-dom.c (edge_info::derive_equivalences) <BIT_IOR_EXPR>: Fix
> 	and move around comment.
> 	<BIT_AND_EXPR>: Likewise.
> 	<BIT_NOT_EXPR>: Add specific handling for boolean types.
> 
> 
> 2019-02-25  Eric Botcazou  <ebotcazou@adacore.com>
> 
> 	* gnat.dg/opt77.adb: New test.
> 	* gnat.dg/opt77_pkg.ad[sb]: Likewise.
Umm, did you look at ssa_name_has_boolean_range?  Isn't the problem that
Ada's BOOLEAN_TYPE has a wider range than [0..1] and thus this is the
wrong bit of code:

  /* Boolean types always have a range [0..1].  */
  if (TREE_CODE (TREE_TYPE (op)) == BOOLEAN_TYPE)
    return true;

IIRC there are other places that have similar logic and rely on
ssa_name_has_boolean_range to filter out anything undesirable.

jeff




More information about the Gcc-patches mailing list