public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
From: Kai Tietz <ktietz70@googlemail.com>
To: Richard Guenther <richard.guenther@gmail.com>
Cc: Kai Tietz <ktietz@redhat.com>, gcc-patches@gcc.gnu.org
Subject: Re: [patch tree-optimization]: Do bitwise operator optimizations for X op !X patterns
Date: Sat, 02 Jul 2011 08:59:00 -0000	[thread overview]
Message-ID: <CAEwic4Z=FSZ__A_sfnVdKUfxZ4tS3MJgf8ihJH9+f9SkW5U6Fw@mail.gmail.com> (raw)
In-Reply-To: <BANLkTi=6spAr50qKsDsOYv+XdnfBSxebSw@mail.gmail.com>

2011/7/1 Kai Tietz <ktietz70@googlemail.com>:
> 2011/7/1 Kai Tietz <ktietz70@googlemail.com>:
>> 2011/7/1 Richard Guenther <richard.guenther@gmail.com>:
>>> On Fri, Jul 1, 2011 at 1:44 PM, Kai Tietz <ktietz@redhat.com> wrote:
>>>> Ok, here is reworked patch with adjusted testcase.
>>>>
>>>> ChangeLog gcc/
>>>>
>>>> 2011-07-01  Kai Tietz  <ktietz@redhat.com>
>>>>
>>>>        * tree-ssa-forwprop.c (truth_valued_ssa): New function.
>>>>        (detect_not_expr_operand): New function.
>>>>        (simplify_bitwise_binary_1): New function.
>>>>        (simplify_bitwise_binary): Use simplify_bitwise_binary_1.
>>>>
>>>> ChangeLog gcc/
>>>>
>>>> 2011-07-01  Kai Tietz  <ktietz@redhat.com>
>>>>
>>>>        * gcc.dg/binop-notand1a.c: New test.
>>>>        * gcc.dg/binop-notand2a.c: New test.
>>>>        * gcc.dg/binop-notand3a.c: New test.
>>>>        * gcc.dg/binop-notand4a.c: New test.
>>>>        * gcc.dg/binop-notand5a.c: New test.
>>>>        * gcc.dg/binop-notand6a.c: New test.
>>>>        * gcc.dg/binop-notor1.c: New test.
>>>>        * gcc.dg/binop-notor2.c: New test.
>>>>        * gcc.dg/binop-notxor1.c: New test.
>>>>        * gcc.dg/binop-notxor2.c: New test.
>>>>
>>>>
>>>> Bootstrapped and regression tested for all standard languages plus Ada and Obj-C++ for x86_64-pc-linux-gnu.  Ok for apply?
>>>
>>> (please post patches inline)
>>>
>>> +/* Checks if expression has type of one-bit precision, or is a known
>>> +   truth-value pression.  */
>>> +static bool
>>> +truth_valued_ssa_name (tree name)
>>>
>>> The function comment should refer to each parameter in capital letters.
>>> The comment is also odd, if you consider the function name.  Better
>>> would be "Return true if the SSA name NAME is of truth-value.  "
>>
>> Ok
>>
>>> +  /* Don't check here for BOOLEAN_TYPE as the precision isn't
>>> +     necessarily one and so ~X is not equal to !X.  */
>>> +  if (TYPE_PRECISION (type) == 1)
>>> +    return true;
>>>
>>> Technically correct, but did you run into actual problems without this?
>> Yes, this makes issues.  See BIT_NOT_EXPR in fold-const.  It uses LHS type
>> for ~0.  [*]
>>
>>> +/* Helper routine for simplify_bitwise_binary_1 function.
>>> +   If a NOT-expression is found, the operand of the NOT-expression is
>>> +   returned.  Othewise NULL_TREE is returned.
>>> +   Detected not-patterns are !X or X == 0 for X with integral type, and
>>> +   X ^ 1 or ~X for X with integral type with precision of one.
>>> +   The value of CNT_CASTS is either zero, or one.   */
>>> +static tree
>>> +detect_not_expr_operand (tree name)
>>>
>>> What's a NOT-expression?  I'd suggest
>>>
>>> /* For the SSA name NAME return an expression X so that
>>>   NAME = !X.  If there is no such X, return NULL_TREE.  */
>>>
>>> Then a better name for the function would be lookup_inverted_value.
>> Hmm, we don't look up inverted values in general. May
>> lookup_inverted_truth_value?
>>
>>> +  def = SSA_NAME_DEF_STMT (name);
>>> +  if (!def || !is_gimple_assign (def))
>>> +    return NULL_TREE;
>>> +
>>>
>>> def is never NULL.
>> Ok
>>
>>> +  code = gimple_assign_rhs_code (def);
>>> +  op1 = gimple_assign_rhs1 (def);
>>> +  op2 = NULL_TREE;
>>> +
>>> +  /* Get for EQ_EXPR or BIT_XOR_EXPR operation the second operand.
>>> +     If CODE isn't an EQ_EXPR, BIT_XOR_EXPR, TRUTH_NOT_EXPR,
>>> +     or BIT_NOT_EXPR, then return.  */
>>> +  if (code == EQ_EXPR || code == BIT_XOR_EXPR)
>>> +    op2 = gimple_assign_rhs2 (def);
>>> +
>>> +  switch (code)
>>> +    {
>>> +    case TRUTH_NOT_EXPR:
>>> +      return op1;
>>> +    case BIT_NOT_EXPR:
>>> +      if (truth_valued_ssa_name (name))
>>>
>>> op1, not name
>>
>> No, name is right. see [*]
>>
>>> +       return op1;
>>> +      break;
>>> +    case EQ_EXPR:
>>> +      /* Check if we have X == 0 and X has an integral type.  */
>>> +      if (!INTEGRAL_TYPE_P (TREE_TYPE (op1)))
>>> +       break;
>>>
>>> I think you want this test generally, before the switch.
>> No, no need for this. Just for comparisons I need to check that
>> operands are equal. The type of NAME
>> is always an integral value.
>>
>>> +      if (integer_zerop (op2))
>>> +       return op1;
>>> +      else if (integer_zerop (op1))
>>> +       return op2;
>>>
>>> It's always op2 that is 0, no need to test op1.
>> So for comparison constant will be moved always right-hand?  Ok fine by this.
>>
>>> What about NE_EXPR?
>> Maybe for X != 1 for an truth-valued X. But I never saw this pattern
>> generated. All other cases related to NE_EXPR, which might be an
>> inverted variant aren't trivial and not sure if it is worth checking
>> them here.
>> Eg. (X | Y) != 0 -> (X != 0 | Y != 0) would be the inverted variant of
>> (X == 0 && Y == 0). But those things might be better placed in
>> and/or_comparison folding in gimple-fold.c, isn't it?
>>
>>> If you allow EQ/NE_EXPRs then what this function returns is
>>> not something for which NAME = !X holds but something
>>> for which NAME = X == 0 holds.  Otherwise you have to
>>> make sure op1 is a truth value.
>> !X is (for integral types) X == (type-x) 0. And this transformation is
>> bijective AFAICS. I don't see the point you mean here.
>>
>>> There is also EQ/NE_EXPR with op2 == 1, which at least
>>> for truth-valued op1 can be handled as well.
>>
>> See comment above. It is true that X != 1 (for truth-valued X) is X ==
>> 0. This might be a special case worth to add, but for X != 0 (for
>> truth-valued X) it isn't. Same as for X == 1 cases. We want to return
>> the argument of the not expression here. So we would need to return
>> for those cases !X.
>>
>>> +      break;
>>> +    case BIT_XOR_EXPR:
>>> +      /* Check if we have X ^ 1 and X is truth valued.  */
>>> +      if (integer_onep (op2) && truth_valued_ssa_name (op1))
>>> +       return op1;
>>> +      break;
>>> +    default:
>>> +      break;
>>> +    }
>>>
>>> +  /* First check if operands ARG1 and ARG2 are equal, if so we
>>> +     won't have a NOT-pattern match.  Fold these patterns, as
>>> +     we have detected it already.  */
>>> +  if (operand_equal_p (arg1, arg2, 0))
>>> +    {
>>> +      /* X & X -> X, and X | X -> X.  */
>>> +      if (code == BIT_AND_EXPR || code == BIT_IOR_EXPR)
>>> +        return arg1;
>>> +      /* X ^ X -> 0.  */
>>> +      return integer_zero_node;
>>> +    }
>>>
>>> gimple_fold catches this already, no reason to do that here.
>> Ok
>>
>>> +  /* Do we have case not(X) op not(X)?  */
>>> +  if (a1not && a2not)
>>> +    {
>>>
>>> CSE would have handled this, so no reason to check this - you've
>>> done this with the previous operand_equal_p test already.
>> No I didn't.  As this will match cases like (X ^ 1) & !X (for
>> truth-valued X). We compare here the operand of the not-expression.
>>
>>> +  /* Get for each operation operand its optional by one integral typed
>>> +     cast stripped argument. And get the not-expression's operand, if
>>> +     argument represents an not-expression.  */
>>> +  a1not = detect_not_expr_operand (arg1);
>>> +  a2not = detect_not_expr_operand (arg2);
>>> +
>>> +  /* If there are no not-expressions found,  return NULL_TREE. */
>>> +  if (!a1not && !a2not)
>>> +    return NULL_TREE;
>>>
>>> ...
>>>
>>> +  if (a2not)
>>> +    {
>>> +      /* X equal to Y for X op not(Y)  */
>>> +      if (operand_equal_p (arg1, a2not, 0))
>>> +        op = arg1;
>>> +    }
>>>
>>> don't need a1not yet
>>>
>>> So I suggest to rewrite this to sth like
>>>
>>> a1not = detect_not_expr_operand (arg1);
>>> if (a1not
>>>    && operand_equal_p (a1not, arg2, 0))
>>>  op = arg2;
>>> else if ((a2not = detect_not_expr_operand (arg2))
>>>           && operand_equal_p (arg1, a2not, 0))
>>>  op = arg1;
>>> else
>>>   return NULL_TREE;
>>>
>>> ...
>>>
>>> as that is cheaper.  The ???s below are probably not worth handling.
>>>
>>> Richard.
>>>
>>>> Regards,
>>>> Kai
>>>>
>>>
>>
>> Regards,
>> Kai
>>
>
> To be more correct here about the use of the LHS for ~ X instead of
> using X. If I check X for truth-valued, I would match also things like
> ~(X == 0). But type of the comparison isn't necessarily bool, So I
> would match for code like 'int foo (int c) { return c & ~(c == 0); }'
> and would fold it to zero. But it has for c with value zero the value
> 0, and for c with value not zero the result c.

Sorry, yesterday wasn't my day. Of course I meant sample 'int foo c) {
return c & ~ (c != 0); }'. Its result for c != 0 is (c & 0xfffffffe),
and for c == 0 it is 0.

Kai

      parent reply	other threads:[~2011-07-02  8:59 UTC|newest]

Thread overview: 14+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
     [not found] <196308741.816832.1309273513615.JavaMail.root@zmail06.collab.prod.int.phx2.redhat.com>
2011-06-28 15:40 ` Kai Tietz
2011-06-29 11:28   ` Richard Guenther
2011-06-29 12:52     ` Kai Tietz
2011-06-29 13:41       ` Kai Tietz
2011-06-30 12:22         ` Richard Guenther
2011-07-01 11:44           ` Kai Tietz
2011-07-01 12:53             ` Richard Guenther
2011-07-01 13:43               ` Kai Tietz
2011-07-01 13:57                 ` Kai Tietz
2011-07-01 15:23                   ` Kai Tietz
2011-07-04 13:17                     ` Richard Guenther
2011-07-04 18:55                       ` Kai Tietz
2011-07-07 14:34                         ` Richard Guenther
2011-07-02  8:59                   ` Kai Tietz [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to='CAEwic4Z=FSZ__A_sfnVdKUfxZ4tS3MJgf8ihJH9+f9SkW5U6Fw@mail.gmail.com' \
    --to=ktietz70@googlemail.com \
    --cc=gcc-patches@gcc.gnu.org \
    --cc=ktietz@redhat.com \
    --cc=richard.guenther@gmail.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).