2011/10/6 Richard Guenther <richard.guent...@gmail.com>:
> On Thu, Oct 6, 2011 at 11:28 AM, Kai Tietz <kti...@redhat.com> wrote:
>> Hello,
>>
>> Sorry attached non-updated change.  Here with proper attached patch.
>> This patch improves in fold_truth_andor the generation of branch-conditions 
>> for targets having LOGICAL_OP_NON_SHORT_CIRCUIT set.  If right-hand side 
>> operation of a TRUTH_(OR|AND)IF_EXPR is simple operand, has no side-effects, 
>> and doesn't trap, then try to convert expression to a TRUTH_(AND|OR)_EXPR, 
>> if left-hand operand is a simple operand, and has no side-effects.
>>
>> ChangeLog
>>
>> 2011-10-06  Kai Tietz  <kti...@redhat.com>
>>
>>        * fold-const.c (fold_truth_andor): Convert TRUTH_(AND|OR)IF_EXPR
>>        to TRUTH_OR_EXPR, if suitable.
>>
>> Bootstrapped and tested for all languages (including Ada and Obj-C++) on 
>> host x86_64-unknown-linux-gnu.  Ok for apply?
>>
>> Regards,
>> Kai
>>
>>
>> ndex: fold-const.c
>> ===================================================================
>> --- fold-const.c        (revision 179592)
>> +++ fold-const.c        (working copy)
>> @@ -8387,6 +8387,33 @@
>>   if ((tem = fold_truthop (loc, code, type, arg0, arg1)) != 0)
>>     return tem;
>>
>> +  if ((code == TRUTH_ANDIF_EXPR || code == TRUTH_ORIF_EXPR)
>> +      && !TREE_SIDE_EFFECTS (arg1)
>> +      && simple_operand_p (arg1)
>> +      && LOGICAL_OP_NON_SHORT_CIRCUIT
>
> Why only for LOGICAL_OP_NON_SHORT_CIRCUIT?  It doesn't make
> a difference for !LOGICAL_OP_NON_SHORT_CIRCUIT targets, but ...
Well, I used this check only for not doing this transformation for
targets, which have low-cost branches.  This is the same thing as in
fold_truthop.  It does this transformation only if
LOGICAL_OP_NON_SHORT_CIRCUIT is true.
>> +      && !FLOAT_TYPE_P (TREE_TYPE (arg1))
>
> ?  I hope we don't have &&|| float.
This can happen.  Operands of TRUTH_AND|OR(IF)_EXPR aren't necessarily
of integral type.  After expansion in gimplifier, we have for sure
comparisons, but not in c-tree.

>> +      && ((TREE_CODE_CLASS (TREE_CODE (arg1)) != tcc_comparison
>> +          && TREE_CODE (arg1) != TRUTH_NOT_EXPR)
>> +         || !FLOAT_TYPE_P (TREE_TYPE (TREE_OPERAND (arg1, 0)))))
>
> ?  simple_operand_p would have rejected both ! and comparisons.
This check is the same as in fold_truthop.  I used this check.  The
point here is that floats might trap.

> I miss a test for side-effects on arg0 (and probably simple_operand_p there,
> as well).
See inner of if condition for those checks.  I moved those checks for
arg1 out of the inner conditions to avoid double-checking.

>> +    {
>> +      if (TREE_CODE (arg0) == code
>> +          && !TREE_SIDE_EFFECTS (TREE_OPERAND (arg0, 1))
>> +          && simple_operand_p (TREE_OPERAND (arg0, 1)))
>
> Err ... so why do you recurse here (and associate)?  Even with different
> predicates than above ...

See, here is the missing check. Point is that even if arg0 has
side-effects and is a (AND|OR)IF expression, we might be able to
associate with right-hand argument of arg0, if for it no side-effects
are existing.  Otherwise we wouldn't catch this case.
We have here in maximum a recursion level of one.

> And similar transforms seem to happen in fold_truthop - did you
> investigate why it didn't trigger there.

This is pretty simple.  The point is that only for comparisons this
transformation is done.  But in c-tree we don't have here necessarily
for TRUTH_(AND|OR)[IF]_EXPR comparison arguments, not necessarily
integral ones (see above).

> And I'm missing a testcase.

Ok, I'll add one.  Effect can be seen best after gimplification.

> Richard.
>
>> +       {
>> +         tem = build2_loc (loc,
>> +                           (code == TRUTH_ANDIF_EXPR ? TRUTH_AND_EXPR
>> +                                                     : TRUTH_OR_EXPR),
>> +                           type, TREE_OPERAND (arg0, 1), arg1);
>> +       return fold_build2_loc (loc, code, type, TREE_OPERAND (arg0, 0), 
>> tem);
>> +      }
>> +      if (!TREE_SIDE_EFFECTS (arg0)
>> +          && simple_operand_p (arg0))
>> +       return build2_loc (loc,
>> +                          (code == TRUTH_ANDIF_EXPR ? TRUTH_AND_EXPR
>> +                                                    : TRUTH_OR_EXPR),
>> +                          type, arg0, arg1);
>> +    }
>> +
>>   return NULL_TREE;
>>  }

Regards.
Kai

Reply via email to