public inbox for gcc-bugs@sourceware.org
help / color / mirror / Atom feed
* [Bug middle-end/101807] New: bool0 < bool1 Should expand as !bool0 &bool1 and bool0 <= bool1 as !bool0 | bool1
@ 2021-08-06 21:22 pinskia at gcc dot gnu.org
2023-05-18 19:18 ` [Bug middle-end/101807] " pinskia at gcc dot gnu.org
` (5 more replies)
0 siblings, 6 replies; 7+ messages in thread
From: pinskia at gcc dot gnu.org @ 2021-08-06 21:22 UTC (permalink / raw)
To: gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=101807
Bug ID: 101807
Summary: bool0 < bool1 Should expand as !bool0 &bool1 and bool0
<= bool1 as !bool0 | bool1
Product: gcc
Version: 12.0
Status: UNCONFIRMED
Keywords: missed-optimization
Severity: enhancement
Priority: P3
Component: middle-end
Assignee: unassigned at gcc dot gnu.org
Reporter: pinskia at gcc dot gnu.org
Target Milestone: ---
Take:
bool f(bool a, bool b)
{
return a<b;
}
bool g(bool a, bool b)
{
return !a & b;
}
These two should produce similar code.
<= is similar.
^ permalink raw reply [flat|nested] 7+ messages in thread
* [Bug middle-end/101807] bool0 < bool1 Should expand as !bool0 &bool1 and bool0 <= bool1 as !bool0 | bool1
2021-08-06 21:22 [Bug middle-end/101807] New: bool0 < bool1 Should expand as !bool0 &bool1 and bool0 <= bool1 as !bool0 | bool1 pinskia at gcc dot gnu.org
@ 2023-05-18 19:18 ` pinskia at gcc dot gnu.org
2023-05-18 20:00 ` pinskia at gcc dot gnu.org
` (4 subsequent siblings)
5 siblings, 0 replies; 7+ messages in thread
From: pinskia at gcc dot gnu.org @ 2023-05-18 19:18 UTC (permalink / raw)
To: gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=101807
Andrew Pinski <pinskia at gcc dot gnu.org> changed:
What |Removed |Added
----------------------------------------------------------------------------
Ever confirmed|0 |1
Assignee|unassigned at gcc dot gnu.org |pinskia at gcc dot gnu.org
Last reconfirmed| |2023-05-18
Status|UNCONFIRMED |ASSIGNED
--- Comment #1 from Andrew Pinski <pinskia at gcc dot gnu.org> ---
I have a patch.
It even handles:
unsigned f(unsigned a, unsigned b)
{
if (a > 1) __builtin_unreachable();
if (b > 1) __builtin_unreachable();
return a<b;
}
Which gives:
xorl $1, %edi
movl %edi, %eax
andl %esi, %eax
^ permalink raw reply [flat|nested] 7+ messages in thread
* [Bug middle-end/101807] bool0 < bool1 Should expand as !bool0 &bool1 and bool0 <= bool1 as !bool0 | bool1
2021-08-06 21:22 [Bug middle-end/101807] New: bool0 < bool1 Should expand as !bool0 &bool1 and bool0 <= bool1 as !bool0 | bool1 pinskia at gcc dot gnu.org
2023-05-18 19:18 ` [Bug middle-end/101807] " pinskia at gcc dot gnu.org
@ 2023-05-18 20:00 ` pinskia at gcc dot gnu.org
2023-05-18 20:01 ` pinskia at gcc dot gnu.org
` (3 subsequent siblings)
5 siblings, 0 replies; 7+ messages in thread
From: pinskia at gcc dot gnu.org @ 2023-05-18 20:00 UTC (permalink / raw)
To: gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=101807
--- Comment #2 from Andrew Pinski <pinskia at gcc dot gnu.org> ---
Actually I need to check the cost, e.g. on MIPS, there is an one instruction
which does the less than without doing anything.
That is for:
bool f0(bool a, bool b)
{
return a<b;
}
bool g(bool a, bool b)
{
return !a & b;
}
f0:
jr $31
sltu $2,$4,$5
g:
xori $4,$4,0x1
jr $31
and $2,$5,$4
And then after my current patch both are expanded like g. which is wrong.
^ permalink raw reply [flat|nested] 7+ messages in thread
* [Bug middle-end/101807] bool0 < bool1 Should expand as !bool0 &bool1 and bool0 <= bool1 as !bool0 | bool1
2021-08-06 21:22 [Bug middle-end/101807] New: bool0 < bool1 Should expand as !bool0 &bool1 and bool0 <= bool1 as !bool0 | bool1 pinskia at gcc dot gnu.org
2023-05-18 19:18 ` [Bug middle-end/101807] " pinskia at gcc dot gnu.org
2023-05-18 20:00 ` pinskia at gcc dot gnu.org
@ 2023-05-18 20:01 ` pinskia at gcc dot gnu.org
2023-05-18 20:35 ` pinskia at gcc dot gnu.org
` (2 subsequent siblings)
5 siblings, 0 replies; 7+ messages in thread
From: pinskia at gcc dot gnu.org @ 2023-05-18 20:01 UTC (permalink / raw)
To: gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=101807
--- Comment #3 from Andrew Pinski <pinskia at gcc dot gnu.org> ---
(In reply to Andrew Pinski from comment #2)
> Actually I need to check the cost, e.g. on MIPS, there is an one instruction
> which does the less than without doing anything.
RISCV too ...
^ permalink raw reply [flat|nested] 7+ messages in thread
* [Bug middle-end/101807] bool0 < bool1 Should expand as !bool0 &bool1 and bool0 <= bool1 as !bool0 | bool1
2021-08-06 21:22 [Bug middle-end/101807] New: bool0 < bool1 Should expand as !bool0 &bool1 and bool0 <= bool1 as !bool0 | bool1 pinskia at gcc dot gnu.org
` (2 preceding siblings ...)
2023-05-18 20:01 ` pinskia at gcc dot gnu.org
@ 2023-05-18 20:35 ` pinskia at gcc dot gnu.org
2023-05-20 17:07 ` pinskia at gcc dot gnu.org
2023-05-20 18:29 ` pinskia at gcc dot gnu.org
5 siblings, 0 replies; 7+ messages in thread
From: pinskia at gcc dot gnu.org @ 2023-05-18 20:35 UTC (permalink / raw)
To: gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=101807
--- Comment #4 from Andrew Pinski <pinskia at gcc dot gnu.org> ---
Here is what I have so far without the cost model:
/* Hand bool0 CMP bool1 because bitwise operators
are normally better than comparisons. */
if (INTEGRAL_TYPE_P (type)
&& ((tree_nonzero_bits (arg0) == 1 && tree_nonzero_bits (arg1) == 1)
|| (unsignedp && TYPE_PRECISION (type) == 1)))
{
tree b0 = arg0;
tree b1 = arg1;
bool not_p = false;
bool operand1_not_p = false;
tree_code code = ERROR_MARK;
switch (ops->code)
{
case EQ_EXPR:
not_p = true;
code = BIT_XOR_EXPR;
break;
case NE_EXPR:
code = BIT_XOR_EXPR;
break;
case GT_EXPR:
std::swap (b0, b1);
code = BIT_AND_EXPR;
operand1_not_p = true;
break;
case LT_EXPR:
code = BIT_AND_EXPR;
operand1_not_p = true;
break;
case GE_EXPR:
std::swap (b0, b1);
code = BIT_IOR_EXPR;
operand1_not_p = true;
break;
case LE_EXPR:
code = BIT_IOR_EXPR;
operand1_not_p = true;
break;
default:
code = ERROR_MARK;
break;
}
if (code != ERROR_MARK)
{
tree exp;
tree one = build_int_cst (type, 1);
if (operand1_not_p)
b0 = build2_loc (loc, BIT_XOR_EXPR, type, b0, one);
exp = build2_loc (loc, code, type, b0, b1);
if (not_p)
exp = build2_loc (loc, BIT_XOR_EXPR, type, exp, one);
return expand_expr (exp, target, VOIDmode, EXPAND_NORMAL);
}
}
^ permalink raw reply [flat|nested] 7+ messages in thread
* [Bug middle-end/101807] bool0 < bool1 Should expand as !bool0 &bool1 and bool0 <= bool1 as !bool0 | bool1
2021-08-06 21:22 [Bug middle-end/101807] New: bool0 < bool1 Should expand as !bool0 &bool1 and bool0 <= bool1 as !bool0 | bool1 pinskia at gcc dot gnu.org
` (3 preceding siblings ...)
2023-05-18 20:35 ` pinskia at gcc dot gnu.org
@ 2023-05-20 17:07 ` pinskia at gcc dot gnu.org
2023-05-20 18:29 ` pinskia at gcc dot gnu.org
5 siblings, 0 replies; 7+ messages in thread
From: pinskia at gcc dot gnu.org @ 2023-05-20 17:07 UTC (permalink / raw)
To: gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=101807
--- Comment #5 from Andrew Pinski <pinskia at gcc dot gnu.org> ---
Created attachment 55128
--> https://gcc.gnu.org/bugzilla/attachment.cgi?id=55128&action=edit
Patch which I am testing
This one includes the cost model here.
Did a quick test on mips to see it produces the set compare instruction still.
^ permalink raw reply [flat|nested] 7+ messages in thread
* [Bug middle-end/101807] bool0 < bool1 Should expand as !bool0 &bool1 and bool0 <= bool1 as !bool0 | bool1
2021-08-06 21:22 [Bug middle-end/101807] New: bool0 < bool1 Should expand as !bool0 &bool1 and bool0 <= bool1 as !bool0 | bool1 pinskia at gcc dot gnu.org
` (4 preceding siblings ...)
2023-05-20 17:07 ` pinskia at gcc dot gnu.org
@ 2023-05-20 18:29 ` pinskia at gcc dot gnu.org
5 siblings, 0 replies; 7+ messages in thread
From: pinskia at gcc dot gnu.org @ 2023-05-20 18:29 UTC (permalink / raw)
To: gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=101807
--- Comment #6 from Andrew Pinski <pinskia at gcc dot gnu.org> ---
Looks like I only implemented this for do_store_flag which is good but it needs
to also implemented for do_jump too.
Take:
```
#define bool _Bool
bool j(void);
bool h(void);
bool f(bool a, bool b)
{
if(a<b) return h();
return j();
}
bool g(bool a, bool b)
{
if (!a & b) return h();
return j();
}
bool fi(signed char a, signed char b)
{
if (a!=0&&a!=1) __builtin_unreachable();
if (b!=0&&b!=1) __builtin_unreachable();
if(a<b) return h();
return j();
}
bool gi(signed char a, signed char b)
{
if (a!=0&&a!=1) __builtin_unreachable();
if (b!=0&&b!=1) __builtin_unreachable();
if (!a & b) return h();
return j();
}
```
on aarch64, we want f and g, and f and gi to produce the same code. But
currently only g and gi produce the best code of:
```
bic x0, x1, x0
tbnz x0, 0, .L13
```
It is even more interesting on x86, g produces two jumps while f and g produces
the best code:
```
cmpb %sil, %dil
jb .L4
```
^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2023-05-20 18:29 UTC | newest]
Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-08-06 21:22 [Bug middle-end/101807] New: bool0 < bool1 Should expand as !bool0 &bool1 and bool0 <= bool1 as !bool0 | bool1 pinskia at gcc dot gnu.org
2023-05-18 19:18 ` [Bug middle-end/101807] " pinskia at gcc dot gnu.org
2023-05-18 20:00 ` pinskia at gcc dot gnu.org
2023-05-18 20:01 ` pinskia at gcc dot gnu.org
2023-05-18 20:35 ` pinskia at gcc dot gnu.org
2023-05-20 17:07 ` pinskia at gcc dot gnu.org
2023-05-20 18:29 ` pinskia at gcc dot gnu.org
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).