/* Expand builtin functions.
Copyright (C) 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
- 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
+ 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
Free Software Foundation, Inc.
This file is part of GCC.
#ifndef PAD_VARARGS_DOWN
#define PAD_VARARGS_DOWN BYTES_BIG_ENDIAN
#endif
-#ifdef HAVE_mpc
static tree do_mpc_arg1 (tree, tree, int (*)(mpc_ptr, mpc_srcptr, mpc_rnd_t));
-#endif
/* Define the names of the builtin function types and codes. */
const char *const built_in_class_names[4]
static rtx builtin_memcpy_read_str (void *, HOST_WIDE_INT, enum machine_mode);
static rtx expand_builtin_memcpy (tree, rtx);
static rtx expand_builtin_mempcpy (tree, rtx, enum machine_mode);
-static rtx expand_builtin_mempcpy_args (tree, tree, tree, rtx,
+static rtx expand_builtin_mempcpy_args (tree, tree, tree, rtx,
enum machine_mode, int);
static rtx expand_builtin_strcpy (tree, rtx);
static rtx expand_builtin_strcpy_args (tree, tree, rtx);
static rtx expand_builtin_alloca (tree, rtx);
static rtx expand_builtin_unop (enum machine_mode, tree, rtx, rtx, optab);
static rtx expand_builtin_frame_address (tree, tree);
-static rtx expand_builtin_printf (tree, rtx, enum machine_mode, bool);
-static rtx expand_builtin_fprintf (tree, rtx, enum machine_mode, bool);
-static rtx expand_builtin_sprintf (tree, rtx, enum machine_mode);
static tree stabilize_va_list_loc (location_t, tree, int);
static rtx expand_builtin_expect (tree, rtx);
static tree fold_builtin_constant_p (tree);
{
HOST_WIDE_INT bitsize, bitpos;
tree offset;
- enum machine_mode mode;
+ enum machine_mode mode;
int unsignedp, volatilep;
exp = get_inner_reference (exp, &bitsize, &bitpos, &offset,
offset = next_offset;
}
}
- if (DECL_P (exp))
+ if (TREE_CODE (exp) == CONST_DECL)
+ exp = DECL_INITIAL (exp);
+ if (DECL_P (exp)
+ && TREE_CODE (exp) != LABEL_DECL)
align = MIN (inner, DECL_ALIGN (exp));
#ifdef CONSTANT_ALIGNMENT
else if (CONSTANT_CLASS_P (exp))
rtx fp, lab, stack, insn, last;
enum machine_mode sa_mode = STACK_SAVEAREA_MODE (SAVE_NONLOCAL);
- /* DRAP is needed for stack realign if longjmp is expanded to current
+ /* DRAP is needed for stack realign if longjmp is expanded to current
function */
if (SUPPORTS_STACK_ALIGNMENT)
crtl->need_drap = true;
INCOMING_REGNO gives the corresponding inbound register. */
static enum machine_mode apply_result_mode[FIRST_PSEUDO_REGISTER];
-/* For each register that may be used for calling a function, this
- gives the offset of that register into the block returned by
- __builtin_apply_args. 0 indicates that the register is not
- used for calling a function. */
-static int apply_args_reg_offset[FIRST_PSEUDO_REGISTER];
-
/* Return the size required for the block returned by __builtin_apply_args,
and initialize apply_args_mode. */
align = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT;
if (size % align != 0)
size = CEIL (size, align) * align;
- apply_args_reg_offset[regno] = size;
size += GET_MODE_SIZE (mode);
apply_args_mode[regno] = mode;
}
else
{
apply_args_mode[regno] = VOIDmode;
- apply_args_reg_offset[regno] = 0;
}
}
return size;
expand_builtin_mathfn (tree exp, rtx target, rtx subtarget)
{
optab builtin_optab;
- rtx op0, insns, before_call;
+ rtx op0, insns;
tree fndecl = get_callee_fndecl (exp);
enum machine_mode mode;
bool errno_set = false;
end_sequence ();
}
- before_call = get_last_insn ();
-
return expand_call (exp, target, target == const0_rtx);
}
fn = built_in_decls[BUILT_IN_SINCOSL];
else
gcc_unreachable ();
-
+
op1 = assign_temp (TREE_TYPE (arg), 0, 1, 1);
op2 = assign_temp (TREE_TYPE (arg), 0, 1, 1);
op1a = copy_to_mode_reg (Pmode, XEXP (op1, 0));
/* Make sure not to fold the cexp call again. */
call = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (fn)), fn);
- return expand_expr (build_call_nary (ctype, call, 1, narg),
+ return expand_expr (build_call_nary (ctype, call, 1, narg),
target, VOIDmode, EXPAND_NORMAL);
}
if (!validate_arglist (exp, REAL_TYPE, VOID_TYPE))
gcc_unreachable ();
-
+
arg = CALL_EXPR_ARG (exp, 0);
switch (DECL_FUNCTION_CODE (fndecl))
static rtx
expand_powi (rtx x, enum machine_mode mode, HOST_WIDE_INT n)
{
- unsigned HOST_WIDE_INT val;
rtx cache[POWI_TABLE_SIZE];
rtx result;
if (n == 0)
return CONST1_RTX (mode);
- val = (n < 0) ? -n : n;
-
memset (cache, 0, sizeof (cache));
cache[1] = x;
return target;
}
-/* Expand expression EXP which is a call to the strlen builtin. Return
+/* Expand expression EXP which is a call to the strlen builtin. Return
NULL_RTX if we failed the caller should emit a normal call, otherwise
try to get the result in TARGET, if convenient. */
rtx dest_mem, src_mem, dest_addr, len_rtx;
HOST_WIDE_INT expected_size = -1;
unsigned int expected_align = 0;
- tree_ann_common_t ann;
/* If DEST is not a pointer type, call the normal function. */
if (dest_align == 0)
operation in-line. */
if (src_align == 0)
return NULL_RTX;
-
- ann = tree_common_ann (exp);
- if (ann)
- stringop_block_profile (ann->stmt, &expected_align, &expected_size);
+
+ if (currently_expanding_gimple_stmt)
+ stringop_block_profile (currently_expanding_gimple_stmt,
+ &expected_align, &expected_size);
if (expected_align < dest_align)
expected_align = dest_align;
return target;
}
-/* Expand expression EXP, which is a call to the strcpy builtin. Return
- NULL_RTX if we failed the caller should emit a normal call, otherwise
+/* Expand expression EXP, which is a call to the strcpy builtin. Return
+ NULL_RTX if we failed the caller should emit a normal call, otherwise
try to get the result in TARGET, if convenient (and in mode MODE if that's
convenient). */
return c_readstr (str + offset, mode);
}
-/* Expand expression EXP, which is a call to the strncpy builtin. Return
+/* Expand expression EXP, which is a call to the strncpy builtin. Return
NULL_RTX if we failed the caller should emit a normal call. */
static rtx
return force_reg (mode, target);
}
-/* Expand expression EXP, which is a call to the memset builtin. Return
- NULL_RTX if we failed the caller should emit a normal call, otherwise
+/* Expand expression EXP, which is a call to the memset builtin. Return
+ NULL_RTX if we failed the caller should emit a normal call, otherwise
try to get the result in TARGET, if convenient (and in mode MODE if that's
convenient). */
rtx dest_mem, dest_addr, len_rtx;
HOST_WIDE_INT expected_size = -1;
unsigned int expected_align = 0;
- tree_ann_common_t ann;
dest_align = get_pointer_alignment (dest, BIGGEST_ALIGNMENT);
if (dest_align == 0)
return NULL_RTX;
- ann = tree_common_ann (orig_exp);
- if (ann)
- stringop_block_profile (ann->stmt, &expected_align, &expected_size);
+ if (currently_expanding_gimple_stmt)
+ stringop_block_profile (currently_expanding_gimple_stmt,
+ &expected_align, &expected_size);
if (expected_align < dest_align)
expected_align = dest_align;
dest_align, expected_align,
expected_size))
goto do_libcall;
-
+
dest_mem = force_operand (XEXP (dest_mem, 0), NULL_RTX);
dest_mem = convert_memory_address (ptr_mode, dest_mem);
return dest_mem;
dest_align, expected_align,
expected_size))
goto do_libcall;
-
+
dest_mem = force_operand (XEXP (dest_mem, 0), NULL_RTX);
dest_mem = convert_memory_address (ptr_mode, dest_mem);
return dest_mem;
return expand_call (fn, target, target == const0_rtx);
}
-/* Expand expression EXP, which is a call to the bzero builtin. Return
+/* Expand expression EXP, which is a call to the bzero builtin. Return
NULL_RTX if we failed the caller should emit a normal call. */
static rtx
return NULL_RTX;
}
-/* Expand expression EXP, which is a call to the strncmp builtin. Return
+/* Expand expression EXP, which is a call to the strncmp builtin. Return
NULL_RTX if we failed the caller should emit a normal call, otherwise try to get
the result in TARGET, if convenient. */
rtx result;
/* Emit normal call if marked not-inlineable. */
- if (CALL_CANNOT_INLINE_P (exp))
+ if (CALL_CANNOT_INLINE_P (exp))
return NULL_RTX;
if (!validate_arglist (exp, INTEGER_TYPE, VOID_TYPE))
return convert_to_mode (target_mode, target, 0);
}
-/* Expand a call to __builtin_expect. We just return our argument
+/* Expand a call to __builtin_expect. We just return our argument
as the builtin_expect semantic should've been already executed by
tree branch prediction pass. */
static rtx
expand_builtin_expect (tree exp, rtx target)
{
- tree arg, c;
+ tree arg;
if (call_expr_nargs (exp) < 2)
return const0_rtx;
arg = CALL_EXPR_ARG (exp, 0);
- c = CALL_EXPR_ARG (exp, 1);
target = expand_expr (arg, target, VOIDmode, EXPAND_NORMAL);
/* When guessing was done, the hints should be already stripped away. */
return t;
}
-/* Expand EXP, a call to printf or printf_unlocked.
- Return NULL_RTX if a normal call should be emitted rather than transforming
- the function inline. If convenient, the result should be placed in
- TARGET with mode MODE. UNLOCKED indicates this is a printf_unlocked
- call. */
-static rtx
-expand_builtin_printf (tree exp, rtx target, enum machine_mode mode,
- bool unlocked)
-{
- /* If we're using an unlocked function, assume the other unlocked
- functions exist explicitly. */
- tree const fn_putchar = unlocked ? built_in_decls[BUILT_IN_PUTCHAR_UNLOCKED]
- : implicit_built_in_decls[BUILT_IN_PUTCHAR];
- tree const fn_puts = unlocked ? built_in_decls[BUILT_IN_PUTS_UNLOCKED]
- : implicit_built_in_decls[BUILT_IN_PUTS];
- const char *fmt_str;
- tree fn = 0;
- tree fmt, arg;
- int nargs = call_expr_nargs (exp);
-
- /* If the return value is used, don't do the transformation. */
- if (target != const0_rtx)
- return NULL_RTX;
-
- /* Verify the required arguments in the original call. */
- if (nargs == 0)
- return NULL_RTX;
- fmt = CALL_EXPR_ARG (exp, 0);
- if (! POINTER_TYPE_P (TREE_TYPE (fmt)))
- return NULL_RTX;
-
- /* Check whether the format is a literal string constant. */
- fmt_str = c_getstr (fmt);
- if (fmt_str == NULL)
- return NULL_RTX;
-
- if (!init_target_chars ())
- return NULL_RTX;
-
- /* If the format specifier was "%s\n", call __builtin_puts(arg). */
- if (strcmp (fmt_str, target_percent_s_newline) == 0)
- {
- if ((nargs != 2)
- || ! POINTER_TYPE_P (TREE_TYPE (CALL_EXPR_ARG (exp, 1))))
- return NULL_RTX;
- if (fn_puts)
- fn = build_call_nofold (fn_puts, 1, CALL_EXPR_ARG (exp, 1));
- }
- /* If the format specifier was "%c", call __builtin_putchar(arg). */
- else if (strcmp (fmt_str, target_percent_c) == 0)
- {
- if ((nargs != 2)
- || TREE_CODE (TREE_TYPE (CALL_EXPR_ARG (exp, 1))) != INTEGER_TYPE)
- return NULL_RTX;
- if (fn_putchar)
- fn = build_call_nofold (fn_putchar, 1, CALL_EXPR_ARG (exp, 1));
- }
- else
- {
- /* We can't handle anything else with % args or %% ... yet. */
- if (strchr (fmt_str, target_percent))
- return NULL_RTX;
-
- if (nargs > 1)
- return NULL_RTX;
-
- /* If the format specifier was "", printf does nothing. */
- if (fmt_str[0] == '\0')
- return const0_rtx;
- /* If the format specifier has length of 1, call putchar. */
- if (fmt_str[1] == '\0')
- {
- /* Given printf("c"), (where c is any one character,)
- convert "c"[0] to an int and pass that to the replacement
- function. */
- arg = build_int_cst (NULL_TREE, fmt_str[0]);
- if (fn_putchar)
- fn = build_call_nofold (fn_putchar, 1, arg);
- }
- else
- {
- /* If the format specifier was "string\n", call puts("string"). */
- size_t len = strlen (fmt_str);
- if ((unsigned char)fmt_str[len - 1] == target_newline)
- {
- /* Create a NUL-terminated string that's one char shorter
- than the original, stripping off the trailing '\n'. */
- char *newstr = XALLOCAVEC (char, len);
- memcpy (newstr, fmt_str, len - 1);
- newstr[len - 1] = 0;
- arg = build_string_literal (len, newstr);
- if (fn_puts)
- fn = build_call_nofold (fn_puts, 1, arg);
- }
- else
- /* We'd like to arrange to call fputs(string,stdout) here,
- but we need stdout and don't have a way to get it yet. */
- return NULL_RTX;
- }
- }
-
- if (!fn)
- return NULL_RTX;
- gcc_assert (TREE_CODE (fn) == CALL_EXPR);
- CALL_EXPR_TAILCALL (fn) = CALL_EXPR_TAILCALL (exp);
- return expand_expr (fn, target, mode, EXPAND_NORMAL);
-}
-
-/* Expand EXP, a call to fprintf or fprintf_unlocked.
- Return NULL_RTX if a normal call should be emitted rather than transforming
- the function inline. If convenient, the result should be placed in
- TARGET with mode MODE. UNLOCKED indicates this is a fprintf_unlocked
- call. */
-static rtx
-expand_builtin_fprintf (tree exp, rtx target, enum machine_mode mode,
- bool unlocked)
-{
- /* If we're using an unlocked function, assume the other unlocked
- functions exist explicitly. */
- tree const fn_fputc = unlocked ? built_in_decls[BUILT_IN_FPUTC_UNLOCKED]
- : implicit_built_in_decls[BUILT_IN_FPUTC];
- tree const fn_fputs = unlocked ? built_in_decls[BUILT_IN_FPUTS_UNLOCKED]
- : implicit_built_in_decls[BUILT_IN_FPUTS];
- const char *fmt_str;
- tree fn = 0;
- tree fmt, fp, arg;
- int nargs = call_expr_nargs (exp);
-
- /* If the return value is used, don't do the transformation. */
- if (target != const0_rtx)
- return NULL_RTX;
-
- /* Verify the required arguments in the original call. */
- if (nargs < 2)
- return NULL_RTX;
- fp = CALL_EXPR_ARG (exp, 0);
- if (! POINTER_TYPE_P (TREE_TYPE (fp)))
- return NULL_RTX;
- fmt = CALL_EXPR_ARG (exp, 1);
- if (! POINTER_TYPE_P (TREE_TYPE (fmt)))
- return NULL_RTX;
-
- /* Check whether the format is a literal string constant. */
- fmt_str = c_getstr (fmt);
- if (fmt_str == NULL)
- return NULL_RTX;
-
- if (!init_target_chars ())
- return NULL_RTX;
-
- /* If the format specifier was "%s", call __builtin_fputs(arg,fp). */
- if (strcmp (fmt_str, target_percent_s) == 0)
- {
- if ((nargs != 3)
- || ! POINTER_TYPE_P (TREE_TYPE (CALL_EXPR_ARG (exp, 2))))
- return NULL_RTX;
- arg = CALL_EXPR_ARG (exp, 2);
- if (fn_fputs)
- fn = build_call_nofold (fn_fputs, 2, arg, fp);
- }
- /* If the format specifier was "%c", call __builtin_fputc(arg,fp). */
- else if (strcmp (fmt_str, target_percent_c) == 0)
- {
- if ((nargs != 3)
- || TREE_CODE (TREE_TYPE (CALL_EXPR_ARG (exp, 2))) != INTEGER_TYPE)
- return NULL_RTX;
- arg = CALL_EXPR_ARG (exp, 2);
- if (fn_fputc)
- fn = build_call_nofold (fn_fputc, 2, arg, fp);
- }
- else
- {
- /* We can't handle anything else with % args or %% ... yet. */
- if (strchr (fmt_str, target_percent))
- return NULL_RTX;
-
- if (nargs > 2)
- return NULL_RTX;
-
- /* If the format specifier was "", fprintf does nothing. */
- if (fmt_str[0] == '\0')
- {
- /* Evaluate and ignore FILE* argument for side-effects. */
- expand_expr (fp, const0_rtx, VOIDmode, EXPAND_NORMAL);
- return const0_rtx;
- }
-
- /* When "string" doesn't contain %, replace all cases of
- fprintf(stream,string) with fputs(string,stream). The fputs
- builtin will take care of special cases like length == 1. */
- if (fn_fputs)
- fn = build_call_nofold (fn_fputs, 2, fmt, fp);
- }
-
- if (!fn)
- return NULL_RTX;
- gcc_assert (TREE_CODE (fn) == CALL_EXPR);
- CALL_EXPR_TAILCALL (fn) = CALL_EXPR_TAILCALL (exp);
- return expand_expr (fn, target, mode, EXPAND_NORMAL);
-}
-
-/* Expand a call EXP to sprintf. Return NULL_RTX if
- a normal call should be emitted rather than expanding the function
- inline. If convenient, the result should be placed in TARGET with
- mode MODE. */
-
-static rtx
-expand_builtin_sprintf (tree exp, rtx target, enum machine_mode mode)
-{
- tree dest, fmt;
- const char *fmt_str;
- int nargs = call_expr_nargs (exp);
-
- /* Verify the required arguments in the original call. */
- if (nargs < 2)
- return NULL_RTX;
- dest = CALL_EXPR_ARG (exp, 0);
- if (! POINTER_TYPE_P (TREE_TYPE (dest)))
- return NULL_RTX;
- fmt = CALL_EXPR_ARG (exp, 0);
- if (! POINTER_TYPE_P (TREE_TYPE (fmt)))
- return NULL_RTX;
-
- /* Check whether the format is a literal string constant. */
- fmt_str = c_getstr (fmt);
- if (fmt_str == NULL)
- return NULL_RTX;
-
- if (!init_target_chars ())
- return NULL_RTX;
-
- /* If the format doesn't contain % args or %%, use strcpy. */
- if (strchr (fmt_str, target_percent) == 0)
- {
- tree fn = implicit_built_in_decls[BUILT_IN_STRCPY];
- tree exp;
-
- if ((nargs > 2) || ! fn)
- return NULL_RTX;
- expand_expr (build_call_nofold (fn, 2, dest, fmt),
- const0_rtx, VOIDmode, EXPAND_NORMAL);
- if (target == const0_rtx)
- return const0_rtx;
- exp = build_int_cst (NULL_TREE, strlen (fmt_str));
- return expand_expr (exp, target, mode, EXPAND_NORMAL);
- }
- /* If the format is "%s", use strcpy if the result isn't used. */
- else if (strcmp (fmt_str, target_percent_s) == 0)
- {
- tree fn, arg, len;
- fn = implicit_built_in_decls[BUILT_IN_STRCPY];
-
- if (! fn)
- return NULL_RTX;
- if (nargs != 3)
- return NULL_RTX;
- arg = CALL_EXPR_ARG (exp, 2);
- if (! POINTER_TYPE_P (TREE_TYPE (arg)))
- return NULL_RTX;
-
- if (target != const0_rtx)
- {
- len = c_strlen (arg, 1);
- if (! len || TREE_CODE (len) != INTEGER_CST)
- return NULL_RTX;
- }
- else
- len = NULL_TREE;
-
- expand_expr (build_call_nofold (fn, 2, dest, arg),
- const0_rtx, VOIDmode, EXPAND_NORMAL);
-
- if (target == const0_rtx)
- return const0_rtx;
- return expand_expr (len, target, mode, EXPAND_NORMAL);
- }
-
- return NULL_RTX;
-}
-
/* Expand a call to either the entry or exit function profiler. */
static rtx
call = rewrite_call_expr (EXPR_LOCATION (exp), exp, 0, decl, 0);
return expand_call (call, target, ignore);
}
-
+
\f
/* Reconstitute a mode for a __sync intrinsic operation. Since the type of
{
rtx addr, mem;
- addr = expand_expr (loc, NULL_RTX, Pmode, EXPAND_SUM);
+ addr = expand_expr (loc, NULL_RTX, ptr_mode, EXPAND_SUM);
+ addr = convert_memory_address (Pmode, addr);
/* Note that we explicitly do not want any alias information for this
memory, so that we kill all other live memories. Otherwise we don't
/* Expand the __sync_lock_test_and_set intrinsic. Note that the most
general form is actually an atomic exchange, and some targets only
support a reduced form with the second argument being a constant 1.
- EXP is the CALL_EXPR; TARGET is an optional place for us to store
+ EXP is the CALL_EXPR; TARGET is an optional place for us to store
the results. */
static rtx
expand_builtin_unreachable ();
return const0_rtx;
- case BUILT_IN_PRINTF:
- target = expand_builtin_printf (exp, target, mode, false);
- if (target)
- return target;
- break;
-
- case BUILT_IN_PRINTF_UNLOCKED:
- target = expand_builtin_printf (exp, target, mode, true);
- if (target)
- return target;
- break;
-
- case BUILT_IN_FPRINTF:
- target = expand_builtin_fprintf (exp, target, mode, false);
- if (target)
- return target;
- break;
-
- case BUILT_IN_FPRINTF_UNLOCKED:
- target = expand_builtin_fprintf (exp, target, mode, true);
- if (target)
- return target;
- break;
-
- case BUILT_IN_SPRINTF:
- target = expand_builtin_sprintf (exp, target, mode);
- if (target)
- return target;
- break;
-
CASE_FLT_FN (BUILT_IN_SIGNBIT):
case BUILT_IN_SIGNBITD32:
case BUILT_IN_SIGNBITD64:
if (! more_const_call_expr_args_p (&iter))
return END_BUILTINS;
-
+
arg = next_const_call_expr_arg (&iter);
argtype = TREE_TYPE (arg);
{
tree res;
- if (TREE_CODE (TREE_TYPE (arg)) != COMPLEX_TYPE
+ if (!validate_arg (arg, COMPLEX_TYPE)
|| TREE_CODE (TREE_TYPE (TREE_TYPE (arg))) != REAL_TYPE)
return NULL_TREE;
&& (res = do_mpfr_arg2 (TREE_REALPART (arg), TREE_IMAGPART (arg),
type, mpfr_hypot)))
return res;
-
+
if (TREE_CODE (arg) == COMPLEX_EXPR)
{
tree real = TREE_OPERAND (arg, 0);
tree imag = TREE_OPERAND (arg, 1);
-
+
/* If either part is zero, cabs is fabs of the other. */
if (real_zerop (real))
return fold_build1_loc (loc, ABS_EXPR, type, imag);
/* Calculate the result when the argument is a constant. */
if ((res = do_mpfr_arg1 (arg, type, mpfr_sqrt, &dconst0, NULL, true)))
return res;
-
+
/* Optimize sqrt(expN(x)) = expN(x*0.5). */
fcode = builtin_mathfn_code (arg);
if (flag_unsafe_math_optimizations && BUILTIN_EXPONENT_P (fcode))
}
/* Optimize cbrt(pow(x,y)) -> pow(x,y/3) iff x is nonnegative. */
- if (fcode == BUILT_IN_POW
+ if (fcode == BUILT_IN_POW
|| fcode == BUILT_IN_POWF
|| fcode == BUILT_IN_POWL)
{
/* Calculate the result when the argument is a constant. */
if ((res = do_mpfr_arg1 (arg, type, mpfr_cos, NULL, NULL, 0)))
return res;
-
+
/* Optimize cos(-x) into cos (x). */
if ((narg = fold_strip_sign_ops (arg)))
return build_call_expr_loc (loc, fndecl, 1, narg);
/* Calculate the result when the argument is a constant. */
if ((res = do_mpfr_arg1 (arg, type, mpfr_cosh, NULL, NULL, 0)))
return res;
-
+
/* Optimize cosh(-x) into cosh (x). */
if ((narg = fold_strip_sign_ops (arg)))
return build_call_expr_loc (loc, fndecl, 1, narg);
}
-
+
return NULL_TREE;
}
NULL_TREE if no simplification can be made. */
static tree
-fold_builtin_ccos (location_t loc,
- tree arg, tree type ATTRIBUTE_UNUSED, tree fndecl,
- bool hyper ATTRIBUTE_UNUSED)
+fold_builtin_ccos (location_t loc, tree arg, tree type, tree fndecl,
+ bool hyper)
{
if (validate_arg (arg, COMPLEX_TYPE)
&& TREE_CODE (TREE_TYPE (TREE_TYPE (arg))) == REAL_TYPE)
{
tree tmp;
-#ifdef HAVE_mpc
/* Calculate the result when the argument is a constant. */
if ((tmp = do_mpc_arg1 (arg, type, (hyper ? mpc_cosh : mpc_cos))))
return tmp;
-#endif
-
+
/* Optimize fn(-x) into fn(x). */
if ((tmp = fold_strip_sign_ops (arg)))
return build_call_expr_loc (loc, fndecl, 1, tmp);
/* Calculate the result when the argument is a constant. */
if ((res = do_mpfr_arg1 (arg, type, mpfr_tan, NULL, NULL, 0)))
return res;
-
+
/* Optimize tan(atan(x)) = x. */
fcode = builtin_mathfn_code (arg);
if (flag_unsafe_math_optimizations
{
tree rtype;
tree realp, imagp, ifn;
-#ifdef HAVE_mpc
tree res;
-#endif
if (!validate_arg (arg0, COMPLEX_TYPE)
- && TREE_CODE (TREE_TYPE (TREE_TYPE (arg0))) == REAL_TYPE)
+ || TREE_CODE (TREE_TYPE (TREE_TYPE (arg0))) != REAL_TYPE)
return NULL_TREE;
-#ifdef HAVE_mpc
/* Calculate the result when the argument is a constant. */
if ((res = do_mpc_arg1 (arg0, type, mpc_exp)))
return res;
-#endif
-
+
rtype = TREE_TYPE (TREE_TYPE (arg0));
/* In case we can figure out the real part of arg0 and it is constant zero
{
CASE_FLT_FN (BUILT_IN_EXP):
/* Prepare to do logN(exp(exponent) -> exponent*logN(e). */
- x = build_real (type, real_value_truncate (TYPE_MODE (type),
+ x = build_real (type, real_value_truncate (TYPE_MODE (type),
dconst_e ()));
exponent = CALL_EXPR_ARG (arg, 0);
break;
/* Calculate the result when the argument is a constant. */
if ((res = do_mpfr_arg2 (arg0, arg1, type, mpfr_hypot)))
return res;
-
+
/* If either argument to hypot has a negate or abs, strip that off.
E.g. hypot(-x,fabs(y)) -> hypot(x,y). */
narg0 = fold_strip_sign_ops (arg0);
narg1 = fold_strip_sign_ops (arg1);
if (narg0 || narg1)
{
- return build_call_expr_loc (loc, fndecl, 2, narg0 ? narg0 : arg0,
+ return build_call_expr_loc (loc, fndecl, 2, narg0 ? narg0 : arg0,
narg1 ? narg1 : arg1);
}
-
+
/* If either argument is zero, hypot is fabs of the other. */
if (real_zerop (arg0))
return fold_build1_loc (loc, ABS_EXPR, type, arg1);
else if (real_zerop (arg1))
return fold_build1_loc (loc, ABS_EXPR, type, arg0);
-
+
/* hypot(x,x) -> fabs(x)*sqrt(2). */
if (flag_unsafe_math_optimizations
&& operand_equal_p (arg0, arg1, OEP_PURE_SAME))
{
tree type = TREE_TYPE (TREE_TYPE (fndecl));
tree res;
-
+
/* Calculate the result when the argument is a constant. */
if ((res = do_mpfr_arg1 (arg, type, func, NULL, NULL, 0)))
return res;
src_align = get_pointer_alignment (src, BIGGEST_ALIGNMENT);
dest_align = get_pointer_alignment (dest, BIGGEST_ALIGNMENT);
- /* Both DEST and SRC must be pointer types.
+ /* Both DEST and SRC must be pointer types.
??? This is what old code did. Is the testing for pointer types
really mandatory?
{
if (!validate_arg (arg, INTEGER_TYPE))
return NULL_TREE;
-
+
/* Transform toascii(c) -> (c & 0x7f). */
return fold_build2_loc (loc, BIT_AND_EXPR, integer_type_node, arg,
build_int_cst (NULL_TREE, 0x7f));
/* Transform fmin/fmax(x,x) -> x. */
if (operand_equal_p (arg0, arg1, OEP_PURE_SAME))
return omit_one_operand_loc (loc, type, arg0, arg1);
-
+
/* Convert fmin/fmax to MIN_EXPR/MAX_EXPR. C99 requires these
functions to return the numeric arg if the other one is NaN.
These tree codes don't honor that, so only transform if
&& TREE_CODE (TREE_TYPE (TREE_TYPE (arg))) == REAL_TYPE)
{
tree atan2_fn = mathfn_built_in (type, BUILT_IN_ATAN2);
-
+
if (atan2_fn)
{
tree new_arg = builtin_save_expr (arg);
return build_call_expr_loc (loc, atan2_fn, 2, i_arg, r_arg);
}
}
-
+
return NULL_TREE;
}
{
if (! validate_arg (arg, REAL_TYPE))
return NULL_TREE;
-
+
STRIP_NOPS (arg);
-
+
if (TREE_CODE (arg) == REAL_CST && ! TREE_OVERFLOW (arg))
{
const REAL_VALUE_TYPE *const value = TREE_REAL_CST_PTR (arg);
-
+
switch (value->cl)
{
case rvc_nan:
break;
}
}
-
+
return NULL_TREE;
}
{
if (! validate_arg (arg, REAL_TYPE))
return NULL_TREE;
-
+
STRIP_NOPS (arg);
-
+
if (TREE_CODE (arg) == REAL_CST && ! TREE_OVERFLOW (arg))
{
const REAL_VALUE_TYPE *const value = TREE_REAL_CST_PTR (arg);
-
+
switch (value->cl)
{
case rvc_zero:
break;
}
}
-
+
return NULL_TREE;
}
{
if (! validate_arg (arg0, REAL_TYPE) || ! validate_arg (arg1, POINTER_TYPE))
return NULL_TREE;
-
+
STRIP_NOPS (arg0);
-
+
if (!(TREE_CODE (arg0) == REAL_CST && ! TREE_OVERFLOW (arg0)))
return NULL_TREE;
-
+
arg1 = build_fold_indirect_ref_loc (loc, arg1);
/* Proceed if a valid pointer type was passed in. */
{
const REAL_VALUE_TYPE *const value = TREE_REAL_CST_PTR (arg0);
tree frac, exp;
-
+
switch (value->cl)
{
case rvc_zero:
default:
gcc_unreachable ();
}
-
+
/* Create the COMPOUND_EXPR (*arg1 = trunc, frac). */
arg1 = fold_build2_loc (loc, MODIFY_EXPR, rettype, arg1, exp);
TREE_SIDE_EFFECTS (arg1) = 1;
|| (TREE_CODE (arg0) == REAL_CST
&& !real_isfinite (&TREE_REAL_CST (arg0))))
return omit_one_operand_loc (loc, type, arg0, arg1);
-
+
/* If both arguments are constant, then try to evaluate it. */
if ((ldexp || REAL_MODE_FORMAT (TYPE_MODE (type))->b == 2)
&& TREE_CODE (arg0) == REAL_CST && !TREE_OVERFLOW (arg0)
/* Bound the maximum adjustment to twice the range of the
mode's valid exponents. Use abs to ensure the range is
positive as a sanity check. */
- const long max_exp_adj = 2 *
+ const long max_exp_adj = 2 *
labs (REAL_MODE_FORMAT (TYPE_MODE (type))->emax
- REAL_MODE_FORMAT (TYPE_MODE (type))->emin);
/* Get the user-requested adjustment. */
const HOST_WIDE_INT req_exp_adj = tree_low_cst (arg1, 0);
-
+
/* The requested adjustment must be inside this range. This
is a preliminary cap to avoid things like overflow, we
may still fail to compute the result for other reasons. */
if (-max_exp_adj < req_exp_adj && req_exp_adj < max_exp_adj)
{
REAL_VALUE_TYPE initial_result;
-
+
real_ldexp (&initial_result, &TREE_REAL_CST (arg0), req_exp_adj);
/* Ensure we didn't overflow. */
{
const REAL_VALUE_TYPE trunc_result
= real_value_truncate (TYPE_MODE (type), initial_result);
-
+
/* Only proceed if the target mode can hold the
resulting value. */
if (REAL_VALUES_EQUAL (initial_result, trunc_result))
{
if (! validate_arg (arg0, REAL_TYPE) || ! validate_arg (arg1, POINTER_TYPE))
return NULL_TREE;
-
+
STRIP_NOPS (arg0);
-
+
if (!(TREE_CODE (arg0) == REAL_CST && ! TREE_OVERFLOW (arg0)))
return NULL_TREE;
-
+
arg1 = build_fold_indirect_ref_loc (loc, arg1);
/* Proceed if a valid pointer type was passed in. */
frac.sign = value->sign;
break;
}
-
+
/* Create the COMPOUND_EXPR (*arg1 = trunc, frac). */
arg1 = fold_build2_loc (loc, MODIFY_EXPR, rettype, arg1,
build_real (rettype, trunc));
return fold_build2_loc (loc, COMPOUND_EXPR, rettype, arg1,
build_real (rettype, frac));
}
-
+
return NULL_TREE;
}
signbit_call, integer_zero_node);
isinf_call = fold_build2_loc (loc, NE_EXPR, integer_type_node,
isinf_call, integer_zero_node);
-
+
tmp = fold_build3_loc (loc, COND_EXPR, integer_type_node, signbit_call,
integer_minus_one_node, integer_one_node);
tmp = fold_build3_loc (loc, COND_EXPR, integer_type_node,
enum machine_mode mode;
REAL_VALUE_TYPE r;
char buf[128];
-
+
/* Verify the required arguments in the original call. */
if (!validate_arglist (exp, INTEGER_TYPE, INTEGER_TYPE,
INTEGER_TYPE, INTEGER_TYPE,
INTEGER_TYPE, REAL_TYPE, VOID_TYPE))
return NULL_TREE;
-
+
fp_nan = CALL_EXPR_ARG (exp, 0);
fp_infinite = CALL_EXPR_ARG (exp, 1);
fp_normal = CALL_EXPR_ARG (exp, 2);
mode = TYPE_MODE (type);
arg = builtin_save_expr (fold_build1_loc (loc, ABS_EXPR, type, arg));
- /* fpclassify(x) ->
+ /* fpclassify(x) ->
isnan(x) ? FP_NAN :
(fabs(x) == Inf ? FP_INFINITE :
(fabs(x) >= DBL_MIN ? FP_NORMAL :
(x == 0 ? FP_ZERO : FP_SUBNORMAL))). */
-
+
tmp = fold_build2_loc (loc, EQ_EXPR, integer_type_node, arg,
build_real (type, dconst0));
res = fold_build3_loc (loc, COND_EXPR, integer_type_node,
tmp = fold_build2_loc (loc, GE_EXPR, integer_type_node,
arg, build_real (type, r));
res = fold_build3_loc (loc, COND_EXPR, integer_type_node, tmp, fp_normal, res);
-
+
if (HONOR_INFINITIES (mode))
{
real_inf (&r);
tmp = fold_build2_loc (loc, ORDERED_EXPR, integer_type_node, arg, arg);
res = fold_build3_loc (loc, COND_EXPR, integer_type_node, tmp, res, fp_nan);
}
-
+
return res;
}
CASE_FLT_FN (BUILT_IN_CONJ):
if (validate_arg (arg0, COMPLEX_TYPE)
- && TREE_CODE (TREE_TYPE (TREE_TYPE (arg0))) == REAL_TYPE)
+ && TREE_CODE (TREE_TYPE (TREE_TYPE (arg0))) == REAL_TYPE)
return fold_build1_loc (loc, CONJ_EXPR, type, arg0);
break;
CASE_FLT_FN (BUILT_IN_CREAL):
if (validate_arg (arg0, COMPLEX_TYPE)
- && TREE_CODE (TREE_TYPE (TREE_TYPE (arg0))) == REAL_TYPE)
+ && TREE_CODE (TREE_TYPE (TREE_TYPE (arg0))) == REAL_TYPE)
return non_lvalue_loc (loc, fold_build1_loc (loc, REALPART_EXPR, type, arg0));;
break;
CASE_FLT_FN (BUILT_IN_CIMAG):
- if (validate_arg (arg0, COMPLEX_TYPE))
+ if (validate_arg (arg0, COMPLEX_TYPE)
+ && TREE_CODE (TREE_TYPE (TREE_TYPE (arg0))) == REAL_TYPE)
return non_lvalue_loc (loc, fold_build1_loc (loc, IMAGPART_EXPR, type, arg0));
break;
CASE_FLT_FN (BUILT_IN_CCOS):
return fold_builtin_ccos(loc, arg0, type, fndecl, /*hyper=*/ false);
-
+
CASE_FLT_FN (BUILT_IN_CCOSH):
return fold_builtin_ccos(loc, arg0, type, fndecl, /*hyper=*/ true);
-
-#ifdef HAVE_mpc
+
CASE_FLT_FN (BUILT_IN_CSIN):
if (validate_arg (arg0, COMPLEX_TYPE)
- && TREE_CODE (TREE_TYPE (TREE_TYPE (arg0))) == REAL_TYPE)
+ && TREE_CODE (TREE_TYPE (TREE_TYPE (arg0))) == REAL_TYPE)
return do_mpc_arg1 (arg0, type, mpc_sin);
break;
-
+
CASE_FLT_FN (BUILT_IN_CSINH):
if (validate_arg (arg0, COMPLEX_TYPE)
- && TREE_CODE (TREE_TYPE (TREE_TYPE (arg0))) == REAL_TYPE)
+ && TREE_CODE (TREE_TYPE (TREE_TYPE (arg0))) == REAL_TYPE)
return do_mpc_arg1 (arg0, type, mpc_sinh);
break;
-
+
CASE_FLT_FN (BUILT_IN_CTAN):
if (validate_arg (arg0, COMPLEX_TYPE)
- && TREE_CODE (TREE_TYPE (TREE_TYPE (arg0))) == REAL_TYPE)
+ && TREE_CODE (TREE_TYPE (TREE_TYPE (arg0))) == REAL_TYPE)
return do_mpc_arg1 (arg0, type, mpc_tan);
break;
-
+
CASE_FLT_FN (BUILT_IN_CTANH):
if (validate_arg (arg0, COMPLEX_TYPE)
- && TREE_CODE (TREE_TYPE (TREE_TYPE (arg0))) == REAL_TYPE)
+ && TREE_CODE (TREE_TYPE (TREE_TYPE (arg0))) == REAL_TYPE)
return do_mpc_arg1 (arg0, type, mpc_tanh);
break;
-
+
CASE_FLT_FN (BUILT_IN_CLOG):
if (validate_arg (arg0, COMPLEX_TYPE)
- && TREE_CODE (TREE_TYPE (TREE_TYPE (arg0))) == REAL_TYPE)
+ && TREE_CODE (TREE_TYPE (TREE_TYPE (arg0))) == REAL_TYPE)
return do_mpc_arg1 (arg0, type, mpc_log);
break;
-
+
CASE_FLT_FN (BUILT_IN_CSQRT):
if (validate_arg (arg0, COMPLEX_TYPE)
- && TREE_CODE (TREE_TYPE (TREE_TYPE (arg0))) == REAL_TYPE)
+ && TREE_CODE (TREE_TYPE (TREE_TYPE (arg0))) == REAL_TYPE)
return do_mpc_arg1 (arg0, type, mpc_sqrt);
break;
-
-#ifdef HAVE_mpc_arc
+
CASE_FLT_FN (BUILT_IN_CASIN):
if (validate_arg (arg0, COMPLEX_TYPE)
- && TREE_CODE (TREE_TYPE (TREE_TYPE (arg0))) == REAL_TYPE)
+ && TREE_CODE (TREE_TYPE (TREE_TYPE (arg0))) == REAL_TYPE)
return do_mpc_arg1 (arg0, type, mpc_asin);
break;
-
+
CASE_FLT_FN (BUILT_IN_CACOS):
if (validate_arg (arg0, COMPLEX_TYPE)
- && TREE_CODE (TREE_TYPE (TREE_TYPE (arg0))) == REAL_TYPE)
+ && TREE_CODE (TREE_TYPE (TREE_TYPE (arg0))) == REAL_TYPE)
return do_mpc_arg1 (arg0, type, mpc_acos);
break;
-
+
CASE_FLT_FN (BUILT_IN_CATAN):
if (validate_arg (arg0, COMPLEX_TYPE)
- && TREE_CODE (TREE_TYPE (TREE_TYPE (arg0))) == REAL_TYPE)
+ && TREE_CODE (TREE_TYPE (TREE_TYPE (arg0))) == REAL_TYPE)
return do_mpc_arg1 (arg0, type, mpc_atan);
break;
-
+
CASE_FLT_FN (BUILT_IN_CASINH):
if (validate_arg (arg0, COMPLEX_TYPE)
- && TREE_CODE (TREE_TYPE (TREE_TYPE (arg0))) == REAL_TYPE)
+ && TREE_CODE (TREE_TYPE (TREE_TYPE (arg0))) == REAL_TYPE)
return do_mpc_arg1 (arg0, type, mpc_asinh);
break;
-
+
CASE_FLT_FN (BUILT_IN_CACOSH):
if (validate_arg (arg0, COMPLEX_TYPE)
- && TREE_CODE (TREE_TYPE (TREE_TYPE (arg0))) == REAL_TYPE)
+ && TREE_CODE (TREE_TYPE (TREE_TYPE (arg0))) == REAL_TYPE)
return do_mpc_arg1 (arg0, type, mpc_acosh);
break;
-
+
CASE_FLT_FN (BUILT_IN_CATANH):
if (validate_arg (arg0, COMPLEX_TYPE)
- && TREE_CODE (TREE_TYPE (TREE_TYPE (arg0))) == REAL_TYPE)
+ && TREE_CODE (TREE_TYPE (TREE_TYPE (arg0))) == REAL_TYPE)
return do_mpc_arg1 (arg0, type, mpc_atanh);
break;
-#endif /* HAVE_mpc_arc */
-#endif /* HAVE_mpc */
-
+
CASE_FLT_FN (BUILT_IN_CABS):
return fold_builtin_cabs (loc, arg0, type, fndecl);
if (validate_arg (arg0, REAL_TYPE))
return do_mpfr_arg1 (arg0, type, mpfr_gamma, NULL, NULL, 0);
break;
-
+
CASE_FLT_FN (BUILT_IN_EXP):
return fold_builtin_exponent (loc, fndecl, arg0, mpfr_exp);
if (validate_arg (arg0, REAL_TYPE))
return do_mpfr_arg1 (arg0, type, mpfr_expm1, NULL, NULL, 0);
break;
-
+
CASE_FLT_FN (BUILT_IN_LOG):
return fold_builtin_logarithm (loc, fndecl, arg0, mpfr_log);
CASE_FLT_FN (BUILT_IN_HYPOT):
return fold_builtin_hypot (loc, fndecl, arg0, arg1, type);
-#ifdef HAVE_mpc_pow
CASE_FLT_FN (BUILT_IN_CPOW):
if (validate_arg (arg0, COMPLEX_TYPE)
&& TREE_CODE (TREE_TYPE (TREE_TYPE (arg0))) == REAL_TYPE
&& validate_arg (arg1, COMPLEX_TYPE)
- && TREE_CODE (TREE_TYPE (TREE_TYPE (arg1))) == REAL_TYPE)
+ && TREE_CODE (TREE_TYPE (TREE_TYPE (arg1))) == REAL_TYPE)
return do_mpc_arg2 (arg0, arg1, type, /*do_nonfinite=*/ 0, mpc_pow);
break;
-#endif
CASE_FLT_FN (BUILT_IN_LDEXP):
return fold_builtin_load_exponent (loc, arg0, arg1, type, /*ldexp=*/true);
ARG2, and ARG3. 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_4 (location_t loc, tree fndecl,
tree arg0, tree arg1, tree arg2, tree arg3, bool ignore)
fixed argument patterns. Foldings that do varargs-to-varargs
transformations, or that match calls with more than 4 arguments,
need to be handled with fold_builtin_varargs instead. */
-
+
#define MAX_ARGS_TO_FOLD_BUILTIN 4
-
+
static tree
fold_builtin_n (location_t loc, tree fndecl, tree *args, int nargs, bool ignore)
{
}
return NULL_TREE;
}
-
+
/* Conveniently construct a function call expression. FNDECL names the
function to be called and ARGLIST is a TREE_LIST of arguments. */
-
+
tree
build_function_call_expr (location_t loc, tree fndecl, tree arglist)
{
/* Conveniently construct a function call expression. FNDECL names the
function to be called, N is the number of arguments, and the "..."
parameters are the argument expressions. */
-
+
tree
build_call_expr_loc (location_t loc, tree fndecl, int n, ...)
{
for (j = skip; j < oldnargs; j++, i++)
buffer[i] = CALL_EXPR_ARG (exp, j);
}
- else
+ else
buffer = CALL_EXPR_ARGP (exp) + skip;
return fold (build_call_array_loc (loc, TREE_TYPE (exp), fn, nargs, buffer));
/* Validate a single argument ARG against a tree code CODE representing
a type. */
-
+
static bool
validate_arg (const_tree arg, enum tree_code code)
{
/* If we don't have a movstr we don't want to emit an strcpy
call. We have to do that if the length of the source string
isn't computable (in that case we can use memcpy probably
- later expanding to a sequence of mov instructions). If we
+ later expanding to a sequence of mov instructions). If we
have movstr instructions we can emit strcpy calls. */
if (!HAVE_movstr)
{
arg = SSA_NAME_VAR (arg);
/* We destructively modify the call to be __builtin_va_start (ap, 0)
- or __builtin_next_arg (0) the first time we see it, after checking
+ or __builtin_next_arg (0) the first time we see it, after checking
the arguments and if needed issuing a warning. */
if (!integer_zerop (arg))
{
static void
maybe_emit_sprintf_chk_warning (tree exp, enum built_in_function fcode)
{
- tree dest, size, len, fmt, flag;
+ tree size, len, fmt;
const char *fmt_str;
int nargs = call_expr_nargs (exp);
/* Verify the required arguments in the original call. */
-
+
if (nargs < 4)
return;
- dest = CALL_EXPR_ARG (exp, 0);
- flag = CALL_EXPR_ARG (exp, 1);
size = CALL_EXPR_ARG (exp, 2);
fmt = CALL_EXPR_ARG (exp, 3);
return NULL_TREE;
}
-#ifdef HAVE_mpc
/* Helper function for do_mpc_arg*(). Ensure M is a normal complex
number and no overflow/underflow occurred. INEXACT is true if M
was not exactly calculated. TYPE is the tree type for the result.
{
REAL_VALUE_TYPE re, im;
- real_from_mpfr (&re, mpc_realref (m), type, GMP_RNDN);
- real_from_mpfr (&im, mpc_imagref (m), type, GMP_RNDN);
+ real_from_mpfr (&re, mpc_realref (m), TREE_TYPE (type), GMP_RNDN);
+ real_from_mpfr (&im, mpc_imagref (m), TREE_TYPE (type), GMP_RNDN);
/* Proceed iff GCC's REAL_VALUE_TYPE can hold the MPFR values,
check for overflow/underflow. If the REAL_VALUE_TYPE is zero
but the mpft_t is not, then we underflowed in the
}
return NULL_TREE;
}
-#endif /* HAVE_mpc */
/* If argument ARG is a REAL_CST, call the one-argument mpfr function
FUNC on it and return the resulting value as a tree with type TYPE.
bool inclusive)
{
tree result = NULL_TREE;
-
+
STRIP_NOPS (arg);
/* To proceed, MPFR must exactly represent the target floating point
mpfr_clear (m);
}
}
-
+
return result;
}
int (*func)(mpfr_ptr, mpfr_srcptr, mpfr_srcptr, mp_rnd_t))
{
tree result = NULL_TREE;
-
+
STRIP_NOPS (arg1);
STRIP_NOPS (arg2);
mpfr_clears (m1, m2, NULL);
}
}
-
+
return result;
}
int (*func)(mpfr_ptr, mpfr_srcptr, mpfr_srcptr, mpfr_srcptr, mp_rnd_t))
{
tree result = NULL_TREE;
-
+
STRIP_NOPS (arg1);
STRIP_NOPS (arg2);
STRIP_NOPS (arg3);
mpfr_clears (m1, m2, m3, NULL);
}
}
-
+
return result;
}
{
tree const type = TREE_TYPE (arg);
tree result = NULL_TREE;
-
+
STRIP_NOPS (arg);
-
+
/* To proceed, MPFR must exactly represent the target floating point
format, which only happens when the target base equals two. */
if (REAL_MODE_FORMAT (TYPE_MODE (type))->b == 2
mpfr_clear (m);
}
}
-
+
return result;
}
{
tree const type = TREE_TYPE (arg0);
tree result = NULL_TREE;
-
+
STRIP_NOPS (arg0);
STRIP_NOPS (arg1);
-
+
/* To proceed, MPFR must exactly represent the target floating point
format, which only happens when the target base equals two. */
if (REAL_MODE_FORMAT (TYPE_MODE (type))->b == 2
tree result = NULL_TREE;
STRIP_NOPS (arg);
-
+
/* To proceed, MPFR must exactly represent the target floating point
format, which only happens when the target base equals two. Also
verify ARG is a constant and that ARG_SG is an int pointer. */
return result;
}
-#ifdef HAVE_mpc
/* If argument ARG is a COMPLEX_CST, call the one-argument mpc
function FUNC on it and return the resulting value as a tree with
type TYPE. The mpfr precision is set to the precision of TYPE. We
do_mpc_arg1 (tree arg, tree type, int (*func)(mpc_ptr, mpc_srcptr, mpc_rnd_t))
{
tree result = NULL_TREE;
-
+
STRIP_NOPS (arg);
/* To proceed, MPFR must exactly represent the target floating point
const mpc_rnd_t crnd = fmt->round_towards_zero ? MPC_RNDZZ : MPC_RNDNN;
int inexact;
mpc_t m;
-
+
mpc_init2 (m, prec);
mpfr_from_real (mpc_realref(m), re, rnd);
mpfr_from_real (mpc_imagref(m), im, rnd);
DO_NONFINITE is true, then fold expressions containing Inf or NaN
in the arguments and/or results. */
-#ifdef HAVE_mpc
tree
do_mpc_arg2 (tree arg0, tree arg1, tree type, int do_nonfinite,
int (*func)(mpc_ptr, mpc_srcptr, mpc_srcptr, mpc_rnd_t))
{
tree result = NULL_TREE;
-
+
STRIP_NOPS (arg0);
STRIP_NOPS (arg1);
const mpc_rnd_t crnd = fmt->round_towards_zero ? MPC_RNDZZ : MPC_RNDNN;
int inexact;
mpc_t m0, m1;
-
+
mpc_init2 (m0, prec);
mpc_init2 (m1, prec);
mpfr_from_real (mpc_realref(m0), re0, rnd);
return result;
}
-# endif
-#endif /* HAVE_mpc */
/* FIXME tuples.
The functions below provide an alternate interface for folding