diff options
author | Joern Rennecke <joern.rennecke@riscy-ip.com> | 2021-05-28 09:34:07 +0100 |
---|---|---|
committer | Joern Rennecke <joern.rennecke@riscy-ip.com> | 2021-05-28 09:40:41 +0100 |
commit | 5b43f6ace51c08dc2bae3c91a2a11300356c573d (patch) | |
tree | 84a796205f9abcd790738ee27cdc82215762ce6c /gcc/match.pd | |
parent | c9114f2804b91690e030383de15a24e0b738e856 (diff) | |
download | gcc-5b43f6ace51c08dc2bae3c91a2a11300356c573d.zip gcc-5b43f6ace51c08dc2bae3c91a2a11300356c573d.tar.gz gcc-5b43f6ace51c08dc2bae3c91a2a11300356c573d.tar.bz2 |
Recognize popcount also when a double width operation is needed.
2021-05-28 Joern Rennecke <joern.rennecke@riscy-ip.com>
gcc/
* match.pd <popcount & / + pattern matching>:
When generating popcount directly fails, try doing it in two halves.
gcc/testsuite/
* gcc.dg/tree-ssa/popcount4ll.c: Remove lp64 condition.
Adjust scanning pattern for !lp64.
* gcc.dg/tree-ssa/popcount5ll.c: Likewise.
* gcc.dg/tree-ssa/popcount4l.c: Adjust scanning pattern
for ! int32plus.
Co-Authored-By: Richard Biener <rguenther@suse.de>
Diffstat (limited to 'gcc/match.pd')
-rw-r--r-- | gcc/match.pd | 29 |
1 files changed, 25 insertions, 4 deletions
diff --git a/gcc/match.pd b/gcc/match.pd index b60e270..d06ff170 100644 --- a/gcc/match.pd +++ b/gcc/match.pd @@ -6642,10 +6642,31 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) && tree_to_uhwi (@3) == c2 && tree_to_uhwi (@9) == c3 && tree_to_uhwi (@7) == c3 - && tree_to_uhwi (@11) == c4 - && direct_internal_fn_supported_p (IFN_POPCOUNT, type, - OPTIMIZE_FOR_BOTH)) - (convert (IFN_POPCOUNT:type @0))))) + && tree_to_uhwi (@11) == c4) + (if (direct_internal_fn_supported_p (IFN_POPCOUNT, type, + OPTIMIZE_FOR_BOTH)) + (convert (IFN_POPCOUNT:type @0)) + /* Try to do popcount in two halves. PREC must be at least + five bits for this to work without extension before adding. */ + (with { + tree half_type = NULL_TREE; + opt_machine_mode m = mode_for_size ((prec + 1) / 2, MODE_INT, 1); + int half_prec = 8; + if (m.exists () + && m.require () != TYPE_MODE (type)) + { + half_prec = GET_MODE_PRECISION (as_a <scalar_int_mode> (m)); + half_type = build_nonstandard_integer_type (half_prec, 1); + } + gcc_assert (half_prec > 2); + } + (if (half_type != NULL_TREE + && direct_internal_fn_supported_p (IFN_POPCOUNT, half_type, + OPTIMIZE_FOR_BOTH)) + (convert (plus + (IFN_POPCOUNT:half_type (convert @0)) + (IFN_POPCOUNT:half_type (convert (rshift @0 + { build_int_cst (integer_type_node, half_prec); } ))))))))))) /* __builtin_ffs needs to deal on many targets with the possible zero argument. If we know the argument is always non-zero, __builtin_ctz + 1 |