On Wed, 13 Apr 2022, Jakub Jelinek wrote: > Hi! > > tree_builtin_call_types_compatible_p uses TYPE_MAIN_VARIANT comparisons > or tree_nop_conversion_p to ensure a builtin has correct GENERIC arguments. > Unfortunately this regressed when get_call_combined_fn is called during > GIMPLE optimizations. E.g. when number_of_iterations_popcount is called, > it doesn't ensure TYPE_MAIN_VARIABLE compatible argument type, it picks > __builtin_popcount{,l,ll} based just on types' precision and doesn't > fold_convert the arg to the right type. We are in GIMPLE, such conversions > are useless... > So, either we'd need to fix number_of_iterations_popcount to add casts > and inspect anything else that creates CALL_EXPRs late, or we can > in tree_builtin_call_types_compatible_p just use the GIMPLE type > comparisons (useless_type_conversion_p) when we are in GIMPLE form and > the TYPE_MAIN_VARIANT comparison or tree_nop_conversion_p test otherwise. > > I think especially this late in stage4 the latter seems safer to me.
Agreed. > Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk? OK. Thanks, Richard. > 2022-04-13 Jakub Jelinek <ja...@redhat.com> > > PR middle-end/105253 > * tree.cc (tree_builtin_call_types_compatible_p): If PROP_gimple, > use useless_type_conversion_p checks instead of TYPE_MAIN_VARIANT > comparisons or tree_nop_conversion_p checks. > > * gcc.target/i386/pr105253.c: New test. > > --- gcc/tree.cc.jj 2022-04-13 09:44:05.021939106 +0200 > +++ gcc/tree.cc 2022-04-13 11:43:25.756747436 +0200 > @@ -8427,8 +8427,12 @@ tree_builtin_call_types_compatible_p (co > if (tree decl = builtin_decl_explicit (DECL_FUNCTION_CODE (fndecl))) > fndecl = decl; > > - if (TYPE_MAIN_VARIANT (TREE_TYPE (call)) > - != TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (fndecl)))) > + bool gimple_form = (cfun && (cfun->curr_properties & PROP_gimple)) != 0; > + if (gimple_form > + ? !useless_type_conversion_p (TREE_TYPE (call), > + TREE_TYPE (TREE_TYPE (fndecl))) > + : (TYPE_MAIN_VARIANT (TREE_TYPE (call)) > + != TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (fndecl))))) > return false; > > tree targs = TYPE_ARG_TYPES (TREE_TYPE (fndecl)); > @@ -8440,12 +8444,15 @@ tree_builtin_call_types_compatible_p (co > return true; > tree arg = CALL_EXPR_ARG (call, i); > tree type = TREE_VALUE (targs); > - if (TYPE_MAIN_VARIANT (type) != TYPE_MAIN_VARIANT (TREE_TYPE (arg))) > + if (gimple_form > + ? !useless_type_conversion_p (type, TREE_TYPE (arg)) > + : TYPE_MAIN_VARIANT (type) != TYPE_MAIN_VARIANT (TREE_TYPE (arg))) > { > /* For pointer arguments be more forgiving, e.g. due to > FILE * vs. fileptr_type_node, or say char * vs. const char * > differences etc. */ > - if (POINTER_TYPE_P (type) > + if (!gimple_form > + && POINTER_TYPE_P (type) > && POINTER_TYPE_P (TREE_TYPE (arg)) > && tree_nop_conversion_p (type, TREE_TYPE (arg))) > continue; > @@ -8457,8 +8464,11 @@ tree_builtin_call_types_compatible_p (co > && INTEGRAL_TYPE_P (TREE_TYPE (arg)) > && !TYPE_UNSIGNED (TREE_TYPE (arg)) > && targetm.calls.promote_prototypes (TREE_TYPE (fndecl)) > - && tree_nop_conversion_p (integer_type_node, > - TREE_TYPE (arg))) > + && (gimple_form > + ? useless_type_conversion_p (integer_type_node, > + TREE_TYPE (arg)) > + : tree_nop_conversion_p (integer_type_node, > + TREE_TYPE (arg)))) > continue; > return false; > } > --- gcc/testsuite/gcc.target/i386/pr105253.c.jj 2022-04-13 > 11:47:52.460016521 +0200 > +++ gcc/testsuite/gcc.target/i386/pr105253.c 2022-04-13 11:48:23.085588161 > +0200 > @@ -0,0 +1,17 @@ > +/* PR middle-end/105253 */ > +/* { dg-do compile } */ > +/* { dg-options "-O2 -mno-popcnt" } */ > +/* { dg-final { scan-assembler-not "__popcount\[sd]i2" } } */ > + > +int > +foo (unsigned long long *p) > +{ > + int i, cnt = 0; > + unsigned long long elem; > + for (i = 0; i < 4; i++) > + { > + for (elem = p[i]; elem; cnt++) > + elem &= elem - 1; > + } > + return cnt; > +} > > Jakub > > -- Richard Biener <rguent...@suse.de> SUSE Software Solutions Germany GmbH, Maxfeldstrasse 5, 90409 Nuernberg, Germany; GF: Ivo Totev; HRB 36809 (AG Nuernberg)