2011/10/6 Richard Guenther <[email protected]>:
> On Thu, Oct 6, 2011 at 11:28 AM, Kai Tietz <[email protected]> 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 <[email protected]>
>>
>> * 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