diff options
author | Tamar Christina <tamar.christina@arm.com> | 2022-08-03 16:00:39 +0100 |
---|---|---|
committer | Tamar Christina <tamar.christina@arm.com> | 2022-08-03 16:00:39 +0100 |
commit | 9bb19e143cfe8863e2e79d4176b5d7e997b08c5f (patch) | |
tree | fe1317a6184004d57927af006a7ea324529157e3 /gcc/testsuite/gcc.dg/tree-ssa | |
parent | b6df113247b9f3f7c3db0e65c481dad5bcfddfb4 (diff) |
middle-end: Support recognition of three-way max/min.
This patch adds support for three-way min/max recognition in phi-opts.
Concretely for e.g.
#include <stdint.h>
uint8_t three_min (uint8_t xc, uint8_t xm, uint8_t xy) {
uint8_t xk;
if (xc < xm) {
xk = (uint8_t) (xc < xy ? xc : xy);
} else {
xk = (uint8_t) (xm < xy ? xm : xy);
}
return xk;
}
we generate:
<bb 2> [local count: 1073741824]:
_5 = MIN_EXPR <xc_1(D), xy_3(D)>;
_7 = MIN_EXPR <xm_2(D), _5>;
return _7;
instead of
<bb 2>:
if (xc_2(D) < xm_3(D))
goto <bb 3>;
else
goto <bb 4>;
<bb 3>:
xk_5 = MIN_EXPR <xc_2(D), xy_4(D)>;
goto <bb 5>;
<bb 4>:
xk_6 = MIN_EXPR <xm_3(D), xy_4(D)>;
<bb 5>:
# xk_1 = PHI <xk_5(3), xk_6(4)>
return xk_1;
The same function also immediately deals with turning a minimization problem
into a maximization one if the results are inverted. We do this here since
doing it in match.pd would end up changing the shape of the BBs and adding
additional instructions which would prevent various optimizations from working.
gcc/ChangeLog:
* tree-ssa-phiopt.cc (minmax_replacement): Optionally search for the phi
sequence of a three-way conditional.
(replace_phi_edge_with_variable): Support diamonds.
(tree_ssa_phiopt_worker): Detect diamond phi structure for three-way
min/max.
(strip_bit_not, invert_minmax_code): New.
gcc/testsuite/ChangeLog:
* gcc.dg/tree-ssa/split-path-1.c: Disable phi-opts so we don't optimize
code away.
* gcc.dg/tree-ssa/minmax-10.c: New test.
* gcc.dg/tree-ssa/minmax-11.c: New test.
* gcc.dg/tree-ssa/minmax-12.c: New test.
* gcc.dg/tree-ssa/minmax-13.c: New test.
* gcc.dg/tree-ssa/minmax-14.c: New test.
* gcc.dg/tree-ssa/minmax-15.c: New test.
* gcc.dg/tree-ssa/minmax-16.c: New test.
* gcc.dg/tree-ssa/minmax-3.c: New test.
* gcc.dg/tree-ssa/minmax-4.c: New test.
* gcc.dg/tree-ssa/minmax-5.c: New test.
* gcc.dg/tree-ssa/minmax-6.c: New test.
* gcc.dg/tree-ssa/minmax-7.c: New test.
* gcc.dg/tree-ssa/minmax-8.c: New test.
* gcc.dg/tree-ssa/minmax-9.c: New test.
Diffstat (limited to 'gcc/testsuite/gcc.dg/tree-ssa')
-rw-r--r-- | gcc/testsuite/gcc.dg/tree-ssa/minmax-10.c | 20 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/tree-ssa/minmax-11.c | 21 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/tree-ssa/minmax-12.c | 20 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/tree-ssa/minmax-13.c | 19 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/tree-ssa/minmax-14.c | 21 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/tree-ssa/minmax-15.c | 21 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/tree-ssa/minmax-16.c | 17 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/tree-ssa/minmax-3.c | 17 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/tree-ssa/minmax-4.c | 17 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/tree-ssa/minmax-5.c | 17 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/tree-ssa/minmax-6.c | 17 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/tree-ssa/minmax-7.c | 16 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/tree-ssa/minmax-8.c | 17 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/tree-ssa/minmax-9.c | 20 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/tree-ssa/split-path-1.c | 2 |
15 files changed, 261 insertions, 1 deletions
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/minmax-10.c b/gcc/testsuite/gcc.dg/tree-ssa/minmax-10.c new file mode 100644 index 00000000000..58995368441 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/minmax-10.c @@ -0,0 +1,20 @@ +/* { dg-do compile } */ +/* { dg-options "-O -fdump-tree-optimized" } */ + +#include <stdint.h> + +uint8_t three_max (uint8_t xc, uint8_t xm, uint8_t xy) { + uint8_t xk; + xc=~xc; + xm=~xm; + xy=~xy; + if (xc > xm) { + xk = (uint8_t) (xc > xy ? xc : xy); + } else { + xk = (uint8_t) (xm > xy ? xm : xy); + } + return xk; +} + +/* { dg-final { scan-tree-dump-times "MIN_EXPR" 2 "optimized" } } */ +/* { dg-final { scan-tree-dump-times "= ~" 1 "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/minmax-11.c b/gcc/testsuite/gcc.dg/tree-ssa/minmax-11.c new file mode 100644 index 00000000000..1c2ef01b5d1 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/minmax-11.c @@ -0,0 +1,21 @@ +/* { dg-do compile } */ +/* { dg-options "-O -fdump-tree-optimized" } */ + +#include <stdint.h> + +uint8_t three_minmax1 (uint8_t xc, uint8_t xm, uint8_t xy) { + uint8_t xk; + xc=~xc; + xm=~xm; + xy=~xy; + if (xc > xm) { + xk = (uint8_t) (xc < xy ? xc : xy); + } else { + xk = (uint8_t) (xm < xy ? xm : xy); + } + return xk; +} + +/* { dg-final { scan-tree-dump-times "MIN_EXPR" 1 "optimized" } } */ +/* { dg-final { scan-tree-dump-times "MAX_EXPR" 1 "optimized" } } */ +/* { dg-final { scan-tree-dump-times "= ~" 1 "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/minmax-12.c b/gcc/testsuite/gcc.dg/tree-ssa/minmax-12.c new file mode 100644 index 00000000000..3d0c07d9b57 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/minmax-12.c @@ -0,0 +1,20 @@ +/* { dg-do compile } */ +/* { dg-options "-O -fdump-tree-phiopt" } */ + +#include <stdint.h> + +uint8_t three_minmax3 (uint8_t xc, uint8_t xm, uint8_t xy) { + uint8_t xk; + xc=~xc; + xm=~xm; + xy=~xy; + if (xc > xm) { + xk = (uint8_t) (xy < xc ? xc : xy); + } else { + xk = (uint8_t) (xm < xy ? xm : xy); + } + return xk; +} + +/* { dg-final { scan-tree-dump-times "MIN_EXPR" 1 "phiopt1" } } */ +/* { dg-final { scan-tree-dump-times "MAX_EXPR" 1 "phiopt1" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/minmax-13.c b/gcc/testsuite/gcc.dg/tree-ssa/minmax-13.c new file mode 100644 index 00000000000..c0d0f27c802 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/minmax-13.c @@ -0,0 +1,19 @@ +/* { dg-do compile } */ +/* { dg-options "-O -fdump-tree-phiopt" } */ + +#include <stdint.h> + +uint8_t three_minmax2 (uint8_t xc, uint8_t xm, uint8_t xy) { + uint8_t xk; + xc=~xc; + xm=~xm; + xy=~xy; + if (xc > xm) { + xk = (uint8_t) (xc > xy ? xc : xy); + } else { + xk = (uint8_t) (xm < xy ? xm : xy); + } + return xk; +} +/* { dg-final { scan-tree-dump-times "MIN_EXPR" 1 "phiopt1" } } */ +/* { dg-final { scan-tree-dump-times "MAX_EXPR" 1 "phiopt1" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/minmax-14.c b/gcc/testsuite/gcc.dg/tree-ssa/minmax-14.c new file mode 100644 index 00000000000..9c0cadbf7e3 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/minmax-14.c @@ -0,0 +1,21 @@ +/* { dg-do compile } */ +/* { dg-options "-O -fdump-tree-optimized" } */ + +#include <stdint.h> + +uint8_t three_minmax11 (uint8_t xc, uint8_t xm, uint8_t xy) { + uint8_t xk; + xc=~xc; + xm=~xm; + xy=~xy; + if (xc < xm) { + xk = (uint8_t) (xc > xy ? xc : xy); + } else { + xk = (uint8_t) (xm > xy ? xm : xy); + } + return xk; +} + +/* { dg-final { scan-tree-dump-times "MIN_EXPR" 1 "optimized" } } */ +/* { dg-final { scan-tree-dump-times "MAX_EXPR" 1 "optimized" } } */ +/* { dg-final { scan-tree-dump-times "= ~" 1 "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/minmax-15.c b/gcc/testsuite/gcc.dg/tree-ssa/minmax-15.c new file mode 100644 index 00000000000..1d97a16564f --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/minmax-15.c @@ -0,0 +1,21 @@ +/* { dg-do compile } */ +/* { dg-options "-O -fdump-tree-phiopt" } */ + +#include <stdint.h> +#include <stdbool.h> + +uint8_t three_min (uint8_t xc, uint8_t xm, uint8_t xy, bool m) { + uint8_t xk; + if (xc) + { + if (xc < xm) { + xk = (uint8_t) (xc < xy ? xc : xy); + } else { + xk = (uint8_t) (xm < xy ? xm : xy); + } + } + + return xk; +} +/* { dg-final { scan-tree-dump-times "MIN_EXPR" 3 "phiopt1" } } */ +/* { dg-final { scan-tree-dump-times "MAX_EXPR" 0 "phiopt1" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/minmax-16.c b/gcc/testsuite/gcc.dg/tree-ssa/minmax-16.c new file mode 100644 index 00000000000..89377a2cb34 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/minmax-16.c @@ -0,0 +1,17 @@ +/* { dg-do compile } */ +/* { dg-options "-O -fdump-tree-phiopt -g" } */ + +#include <stdint.h> + +uint8_t three_min (uint8_t xc, uint8_t xm, uint8_t xy) { + uint8_t xk; + if (xc < xm) { + xk = (uint8_t) (xc < xy ? xc : xy); + } else { + xk = (uint8_t) (xm < xy ? xm : xy); + } + return xk; +} + +/* { dg-final { scan-tree-dump-times "MIN_EXPR" 3 "phiopt1" } } */ +/* { dg-final { scan-tree-dump-times "MAX_EXPR" 0 "phiopt1" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/minmax-3.c b/gcc/testsuite/gcc.dg/tree-ssa/minmax-3.c new file mode 100644 index 00000000000..de3b2e946e8 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/minmax-3.c @@ -0,0 +1,17 @@ +/* { dg-do compile } */ +/* { dg-options "-O -fdump-tree-phiopt" } */ + +#include <stdint.h> + +uint8_t three_min (uint8_t xc, uint8_t xm, uint8_t xy) { + uint8_t xk; + if (xc < xm) { + xk = (uint8_t) (xc < xy ? xc : xy); + } else { + xk = (uint8_t) (xm < xy ? xm : xy); + } + return xk; +} + +/* { dg-final { scan-tree-dump-times "MIN_EXPR" 3 "phiopt1" } } */ +/* { dg-final { scan-tree-dump-times "MAX_EXPR" 0 "phiopt1" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/minmax-4.c b/gcc/testsuite/gcc.dg/tree-ssa/minmax-4.c new file mode 100644 index 00000000000..0b6d667be86 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/minmax-4.c @@ -0,0 +1,17 @@ +/* { dg-do compile } */ +/* { dg-options "-O -fdump-tree-phiopt" } */ + +#include <stdint.h> + +uint8_t three_max (uint8_t xc, uint8_t xm, uint8_t xy) { + uint8_t xk; + if (xc > xm) { + xk = (uint8_t) (xc > xy ? xc : xy); + } else { + xk = (uint8_t) (xm > xy ? xm : xy); + } + return xk; +} + +/* { dg-final { scan-tree-dump-times "MIN_EXPR" 0 "phiopt1" } } */ +/* { dg-final { scan-tree-dump-times "MAX_EXPR" 3 "phiopt1" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/minmax-5.c b/gcc/testsuite/gcc.dg/tree-ssa/minmax-5.c new file mode 100644 index 00000000000..650601a3cc7 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/minmax-5.c @@ -0,0 +1,17 @@ +/* { dg-do compile } */ +/* { dg-options "-O -fdump-tree-phiopt" } */ + +#include <stdint.h> + +uint8_t three_minmax1 (uint8_t xc, uint8_t xm, uint8_t xy) { + uint8_t xk; + if (xc > xm) { + xk = (uint8_t) (xc < xy ? xc : xy); + } else { + xk = (uint8_t) (xm < xy ? xm : xy); + } + return xk; +} + +/* { dg-final { scan-tree-dump-times "MIN_EXPR" 2 "phiopt1" } } */ +/* { dg-final { scan-tree-dump-times "MAX_EXPR" 1 "phiopt1" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/minmax-6.c b/gcc/testsuite/gcc.dg/tree-ssa/minmax-6.c new file mode 100644 index 00000000000..a628f6d9922 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/minmax-6.c @@ -0,0 +1,17 @@ +/* { dg-do compile } */ +/* { dg-options "-O -fdump-tree-phiopt" } */ + +#include <stdint.h> + +uint8_t three_minmax3 (uint8_t xc, uint8_t xm, uint8_t xy) { + uint8_t xk; + if (xc > xm) { + xk = (uint8_t) (xy < xc ? xc : xy); + } else { + xk = (uint8_t) (xm < xy ? xm : xy); + } + return xk; +} + +/* { dg-final { scan-tree-dump-times "MIN_EXPR" 1 "phiopt1" } } */ +/* { dg-final { scan-tree-dump-times "MAX_EXPR" 1 "phiopt1" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/minmax-7.c b/gcc/testsuite/gcc.dg/tree-ssa/minmax-7.c new file mode 100644 index 00000000000..cb42412c4ad --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/minmax-7.c @@ -0,0 +1,16 @@ +/* { dg-do compile } */ +/* { dg-options "-O -fdump-tree-phiopt" } */ + +#include <stdint.h> + +uint8_t three_minmax2 (uint8_t xc, uint8_t xm, uint8_t xy) { + uint8_t xk; + if (xc > xm) { + xk = (uint8_t) (xc > xy ? xc : xy); + } else { + xk = (uint8_t) (xm < xy ? xm : xy); + } + return xk; +} +/* { dg-final { scan-tree-dump-times "MIN_EXPR" 1 "phiopt1" } } */ +/* { dg-final { scan-tree-dump-times "MAX_EXPR" 1 "phiopt1" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/minmax-8.c b/gcc/testsuite/gcc.dg/tree-ssa/minmax-8.c new file mode 100644 index 00000000000..9cd050e9323 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/minmax-8.c @@ -0,0 +1,17 @@ +/* { dg-do compile } */ +/* { dg-options "-O -fdump-tree-phiopt" } */ + +#include <stdint.h> + +uint8_t three_minmax11 (uint8_t xc, uint8_t xm, uint8_t xy) { + uint8_t xk; + if (xc < xm) { + xk = (uint8_t) (xc > xy ? xc : xy); + } else { + xk = (uint8_t) (xm > xy ? xm : xy); + } + return xk; +} + +/* { dg-final { scan-tree-dump-times "MIN_EXPR" 1 "phiopt1" } } */ +/* { dg-final { scan-tree-dump-times "MAX_EXPR" 2 "phiopt1" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/minmax-9.c b/gcc/testsuite/gcc.dg/tree-ssa/minmax-9.c new file mode 100644 index 00000000000..24f580271c3 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/minmax-9.c @@ -0,0 +1,20 @@ +/* { dg-do compile } */ +/* { dg-options "-O -fdump-tree-optimized" } */ + +#include <stdint.h> + +uint8_t three_min (uint8_t xc, uint8_t xm, uint8_t xy) { + uint8_t xk; + xc=~xc; + xm=~xm; + xy=~xy; + if (xc < xm) { + xk = (uint8_t) (xc < xy ? xc : xy); + } else { + xk = (uint8_t) (xm < xy ? xm : xy); + } + return xk; +} + +/* { dg-final { scan-tree-dump-times "= ~" 1 "optimized" } } */ +/* { dg-final { scan-tree-dump-times "MAX_EXPR" 2 "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/split-path-1.c b/gcc/testsuite/gcc.dg/tree-ssa/split-path-1.c index 8b23ef4c7a3..902dde44a50 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/split-path-1.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/split-path-1.c @@ -1,5 +1,5 @@ /* { dg-do run } */ -/* { dg-options "-O2 -fsplit-paths -fdump-tree-split-paths-details --param max-jump-thread-duplication-stmts=20" } */ +/* { dg-options "-O2 -fsplit-paths -fdump-tree-split-paths-details --param max-jump-thread-duplication-stmts=20 -fno-ssa-phiopt" } */ #include <stdio.h> #include <stdlib.h> |