aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorAldy Hernandez <aldyh@redhat.com>2022-10-03 17:31:32 +0200
committerAldy Hernandez <aldyh@redhat.com>2022-10-04 06:23:14 +0200
commitf50d103183c551c7f9f9f20efaf2ebbf83d5e99f (patch)
tree77e624677cb5b50d227f3697078e6d93f18a8dc1 /gcc
parent70e3f71a279856eabf99bbc92c0345c3ad20b615 (diff)
downloadgcc-f50d103183c551c7f9f9f20efaf2ebbf83d5e99f.zip
gcc-f50d103183c551c7f9f9f20efaf2ebbf83d5e99f.tar.gz
gcc-f50d103183c551c7f9f9f20efaf2ebbf83d5e99f.tar.bz2
[PR107130] range-ops: Separate out ffs and popcount optimizations.
__builtin_popcount and __builtin_ffs were sharing the same range-ops entry, but the nonzero mask optimization is not valid for ffs. Separate them out into two entries. PR tree-optimization/107130 gcc/ChangeLog: * gimple-range-op.cc (class cfn_popcount): Call op_cfn_ffs. (class cfn_ffs): New. (gimple_range_op_handler::maybe_builtin_call): Separate out CASE_CFN_FFS into its own case. gcc/testsuite/ChangeLog: * gcc.dg/tree-ssa/pr107130.c: New test.
Diffstat (limited to 'gcc')
-rw-r--r--gcc/gimple-range-op.cc37
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/pr107130.c19
2 files changed, 46 insertions, 10 deletions
diff --git a/gcc/gimple-range-op.cc b/gcc/gimple-range-op.cc
index 3a7c907..5b71d1c 100644
--- a/gcc/gimple-range-op.cc
+++ b/gcc/gimple-range-op.cc
@@ -387,8 +387,8 @@ cfn_toupper_tolower::fold_range (irange &r, tree type, const irange &lh,
return true;
}
-// Implement range operator for CFN_BUILT_IN_FFS and CFN_BUILT_IN_POPCOUNT.
-class cfn_popcount : public range_operator
+// Implement range operator for CFN_BUILT_IN_FFS.
+class cfn_ffs : public range_operator
{
public:
using range_operator::fold_range;
@@ -397,14 +397,6 @@ public:
{
if (lh.undefined_p ())
return false;
- // Calculating the popcount of a singleton is trivial.
- if (lh.singleton_p ())
- {
- wide_int nz = lh.get_nonzero_bits ();
- wide_int pop = wi::shwi (wi::popcount (nz), TYPE_PRECISION (type));
- r.set (type, pop, pop);
- return true;
- }
// __builtin_ffs* and __builtin_popcount* return [0, prec].
int prec = TYPE_PRECISION (lh.type ());
// If arg is non-zero, then ffs or popcount are non-zero.
@@ -420,6 +412,26 @@ public:
r.set (build_int_cst (type, mini), build_int_cst (type, maxi));
return true;
}
+} op_cfn_ffs;
+
+// Implement range operator for CFN_BUILT_IN_POPCOUNT.
+class cfn_popcount : public cfn_ffs
+{
+public:
+ using range_operator::fold_range;
+ virtual bool fold_range (irange &r, tree type, const irange &lh,
+ const irange &rh, relation_kind rel) const
+ {
+ // Calculating the popcount of a singleton is trivial.
+ if (lh.singleton_p ())
+ {
+ wide_int nz = lh.get_nonzero_bits ();
+ wide_int pop = wi::shwi (wi::popcount (nz), TYPE_PRECISION (type));
+ r.set (type, pop, pop);
+ return true;
+ }
+ return cfn_ffs::fold_range (r, type, lh, rh, rel);
+ }
} op_cfn_popcount;
// Implement range operator for CFN_BUILT_IN_CLZ
@@ -734,6 +746,11 @@ gimple_range_op_handler::maybe_builtin_call ()
break;
CASE_CFN_FFS:
+ m_op1 = gimple_call_arg (call, 0);
+ m_int = &op_cfn_ffs;
+ m_valid = true;
+ break;
+
CASE_CFN_POPCOUNT:
m_op1 = gimple_call_arg (call, 0);
m_int = &op_cfn_popcount;
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr107130.c b/gcc/testsuite/gcc.dg/tree-ssa/pr107130.c
new file mode 100644
index 0000000..11fb816
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr107130.c
@@ -0,0 +1,19 @@
+// { dg-do compile }
+// { dg-options "-Os -fno-tree-ccp -fno-tree-forwprop -fno-tree-fre -fdump-tree-vrp1" }
+
+static inline int
+foo (int i)
+{
+ return __builtin_ffsl (i);
+}
+
+int
+main (void)
+{
+ int x = foo (41);
+ if (x != 1)
+ __builtin_abort ();
+ return 0;
+}
+
+// { dg-final { scan-tree-dump-not "builtin_abort" "vrp1" } }