match: a CMP nonnegative ? a : ABS<a> simplified to just ABS<a> [PR112392]

We can optimize `a == nonnegative ? a : ABS<a>`, `a > nonnegative ? a : ABS<a>`
and `a >= nonnegative ? a : ABS<a>` into `ABS<a>`. This allows removal of
some extra comparison and extra conditional moves in some cases.
I don't remember where I had found though but it is simple to add so
let's add it.

Bootstrapped and tested on x86_64-linux-gnu with no regressions.

Note I have a secondary pattern for the equal case as either a or nonnegative
could be used.

	PR tree-optimization/112392

gcc/ChangeLog:

	* match.pd (`x CMP nonnegative ? x : ABS<x>`): New pattern;
	where CMP is ==, > and >=.
	(`x CMP nonnegative@y ? y : ABS<x>`): New pattern.

gcc/testsuite/ChangeLog:

	* gcc.dg/tree-ssa/phi-opt-41.c: New test.

Signed-off-by: Andrew Pinski <quic_apinski@quicinc.com>
This commit is contained in:
Andrew Pinski 2024-05-06 23:53:41 -07:00
parent f4b86ab09d
commit 5726de79e2
2 changed files with 49 additions and 0 deletions

View File

@ -5876,6 +5876,21 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
(convert (absu:utype @0)))
@3))))
/* X > Positive ? X : ABS(X) -> ABS(X) */
/* X >= Positive ? X : ABS(X) -> ABS(X) */
/* X == Positive ? X : ABS(X) -> ABS(X) */
(for cmp (eq gt ge)
(simplify
(cond (cmp:c @0 tree_expr_nonnegative_p@1) @0 (abs@3 @0))
(if (INTEGRAL_TYPE_P (type))
@3)))
/* X == Positive ? Positive : ABS(X) -> ABS(X) */
(simplify
(cond (eq:c @0 tree_expr_nonnegative_p@1) @1 (abs@3 @0))
(if (INTEGRAL_TYPE_P (type))
@3))
/* (X + 1) > Y ? -X : 1 simplifies to X >= Y ? -X : 1 when
X is unsigned, as when X + 1 overflows, X is -1, so -X == 1. */
(simplify

View File

@ -0,0 +1,34 @@
/* { dg-do compile } */
/* { dg-options "-O1 -fdump-tree-phiopt1" } */
/* PR tree-optimization/112392 */
int feq_1(int a, unsigned char b)
{
int absb = b;
if (a == absb) return absb;
return a > 0 ? a : -a;
}
int feq_2(int a, unsigned char b)
{
int absb = b;
if (a == absb) return a;
return a > 0 ? a : -a;
}
int fgt(int a, unsigned char b)
{
int absb = b;
if (a > absb) return a;
return a > 0 ? a : -a;
}
int fge(int a, unsigned char b)
{
int absb = b;
if (a >= absb) return a;
return a > 0 ? a : -a;
}
/* { dg-final { scan-tree-dump-not "if " "phiopt1" } } */
/* { dg-final { scan-tree-dump-times "ABS_EXPR <" 4 "phiopt1" } } */