__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. --- gcc/gimple-range-op.cc | 37 +++++++++++++++++------- gcc/testsuite/gcc.dg/tree-ssa/pr107130.c | 19 ++++++++++++ 2 files changed, 46 insertions(+), 10 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/pr107130.c diff --git a/gcc/gimple-range-op.cc b/gcc/gimple-range-op.cc index 3a7c9074659..5b71d1cce6d 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 00000000000..11fb816ad71 --- /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" } } -- 2.37.1