#include "explow.h"
#include "rtl-iter.h"
#include "gimple-range.h"
+#include "fold-const-call.h"
/* For lang_hooks.types.type_for_mode. */
#include "langhooks.h"
emit_move_insn (target, val);
}
+static bool
+expand_bitquery (internal_fn fn, gcall *stmt)
+{
+ tree lhs = gimple_call_lhs (stmt);
+ if (lhs == NULL_TREE)
+ return false;
+ tree arg = gimple_call_arg (stmt, 0);
+ if (TREE_CODE (arg) == INTEGER_CST)
+ {
+ tree ret = fold_const_call (as_combined_fn (fn), TREE_TYPE (arg), arg);
+ gcc_checking_assert (ret && TREE_CODE (ret) == INTEGER_CST);
+ expand_assignment (lhs, ret, false);
+ return false;
+ }
+ return true;
+}
+
+void
+expand_CLRSB (internal_fn fn, gcall *stmt)
+{
+ if (expand_bitquery (fn, stmt))
+ expand_unary_optab_fn (fn, stmt, clrsb_optab);
+}
+
+void
+expand_CLZ (internal_fn fn, gcall *stmt)
+{
+ if (expand_bitquery (fn, stmt))
+ expand_unary_optab_fn (fn, stmt, clz_optab);
+}
+
+void
+expand_CTZ (internal_fn fn, gcall *stmt)
+{
+ if (expand_bitquery (fn, stmt))
+ expand_unary_optab_fn (fn, stmt, ctz_optab);
+}
+
+void
+expand_FFS (internal_fn fn, gcall *stmt)
+{
+ if (expand_bitquery (fn, stmt))
+ expand_unary_optab_fn (fn, stmt, ffs_optab);
+}
+
+void
+expand_PARITY (internal_fn fn, gcall *stmt)
+{
+ if (expand_bitquery (fn, stmt))
+ expand_unary_optab_fn (fn, stmt, parity_optab);
+}
+
void
expand_POPCOUNT (internal_fn fn, gcall *stmt)
{
+ if (!expand_bitquery (fn, stmt))
+ return;
if (gimple_call_num_args (stmt) == 1)
{
expand_unary_optab_fn (fn, stmt, popcount_optab);
DEF_INTERNAL_OPTAB_FN (COMPLEX_FMS_CONJ, ECF_CONST, cmls_conj, ternary)
/* Unary integer ops. */
-DEF_INTERNAL_INT_FN (CLRSB, ECF_CONST | ECF_NOTHROW, clrsb, unary)
-DEF_INTERNAL_INT_FN (CLZ, ECF_CONST | ECF_NOTHROW, clz, unary)
-DEF_INTERNAL_INT_FN (CTZ, ECF_CONST | ECF_NOTHROW, ctz, unary)
-DEF_INTERNAL_INT_FN (FFS, ECF_CONST | ECF_NOTHROW, ffs, unary)
-DEF_INTERNAL_INT_FN (PARITY, ECF_CONST | ECF_NOTHROW, parity, unary)
+DEF_INTERNAL_INT_EXT_FN (CLRSB, ECF_CONST | ECF_NOTHROW, clrsb, unary)
+DEF_INTERNAL_INT_EXT_FN (CLZ, ECF_CONST | ECF_NOTHROW, clz, unary)
+DEF_INTERNAL_INT_EXT_FN (CTZ, ECF_CONST | ECF_NOTHROW, ctz, unary)
+DEF_INTERNAL_INT_EXT_FN (FFS, ECF_CONST | ECF_NOTHROW, ffs, unary)
+DEF_INTERNAL_INT_EXT_FN (PARITY, ECF_CONST | ECF_NOTHROW, parity, unary)
DEF_INTERNAL_INT_EXT_FN (POPCOUNT, ECF_CONST | ECF_NOTHROW, popcount, unary)
DEF_INTERNAL_FN (GOMP_TARGET_REV, ECF_NOVOPS | ECF_LEAF | ECF_NOTHROW, NULL)
extern void expand_DIVMODBITINT (internal_fn, gcall *);
extern void expand_FLOATTOBITINT (internal_fn, gcall *);
extern void expand_BITINTTOFLOAT (internal_fn, gcall *);
+extern void expand_CLRSB (internal_fn, gcall *);
+extern void expand_CLZ (internal_fn, gcall *);
+extern void expand_CTZ (internal_fn, gcall *);
+extern void expand_FFS (internal_fn, gcall *);
+extern void expand_PARITY (internal_fn, gcall *);
extern void expand_POPCOUNT (internal_fn, gcall *);
extern bool vectorized_internal_fn_supported_p (internal_fn, tree);
--- /dev/null
+/* PR rtl-optimization/114044 */
+/* { dg-do compile { target bitint575 } } */
+/* { dg-options "-O -fno-tree-dce" } */
+
+void
+foo (void)
+{
+ unsigned _BitInt (575) a = 3;
+ __builtin_clzg (a);
+}
+
+void
+bar (void)
+{
+ unsigned _BitInt (575) a = 3;
+ __builtin_ctzg (a);
+}
+
+void
+baz (void)
+{
+ signed _BitInt (575) a = 3;
+ __builtin_clrsbg (a);
+}
+
+void
+qux (void)
+{
+ signed _BitInt (575) a = 3;
+ __builtin_ffsg (a);
+}
+
+void
+garply (void)
+{
+ unsigned _BitInt (575) a = 3;
+ __builtin_parityg (a);
+}
+
+void
+corge (void)
+{
+ unsigned _BitInt (575) a = 3;
+ __builtin_popcountg (a);
+}