2011/5/26 Richard Guenther <richard.guent...@gmail.com>:
> On Thu, May 26, 2011 at 1:28 PM, Kai Tietz <ktiet...@googlemail.com> wrote:
>> 2011/5/26 Richard Guenther <richard.guent...@gmail.com>:
>>> On Thu, May 26, 2011 at 1:20 PM, Kai Tietz <ktiet...@googlemail.com> wrote:
>>>> 2011/5/26 Richard Guenther <richard.guent...@gmail.com>:
>>>>> On Thu, May 26, 2011 at 1:11 PM, Kai Tietz <ktiet...@googlemail.com> 
>>>>> wrote:
>>>>>> 2011/5/26 Richard Guenther <richard.guent...@gmail.com>:
>>>>>>> On Thu, May 26, 2011 at 12:46 PM, Richard Guenther
>>>>>>> <richard.guent...@gmail.com> wrote:
>>>>>>>> On Thu, May 26, 2011 at 12:20 PM, Kai Tietz <kti...@redhat.com> wrote:
>>>>>>>>> Hello,
>>>>>>>>>
>>>>>>>>> this patch ensures that after gimplification also comparison 
>>>>>>>>> expressions using FE's boolean_type_node.  As we need to deal here 
>>>>>>>>> with C/C++'s (obj-c/c++ and java's), Ada's, and Fortran's specific 
>>>>>>>>> boolean types, this patch alters some checks in tree-cfg for Ada's 
>>>>>>>>> sake, and we need to deal in fold-const about type-conversion of 
>>>>>>>>> comparisons special.
>>>>>>>>> Additionally it takes care that in forwprop pass we don't do type 
>>>>>>>>> hoising for boolean types.
>>>>>>>>>
>>>>>>>>> ChangeLog
>>>>>>>>>
>>>>>>>>> 2011-05-26  Kai Tietz
>>>>>>>>>
>>>>>>>>>          * gimplify.c (gimple_boolify): Boolify all comparison
>>>>>>>>>          expressions.
>>>>>>>>>          (gimplify_expr): Use 'useless_type_conversion_p' for 
>>>>>>>>> comparing
>>>>>>>>>          org_type with boolean_type_node for TRUTH-expressions and 
>>>>>>>>> comparisons.
>>>>>>>>>          * fold-const.c (fold_unary_loc): Handle comparison 
>>>>>>>>> conversions with
>>>>>>>>>          boolean-type special.
>>>>>>>>>          * tree-cfg.c (verify_gimple_comparison): Adjust check for 
>>>>>>>>> boolean
>>>>>>>>>          or compatible types.
>>>>>>>>>          (verify_gimple_assign_unary): Likewise.
>>>>>>>>>          * tree-ssa-forwprop.c (forward_propagate_comparison): Handle
>>>>>>>>>          boolean case special.
>>>>>>>>>
>>>>>>>>> Tested on x86_64-pc-linux-gnu (multilib) with regression test for all 
>>>>>>>>> standard languages (C, C++, Obj-C, Fortran, Java) plus Obj-C++ and 
>>>>>>>>> Ada. Ok for apply?
>>>>>>>>
>>>>>>>> It obviously isn't ok to apply before a patch has gone in that will 
>>>>>>>> resolve
>>>>>>>> all of the FAILs you specify.  Comments on the patch:
>>>>>>>>
>>>>>>>> @@ -7281,9 +7284,28 @@ gimplify_expr (tree *expr_p, gimple_seq
>>>>>>>>                 plain wrong if bitfields are involved.  */
>>>>>>>>                {
>>>>>>>>                  tree type = TREE_TYPE (TREE_OPERAND (*expr_p, 1));
>>>>>>>> +                 tree org_type = TREE_TYPE (*expr_p);
>>>>>>>> +
>>>>>>>> +                 if (!useless_type_conversion_p (org_type, 
>>>>>>>> boolean_type_node))
>>>>>>>> +                   {
>>>>>>>> +                     TREE_TYPE (*expr_p) = boolean_type_node;
>>>>>>>> +                     *expr_p = fold_convert_loc (saved_location, 
>>>>>>>> org_type, *expr_p);
>>>>>>>> +                     ret = GS_OK;
>>>>>>>> +                     goto dont_recalculate;
>>>>>>>> +                   }
>>>>>>>>
>>>>>>>> The above should be only done for !AGGREGATE_TYPE_P.  Probably then
>>>>>>>> the strange dont_recalcuate goto can go away as well.
>>>>>>>>
>>>>>>>>                  if (!AGGREGATE_TYPE_P (type))
>>>>>>>> -                   goto expr_2;
>>>>>>>> +                   {
>>>>>>>> +                     enum gimplify_status r0, r1;
>>>>>>>> +
>>>>>>>> +                     r0 = gimplify_expr (&TREE_OPERAND (*expr_p, 0), 
>>>>>>>> pre_p,
>>>>>>>> +                                         post_p, is_gimple_val, 
>>>>>>>> fb_rvalue);
>>>>>>>> +                     r1 = gimplify_expr (&TREE_OPERAND (*expr_p, 1), 
>>>>>>>> pre_p,
>>>>>>>> +                                         post_p, is_gimple_val, 
>>>>>>>> fb_rvalue);
>>>>>>>> +
>>>>>>>> +                     ret = MIN (r0, r1);
>>>>>>>> +                   }
>>>>>>>> +
>>>>>>>>
>>>>>>>> why change this?
>>>>>>>>
>>>>>>>> @@ -7641,6 +7641,12 @@ fold_unary_loc (location_t loc, enum tre
>>>>>>>>        }
>>>>>>>>       else if (COMPARISON_CLASS_P (arg0))
>>>>>>>>        {
>>>>>>>> +         /* Don't optimize type change, if op0 is of kind 
>>>>>>>> boolean_type_node.
>>>>>>>> +            Otherwise this will lead to race-condition on 
>>>>>>>> gimplification
>>>>>>>> +            trying to boolify comparison expression.  */
>>>>>>>> +         if (TREE_TYPE (op0) == boolean_type_node)
>>>>>>>> +           return NULL_TREE;
>>>>>>>> +
>>>>>>>>          if (TREE_CODE (type) == BOOLEAN_TYPE)
>>>>>>>>            {
>>>>>>>>              arg0 = copy_node (arg0);
>>>>>>>>
>>>>>>>> The code leading here looks quite strange to me ...
>>>>>>>>
>>>>>>>> tree
>>>>>>>> fold_unary_loc (location_t loc, enum tree_code code, tree type, tree 
>>>>>>>> op0)
>>>>>>>> {
>>>>>>>> ...
>>>>>>>>  if (TREE_CODE_CLASS (code) == tcc_unary)
>>>>>>>>    {
>>>>>>>> ...
>>>>>>>>      else if (COMPARISON_CLASS_P (arg0))
>>>>>>>>        {
>>>>>>>>          if (TREE_CODE (type) == BOOLEAN_TYPE)
>>>>>>>>            {
>>>>>>>>              arg0 = copy_node (arg0);
>>>>>>>>              TREE_TYPE (arg0) = type;
>>>>>>>>              return arg0;
>>>>>>>>            }
>>>>>>>>          else if (TREE_CODE (type) != INTEGER_TYPE)
>>>>>>>>            return fold_build3_loc (loc, COND_EXPR, type, arg0,
>>>>>>>>                                fold_build1_loc (loc, code, type,
>>>>>>>>                                             integer_one_node),
>>>>>>>>                                fold_build1_loc (loc, code, type,
>>>>>>>>                                             integer_zero_node));
>>>>>>>>        }
>>>>>>>>
>>>>>>>> so, for any tcc_unary, like NEGATE_EXPR, with BOOLEAN_TYPE,
>>>>>>>> return arg0 ... sure.  Same for the 2nd case.  ~ (a == b) isn't
>>>>>>>> the same as a == b ? ~1 : ~0.  I _suppose_ those cases were
>>>>>>>> ment for CONVERT_EXPR_CODE_P (code) instead of all of tcc_unary,
>>>>>>>> in which case they should be dropped or moved below where we
>>>>>>>> handle conversions explicitly.
>>>>>>>>
>>>>>>>> That said - does anyone remember anything about that above code?
>>>>>>>> Trying to do some svn blame history tracking now ...
>>>>>>>
>>>>>>> Oh, the patch continues...
>>>>>>>
>>>>>>> @@ -3208,7 +3208,10 @@ verify_gimple_comparison (tree type, tre
>>>>>>>        && (!POINTER_TYPE_P (op0_type)
>>>>>>>           || !POINTER_TYPE_P (op1_type)
>>>>>>>           || TYPE_MODE (op0_type) != TYPE_MODE (op1_type)))
>>>>>>> -      || !INTEGRAL_TYPE_P (type))
>>>>>>> +      || !(TREE_CODE (type) == BOOLEAN_TYPE
>>>>>>> +          || (TREE_TYPE (type) && TREE_CODE (type) == INTEGER_TYPE
>>>>>>> +              && TREE_CODE (TREE_TYPE (type)) == BOOLEAN_TYPE)
>>>>>>> +          || (INTEGRAL_TYPE_P (type) && TYPE_PRECISION (type) == 1)))
>>>>>>>     {
>>>>>>>
>>>>>>> why that strange TREE_TYPE (TREE_TYPE ())) thing again?  Drop
>>>>>>> that.
>>>>>>>
>>>>>>> @@ -3352,6 +3355,8 @@ verify_gimple_assign_unary (gimple stmt)
>>>>>>>     case TRUTH_NOT_EXPR:
>>>>>>>       /* We require two-valued operand types.  */
>>>>>>>       if (!(TREE_CODE (rhs1_type) == BOOLEAN_TYPE
>>>>>>> +           || (TREE_TYPE (rhs1_type) && TREE_CODE (rhs1_type) == 
>>>>>>> INTEGER_TYPE
>>>>>>> +               && TREE_CODE (TREE_TYPE (rhs1_type)) == BOOLEAN_TYPE)
>>>>>>>            || (INTEGRAL_TYPE_P (rhs1_type)
>>>>>>>                && TYPE_PRECISION (rhs1_type) == 1)))
>>>>>>>         {
>>>>>>>
>>>>>>> likewise.
>>>>>>
>>>>>> Well, those checks are necessary for Ada and its crippled
>>>>>> boolean_type_node and computed boolean-based integer construct.  Ada
>>>>>> derives here the boolean-type to an integer with range 0..1 and the
>>>>>> only way to find out that it is in fact such a beast is by looking
>>>>>> into TREE_TYPE of type.  See here Ada's code for getting base-type
>>>>>> information.
>>>>>> As such things are treated as compatible they can appear for TRUTH_NOT
>>>>>> expressions and comparisons.
>>>>>
>>>>> No they can't as we boolify them.
>>>>>
>>>>> Richard.
>>>>
>>>> Well, they do.  Test can prove this by running fortran's dg tests.
>>>>
>>>> The logic we do in gimplification is:
>>>>
>>>> 1) save original type of expression.
>>>> 2) set expression's type to boolean_type_node.
>>>> 3) if conversion from boolean_type_node to saved type isn't useless
>>>> (and here we have the issue about Fortran's different booleans with
>>>> different modes, which make those kinds not useless) then cast
>>>> expression's result to original type and retry gimplification.
>>>> 4) Otherwise gimplify operands and continue.
>>>
>>> You don't make sense.  Btw,
>>>
>>>>>>> +                 if (!useless_type_conversion_p (org_type, 
>>>>>>> boolean_type_node))
>>>>>>> +                   {
>>>>>>> +                     TREE_TYPE (*expr_p) = boolean_type_node;
>>>>>>> +                     *expr_p = fold_convert_loc (saved_location, 
>>>>>>> org_type,
>>>
>>> is bogus it should be
>>>
>>> TREE_TYPE (*expr_p) = boolean_type_node;
>>> if (!useless_type_conversion_p (org_type, boolean_type_node))
>>>  {
>>>    *expr_p = fold_convert_loc (saved_location, org_type,
>>
>> Well, I spared here the type conversion to boolean_type_node for
>> useless conversion,
>
> useless_type_conversion_p isn't symmetric, so you can't do that.

Right, I am aware of that.  I will move in updated patch the setting
boolean before the if here. As type conversion for the cast back to
original-type via fold_convert_loc is only of interest AFAICS, when
this cast isn't useless (means outter is org_type, and inner is
boolean_type_node). But well, we can replace the if here to the check
against org_type != boolean_type_node, if you prefer this.

Kai

Reply via email to