--- /dev/null
+/* 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;
+}
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));
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;
&& 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;
}