+ return fold_builtin_classify (fndecl, arg0, BUILT_IN_ISINF);
+
+ CASE_FLT_FN (BUILT_IN_ISNAN):
+ case BUILT_IN_ISNAND32:
+ case BUILT_IN_ISNAND64:
+ case BUILT_IN_ISNAND128:
+ return fold_builtin_classify (fndecl, arg0, BUILT_IN_ISNAN);
+
+ case BUILT_IN_PRINTF:
+ case BUILT_IN_PRINTF_UNLOCKED:
+ case BUILT_IN_VPRINTF:
+ return fold_builtin_printf (fndecl, arg0, NULL_TREE, ignore, fcode);
+
+ default:
+ break;
+ }
+
+ return NULL_TREE;
+
+}
+
+/* Fold a call to built-in function FNDECL with 2 arguments, ARG0 and ARG1.
+ IGNORE is true if the result of the function call is ignored. This
+ function returns NULL_TREE if no simplification was possible. */
+
+static tree
+fold_builtin_2 (tree fndecl, tree arg0, tree arg1, bool ignore)
+{
+ tree type = TREE_TYPE (TREE_TYPE (fndecl));
+ enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
+
+ switch (fcode)
+ {
+#if MPFR_VERSION >= MPFR_VERSION_NUM(2,3,0)
+ CASE_FLT_FN (BUILT_IN_JN):
+ if (validate_arg (arg0, INTEGER_TYPE)
+ && validate_arg (arg1, REAL_TYPE))
+ return do_mpfr_bessel_n (arg0, arg1, type, mpfr_jn, NULL, 0);
+ break;
+
+ CASE_FLT_FN (BUILT_IN_YN):
+ if (validate_arg (arg0, INTEGER_TYPE)
+ && validate_arg (arg1, REAL_TYPE))
+ return do_mpfr_bessel_n (arg0, arg1, type, mpfr_yn,
+ &dconst0, false);
+ break;
+
+ CASE_FLT_FN (BUILT_IN_DREM):
+ CASE_FLT_FN (BUILT_IN_REMAINDER):
+ if (validate_arg (arg0, REAL_TYPE)
+ && validate_arg(arg1, REAL_TYPE))
+ return do_mpfr_arg2 (arg0, arg1, type, mpfr_remainder);
+ break;
+
+ CASE_FLT_FN_REENT (BUILT_IN_GAMMA): /* GAMMA_R */
+ CASE_FLT_FN_REENT (BUILT_IN_LGAMMA): /* LGAMMA_R */
+ if (validate_arg (arg0, REAL_TYPE)
+ && validate_arg(arg1, POINTER_TYPE))
+ return do_mpfr_lgamma_r (arg0, arg1, type);
+ break;
+#endif
+
+ CASE_FLT_FN (BUILT_IN_ATAN2):
+ if (validate_arg (arg0, REAL_TYPE)
+ && validate_arg(arg1, REAL_TYPE))
+ return do_mpfr_arg2 (arg0, arg1, type, mpfr_atan2);
+ break;
+
+ CASE_FLT_FN (BUILT_IN_FDIM):
+ if (validate_arg (arg0, REAL_TYPE)
+ && validate_arg(arg1, REAL_TYPE))
+ return do_mpfr_arg2 (arg0, arg1, type, mpfr_dim);
+ break;
+
+ CASE_FLT_FN (BUILT_IN_HYPOT):
+ return fold_builtin_hypot (fndecl, arg0, arg1, type);
+
+ CASE_FLT_FN (BUILT_IN_LDEXP):
+ return fold_builtin_load_exponent (arg0, arg1, type, /*ldexp=*/true);
+ CASE_FLT_FN (BUILT_IN_SCALBN):
+ CASE_FLT_FN (BUILT_IN_SCALBLN):
+ return fold_builtin_load_exponent (arg0, arg1, type, /*ldexp=*/false);
+
+ CASE_FLT_FN (BUILT_IN_FREXP):
+ return fold_builtin_frexp (arg0, arg1, type);
+
+ CASE_FLT_FN (BUILT_IN_MODF):
+ return fold_builtin_modf (arg0, arg1, type);
+
+ case BUILT_IN_BZERO:
+ return fold_builtin_bzero (arg0, arg1, ignore);
+
+ case BUILT_IN_FPUTS:
+ return fold_builtin_fputs (arg0, arg1, ignore, false, NULL_TREE);
+
+ case BUILT_IN_FPUTS_UNLOCKED:
+ return fold_builtin_fputs (arg0, arg1, ignore, true, NULL_TREE);
+
+ case BUILT_IN_STRSTR:
+ return fold_builtin_strstr (arg0, arg1, type);
+
+ case BUILT_IN_STRCAT:
+ return fold_builtin_strcat (arg0, arg1);
+
+ case BUILT_IN_STRSPN:
+ return fold_builtin_strspn (arg0, arg1);
+
+ case BUILT_IN_STRCSPN:
+ return fold_builtin_strcspn (arg0, arg1);
+
+ case BUILT_IN_STRCHR:
+ case BUILT_IN_INDEX:
+ return fold_builtin_strchr (arg0, arg1, type);
+
+ case BUILT_IN_STRRCHR:
+ case BUILT_IN_RINDEX:
+ return fold_builtin_strrchr (arg0, arg1, type);
+
+ case BUILT_IN_STRCPY:
+ return fold_builtin_strcpy (fndecl, arg0, arg1, NULL_TREE);
+
+ case BUILT_IN_STRCMP:
+ return fold_builtin_strcmp (arg0, arg1);
+
+ case BUILT_IN_STRPBRK:
+ return fold_builtin_strpbrk (arg0, arg1, type);
+
+ case BUILT_IN_EXPECT:
+ return fold_builtin_expect (arg0);
+
+ CASE_FLT_FN (BUILT_IN_POW):
+ return fold_builtin_pow (fndecl, arg0, arg1, type);
+
+ CASE_FLT_FN (BUILT_IN_POWI):
+ return fold_builtin_powi (fndecl, arg0, arg1, type);
+
+ CASE_FLT_FN (BUILT_IN_COPYSIGN):
+ return fold_builtin_copysign (fndecl, arg0, arg1, type);
+
+ CASE_FLT_FN (BUILT_IN_FMIN):
+ return fold_builtin_fmin_fmax (arg0, arg1, type, /*max=*/false);
+
+ CASE_FLT_FN (BUILT_IN_FMAX):
+ return fold_builtin_fmin_fmax (arg0, arg1, type, /*max=*/true);
+
+ case BUILT_IN_ISGREATER:
+ return fold_builtin_unordered_cmp (fndecl, arg0, arg1, UNLE_EXPR, LE_EXPR);
+ case BUILT_IN_ISGREATEREQUAL:
+ return fold_builtin_unordered_cmp (fndecl, arg0, arg1, UNLT_EXPR, LT_EXPR);
+ case BUILT_IN_ISLESS:
+ return fold_builtin_unordered_cmp (fndecl, arg0, arg1, UNGE_EXPR, GE_EXPR);
+ case BUILT_IN_ISLESSEQUAL:
+ return fold_builtin_unordered_cmp (fndecl, arg0, arg1, UNGT_EXPR, GT_EXPR);
+ case BUILT_IN_ISLESSGREATER:
+ return fold_builtin_unordered_cmp (fndecl, arg0, arg1, UNEQ_EXPR, EQ_EXPR);
+ case BUILT_IN_ISUNORDERED:
+ return fold_builtin_unordered_cmp (fndecl, arg0, arg1, UNORDERED_EXPR,
+ NOP_EXPR);
+
+ /* We do the folding for va_start in the expander. */
+ case BUILT_IN_VA_START:
+ break;
+
+ case BUILT_IN_SPRINTF:
+ return fold_builtin_sprintf (arg0, arg1, NULL_TREE, ignore);
+
+ case BUILT_IN_OBJECT_SIZE:
+ return fold_builtin_object_size (arg0, arg1);
+
+ case BUILT_IN_PRINTF:
+ case BUILT_IN_PRINTF_UNLOCKED:
+ case BUILT_IN_VPRINTF:
+ return fold_builtin_printf (fndecl, arg0, arg1, ignore, fcode);
+
+ case BUILT_IN_PRINTF_CHK:
+ case BUILT_IN_VPRINTF_CHK:
+ if (!validate_arg (arg0, INTEGER_TYPE)
+ || TREE_SIDE_EFFECTS (arg0))
+ return NULL_TREE;
+ else
+ return fold_builtin_printf (fndecl, arg1, NULL_TREE, ignore, fcode);
+ break;
+
+ case BUILT_IN_FPRINTF:
+ case BUILT_IN_FPRINTF_UNLOCKED:
+ case BUILT_IN_VFPRINTF:
+ return fold_builtin_fprintf (fndecl, arg0, arg1, NULL_TREE,
+ ignore, fcode);
+
+ default:
+ break;
+ }
+ return NULL_TREE;
+}
+
+/* Fold a call to built-in function FNDECL with 3 arguments, ARG0, ARG1,
+ and ARG2. IGNORE is true if the result of the function call is ignored.
+ This function returns NULL_TREE if no simplification was possible. */
+
+static tree
+fold_builtin_3 (tree fndecl, tree arg0, tree arg1, tree arg2, bool ignore)
+{
+ tree type = TREE_TYPE (TREE_TYPE (fndecl));
+ enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
+ switch (fcode)
+ {
+
+ CASE_FLT_FN (BUILT_IN_SINCOS):
+ return fold_builtin_sincos (arg0, arg1, arg2);
+
+ CASE_FLT_FN (BUILT_IN_FMA):
+ if (validate_arg (arg0, REAL_TYPE)
+ && validate_arg(arg1, REAL_TYPE)
+ && validate_arg(arg2, REAL_TYPE))
+ return do_mpfr_arg3 (arg0, arg1, arg2, type, mpfr_fma);
+ break;
+
+#if MPFR_VERSION >= MPFR_VERSION_NUM(2,3,0)
+ CASE_FLT_FN (BUILT_IN_REMQUO):
+ if (validate_arg (arg0, REAL_TYPE)
+ && validate_arg(arg1, REAL_TYPE)
+ && validate_arg(arg2, POINTER_TYPE))
+ return do_mpfr_remquo (arg0, arg1, arg2);
+ break;
+#endif
+
+ case BUILT_IN_MEMSET:
+ return fold_builtin_memset (arg0, arg1, arg2, type, ignore);
+
+ case BUILT_IN_BCOPY:
+ return fold_builtin_memory_op (arg1, arg0, arg2, void_type_node, true, /*endp=*/3);
+
+ case BUILT_IN_MEMCPY:
+ return fold_builtin_memory_op (arg0, arg1, arg2, type, ignore, /*endp=*/0);
+
+ case BUILT_IN_MEMPCPY:
+ return fold_builtin_memory_op (arg0, arg1, arg2, type, ignore, /*endp=*/1);
+
+ case BUILT_IN_MEMMOVE:
+ return fold_builtin_memory_op (arg0, arg1, arg2, type, ignore, /*endp=*/3);
+
+ case BUILT_IN_STRNCAT:
+ return fold_builtin_strncat (arg0, arg1, arg2);
+
+ case BUILT_IN_STRNCPY:
+ return fold_builtin_strncpy (fndecl, arg0, arg1, arg2, NULL_TREE);
+
+ case BUILT_IN_STRNCMP:
+ return fold_builtin_strncmp (arg0, arg1, arg2);
+
+ case BUILT_IN_MEMCHR:
+ return fold_builtin_memchr (arg0, arg1, arg2, type);
+
+ case BUILT_IN_BCMP:
+ case BUILT_IN_MEMCMP:
+ return fold_builtin_memcmp (arg0, arg1, arg2);;
+
+ case BUILT_IN_SPRINTF:
+ return fold_builtin_sprintf (arg0, arg1, arg2, ignore);
+
+ case BUILT_IN_STRCPY_CHK:
+ case BUILT_IN_STPCPY_CHK:
+ return fold_builtin_stxcpy_chk (fndecl, arg0, arg1, arg2, NULL_TREE,
+ ignore, fcode);
+
+ case BUILT_IN_STRCAT_CHK:
+ return fold_builtin_strcat_chk (fndecl, arg0, arg1, arg2);
+
+ case BUILT_IN_PRINTF_CHK:
+ case BUILT_IN_VPRINTF_CHK:
+ if (!validate_arg (arg0, INTEGER_TYPE)
+ || TREE_SIDE_EFFECTS (arg0))
+ return NULL_TREE;
+ else
+ return fold_builtin_printf (fndecl, arg1, arg2, ignore, fcode);
+ break;