aboutsummaryrefslogtreecommitdiff
path: root/gcc/match.pd
diff options
context:
space:
mode:
authorJoern Rennecke <joern.rennecke@riscy-ip.com>2021-05-28 09:34:07 +0100
committerJoern Rennecke <joern.rennecke@riscy-ip.com>2021-05-28 09:40:41 +0100
commit5b43f6ace51c08dc2bae3c91a2a11300356c573d (patch)
tree84a796205f9abcd790738ee27cdc82215762ce6c /gcc/match.pd
parentc9114f2804b91690e030383de15a24e0b738e856 (diff)
downloadgcc-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.pd29
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