Bug 52345 - Missed optimization dealing with bools
Summary: Missed optimization dealing with bools
Status: ASSIGNED
Alias: None
Product: gcc
Classification: Unclassified
Component: tree-optimization (show other bugs)
Version: 4.7.0
: P3 enhancement
Target Milestone: ---
Assignee: Andrew Pinski
URL:
Keywords: missed-optimization
Depends on:
Blocks:
 
Reported: 2012-02-22 21:43 UTC by Andrew Pinski
Modified: 2023-09-17 01:49 UTC (History)
0 users

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed: 2023-06-13 00:00:00


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Andrew Pinski 2012-02-22 21:43:58 UTC
Take the following three functions:
int f(int a, int b)
{
  int c = a != 0;
  int d = (c!=0|b!=0);
  return d;
}

int f1(int a, int b)
{
  int c = a != 0;
  int e = c!=0;
  int h = b!=0;
  int d = e|h;
  return d;
}

int f2(int a, int b)
{
  return (a!=0|b!=0);
}

--- CUT ---
Right now only f2 produces good code while the other two are not so good.
Comment 1 Andrew Pinski 2012-02-22 21:44:52 UTC
I have a fix in mind.
Comment 2 Andrew Pinski 2016-08-29 07:35:30 UTC
For the trunk, they all come close (at least for aarch64):
f:
        cmp     w0, 0
        cset    w0, ne
        orr     w1, w0, w1
        cmp     w1, 0
        cset    w0, ne
        ret
        .size   f, .-f
        .align  2
        .p2align 3,,7
        .global f1
        .type   f1, %function
f1:
        cmp     w0, 0
        ccmp    w1, 0, 0, eq
        cset    w0, ne
        ret
        .size   f1, .-f1
        .align  2
        .p2align 3,,7
        .global f2
        .type   f2, %function
f2:
        orr     w0, w0, w1
        cmp     w0, 0
        cset    w0, ne
        ret

f1 and f2 are similar enough for aarch64 (at least for ThunderX).
Comment 3 Andrew Pinski 2017-09-21 06:54:02 UTC
I don't remember what the patch was ... so unassigning.
Comment 4 Andrew Pinski 2018-04-22 03:37:02 UTC
The generic rule is:
original 3 expressions;

(((int)b) | i) == 0 -> (b == 0) & (i == 0) -> ~b & (i == 0)
    (4 expressions; maybe 3 if b is a comparison and single use)
(((int)b) | i) != 0 -> (b != 0) | (i != 0) -> b | (i != 0)
    (still 3 expressions)

(((int)b) & i) == 0 -> (b == 0) | ((i&1) == 0) -> ~b | ((i&1) == 0)
    (4 expressions; maybe 3 if b is a comparison and single use)

(((int)b) & i) != 0 -> (b != 0) & ((i&1) != 0) -> b & ((i&1) != 0)
    (still 3 expressions)
Where b is a "boolean" type variable.
Comment 5 Andrew Pinski 2023-09-16 19:51:30 UTC
// (a | zero_one) != 0 -> a!=0 | zero_one

(simplify
 (ne (bit_ior:c @1 zero_one_value_p@2) integer_zerop@3)
 (bit_ior (convert @1) (ne @2 @3)))


// (a & zero_one) != 0 -> a==0 & (zero_one^1)
(simplify
 (eq (bit_and:c @1 zero_one_value_p@2) integer_zerop@3)
 (bit_and
  (convert (bit_xor @1 { build_one_cst (TREE_TYPE (@1)); } ))
  (ne @2 @3)))


Similar to:
https://gcc.gnu.org/pipermail/gcc-patches/2023-September/630651.html
Comment 6 Andrew Pinski 2023-09-16 20:05:05 UTC
(In reply to Andrew Pinski from comment #5)
> // (a | zero_one) != 0 -> a!=0 | zero_one
> 
> (simplify
>  (ne (bit_ior:c @1 zero_one_value_p@2) integer_zerop@3)
>  (bit_ior (convert @1) (ne @2 @3)))
> 
> 
> // (a & zero_one) != 0 -> a==0 & (zero_one^1)
Should have been:
  // (a & zero_one) == 0 -> a==0 & (zero_one^1)

> (simplify
>  (eq (bit_and:c @1 zero_one_value_p@2) integer_zerop@3)
>  (bit_and
>   (convert (bit_xor @1 { build_one_cst (TREE_TYPE (@1)); } ))
>   (ne @2 @3)))
> 
> 
> Similar to:
> https://gcc.gnu.org/pipermail/gcc-patches/2023-September/630651.html