diff options
author | Jakub Jelinek <jakub@redhat.com> | 2023-11-28 10:14:55 +0100 |
---|---|---|
committer | Jakub Jelinek <jakub@redhat.com> | 2023-11-28 10:14:55 +0100 |
commit | 03877e7eccd2734ca93a2d13aa2abf55e0aec923 (patch) | |
tree | 7da4dbc1c5d83219b9e31fd3b2eda0c5af36f2a9 /gcc | |
parent | 594ef1ff707866bcdc1f077c5d078a5bd250320f (diff) | |
download | gcc-03877e7eccd2734ca93a2d13aa2abf55e0aec923.zip gcc-03877e7eccd2734ca93a2d13aa2abf55e0aec923.tar.gz gcc-03877e7eccd2734ca93a2d13aa2abf55e0aec923.tar.bz2 |
match.pd: Fix popcount (X) + popcount (Y) simplification [PR112719]
Since my PR112566 r14-5557 changes the following testcase ICEs, because
.POPCOUNT (x) + .POPCOUNT (y) has a simplification attempted even when
x and y have incompatible types (different precisions).
Note, with _BitInt it can ICE already starting with r14-5435 and
I think as a latent problem it exists for years, because IFN_POPCOUNT
calls inherently can have different argument types and return type
is always the same.
The following patch fixes it by using widest_int during the analysis
(which is where it was ICEing) and if it is optimizable, casting to
the wider type so that bit_ior has matching argument types.
2023-11-28 Jakub Jelinek <jakub@redhat.com>
PR tree-optimization/112719
* match.pd (popcount (X) + popcount (Y) -> POPCOUNT (X | Y)): Deal
with argument types with different precisions.
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/match.pd | 9 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/pr112719.c | 18 |
2 files changed, 25 insertions, 2 deletions
diff --git a/gcc/match.pd b/gcc/match.pd index 95225e4..0382fd5 100644 --- a/gcc/match.pd +++ b/gcc/match.pd @@ -8732,8 +8732,13 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) (simplify (plus (POPCOUNT:s @0) (POPCOUNT:s @1)) (if (INTEGRAL_TYPE_P (type) - && wi::bit_and (tree_nonzero_bits (@0), tree_nonzero_bits (@1)) == 0) - (POPCOUNT (bit_ior @0 @1)))) + && (wi::bit_and (widest_int::from (tree_nonzero_bits (@0), UNSIGNED), + widest_int::from (tree_nonzero_bits (@1), UNSIGNED)) + == 0)) + (with { tree utype = TREE_TYPE (@0); + if (TYPE_PRECISION (utype) < TYPE_PRECISION (TREE_TYPE (@1))) + utype = TREE_TYPE (@1); } + (POPCOUNT (bit_ior (convert:utype @0) (convert:utype @1)))))) /* popcount(X) == 0 is X == 0, and related (in)equalities. */ (for popcount (POPCOUNT) diff --git a/gcc/testsuite/gcc.dg/pr112719.c b/gcc/testsuite/gcc.dg/pr112719.c new file mode 100644 index 0000000..c69a7c1 --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr112719.c @@ -0,0 +1,18 @@ +/* PR tree-optimization/112719 */ +/* { dg-do compile } */ +/* { dg-options "-O" } */ +/* { dg-additional-options "-msse4" { target i?86-*-* x86_64-*-* } } */ + +int +foo (unsigned int a, unsigned short b) +{ + return __builtin_popcountl (a) + __builtin_popcountl (b); +} + +int +bar (unsigned int a, unsigned short b) +{ + a &= 0xaaaaaaaaUL; + b &= 0x5555; + return __builtin_popcountll (a) + __builtin_popcountll (b); +} |