diff --git a/gcc/internal-fn.cc b/gcc/internal-fn.cc index a07f25f3aee..fcf47c7fa12 100644 --- a/gcc/internal-fn.cc +++ b/gcc/internal-fn.cc @@ -52,6 +52,7 @@ along with GCC; see the file COPYING3. If not see #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" @@ -5107,9 +5108,63 @@ expand_BITINTTOFLOAT (internal_fn, gcall *stmt) 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); diff --git a/gcc/internal-fn.def b/gcc/internal-fn.def index c14d30365c1..848bb9dbff3 100644 --- a/gcc/internal-fn.def +++ b/gcc/internal-fn.def @@ -440,11 +440,11 @@ DEF_INTERNAL_OPTAB_FN (COMPLEX_FMS, ECF_CONST, cmls, ternary) 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) diff --git a/gcc/internal-fn.h b/gcc/internal-fn.h index bccee1c3e09..2785a5a95a2 100644 --- a/gcc/internal-fn.h +++ b/gcc/internal-fn.h @@ -262,6 +262,11 @@ extern void expand_MULBITINT (internal_fn, gcall *); 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); diff --git a/gcc/testsuite/gcc.dg/bitint-95.c b/gcc/testsuite/gcc.dg/bitint-95.c new file mode 100644 index 00000000000..9794652ed13 --- /dev/null +++ b/gcc/testsuite/gcc.dg/bitint-95.c @@ -0,0 +1,45 @@ +/* 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); +}