On Fri, Mar 4, 2016 at 12:56 PM, Jakub Jelinek <ja...@redhat.com> wrote:
> On Fri, Mar 04, 2016 at 06:49:58PM +0100, Bernd Schmidt wrote:
>> On 03/04/2016 06:27 PM, Bernd Schmidt wrote:
>> >On 03/04/2016 06:14 PM, Patrick Palka wrote:
>> >
>> >>I just quickly tested building the generated insn-attrtab.c with and
>> >>without the patch using my host gcc 5.3 compiler and the .s output is
>> >>not the same.
>> >
>> >Hmm, looking at the 003t.original dump it looks like there are
>> >differences in SAVE_EXPRs. Indeed we seem to generate different code for
>> >
>> >int at;
>> >
>> >int foo ()
>> >{
>> >   if (at == 2 || at == 4 || at == 7)
>> >     return 1;
>> >   return 0;
>> >}
>> >
>> >int bar ()
>> >{
>> >   if (at == 2 || (at == 4 || at == 7))
>> >     return 1;
>> >   return 0;
>> >}
>>
>> Ahh... it's not just different placement of SAVE_EXPRs, it's actually a case
>> of TRUTH_ORIF_EXPR vs. TRUTH_OR_EXPR (the distinction is invisible in the
>> dumps), the latter being created by fold_range_test. That's a bit of a
>> broken optimization what with its inability to see more than two comparisons
>> at a time... we convert one ORIF per function, but a different one.
>
> I think we don't need to guarantee identical assembly, the reason I've
> suggested that was if it passed, it would be much easier to verify.
> Without that, I think it should be bootstrapped at least on one other
> target.  Note the cases you remove the parens aren't just || and &&, but
> most likely also | and & (at least there is some flag whether to print those
> as && or &).  And there is code for the caching of the attributes where the
> result is still usable, I believe the patch doesn't break that, but it
> wouldn't hurt to verify that.

Here's an updated patch that mentions that & and | are also affected.  And I
can't see how this change would possibly affect the attr caching stuff since it
just makes

  (a) OP ((b) OP (c))

get emitted as

  (a) OP (b) OP (c)

For OP = || or &&, the expressions a, b and c will still get evaluated left to
right.  And for OP = | or &, the order of evaluation of a, b and c remains
undefined.

Is this OK to commit after testing on x86_64-pc-linux-gnu?

gcc/ChangeLog:

        * genattrtab.c (write_test_expr): New parameter EMIT_PARENS
        which defaults to true.  Emit an outer pair of parentheses only if
        EMIT_PARENS.  When continuing a chain of && or || (or & or |),
        don't emit parentheses for the right-hand operand.
---
 gcc/genattrtab.c | 31 +++++++++++++++++++++++--------
 1 file changed, 23 insertions(+), 8 deletions(-)

diff --git a/gcc/genattrtab.c b/gcc/genattrtab.c
index b64d8b9..c956527 100644
--- a/gcc/genattrtab.c
+++ b/gcc/genattrtab.c
@@ -3416,7 +3416,10 @@ find_attrs_to_cache (rtx exp, bool create)
 
 /* Given a piece of RTX, print a C expression to test its truth value to OUTF.
    We use AND and IOR both for logical and bit-wise operations, so
-   interpret them as logical unless they are inside a comparison expression.  
*/
+   interpret them as logical unless they are inside a comparison expression.
+
+   An outermost pair of parentheses is emitted around this C expression unless
+   EMIT_PARENS is false.  */
 
 /* Interpret AND/IOR as bit-wise operations instead of logical.  */
 #define FLG_BITWISE            1
@@ -3432,16 +3435,16 @@ find_attrs_to_cache (rtx exp, bool create)
 #define FLG_OUTSIDE_AND                8
 
 static unsigned int
-write_test_expr (FILE *outf, rtx exp, unsigned int attrs_cached, int flags)
+write_test_expr (FILE *outf, rtx exp, unsigned int attrs_cached, int flags,
+                bool emit_parens = true)
 {
   int comparison_operator = 0;
   RTX_CODE code;
   struct attr_desc *attr;
 
-  /* In order not to worry about operator precedence, surround our part of
-     the expression with parentheses.  */
+  if (emit_parens)
+    fprintf (outf, "(");
 
-  fprintf (outf, "(");
   code = GET_CODE (exp);
   switch (code)
     {
@@ -3575,8 +3578,18 @@ write_test_expr (FILE *outf, rtx exp, unsigned int 
attrs_cached, int flags)
              || GET_CODE (XEXP (exp, 1)) == EQ_ATTR
              || (GET_CODE (XEXP (exp, 1)) == NOT
                  && GET_CODE (XEXP (XEXP (exp, 1), 0)) == EQ_ATTR)))
-       attrs_cached
-         = write_test_expr (outf, XEXP (exp, 1), attrs_cached, flags);
+       {
+         bool need_parens = true;
+
+         /* No need to emit parentheses around the right-hand operand if we are
+            continuing a chain of && or || (or & or |).  */
+         if (GET_CODE (XEXP (exp, 1)) == code)
+           need_parens = false;
+
+         attrs_cached
+           = write_test_expr (outf, XEXP (exp, 1), attrs_cached, flags,
+                              need_parens);
+       }
       else
        write_test_expr (outf, XEXP (exp, 1), attrs_cached,
                         flags | comparison_operator);
@@ -3794,7 +3807,9 @@ write_test_expr (FILE *outf, rtx exp, unsigned int 
attrs_cached, int flags)
             GET_RTX_NAME (code));
     }
 
-  fprintf (outf, ")");
+  if (emit_parens)
+    fprintf (outf, ")");
+
   return attrs_cached;
 }
 
-- 
2.8.1.361.g2fbef4c

Reply via email to