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  <ebotca...@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  <ebotca...@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


Reply via email to