expand: Add trivial folding for bit query builtins at expansion time [PR114044]

While it seems a lot of places in various optimization passes fold
bit query internal functions with INTEGER_CST arguments to INTEGER_CST
when there is a lhs, when lhs is missing, all the removals of such dead
stmts are guarded with -ftree-dce, so with -fno-tree-dce those unfolded
ifn calls remain in the IL until expansion.  If they have large/huge
BITINT_TYPE arguments, there is no BLKmode optab and so expansion ICEs,
and bitint lowering doesn't touch such calls because it doesn't know they
need touching, functions only containing those will not even be further
processed by the pass because there are no non-small BITINT_TYPE SSA_NAMEs
+ the 2 exceptions (stores of BITINT_TYPE INTEGER_CSTs and conversions
from BITINT_TYPE INTEGER_CSTs to floating point SSA_NAMEs) and when walking
there is no special case for calls with BITINT_TYPE INTEGER_CSTs either,
those are for normal calls normally handled at expansion time.

So, the following patch adjust the expansion of these 6 ifns, by doing
nothing if there is no lhs, and also just in case and user disabled all
possible passes that would fold this handles the case of setting lhs
to ifn call with INTEGER_CST argument.

2024-02-27  Jakub Jelinek  <jakub@redhat.com>

	PR rtl-optimization/114044
	* internal-fn.def (CLRSB, CLZ, CTZ, FFS, PARITY): Use
	DEF_INTERNAL_INT_EXT_FN macro rather than DEF_INTERNAL_INT_FN.
	* internal-fn.h (expand_CLRSB, expand_CLZ, expand_CTZ, expand_FFS,
	expand_PARITY): Declare.
	* internal-fn.cc (expand_bitquery, expand_CLRSB, expand_CLZ,
	expand_CTZ, expand_FFS, expand_PARITY): New functions.
	(expand_POPCOUNT): Use expand_bitquery.

	* gcc.dg/bitint-95.c: New test.
pull/79/merge
Jakub Jelinek 2024-02-27 09:52:07 +01:00
parent 8a5d940958
commit c3c44c01d2
4 changed files with 110 additions and 5 deletions

View File

@ -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);

View File

@ -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)

View File

@ -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);

View File

@ -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);
}