summaryrefslogtreecommitdiff
path: root/gcc/match.pd
diff options
context:
space:
mode:
authorDmitrij Pochepko <dmitrij.pochepko@bell-sw.com>2019-10-08 21:50:05 +0000
committerSteve Ellcey <sje@gcc.gnu.org>2019-10-08 21:50:05 +0000
commitac87f0f3459a57f03503e51aeffc54bb6ef36b90 (patch)
tree17ab8394fbe1f478d4ccabe2f9aa8d5f28955f99 /gcc/match.pd
parent7c3ed632601bf485335a7fe00d1db34b23ebacd2 (diff)
re PR tree-optimization/90836 (Missing popcount pattern matching)
2019-10-08 Dmitrij Pochepko <dmitrij.pochepko@bell-sw.com> PR tree-optimization/90836 * gcc/match.pd (popcount): New pattern. From-SVN: r276721
Diffstat (limited to 'gcc/match.pd')
-rw-r--r--gcc/match.pd58
1 files changed, 58 insertions, 0 deletions
diff --git a/gcc/match.pd b/gcc/match.pd
index e3ac06c8ef5..2c82287f216 100644
--- a/gcc/match.pd
+++ b/gcc/match.pd
@@ -5689,6 +5689,64 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
(cmp (popcount @0) integer_zerop)
(rep @0 { build_zero_cst (TREE_TYPE (@0)); }))))
+#if GIMPLE
+/* 64- and 32-bits branchless implementations of popcount are detected:
+
+ int popcount64c (uint64_t x)
+ {
+ x -= (x >> 1) & 0x5555555555555555ULL;
+ x = (x & 0x3333333333333333ULL) + ((x >> 2) & 0x3333333333333333ULL);
+ x = (x + (x >> 4)) & 0x0f0f0f0f0f0f0f0fULL;
+ return (x * 0x0101010101010101ULL) >> 56;
+ }
+
+ int popcount32c (uint32_t x)
+ {
+ x -= (x >> 1) & 0x55555555;
+ x = (x & 0x33333333) + ((x >> 2) & 0x33333333);
+ x = (x + (x >> 4)) & 0x0f0f0f0f;
+ return (x * 0x01010101) >> 24;
+ } */
+(simplify
+ (rshift
+ (mult
+ (bit_and
+ (plus:c
+ (rshift @8 INTEGER_CST@5)
+ (plus:c@8
+ (bit_and @6 INTEGER_CST@7)
+ (bit_and
+ (rshift
+ (minus@6
+ @0
+ (bit_and
+ (rshift @0 INTEGER_CST@4)
+ INTEGER_CST@11))
+ INTEGER_CST@10)
+ INTEGER_CST@9)))
+ INTEGER_CST@3)
+ INTEGER_CST@2)
+ INTEGER_CST@1)
+ /* Check constants and optab. */
+ (with
+ {
+ unsigned prec = TYPE_PRECISION (type);
+ int shift = 64 - prec;
+ const unsigned HOST_WIDE_INT c1 = 0x0101010101010101ULL >> shift,
+ c2 = 0x0F0F0F0F0F0F0F0FULL >> shift,
+ c3 = 0x3333333333333333ULL >> shift,
+ c4 = 0x5555555555555555ULL >> shift;
+ }
+ (if (prec <= 64 && TYPE_UNSIGNED (type) && tree_to_uhwi (@4) == 1
+ && tree_to_uhwi (@10) == 2 && tree_to_uhwi (@5) == 4
+ && tree_to_uhwi (@1) == prec - 8 && tree_to_uhwi (@2) == c1
+ && 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)))))
+#endif
+
/* Simplify:
a = a1 op a2