[patch middle-end]: Missed optimization for (x & ~y) | (~x & y)
Richard Guenther
richard.guenther@gmail.com
Thu Apr 21 09:19:00 GMT 2011
On Wed, Apr 20, 2011 at 5:58 PM, Kai Tietz <ktietz70@googlemail.com> wrote:
> 2011/4/20 Jakub Jelinek <jakub@redhat.com>:
>> On Wed, Apr 20, 2011 at 05:22:31PM +0200, Kai Tietz wrote:
>>> --- gcc.orig/gcc/fold-const.c 2011-04-20 17:10:39.478091900 +0200
>>> +++ gcc/gcc/fold-const.c 2011-04-20 17:11:22.901039400 +0200
>>> @@ -10660,6 +10660,28 @@ fold_binary_loc (location_t loc,
>>> && reorder_operands_p (arg0, TREE_OPERAND (arg1, 0)))
>>> return omit_one_operand_loc (loc, type, arg0, TREE_OPERAND (arg1, 0));
>>>
>>> + /* (X & ~Y) | (~X & Y) is X ^ Y */
>>> + if (TREE_CODE (arg0) == BIT_AND_EXPR
>>> + && TREE_CODE (arg1) == BIT_AND_EXPR)
>>> + {
>>> + tree a0, a1, l0, l1, n0, n1;
>>> +
>>> + a0 = fold_convert_loc (loc, type, TREE_OPERAND (arg1, 0));
>>> + a1 = fold_convert_loc (loc, type, TREE_OPERAND (arg1, 1));
>>> +
>>> + l0 = fold_convert_loc (loc, type, TREE_OPERAND (arg0, 0));
>>> + l1 = fold_convert_loc (loc, type, TREE_OPERAND (arg0, 1));
>>> +
>>> + n0 = fold_build1_loc (loc, BIT_NOT_EXPR, type, l0);
>>> + n1 = fold_build1_loc (loc, BIT_NOT_EXPR, type, l1);
>>> +
>>> + if ((operand_equal_p (n0, a0, 0)
>>> + && operand_equal_p (n1, a1, 0))
>>> + || (operand_equal_p (n0, a1, 0)
>>> + && operand_equal_p (n1, a0, 0)))
>>> + return fold_build2_loc (loc, TRUTH_XOR_EXPR, type, l0, n1);
>>> + }
>>> +
>>
>> I must say I don't like first folding/building new trees, then testing
>> and then maybe optimizing, that is slow and creates unnecessary garbage
>> in the likely case the optimization can't do anything.
>>
>> Wouldn't something like:
>> int arg0_not = TREE_CODE (TREE_OPERAND (arg0, 1)) == BIT_NOT_EXPR;
>> int arg1_not = TREE_CODE (TREE_OPERAND (arg1, 1)) == BIT_NOT_EXPR;
>> if (TREE_CODE (TREE_OPERAND (arg0, arg0_not)) == BIT_NOT_EXPR
>> && TREE_CODE (TREE_OPERAND (arg1, arg1_not)) == BIT_NOT_EXPR
>> && operand_equal_p (TREE_OPERAND (TREE_OPERAND (arg0, arg0_not), 0),
>> TREE_OPERAND (arg1, 1 - arg1_not), 0)
>> && operand_equal_p (TREE_OPERAND (TREE_OPERAND (arg1, arg1_not), 0),
>> TREE_OPERAND (arg0, 1 - arg0_not), 0))
>> return fold_build2_loc (loc, TRUTH_XOR_EXPR, type,
>> fold_convert_loc (loc, type,
>> TREE_OPERAND (arg0, 1 - arg0_not)),
>> fold_convert_loc (loc, type,
>> TREE_OPERAND (arg1, 1 - arg1_not)));
>> work better?
>>
>> Jakub
>>
>
> Well, as special case we could use that, but we have here also to
> handle integer-values, so I used fold to make sure I get inverse. Also
> there might be some transformations, which otherwise might be not
> caught, like !(X || Y) == !X && !Y ...
Btw, I agree with Jakub. Fold is suppose to not create any garbage
if a folding does not apply. So I don't like your patch either.
Richard.
> Regards,
> Kai
>
>
> --
> | (\_/) This is Bunny. Copy and paste
> | (='.'=) Bunny into your signature to help
> | (")_(") him gain world domination
>
More information about the Gcc-patches
mailing list