diff options
-rw-r--r-- | gcc/ChangeLog | 54 | ||||
-rw-r--r-- | gcc/builtins.c | 374 | ||||
-rw-r--r-- | gcc/builtins.def | 2 | ||||
-rw-r--r-- | gcc/c/c-typeck.c | 2 | ||||
-rw-r--r-- | gcc/doc/extend.texi | 53 | ||||
-rw-r--r-- | gcc/gimple-low.c | 910 | ||||
-rw-r--r-- | gcc/real.c | 34 | ||||
-rw-r--r-- | gcc/real.h | 18 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 17 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/builtins-43.c | 4 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/fold-notunord.c | 9 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/pr28796-1.c | 2 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/pr77925.c | 11 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/tg-tests.h | 47 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/torture/float128-tg-4.c | 11 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/torture/float128x-tg-4.c | 11 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/torture/float16-tg-4.c | 11 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/torture/float32-tg-4.c | 11 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/torture/float32x-tg-4.c | 11 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/torture/float64-tg-4.c | 11 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/torture/float64x-tg-4.c | 11 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/torture/floatn-tg-4.h | 99 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/aarch64/builtin-fpclassify.c | 22 |
23 files changed, 380 insertions, 1355 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index ded9797..d61dc3e 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -161,60 +161,6 @@ PR gcov-profile/80911 * gcov.c (block_info::block_info): New constructor. -2017-06-08 Tamar Christina <tamar.christina@arm.com> - - PR middle-end/77925 - PR middle-end/77926 - PR middle-end/66462 - - * gcc/builtins.c (fold_builtin_fpclassify): Remove. - (fold_builtin_interclass_mathfn): Remove. - (expand_builtin): Add builtins to lowering list. - (fold_builtin_n): Remove fold_builtin_varargs. - (fold_builtin_varargs): Remove. - * gcc/builtins.def (BUILT_IN_ISZERO, BUILT_IN_ISSUBNORMAL): New. - * gcc/real.h (get_min_float): New. - (real_format): Add is_ieee_compatible field. - * gcc/real.c (get_min_float): New. - (ieee_single_format): Set is_ieee_compatible flag. - * gcc/gimple-low.c (lower_stm): Define BUILT_IN_FPCLASSIFY, - CASE_FLT_FN (BUILT_IN_ISINF), BUILT_IN_ISINFD32, BUILT_IN_ISINFD64, - BUILT_IN_ISINFD128, BUILT_IN_ISNAND32, BUILT_IN_ISNAND64, - BUILT_IN_ISNAND128, BUILT_IN_ISNAN, BUILT_IN_ISNORMAL, BUILT_IN_ISZERO, - BUILT_IN_ISSUBNORMAL, CASE_FLT_FN (BUILT_IN_FINITE), BUILT_IN_FINITED32 - BUILT_IN_FINITED64, BUILT_IN_FINITED128, BUILT_IN_ISFINITE. - (lower_builtin_fpclassify, is_nan, is_normal, is_infinity): New. - (is_zero, is_subnormal, is_finite, use_ieee_int_mode): Likewise. - (lower_builtin_isnan, lower_builtin_isinfinite): Likewise. - (lower_builtin_isnormal, lower_builtin_iszero): Likewise. - (lower_builtin_issubnormal, lower_builtin_isfinite): Likewise. - (emit_tree_cond, get_num_as_int, emit_tree_and_return_var): New. - (mips_single_format): Likewise. - (motorola_single_format): Likewise. - (spu_single_format): Likewise. - (ieee_double_format): Likewise. - (mips_double_format): Likewise. - (motorola_double_format): Likewise. - (ieee_extended_motorola_format): Likewise. - (ieee_extended_intel_128_format): Likewise. - (ieee_extended_intel_96_round_53_format): Likewise. - (ibm_extended_format): Likewise. - (mips_extended_format): Likewise. - (ieee_quad_format): Likewise. - (mips_quad_format): Likewise. - (vax_f_format): Likewise. - (vax_d_format): Likewise. - (vax_g_format): Likewise. - (decimal_single_format): Likewise. - (decimal_quad_format): Likewise. - (iee_half_format): Likewise. - (mips_single_format): Likewise. - (arm_half_format): Likewise. - (real_internal_format): Likewise. - * gcc/doc/extend.texi: Add documentation for built-ins. - * gcc/c/c-typeck.c (convert_arguments): Add BUILT_IN_ISZERO - and BUILT_IN_ISSUBNORMAL. - 2017-06-07 Carl Love <cel@us.ibm.com> * config/rs6000/rs6000-c: The return type of the following diff --git a/gcc/builtins.c b/gcc/builtins.c index 254dab6..30462ad 100644 --- a/gcc/builtins.c +++ b/gcc/builtins.c @@ -165,6 +165,7 @@ static tree fold_builtin_0 (location_t, tree); static tree fold_builtin_1 (location_t, tree, tree); static tree fold_builtin_2 (location_t, tree, tree, tree); static tree fold_builtin_3 (location_t, tree, tree, tree, tree); +static tree fold_builtin_varargs (location_t, tree, tree*, int); static tree fold_builtin_strpbrk (location_t, tree, tree, tree); static tree fold_builtin_strspn (location_t, tree, tree); @@ -2226,8 +2227,19 @@ interclass_mathfn_icode (tree arg, tree fndecl) switch (DECL_FUNCTION_CODE (fndecl)) { CASE_FLT_FN (BUILT_IN_ILOGB): - errno_set = true; - builtin_optab = ilogb_optab; + errno_set = true; builtin_optab = ilogb_optab; break; + CASE_FLT_FN (BUILT_IN_ISINF): + builtin_optab = isinf_optab; break; + case BUILT_IN_ISNORMAL: + case BUILT_IN_ISFINITE: + CASE_FLT_FN (BUILT_IN_FINITE): + case BUILT_IN_FINITED32: + case BUILT_IN_FINITED64: + case BUILT_IN_FINITED128: + case BUILT_IN_ISINFD32: + case BUILT_IN_ISINFD64: + case BUILT_IN_ISINFD128: + /* These builtins have no optabs (yet). */ break; default: gcc_unreachable (); @@ -2246,7 +2258,8 @@ interclass_mathfn_icode (tree arg, tree fndecl) } /* Expand a call to one of the builtin math functions that operate on - floating point argument and output an integer result (ilogb, etc). + floating point argument and output an integer result (ilogb, isinf, + isnan, etc). Return 0 if a normal call should be emitted rather than expanding the function in-line. EXP is the expression that is a call to the builtin function; if convenient, the result should be placed in TARGET. */ @@ -6592,7 +6605,11 @@ expand_builtin (tree exp, rtx target, rtx subtarget, machine_mode mode, CASE_FLT_FN (BUILT_IN_ILOGB): if (! flag_unsafe_math_optimizations) break; - + gcc_fallthrough (); + CASE_FLT_FN (BUILT_IN_ISINF): + CASE_FLT_FN (BUILT_IN_FINITE): + case BUILT_IN_ISFINITE: + case BUILT_IN_ISNORMAL: target = expand_builtin_interclass_mathfn (exp, target); if (target) return target; @@ -6900,25 +6917,8 @@ expand_builtin (tree exp, rtx target, rtx subtarget, machine_mode mode, } break; - CASE_FLT_FN (BUILT_IN_ISINF): - case BUILT_IN_ISNAND32: - case BUILT_IN_ISNAND64: - case BUILT_IN_ISNAND128: - case BUILT_IN_ISNAN: - case BUILT_IN_ISINFD32: - case BUILT_IN_ISINFD64: - case BUILT_IN_ISINFD128: - case BUILT_IN_ISNORMAL: - case BUILT_IN_ISZERO: - case BUILT_IN_ISSUBNORMAL: - case BUILT_IN_FPCLASSIFY: case BUILT_IN_SETJMP: - CASE_FLT_FN (BUILT_IN_FINITE): - case BUILT_IN_FINITED32: - case BUILT_IN_FINITED64: - case BUILT_IN_FINITED128: - case BUILT_IN_ISFINITE: - /* These should have been lowered to the builtins in gimple-low.c. */ + /* This should have been lowered to the builtins below. */ gcc_unreachable (); case BUILT_IN_SETJMP_SETUP: @@ -8258,19 +8258,184 @@ fold_builtin_modf (location_t loc, tree arg0, tree arg1, tree rettype) return NULL_TREE; } +/* Given a location LOC, an interclass builtin function decl FNDECL + and its single argument ARG, return an folded expression computing + the same, or NULL_TREE if we either couldn't or didn't want to fold + (the latter happen if there's an RTL instruction available). */ + +static tree +fold_builtin_interclass_mathfn (location_t loc, tree fndecl, tree arg) +{ + machine_mode mode; + + if (!validate_arg (arg, REAL_TYPE)) + return NULL_TREE; + + if (interclass_mathfn_icode (arg, fndecl) != CODE_FOR_nothing) + return NULL_TREE; + + mode = TYPE_MODE (TREE_TYPE (arg)); + + bool is_ibm_extended = MODE_COMPOSITE_P (mode); + /* If there is no optab, try generic code. */ + switch (DECL_FUNCTION_CODE (fndecl)) + { + tree result; -/* Fold a call to __builtin_isinf_sign. + CASE_FLT_FN (BUILT_IN_ISINF): + { + /* isinf(x) -> isgreater(fabs(x),DBL_MAX). */ + tree const isgr_fn = builtin_decl_explicit (BUILT_IN_ISGREATER); + tree type = TREE_TYPE (arg); + REAL_VALUE_TYPE r; + char buf[128]; + + if (is_ibm_extended) + { + /* NaN and Inf are encoded in the high-order double value + only. The low-order value is not significant. */ + type = double_type_node; + mode = DFmode; + arg = fold_build1_loc (loc, NOP_EXPR, type, arg); + } + get_max_float (REAL_MODE_FORMAT (mode), buf, sizeof (buf)); + real_from_string (&r, buf); + result = build_call_expr (isgr_fn, 2, + fold_build1_loc (loc, ABS_EXPR, type, arg), + build_real (type, r)); + return result; + } + CASE_FLT_FN (BUILT_IN_FINITE): + case BUILT_IN_ISFINITE: + { + /* isfinite(x) -> islessequal(fabs(x),DBL_MAX). */ + tree const isle_fn = builtin_decl_explicit (BUILT_IN_ISLESSEQUAL); + tree type = TREE_TYPE (arg); + REAL_VALUE_TYPE r; + char buf[128]; + + if (is_ibm_extended) + { + /* NaN and Inf are encoded in the high-order double value + only. The low-order value is not significant. */ + type = double_type_node; + mode = DFmode; + arg = fold_build1_loc (loc, NOP_EXPR, type, arg); + } + get_max_float (REAL_MODE_FORMAT (mode), buf, sizeof (buf)); + real_from_string (&r, buf); + result = build_call_expr (isle_fn, 2, + fold_build1_loc (loc, ABS_EXPR, type, arg), + build_real (type, r)); + /*result = fold_build2_loc (loc, UNGT_EXPR, + TREE_TYPE (TREE_TYPE (fndecl)), + fold_build1_loc (loc, ABS_EXPR, type, arg), + build_real (type, r)); + result = fold_build1_loc (loc, TRUTH_NOT_EXPR, + TREE_TYPE (TREE_TYPE (fndecl)), + result);*/ + return result; + } + case BUILT_IN_ISNORMAL: + { + /* isnormal(x) -> isgreaterequal(fabs(x),DBL_MIN) & + islessequal(fabs(x),DBL_MAX). */ + tree const isle_fn = builtin_decl_explicit (BUILT_IN_ISLESSEQUAL); + tree type = TREE_TYPE (arg); + tree orig_arg, max_exp, min_exp; + machine_mode orig_mode = mode; + REAL_VALUE_TYPE rmax, rmin; + char buf[128]; + + orig_arg = arg = builtin_save_expr (arg); + if (is_ibm_extended) + { + /* Use double to test the normal range of IBM extended + precision. Emin for IBM extended precision is + different to emin for IEEE double, being 53 higher + since the low double exponent is at least 53 lower + than the high double exponent. */ + type = double_type_node; + mode = DFmode; + arg = fold_build1_loc (loc, NOP_EXPR, type, arg); + } + arg = fold_build1_loc (loc, ABS_EXPR, type, arg); + + get_max_float (REAL_MODE_FORMAT (mode), buf, sizeof (buf)); + real_from_string (&rmax, buf); + sprintf (buf, "0x1p%d", REAL_MODE_FORMAT (orig_mode)->emin - 1); + real_from_string (&rmin, buf); + max_exp = build_real (type, rmax); + min_exp = build_real (type, rmin); + + max_exp = build_call_expr (isle_fn, 2, arg, max_exp); + if (is_ibm_extended) + { + /* Testing the high end of the range is done just using + the high double, using the same test as isfinite(). + For the subnormal end of the range we first test the + high double, then if its magnitude is equal to the + limit of 0x1p-969, we test whether the low double is + non-zero and opposite sign to the high double. */ + tree const islt_fn = builtin_decl_explicit (BUILT_IN_ISLESS); + tree const isgt_fn = builtin_decl_explicit (BUILT_IN_ISGREATER); + tree gt_min = build_call_expr (isgt_fn, 2, arg, min_exp); + tree eq_min = fold_build2 (EQ_EXPR, integer_type_node, + arg, min_exp); + tree as_complex = build1 (VIEW_CONVERT_EXPR, + complex_double_type_node, orig_arg); + tree hi_dbl = build1 (REALPART_EXPR, type, as_complex); + tree lo_dbl = build1 (IMAGPART_EXPR, type, as_complex); + tree zero = build_real (type, dconst0); + tree hilt = build_call_expr (islt_fn, 2, hi_dbl, zero); + tree lolt = build_call_expr (islt_fn, 2, lo_dbl, zero); + tree logt = build_call_expr (isgt_fn, 2, lo_dbl, zero); + tree ok_lo = fold_build1 (TRUTH_NOT_EXPR, integer_type_node, + fold_build3 (COND_EXPR, + integer_type_node, + hilt, logt, lolt)); + eq_min = fold_build2 (TRUTH_ANDIF_EXPR, integer_type_node, + eq_min, ok_lo); + min_exp = fold_build2 (TRUTH_ORIF_EXPR, integer_type_node, + gt_min, eq_min); + } + else + { + tree const isge_fn + = builtin_decl_explicit (BUILT_IN_ISGREATEREQUAL); + min_exp = build_call_expr (isge_fn, 2, arg, min_exp); + } + result = fold_build2 (BIT_AND_EXPR, integer_type_node, + max_exp, min_exp); + return result; + } + default: + break; + } + + return NULL_TREE; +} + +/* Fold a call to __builtin_isnan(), __builtin_isinf, __builtin_finite. ARG is the argument for the call. */ static tree -fold_builtin_classify (location_t loc, tree arg, int builtin_index) +fold_builtin_classify (location_t loc, tree fndecl, tree arg, int builtin_index) { + tree type = TREE_TYPE (TREE_TYPE (fndecl)); + if (!validate_arg (arg, REAL_TYPE)) return NULL_TREE; switch (builtin_index) { + case BUILT_IN_ISINF: + if (!HONOR_INFINITIES (arg)) + return omit_one_operand_loc (loc, type, integer_zero_node, arg); + + return NULL_TREE; + case BUILT_IN_ISINF_SIGN: { /* isinf_sign(x) -> isinf(x) ? (signbit(x) ? -1 : 1) : 0 */ @@ -8303,11 +8468,106 @@ fold_builtin_classify (location_t loc, tree arg, int builtin_index) return tmp; } + case BUILT_IN_ISFINITE: + if (!HONOR_NANS (arg) + && !HONOR_INFINITIES (arg)) + return omit_one_operand_loc (loc, type, integer_one_node, arg); + + return NULL_TREE; + + case BUILT_IN_ISNAN: + if (!HONOR_NANS (arg)) + return omit_one_operand_loc (loc, type, integer_zero_node, arg); + + { + bool is_ibm_extended = MODE_COMPOSITE_P (TYPE_MODE (TREE_TYPE (arg))); + if (is_ibm_extended) + { + /* NaN and Inf are encoded in the high-order double value + only. The low-order value is not significant. */ + arg = fold_build1_loc (loc, NOP_EXPR, double_type_node, arg); + } + } + arg = builtin_save_expr (arg); + return fold_build2_loc (loc, UNORDERED_EXPR, type, arg, arg); + default: gcc_unreachable (); } } +/* Fold a call to __builtin_fpclassify(int, int, int, int, int, ...). + This builtin will generate code to return the appropriate floating + point classification depending on the value of the floating point + number passed in. The possible return values must be supplied as + int arguments to the call in the following order: FP_NAN, FP_INFINITE, + FP_NORMAL, FP_SUBNORMAL and FP_ZERO. The ellipses is for exactly + one floating point argument which is "type generic". */ + +static tree +fold_builtin_fpclassify (location_t loc, tree *args, int nargs) +{ + tree fp_nan, fp_infinite, fp_normal, fp_subnormal, fp_zero, + arg, type, res, tmp; + machine_mode mode; + REAL_VALUE_TYPE r; + char buf[128]; + + /* Verify the required arguments in the original call. */ + if (nargs != 6 + || !validate_arg (args[0], INTEGER_TYPE) + || !validate_arg (args[1], INTEGER_TYPE) + || !validate_arg (args[2], INTEGER_TYPE) + || !validate_arg (args[3], INTEGER_TYPE) + || !validate_arg (args[4], INTEGER_TYPE) + || !validate_arg (args[5], REAL_TYPE)) + return NULL_TREE; + + fp_nan = args[0]; + fp_infinite = args[1]; + fp_normal = args[2]; + fp_subnormal = args[3]; + fp_zero = args[4]; + arg = args[5]; + type = TREE_TYPE (arg); + mode = TYPE_MODE (type); + arg = builtin_save_expr (fold_build1_loc (loc, ABS_EXPR, type, arg)); + + /* 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, fp_zero, fp_subnormal); + + sprintf (buf, "0x1p%d", REAL_MODE_FORMAT (mode)->emin - 1); + real_from_string (&r, buf); + 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, EQ_EXPR, integer_type_node, arg, + build_real (type, r)); + res = fold_build3_loc (loc, COND_EXPR, integer_type_node, tmp, + fp_infinite, res); + } + + if (HONOR_NANS (mode)) + { + 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; +} + /* Fold a call to an unordered comparison function such as __builtin_isgreater(). FNDECL is the FUNCTION_DECL for the function being called and ARG0 and ARG1 are the arguments for the call. @@ -8608,8 +8868,40 @@ fold_builtin_1 (location_t loc, tree fndecl, tree arg0) case BUILT_IN_ISDIGIT: return fold_builtin_isdigit (loc, arg0); + CASE_FLT_FN (BUILT_IN_FINITE): + case BUILT_IN_FINITED32: + case BUILT_IN_FINITED64: + case BUILT_IN_FINITED128: + case BUILT_IN_ISFINITE: + { + tree ret = fold_builtin_classify (loc, fndecl, arg0, BUILT_IN_ISFINITE); + if (ret) + return ret; + return fold_builtin_interclass_mathfn (loc, fndecl, arg0); + } + + CASE_FLT_FN (BUILT_IN_ISINF): + case BUILT_IN_ISINFD32: + case BUILT_IN_ISINFD64: + case BUILT_IN_ISINFD128: + { + tree ret = fold_builtin_classify (loc, fndecl, arg0, BUILT_IN_ISINF); + if (ret) + return ret; + return fold_builtin_interclass_mathfn (loc, fndecl, arg0); + } + + case BUILT_IN_ISNORMAL: + return fold_builtin_interclass_mathfn (loc, fndecl, arg0); + case BUILT_IN_ISINF_SIGN: - return fold_builtin_classify (loc, arg0, BUILT_IN_ISINF_SIGN); + return fold_builtin_classify (loc, fndecl, arg0, BUILT_IN_ISINF_SIGN); + + CASE_FLT_FN (BUILT_IN_ISNAN): + case BUILT_IN_ISNAND32: + case BUILT_IN_ISNAND64: + case BUILT_IN_ISNAND128: + return fold_builtin_classify (loc, fndecl, arg0, BUILT_IN_ISNAN); case BUILT_IN_FREE: if (integer_zerop (arg0)) @@ -8806,6 +9098,7 @@ fold_builtin_n (location_t loc, tree fndecl, tree *args, int nargs, bool) ret = fold_builtin_3 (loc, fndecl, args[0], args[1], args[2]); break; default: + ret = fold_builtin_varargs (loc, fndecl, args, nargs); break; } if (ret) @@ -9696,6 +9989,37 @@ fold_builtin_object_size (tree ptr, tree ost) return NULL_TREE; } +/* Builtins with folding operations that operate on "..." arguments + need special handling; we need to store the arguments in a convenient + data structure before attempting any folding. Fortunately there are + only a few builtins that fall into this category. FNDECL is the + function, EXP is the CALL_EXPR for the call. */ + +static tree +fold_builtin_varargs (location_t loc, tree fndecl, tree *args, int nargs) +{ + enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl); + tree ret = NULL_TREE; + + switch (fcode) + { + case BUILT_IN_FPCLASSIFY: + ret = fold_builtin_fpclassify (loc, args, nargs); + break; + + default: + break; + } + if (ret) + { + ret = build1 (NOP_EXPR, TREE_TYPE (ret), ret); + SET_EXPR_LOCATION (ret, loc); + TREE_NO_WARNING (ret) = 1; + return ret; + } + return NULL_TREE; +} + /* Initialize format string characters in the target charset. */ bool diff --git a/gcc/builtins.def b/gcc/builtins.def index db45c07..58d78db 100644 --- a/gcc/builtins.def +++ b/gcc/builtins.def @@ -845,8 +845,6 @@ DEF_EXT_LIB_BUILTIN (BUILT_IN_ISINFL, "isinfl", BT_FN_INT_LONGDOUBLE, ATTR_CO DEF_EXT_LIB_BUILTIN (BUILT_IN_ISINFD32, "isinfd32", BT_FN_INT_DFLOAT32, ATTR_CONST_NOTHROW_LEAF_LIST) DEF_EXT_LIB_BUILTIN (BUILT_IN_ISINFD64, "isinfd64", BT_FN_INT_DFLOAT64, ATTR_CONST_NOTHROW_LEAF_LIST) DEF_EXT_LIB_BUILTIN (BUILT_IN_ISINFD128, "isinfd128", BT_FN_INT_DFLOAT128, ATTR_CONST_NOTHROW_LEAF_LIST) -DEF_GCC_BUILTIN (BUILT_IN_ISZERO, "iszero", BT_FN_INT_VAR, ATTR_CONST_NOTHROW_TYPEGENERIC_LEAF) -DEF_GCC_BUILTIN (BUILT_IN_ISSUBNORMAL, "issubnormal", BT_FN_INT_VAR, ATTR_CONST_NOTHROW_TYPEGENERIC_LEAF) DEF_C99_C90RES_BUILTIN (BUILT_IN_ISNAN, "isnan", BT_FN_INT_VAR, ATTR_CONST_NOTHROW_TYPEGENERIC_LEAF) DEF_EXT_LIB_BUILTIN (BUILT_IN_ISNANF, "isnanf", BT_FN_INT_FLOAT, ATTR_CONST_NOTHROW_LEAF_LIST) DEF_EXT_LIB_BUILTIN (BUILT_IN_ISNANL, "isnanl", BT_FN_INT_LONGDOUBLE, ATTR_CONST_NOTHROW_LEAF_LIST) diff --git a/gcc/c/c-typeck.c b/gcc/c/c-typeck.c index 00e16e8..ba44406 100644 --- a/gcc/c/c-typeck.c +++ b/gcc/c/c-typeck.c @@ -3241,8 +3241,6 @@ convert_arguments (location_t loc, vec<location_t> arg_loc, tree typelist, case BUILT_IN_ISINF_SIGN: case BUILT_IN_ISNAN: case BUILT_IN_ISNORMAL: - case BUILT_IN_ISZERO: - case BUILT_IN_ISSUBNORMAL: case BUILT_IN_FPCLASSIFY: type_generic_remove_excess_precision = true; break; diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi index 7d39335..d467a16 100644 --- a/gcc/doc/extend.texi +++ b/gcc/doc/extend.texi @@ -10501,10 +10501,6 @@ in the Cilk Plus language manual which can be found at @findex __builtin_isgreater @findex __builtin_isgreaterequal @findex __builtin_isinf_sign -@findex __builtin_isinf -@findex __builtin_isnan -@findex __builtin_iszero -@findex __builtin_issubnormal @findex __builtin_isless @findex __builtin_islessequal @findex __builtin_islessgreater @@ -11568,54 +11564,7 @@ constant values and they must appear in this order: @code{FP_NAN}, @code{FP_INFINITE}, @code{FP_NORMAL}, @code{FP_SUBNORMAL} and @code{FP_ZERO}. The ellipsis is for exactly one floating-point value to classify. GCC treats the last argument as type-generic, which -means it does not do default promotion from @code{float} to @code{double}. -@end deftypefn - -@deftypefn {Built-in Function} int __builtin_isnan (...) -This built-in implements the C99 isnan functionality which checks if -the given argument represents a NaN. The return value of the -function will either be a 0 (false) or a 1 (true). -On most systems, when an IEEE 754 floating-point type is used this -built-in does not produce a signal when a signaling NaN is used. - -GCC treats the argument as type-generic, which means it does -not do default promotion from @code{float} to @code{double}. -@end deftypefn - -@deftypefn {Built-in Function} int __builtin_isinf (...) -This built-in implements the C99 isinf functionality which checks if -the given argument represents an infinite number. The return -value of the function will either be a 0 (false) or a 1 (true). - -GCC treats the argument as type-generic, which means it does -not do default promotion from @code{float} to @code{double}. -@end deftypefn - -@deftypefn {Built-in Function} int __builtin_isnormal (...) -This built-in implements the C99 isnormal functionality which checks if -the given argument represents a normal number. The return -value of the function will either be a 0 (false) or a 1 (true). - -GCC treats the argument as type-generic, which means it does -not do default promotion from @code{float} to @code{double}. -@end deftypefn - -@deftypefn {Built-in Function} int __builtin_iszero (...) -This built-in implements the TS 18661-1:2014 iszero functionality which checks if -the given argument represents the number 0 or -0. The return -value of the function will either be a 0 (false) or a 1 (true). - -GCC treats the argument as type-generic, which means it does -not do default promotion from @code{float} to @code{double}. -@end deftypefn - -@deftypefn {Built-in Function} int __builtin_issubnormal (...) -This built-in implements the TS 18661-1:2014 issubnormal functionality which checks if -the given argument represents a subnormal number. The return -value of the function will either be a 0 (false) or a 1 (true). - -GCC treats the argument as type-generic, which means it does -not do default promotion from @code{float} to @code{double}. +means it does not do default promotion from float to double. @end deftypefn @deftypefn {Built-in Function} double __builtin_inf (void) diff --git a/gcc/gimple-low.c b/gcc/gimple-low.c index 1cc4a4d..619b9d7 100644 --- a/gcc/gimple-low.c +++ b/gcc/gimple-low.c @@ -30,9 +30,6 @@ along with GCC; see the file COPYING3. If not see #include "calls.h" #include "gimple-iterator.h" #include "gimple-low.h" -#include "stor-layout.h" -#include "target.h" -#include "gimplify.h" /* The differences between High GIMPLE and Low GIMPLE are the following: @@ -75,13 +72,6 @@ static void lower_gimple_bind (gimple_stmt_iterator *, struct lower_data *); static void lower_try_catch (gimple_stmt_iterator *, struct lower_data *); static void lower_gimple_return (gimple_stmt_iterator *, struct lower_data *); static void lower_builtin_setjmp (gimple_stmt_iterator *); -static void lower_builtin_fpclassify (gimple_stmt_iterator *); -static void lower_builtin_isnan (gimple_stmt_iterator *); -static void lower_builtin_isinfinite (gimple_stmt_iterator *); -static void lower_builtin_isnormal (gimple_stmt_iterator *); -static void lower_builtin_iszero (gimple_stmt_iterator *); -static void lower_builtin_issubnormal (gimple_stmt_iterator *); -static void lower_builtin_isfinite (gimple_stmt_iterator *); static void lower_builtin_posix_memalign (gimple_stmt_iterator *); @@ -340,69 +330,18 @@ lower_stmt (gimple_stmt_iterator *gsi, struct lower_data *data) if (decl && DECL_BUILT_IN_CLASS (decl) == BUILT_IN_NORMAL) { - switch (DECL_FUNCTION_CODE (decl)) + if (DECL_FUNCTION_CODE (decl) == BUILT_IN_SETJMP) { - case BUILT_IN_SETJMP: lower_builtin_setjmp (gsi); data->cannot_fallthru = false; return; - - case BUILT_IN_POSIX_MEMALIGN: - if (flag_tree_bit_ccp - && gimple_builtin_call_types_compatible_p (stmt, decl)) - { - lower_builtin_posix_memalign (gsi); - return; - } - break; - - case BUILT_IN_FPCLASSIFY: - lower_builtin_fpclassify (gsi); - data->cannot_fallthru = false; - return; - - CASE_FLT_FN (BUILT_IN_ISINF): - case BUILT_IN_ISINFD32: - case BUILT_IN_ISINFD64: - case BUILT_IN_ISINFD128: - lower_builtin_isinfinite (gsi); - data->cannot_fallthru = false; - return; - - case BUILT_IN_ISNAND32: - case BUILT_IN_ISNAND64: - case BUILT_IN_ISNAND128: - CASE_FLT_FN (BUILT_IN_ISNAN): - lower_builtin_isnan (gsi); - data->cannot_fallthru = false; - return; - - case BUILT_IN_ISNORMAL: - lower_builtin_isnormal (gsi); - data->cannot_fallthru = false; - return; - - case BUILT_IN_ISZERO: - lower_builtin_iszero (gsi); - data->cannot_fallthru = false; - return; - - case BUILT_IN_ISSUBNORMAL: - lower_builtin_issubnormal (gsi); - data->cannot_fallthru = false; - return; - - CASE_FLT_FN (BUILT_IN_FINITE): - case BUILT_IN_FINITED32: - case BUILT_IN_FINITED64: - case BUILT_IN_FINITED128: - case BUILT_IN_ISFINITE: - lower_builtin_isfinite (gsi); - data->cannot_fallthru = false; + } + else if (DECL_FUNCTION_CODE (decl) == BUILT_IN_POSIX_MEMALIGN + && flag_tree_bit_ccp + && gimple_builtin_call_types_compatible_p (stmt, decl)) + { + lower_builtin_posix_memalign (gsi); return; - - default: - break; } } @@ -883,841 +822,6 @@ lower_builtin_setjmp (gimple_stmt_iterator *gsi) gsi_remove (gsi, false); } -/* This function will if ARG is not already a variable or SSA_NAME, - create a new temporary TMP and bind ARG to TMP. This new binding is then - emitted into SEQ and TMP is returned. */ -static tree -emit_tree_and_return_var (gimple_seq *seq, tree arg) -{ - if (TREE_CODE (arg) == SSA_NAME || VAR_P (arg)) - return arg; - - tree tmp = create_tmp_reg (TREE_TYPE (arg)); - gassign *stm = gimple_build_assign (tmp, arg); - gimple_seq_add_stmt (seq, stm); - return tmp; -} - -/* This function builds an if statement that ends up using explicit branches - instead of becoming a ternary conditional select. This function assumes you - will fall through to the next statements after the condition for the false - branch. The code emitted looks like: - - if (COND) - RESULT_VARIABLE = TRUE_BRANCH - GOTO EXIT_LABEL - else - ... - - SEQ is the gimple sequence/buffer to emit any new bindings to. - RESULT_VARIABLE is the value to set if COND. - EXIT_LABEL is the label to jump to in case COND. - COND is condition to use in the conditional statement of the if. - TRUE_BRANCH is the value to set RESULT_VARIABLE to if COND. */ -static void -emit_tree_cond (gimple_seq *seq, tree result_variable, tree exit_label, - tree cond, tree true_branch) -{ - /* Create labels for fall through. */ - tree true_label = create_artificial_label (UNKNOWN_LOCATION); - tree false_label = create_artificial_label (UNKNOWN_LOCATION); - gcond *stmt = gimple_build_cond_from_tree (cond, true_label, false_label); - gimple_seq_add_stmt (seq, stmt); - - /* Build the true case. */ - gimple_seq_add_stmt (seq, gimple_build_label (true_label)); - tree value = TREE_CONSTANT (true_branch) - ? true_branch - : emit_tree_and_return_var (seq, true_branch); - gimple_seq_add_stmt (seq, gimple_build_assign (result_variable, value)); - gimple_seq_add_stmt (seq, gimple_build_goto (exit_label)); - - /* Build the false case. */ - gimple_seq_add_stmt (seq, gimple_build_label (false_label)); -} - -/* This function returns a variable containing an reinterpreted ARG as an - integer. - - SEQ is the gimple sequence/buffer to write any new bindings to. - ARG is the floating point number to reinterpret as an integer. - LOC is the location to use when doing folding operations. */ -static tree -get_num_as_int (gimple_seq *seq, tree arg, location_t loc) -{ - tree type = TREE_TYPE (arg); - - const HOST_WIDE_INT type_width = TYPE_PRECISION (type); - - /* Re-interpret the float as an unsigned integer type - with equal precision. */ - tree int_arg_type = build_nonstandard_integer_type (type_width, true); - tree conv_arg = fold_build1_loc (loc, VIEW_CONVERT_EXPR, int_arg_type, arg); - return emit_tree_and_return_var (seq, conv_arg); -} - -/* Check if ARG which is the floating point number being classified is close - enough to IEEE 754 format to be able to go in the early exit code. */ -static bool -use_ieee_int_mode (tree arg) -{ - tree type = TREE_TYPE (arg); - machine_mode mode = TYPE_MODE (type); - - const real_format *format = REAL_MODE_FORMAT (mode); - machine_mode imode = int_mode_for_mode (mode); - bool is_ibm_extended = MODE_COMPOSITE_P (mode); - - return (format->is_binary_ieee_compatible - && FLOAT_WORDS_BIG_ENDIAN == WORDS_BIG_ENDIAN - /* Check if there's a usable integer mode. */ - && imode != BLKmode - && targetm.scalar_mode_supported_p (imode) - && !is_ibm_extended); -} - -/* Perform some IBM extended format fixups on ARG for use by FP functions. - This is done by ignoring the lower 64 bits of the number. - - MODE is the machine mode of ARG. - TYPE is the type of ARG. - LOC is the location to be used in fold functions. Usually is the location - of the definition of ARG. */ -static bool -perform_ibm_extended_fixups (tree *arg, machine_mode *mode, - tree *type, location_t loc) -{ - bool is_ibm_extended = MODE_COMPOSITE_P (*mode); - if (is_ibm_extended) - { - /* NaN and Inf are encoded in the high-order double value - only. The low-order value is not significant. */ - *type = double_type_node; - *mode = DFmode; - *arg = fold_build1_loc (loc, NOP_EXPR, *type, *arg); - } - - return is_ibm_extended; -} - -/* Generates code to check if ARG is a normal number. For the FP case we check - MIN_VALUE(ARG) <= ABS(ARG) > INF and for the INT value we check the exp and - mantissa bits. Returns a variable containing a boolean which has the result - of the check. - - SEQ is the buffer to use to emit the gimple instructions into. - LOC is the location to use during fold calls. */ -static tree -is_normal (gimple_seq *seq, tree arg, location_t loc) -{ - tree type = TREE_TYPE (arg); - - machine_mode mode = TYPE_MODE (type); - const real_format *format = REAL_MODE_FORMAT (mode); - const tree bool_type = boolean_type_node; - - - /* If not using optimized route then exit early. */ - if (!use_ieee_int_mode (arg)) - { - tree orig_arg = arg; - machine_mode orig_mode = mode; - if (TREE_CODE (arg) != SSA_NAME - && (TREE_ADDRESSABLE (arg) != 0 - || (TREE_CODE (arg) != PARM_DECL - && (!VAR_P (arg) || TREE_STATIC (arg))))) - orig_arg = save_expr (arg); - - /* Perform IBM extended format fixups if required. */ - bool is_ibm_extended = perform_ibm_extended_fixups (&arg, &mode, - &type, loc); - - REAL_VALUE_TYPE rinf, rmin; - tree arg_p = fold_build1_loc (loc, ABS_EXPR, type, arg); - - tree const islt_fn = builtin_decl_explicit (BUILT_IN_ISLESS); - tree const isgt_fn = builtin_decl_explicit (BUILT_IN_ISGREATER); - tree const isge_fn = builtin_decl_explicit (BUILT_IN_ISGREATEREQUAL); - - char buf[128]; - real_inf (&rinf); - get_min_float (REAL_MODE_FORMAT (orig_mode), buf, sizeof (buf)); - real_from_string (&rmin, buf); - - tree inf_exp = build_call_expr (islt_fn, 2, arg_p, - build_real (type, rinf)); - tree min_exp = build_real (type, rmin); - if (is_ibm_extended) - { - /* Testing the high end of the range is done just using - the high double, using the same test as isfinite(). - For the subnormal end of the range we first test the - high double, then if its magnitude is equal to the - limit of 0x1p-969, we test whether the low double is - non-zero and opposite sign to the high double. */ - tree gt_min = build_call_expr (isgt_fn, 2, arg_p, min_exp); - tree eq_min = fold_build2 (EQ_EXPR, integer_type_node, - arg_p, min_exp); - tree as_complex = build1 (VIEW_CONVERT_EXPR, - complex_double_type_node, orig_arg); - tree hi_dbl = build1 (REALPART_EXPR, type, as_complex); - tree lo_dbl = build1 (IMAGPART_EXPR, type, as_complex); - tree zero = build_real (type, dconst0); - tree hilt = build_call_expr (islt_fn, 2, hi_dbl, zero); - tree lolt = build_call_expr (islt_fn, 2, lo_dbl, zero); - tree logt = build_call_expr (isgt_fn, 2, lo_dbl, zero); - tree ok_lo = fold_build1 (TRUTH_NOT_EXPR, integer_type_node, - fold_build3 (COND_EXPR, - integer_type_node, - hilt, logt, lolt)); - eq_min = fold_build2 (TRUTH_ANDIF_EXPR, integer_type_node, - eq_min, ok_lo); - min_exp = fold_build2 (TRUTH_ORIF_EXPR, integer_type_node, - gt_min, eq_min); - } - else - { - min_exp = build_call_expr (isge_fn, 2, arg_p, min_exp); - } - - push_gimplify_context (); - gimplify_expr (&min_exp, seq, NULL, is_gimple_val, fb_either); - gimplify_expr (&inf_exp, seq, NULL, is_gimple_val, fb_either); - - tree res - = fold_build2_loc (loc, BIT_AND_EXPR, bool_type, - emit_tree_and_return_var (seq, - gimple_boolify (min_exp)), - emit_tree_and_return_var (seq, - gimple_boolify (inf_exp))); - pop_gimplify_context (NULL); - - return emit_tree_and_return_var (seq, res); - } - - const tree int_type = unsigned_type_node; - const int exp_bits = (GET_MODE_SIZE (mode) * BITS_PER_UNIT) - format->p; - const int exp_mask = (1 << exp_bits) - 1; - - /* Get the number reinterpreted as an integer. */ - tree int_arg = get_num_as_int (seq, arg, loc); - - /* Extract exp bits from the float, where we expect the exponent to be. - We create a new type because BIT_FIELD_REF does not allow you to - extract less bits than the precision of the storage variable. */ - tree exp_tmp - = fold_build3_loc (loc, BIT_FIELD_REF, - build_nonstandard_integer_type (exp_bits, true), - int_arg, - build_int_cstu (int_type, exp_bits), - build_int_cstu (int_type, format->p - 1)); - tree exp_bitfield = emit_tree_and_return_var (seq, exp_tmp); - - /* Re-interpret the extracted exponent bits as a 32 bit int. - This allows us to continue doing operations as int_type. */ - tree exp - = emit_tree_and_return_var (seq, fold_build1_loc (loc, NOP_EXPR, int_type, - exp_bitfield)); - - /* exp_mask & ~1. */ - tree mask_check - = fold_build2_loc (loc, BIT_AND_EXPR, int_type, - build_int_cstu (int_type, exp_mask), - fold_build1_loc (loc, BIT_NOT_EXPR, int_type, - build_int_cstu (int_type, 1))); - - /* (exp + 1) & mask_check. - Check to see if exp is not all 0 or all 1. */ - tree exp_check - = fold_build2_loc (loc, BIT_AND_EXPR, int_type, - emit_tree_and_return_var (seq, - fold_build2_loc (loc, PLUS_EXPR, int_type, exp, - build_int_cstu (int_type, 1))), - mask_check); - - tree res = fold_build2_loc (loc, NE_EXPR, boolean_type_node, - build_int_cstu (int_type, 0), - emit_tree_and_return_var (seq, exp_check)); - - return emit_tree_and_return_var (seq, res); -} - -/* Generates code to check if ARG is a zero. For both the FP and INT case we - check if ARG == 0 (modulo sign bit). Returns a variable containing a boolean - which has the result of the check. - - SEQ is the buffer to use to emit the gimple instructions into. - LOC is the location to use during fold calls. */ -static tree -is_zero (gimple_seq *seq, tree arg, location_t loc) -{ - tree type = TREE_TYPE (arg); - - /* If not using optimized route then exit early. */ - if (!use_ieee_int_mode (arg)) - { - machine_mode mode = TYPE_MODE (type); - /* Perform IBM extended format fixups if required. */ - perform_ibm_extended_fixups (&arg, &mode, &type, loc); - - tree res = fold_build2_loc (loc, EQ_EXPR, boolean_type_node, arg, - build_real (type, dconst0)); - return emit_tree_and_return_var (seq, res); - } - - const HOST_WIDE_INT type_width = TYPE_PRECISION (type); - - tree int_arg_type = build_nonstandard_integer_type (type_width, true); - - /* Get the number reinterpreted as an integer. - Shift left to remove the sign. */ - tree int_arg - = fold_build2_loc (loc, LSHIFT_EXPR, int_arg_type, - get_num_as_int (seq, arg, loc), - build_int_cstu (int_arg_type, 1)); - - /* num << 1 == 0. - This checks to see if the number is zero. */ - tree zero_check - = fold_build2_loc (loc, EQ_EXPR, boolean_type_node, - build_int_cstu (int_arg_type, 0), - emit_tree_and_return_var (seq, int_arg)); - - return emit_tree_and_return_var (seq, zero_check); -} - -/* Generates code to check if ARG is a subnormal number. In the FP case we test - fabs (ARG) != 0 && fabs (ARG) < MIN_VALUE (ARG) and in the INT case we check - the exp and mantissa bits on ARG. Returns a variable containing a boolean - which has the result of the check. - - SEQ is the buffer to use to emit the gimple instructions into. - LOC is the location to use during fold calls. */ -static tree -is_subnormal (gimple_seq *seq, tree arg, location_t loc) -{ - const tree bool_type = boolean_type_node; - - tree type = TREE_TYPE (arg); - - machine_mode mode = TYPE_MODE (type); - const real_format *format = REAL_MODE_FORMAT (mode); - const HOST_WIDE_INT type_width = TYPE_PRECISION (type); - - tree int_arg_type = build_nonstandard_integer_type (type_width, true); - - /* If not using optimized route then exit early. */ - if (!use_ieee_int_mode (arg)) - { - tree const islt_fn = builtin_decl_explicit (BUILT_IN_ISLESS); - tree const isgt_fn = builtin_decl_explicit (BUILT_IN_ISGREATER); - - tree arg_p - = emit_tree_and_return_var (seq, fold_build1_loc (loc, ABS_EXPR, type, - arg)); - REAL_VALUE_TYPE r; - char buf[128]; - get_min_float (REAL_MODE_FORMAT (mode), buf, sizeof (buf)); - real_from_string (&r, buf); - tree subnorm = build_call_expr (islt_fn, 2, arg_p, build_real (type, r)); - - tree zero = build_call_expr (isgt_fn, 2, arg_p, - build_real (type, dconst0)); - - push_gimplify_context (); - gimplify_expr (&subnorm, seq, NULL, is_gimple_val, fb_either); - gimplify_expr (&zero, seq, NULL, is_gimple_val, fb_either); - - tree res - = fold_build2_loc (loc, BIT_AND_EXPR, bool_type, - emit_tree_and_return_var (seq, - gimple_boolify (subnorm)), - emit_tree_and_return_var (seq, - gimple_boolify (zero))); - pop_gimplify_context (NULL); - - return emit_tree_and_return_var (seq, res); - } - - /* Get the number reinterpreted as an integer. - Shift left to remove the sign. */ - tree int_arg - = fold_build2_loc (loc, LSHIFT_EXPR, int_arg_type, - get_num_as_int (seq, arg, loc), - build_int_cstu (int_arg_type, 1)); - - /* Check for a zero exponent and non-zero mantissa. - This can be done with two comparisons by first apply a - removing the sign bit and checking if the value is larger - than the mantissa mask. */ - - /* This creates a mask to be used to check the mantissa value in the shifted - integer representation of the fpnum. */ - tree significant_bit = build_int_cstu (int_arg_type, format->p - 1); - tree mantissa_mask - = fold_build2_loc (loc, MINUS_EXPR, int_arg_type, - fold_build2_loc (loc, LSHIFT_EXPR, int_arg_type, - build_int_cstu (int_arg_type, 2), - significant_bit), - build_int_cstu (int_arg_type, 1)); - - /* Check if exponent is zero and mantissa is not. */ - tree subnorm_cond_tmp - = fold_build2_loc (loc, LE_EXPR, bool_type, - emit_tree_and_return_var (seq, int_arg), - mantissa_mask); - - tree subnorm_cond = emit_tree_and_return_var (seq, subnorm_cond_tmp); - - tree zero_cond - = fold_build2_loc (loc, GT_EXPR, boolean_type_node, - emit_tree_and_return_var (seq, int_arg), - build_int_cstu (int_arg_type, 0)); - - tree subnorm_check - = fold_build2_loc (loc, BIT_AND_EXPR, boolean_type_node, - emit_tree_and_return_var (seq, subnorm_cond), - emit_tree_and_return_var (seq, zero_cond)); - - return emit_tree_and_return_var (seq, subnorm_check); -} - -/* Generates code to check if ARG is an infinity. In the FP case we test - FABS(ARG) == INF and in the INT case we check the bits on the exp and - mantissa. Returns a variable containing a boolean which has the result - of the check. - - SEQ is the buffer to use to emit the gimple instructions into. - LOC is the location to use during fold calls. */ -static tree -is_infinity (gimple_seq *seq, tree arg, location_t loc) -{ - tree type = TREE_TYPE (arg); - - machine_mode mode = TYPE_MODE (type); - const tree bool_type = boolean_type_node; - - if (!HONOR_INFINITIES (mode)) - { - return build_int_cst (bool_type, false); - } - - /* If not using optimized route then exit early. */ - if (!use_ieee_int_mode (arg)) - { - /* Perform IBM extended format fixups if required. */ - perform_ibm_extended_fixups (&arg, &mode, &type, loc); - - tree arg_p - = emit_tree_and_return_var (seq, fold_build1_loc (loc, ABS_EXPR, type, - arg)); - REAL_VALUE_TYPE r; - real_inf (&r); - tree res = fold_build2_loc (loc, EQ_EXPR, bool_type, arg_p, - build_real (type, r)); - - return emit_tree_and_return_var (seq, res); - } - - const real_format *format = REAL_MODE_FORMAT (mode); - const HOST_WIDE_INT type_width = TYPE_PRECISION (type); - - tree int_arg_type = build_nonstandard_integer_type (type_width, true); - - /* This creates a mask to be used to check the exp value in the shifted - integer representation of the fpnum. */ - const int exp_bits = (GET_MODE_SIZE (mode) * BITS_PER_UNIT) - format->p; - gcc_assert (format->p > 0); - - tree significant_bit = build_int_cstu (int_arg_type, format->p); - tree exp_mask - = fold_build2_loc (loc, MINUS_EXPR, int_arg_type, - fold_build2_loc (loc, LSHIFT_EXPR, int_arg_type, - build_int_cstu (int_arg_type, 2), - build_int_cstu (int_arg_type, - exp_bits - 1)), - build_int_cstu (int_arg_type, 1)); - - /* Get the number reinterpreted as an integer. - Shift left to remove the sign. */ - tree int_arg - = fold_build2_loc (loc, LSHIFT_EXPR, int_arg_type, - get_num_as_int (seq, arg, loc), - build_int_cstu (int_arg_type, 1)); - - /* This mask checks to see if the exp has all bits set and mantissa no - bits set. */ - tree inf_mask - = fold_build2_loc (loc, LSHIFT_EXPR, int_arg_type, - exp_mask, significant_bit); - - /* Check if exponent has all bits set and mantissa is 0. */ - tree inf_check - = emit_tree_and_return_var(seq, - fold_build2_loc (loc, EQ_EXPR, bool_type, - emit_tree_and_return_var(seq, int_arg), - inf_mask)); - - return emit_tree_and_return_var (seq, inf_check); -} - -/* Generates code to check if ARG is a finite number. In the FP case we check - if FABS(ARG) <= MAX_VALUE(ARG) and in the INT case we check the exp and - mantissa bits. Returns a variable containing a boolean which has the result - of the check. - - SEQ is the buffer to use to emit the gimple instructions into. - LOC is the location to use during fold calls. */ -static tree -is_finite (gimple_seq *seq, tree arg, location_t loc) -{ - tree type = TREE_TYPE (arg); - - machine_mode mode = TYPE_MODE (type); - const tree bool_type = boolean_type_node; - - if (!HONOR_NANS (arg) && !HONOR_INFINITIES (arg)) - { - return build_int_cst (bool_type, true); - } - - /* If not using optimized route then exit early. */ - if (!use_ieee_int_mode (arg)) - { - - /* Perform IBM extended format fixups if required. */ - perform_ibm_extended_fixups (&arg, &mode, &type, loc); - - tree const isle_fn = builtin_decl_explicit (BUILT_IN_ISLESSEQUAL); - - tree arg_p - = emit_tree_and_return_var (seq, fold_build1_loc (loc, ABS_EXPR, type, - arg)); - REAL_VALUE_TYPE rmax; - char buf[128]; - get_max_float (REAL_MODE_FORMAT (mode), buf, sizeof (buf)); - real_from_string (&rmax, buf); - - tree res = build_call_expr (isle_fn, 2, arg_p, build_real (type, rmax)); - - push_gimplify_context (); - gimplify_expr (&res, seq, NULL, is_gimple_val, fb_either); - pop_gimplify_context (NULL); - - return emit_tree_and_return_var (seq, gimple_boolify(res)); - } - - const real_format *format = REAL_MODE_FORMAT (mode); - const HOST_WIDE_INT type_width = TYPE_PRECISION (type); - - tree int_arg_type = build_nonstandard_integer_type (type_width, true); - - /* This creates a mask to be used to check the exp value in the shifted - integer representation of the fpnum. */ - const int exp_bits = (GET_MODE_SIZE (mode) * BITS_PER_UNIT) - format->p; - gcc_assert (format->p > 0); - - tree significant_bit = build_int_cstu (int_arg_type, format->p); - tree exp_mask - = fold_build2_loc (loc, MINUS_EXPR, int_arg_type, - fold_build2_loc (loc, LSHIFT_EXPR, int_arg_type, - build_int_cstu (int_arg_type, 2), - build_int_cstu (int_arg_type, - exp_bits - 1)), - build_int_cstu (int_arg_type, 1)); - - /* Get the number reinterpreted as an integer. - Shift left to remove the sign. */ - tree int_arg - = fold_build2_loc (loc, LSHIFT_EXPR, int_arg_type, - get_num_as_int (seq, arg, loc), - build_int_cstu (int_arg_type, 1)); - - /* This mask checks to see if the exp has all bits set and mantissa no - bits set. */ - tree inf_mask - = fold_build2_loc (loc, LSHIFT_EXPR, int_arg_type, - exp_mask, significant_bit); - - /* Check if exponent has all bits set and mantissa is 0. */ - tree inf_check_tmp - = fold_build2_loc (loc, LT_EXPR, bool_type, - emit_tree_and_return_var (seq, int_arg), - inf_mask); - - tree inf_check = emit_tree_and_return_var (seq, inf_check_tmp); - - return emit_tree_and_return_var (seq, inf_check); -} - -/* Generates code to check if ARG is a NaN. In the FP case we simply check if - ARG != ARG and in the INT case we check the bits in the exp and mantissa. - Returns a variable containing a boolean which has the result of the check. - - SEQ is the buffer to use to emit the gimple instructions into. - LOC is the location to use during fold calls. */ -static tree -is_nan (gimple_seq *seq, tree arg, location_t loc) -{ - tree type = TREE_TYPE (arg); - - machine_mode mode = TYPE_MODE (type); - const tree bool_type = boolean_type_node; - - if (!HONOR_NANS (mode)) - { - return build_int_cst (bool_type, false); - } - - const real_format *format = REAL_MODE_FORMAT (mode); - - /* If not using optimized route then exit early. */ - if (!use_ieee_int_mode (arg)) - { - /* Perform IBM extended format fixups if required. */ - perform_ibm_extended_fixups (&arg, &mode, &type, loc); - - tree arg_p - = emit_tree_and_return_var (seq, fold_build1_loc (loc, ABS_EXPR, type, - arg)); - tree res - = fold_build2_loc (loc, UNORDERED_EXPR, bool_type,arg_p, arg_p); - - return emit_tree_and_return_var (seq, res); - } - - const HOST_WIDE_INT type_width = TYPE_PRECISION (type); - tree int_arg_type = build_nonstandard_integer_type (type_width, true); - - /* This creates a mask to be used to check the exp value in the shifted - integer representation of the fpnum. */ - const int exp_bits = (GET_MODE_SIZE (mode) * BITS_PER_UNIT) - format->p; - tree significant_bit = build_int_cstu (int_arg_type, format->p); - tree exp_mask - = fold_build2_loc (loc, MINUS_EXPR, int_arg_type, - fold_build2_loc (loc, LSHIFT_EXPR, int_arg_type, - build_int_cstu (int_arg_type, 2), - build_int_cstu (int_arg_type, - exp_bits - 1)), - build_int_cstu (int_arg_type, 1)); - - /* Get the number reinterpreted as an integer. - Shift left to remove the sign. */ - tree int_arg - = fold_build2_loc (loc, LSHIFT_EXPR, int_arg_type, - get_num_as_int (seq, arg, loc), - build_int_cstu (int_arg_type, 1)); - - /* This mask checks to see if the exp has all bits set and mantissa no - bits set. */ - tree inf_mask - = fold_build2_loc (loc, LSHIFT_EXPR, int_arg_type, - exp_mask, significant_bit); - - /* Check if exponent has all bits set and mantissa is not 0. */ - tree nan_check - = emit_tree_and_return_var(seq, - fold_build2_loc (loc, GT_EXPR, bool_type, - emit_tree_and_return_var(seq, int_arg), - inf_mask)); - - return emit_tree_and_return_var (seq, nan_check); -} - -/* Validates a single argument from the arguments list CALL at position INDEX. - The extracted parameter is compared against the expected type CODE. - - A boolean is returned indicating if the parameter exist and if of the - expected type. */ -static bool -gimple_validate_arg (gimple* call, int index, enum tree_code code) -{ - const tree arg = gimple_call_arg (call, index); - if (!arg) - return false; - else if (code == POINTER_TYPE) - return POINTER_TYPE_P (TREE_TYPE (arg)); - else if (code == INTEGER_TYPE) - return INTEGRAL_TYPE_P (TREE_TYPE (arg)); - return code == TREE_CODE (TREE_TYPE (arg)); -} - -/* Lowers calls to __builtin_fpclassify to - fpclassify (x) -> - isnormal(x) ? FP_NORMAL : - iszero (x) ? FP_ZERO : - isnan (x) ? FP_NAN : - isinfinite (x) ? FP_INFINITE : - FP_SUBNORMAL. - - The code may use integer arithmentic if it decides - that the produced assembly would be faster. This can only be done - for numbers that are similar to IEEE-754 in format. - - This builtin will generate code to return the appropriate floating - point classification depending on the value of the floating point - number passed in. The possible return values must be supplied as - int arguments to the call in the following order: FP_NAN, FP_INFINITE, - FP_NORMAL, FP_SUBNORMAL and FP_ZERO. The ellipses is for exactly - one floating point argument which is "type generic". - - GSI is the gimple iterator containing the fpclassify call to lower. - The call will be expanded and replaced inline in the given GSI. */ -static void -lower_builtin_fpclassify (gimple_stmt_iterator *gsi) -{ - gimple *call = gsi_stmt (*gsi); - location_t loc = gimple_location (call); - - /* Verify the required arguments in the original call. */ - if (gimple_call_num_args (call) != 6 - || !gimple_validate_arg (call, 0, INTEGER_TYPE) - || !gimple_validate_arg (call, 1, INTEGER_TYPE) - || !gimple_validate_arg (call, 2, INTEGER_TYPE) - || !gimple_validate_arg (call, 3, INTEGER_TYPE) - || !gimple_validate_arg (call, 4, INTEGER_TYPE) - || !gimple_validate_arg (call, 5, REAL_TYPE)) - return; - - /* Collect the arguments from the call. */ - tree fp_nan = gimple_call_arg (call, 0); - tree fp_infinite = gimple_call_arg (call, 1); - tree fp_normal = gimple_call_arg (call, 2); - tree fp_subnormal = gimple_call_arg (call, 3); - tree fp_zero = gimple_call_arg (call, 4); - tree arg = gimple_call_arg (call, 5); - - gimple_seq body = NULL; - - /* Create label to jump to to exit. */ - tree done_label = create_artificial_label (UNKNOWN_LOCATION); - tree dest; - tree orig_dest = dest = gimple_call_lhs (call); - if (orig_dest && TREE_CODE (orig_dest) == SSA_NAME) - dest = create_tmp_reg (TREE_TYPE (orig_dest)); - - emit_tree_cond (&body, dest, done_label, - is_normal (&body, arg, loc), fp_normal); - emit_tree_cond (&body, dest, done_label, - is_zero (&body, arg, loc), fp_zero); - emit_tree_cond (&body, dest, done_label, - is_nan (&body, arg, loc), fp_nan); - emit_tree_cond (&body, dest, done_label, - is_infinity (&body, arg, loc), fp_infinite); - - /* And finally, emit the default case if nothing else matches. - This replaces the call to is_subnormal. */ - gimple_seq_add_stmt (&body, gimple_build_assign (dest, fp_subnormal)); - gimple_seq_add_stmt (&body, gimple_build_label (done_label)); - - /* Build orig_dest = dest if necessary. */ - if (dest != orig_dest) - { - gimple_seq_add_stmt (&body, gimple_build_assign (orig_dest, dest)); - } - - gsi_insert_seq_before (gsi, body, GSI_SAME_STMT); - - - /* Remove the call to __builtin_fpclassify. */ - gsi_remove (gsi, false); -} - -/* Generic wrapper for the is_nan, is_normal, is_subnormal, is_zero, etc. - All these functions have the same setup. The wrapper validates the parameter - and also creates the branches and labels required to properly invoke. - This has been generalize and the function to call is passed as argument FNDECL. - - GSI is the gimple iterator containing the fpclassify call to lower. - The call will be expanded and replaced inline in the given GSI. */ -static void -gen_call_fp_builtin (gimple_stmt_iterator *gsi, - tree (*fndecl)(gimple_seq *, tree, location_t)) -{ - gimple *call = gsi_stmt (*gsi); - location_t loc = gimple_location (call); - - /* Verify the required arguments in the original call. */ - if (gimple_call_num_args (call) != 1 - || !gimple_validate_arg (call, 0, REAL_TYPE)) - return; - - tree arg = gimple_call_arg (call, 0); - gimple_seq body = NULL; - - /* Create label to jump to to exit. */ - tree done_label = create_artificial_label (UNKNOWN_LOCATION); - tree dest; - tree orig_dest = dest = gimple_call_lhs (call); - tree type = TREE_TYPE (orig_dest); - if (orig_dest && TREE_CODE (orig_dest) == SSA_NAME) - dest = create_tmp_reg (type); - - tree t_true = build_int_cst (type, true); - tree t_false = build_int_cst (type, false); - - emit_tree_cond (&body, dest, done_label, - fndecl (&body, arg, loc), t_true); - - /* And finally, emit the default case if nothing else matches. - This replaces the call to false. */ - gimple_seq_add_stmt (&body, gimple_build_assign (dest, t_false)); - gimple_seq_add_stmt (&body, gimple_build_label (done_label)); - - /* Build orig_dest = dest if necessary. */ - if (dest != orig_dest) - { - gimple_seq_add_stmt (&body, gimple_build_assign (orig_dest, dest)); - } - - gsi_insert_seq_before (gsi, body, GSI_SAME_STMT); - - /* Remove the call to the builtin. */ - gsi_remove (gsi, false); -} - -/* Lower and expand calls to __builtin_isnan in GSI. */ -static void -lower_builtin_isnan (gimple_stmt_iterator *gsi) -{ - gen_call_fp_builtin (gsi, &is_nan); -} - -/* Lower and expand calls to __builtin_isinfinite in GSI. */ -static void -lower_builtin_isinfinite (gimple_stmt_iterator *gsi) -{ - gen_call_fp_builtin (gsi, &is_infinity); -} - -/* Lower and expand calls to __builtin_isnormal in GSI. */ -static void -lower_builtin_isnormal (gimple_stmt_iterator *gsi) -{ - gen_call_fp_builtin (gsi, &is_normal); -} - -/* Lower and expand calls to __builtin_iszero in GSI. */ -static void -lower_builtin_iszero (gimple_stmt_iterator *gsi) -{ - gen_call_fp_builtin (gsi, &is_zero); -} - -/* Lower and expand calls to __builtin_issubnormal in GSI. */ -static void -lower_builtin_issubnormal (gimple_stmt_iterator *gsi) -{ - gen_call_fp_builtin (gsi, &is_subnormal); -} - -/* Lower and expand calls to __builtin_isfinite in GSI. */ -static void -lower_builtin_isfinite (gimple_stmt_iterator *gsi) -{ - gen_call_fp_builtin (gsi, &is_finite); -} - /* Lower calls to posix_memalign to res = posix_memalign (ptr, align, size); if (res == 0) @@ -3052,7 +3052,6 @@ const struct real_format ieee_single_format = true, true, false, - true, "ieee_single" }; @@ -3076,7 +3075,6 @@ const struct real_format mips_single_format = true, false, true, - true, "mips_single" }; @@ -3100,7 +3098,6 @@ const struct real_format motorola_single_format = true, true, true, - true, "motorola_single" }; @@ -3135,7 +3132,6 @@ const struct real_format spu_single_format = true, false, false, - false, "spu_single" }; @@ -3347,7 +3343,6 @@ const struct real_format ieee_double_format = true, true, false, - true, "ieee_double" }; @@ -3371,7 +3366,6 @@ const struct real_format mips_double_format = true, false, true, - true, "mips_double" }; @@ -3395,7 +3389,6 @@ const struct real_format motorola_double_format = true, true, true, - true, "motorola_double" }; @@ -3742,7 +3735,6 @@ const struct real_format ieee_extended_motorola_format = true, true, true, - false, "ieee_extended_motorola" }; @@ -3766,7 +3758,6 @@ const struct real_format ieee_extended_intel_96_format = true, true, false, - false, "ieee_extended_intel_96" }; @@ -3790,7 +3781,6 @@ const struct real_format ieee_extended_intel_128_format = true, true, false, - false, "ieee_extended_intel_128" }; @@ -3816,7 +3806,6 @@ const struct real_format ieee_extended_intel_96_round_53_format = true, true, false, - false, "ieee_extended_intel_96_round_53" }; @@ -3907,7 +3896,6 @@ const struct real_format ibm_extended_format = true, true, false, - false, "ibm_extended" }; @@ -3931,7 +3919,6 @@ const struct real_format mips_extended_format = true, false, true, - false, "mips_extended" }; @@ -4197,7 +4184,6 @@ const struct real_format ieee_quad_format = true, true, false, - true, "ieee_quad" }; @@ -4221,7 +4207,6 @@ const struct real_format mips_quad_format = true, false, true, - true, "mips_quad" }; @@ -4524,7 +4509,6 @@ const struct real_format vax_f_format = false, false, false, - false, "vax_f" }; @@ -4548,7 +4532,6 @@ const struct real_format vax_d_format = false, false, false, - false, "vax_d" }; @@ -4572,7 +4555,6 @@ const struct real_format vax_g_format = false, false, false, - false, "vax_g" }; @@ -4651,7 +4633,6 @@ const struct real_format decimal_single_format = true, true, false, - false, "decimal_single" }; @@ -4676,7 +4657,6 @@ const struct real_format decimal_double_format = true, true, false, - false, "decimal_double" }; @@ -4701,7 +4681,6 @@ const struct real_format decimal_quad_format = true, true, false, - false, "decimal_quad" }; @@ -4841,7 +4820,6 @@ const struct real_format ieee_half_format = true, true, false, - true, "ieee_half" }; @@ -4868,7 +4846,6 @@ const struct real_format arm_half_format = true, false, false, - false, "arm_half" }; @@ -4916,7 +4893,6 @@ const struct real_format real_internal_format = true, true, false, - false, "real_internal" }; @@ -5104,16 +5080,6 @@ get_max_float (const struct real_format *fmt, char *buf, size_t len) gcc_assert (strlen (buf) < len); } -/* Write into BUF the minimum negative representable finite floating-point - number, x, such that b**(x-1) is normalized. - BUF must be large enough to contain the result. */ -void -get_min_float (const struct real_format *fmt, char *buf, size_t len) -{ - sprintf (buf, "0x1p%d", fmt->emin - 1); - gcc_assert (strlen (buf) < len); -} - /* True if mode M has a NaN representation and the treatment of NaN operands is important. */ @@ -161,19 +161,6 @@ struct real_format bool has_signed_zero; bool qnan_msb_set; bool canonical_nan_lsbs_set; - - /* This flag indicates whether the format is suitable for the optimized - code paths for the __builtin_fpclassify function and friends. For - this, the format must be a base 2 representation with the sign bit as - the most-significant bit followed by (exp <= 32) exponent bits - followed by the mantissa bits. It must be possible to interpret the - bits of the floating-point representation as an integer. NaNs and - INFs (if available) must be represented by the same schema used by - IEEE 754. (NaNs must be represented by an exponent with all bits 1, - any mantissa except all bits 0 and any sign bit. +INF and -INF must be - represented by an exponent with all bits 1, a mantissa with all bits 0 and - a sign bit of 0 and 1 respectively.) */ - bool is_binary_ieee_compatible; const char *name; }; @@ -524,11 +511,6 @@ extern bool real_isinteger (const REAL_VALUE_TYPE *, HOST_WIDE_INT *); float string. BUF must be large enough to contain the result. */ extern void get_max_float (const struct real_format *, char *, size_t); -/* Write into BUF the smallest positive normalized number x, - such that b**(x-1) is normalized. BUF must be large enough - to contain the result. */ -extern void get_min_float (const struct real_format *, char *, size_t); - #ifndef GENERATOR_FILE /* real related routines. */ extern wide_int real_to_integer (const REAL_VALUE_TYPE *, bool *, int); diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 459d80b..4c577de 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -112,23 +112,6 @@ PR target/73350,80862 * gcc.target/i386/pr73350.c: New test. -2017-06-08 Tamar Christina <tamar.christina@arm.com> - - * gcc.target/aarch64/builtin-fpclassify.c: New codegen test. - * gcc.dg/fold-notunord.c: Removed. - * gcc.dg/torture/floatn-tg-4.h: Add tests for iszero and issubnormal. - * gcc.dg/torture/float128-tg-4.c: Likewise. - * gcc.dg/torture/float128x-tg-4: Likewise. - * gcc.dg/torture/float16-tg-4.c: Likewise. - * gcc.dg/torture/float32-tg-4.c: Likewise. - * gcc.dg/torture/float32x-tg-4.c: Likewise. - * gcc.dg/torture/float64-tg-4.c: Likewise. - * gcc.dg/torture/float64x-tg-4.c: Likewise. - * gcc.dg/pr28796-1.c: Add -O2. - * gcc.dg/builtins-43.c: Check lower instead of gimple. - * gcc.dg/tg-tests.h: Add iszero and issubnormal. - * gcc.dg/pr77925.c: Add to test safe cases. - 2017-06-08 Richard Biener <rguenther@suse.de> PR tree-optimization/80928 diff --git a/gcc/testsuite/gcc.dg/builtins-43.c b/gcc/testsuite/gcc.dg/builtins-43.c index 5d41c28..f7c318e 100644 --- a/gcc/testsuite/gcc.dg/builtins-43.c +++ b/gcc/testsuite/gcc.dg/builtins-43.c @@ -1,5 +1,5 @@ /* { dg-do compile } */ -/* { dg-options "-O1 -fno-trapping-math -fno-finite-math-only -fdump-tree-lower -fdump-tree-optimized" } */ +/* { dg-options "-O1 -fno-trapping-math -fno-finite-math-only -fdump-tree-gimple -fdump-tree-optimized" } */ extern void f(int); extern void link_error (); @@ -51,7 +51,7 @@ main () /* Check that all instances of __builtin_isnan were folded. */ -/* { dg-final { scan-tree-dump-times "isnan" 0 "lower" } } */ +/* { dg-final { scan-tree-dump-times "isnan" 0 "gimple" } } */ /* Check that all instances of link_error were subject to DCE. */ /* { dg-final { scan-tree-dump-times "link_error" 0 "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/fold-notunord.c b/gcc/testsuite/gcc.dg/fold-notunord.c new file mode 100644 index 0000000..ca34515 --- /dev/null +++ b/gcc/testsuite/gcc.dg/fold-notunord.c @@ -0,0 +1,9 @@ +/* { dg-do compile } */ +/* { dg-options "-O -ftrapping-math -fdump-tree-optimized" } */ + +int f (double d) +{ + return !__builtin_isnan (d); +} + +/* { dg-final { scan-tree-dump " ord " "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/pr28796-1.c b/gcc/testsuite/gcc.dg/pr28796-1.c index a57b4e3..077118a 100644 --- a/gcc/testsuite/gcc.dg/pr28796-1.c +++ b/gcc/testsuite/gcc.dg/pr28796-1.c @@ -1,5 +1,5 @@ /* { dg-do link } */ -/* { dg-options "-ffinite-math-only -O2" } */ +/* { dg-options "-ffinite-math-only" } */ extern void link_error(void); diff --git a/gcc/testsuite/gcc.dg/pr77925.c b/gcc/testsuite/gcc.dg/pr77925.c deleted file mode 100644 index f92518b..0000000 --- a/gcc/testsuite/gcc.dg/pr77925.c +++ /dev/null @@ -1,11 +0,0 @@ -/* { dg-do run } */ -/* { dg-options "-O2" } */ -/* { dg-add-options ieee } */ -/* { dg-skip-if "No Inf/NaN support" { spu-*-* } } */ - -#include "tg-tests.h" - -int main(void) -{ - return main_tests (); -} diff --git a/gcc/testsuite/gcc.dg/tg-tests.h b/gcc/testsuite/gcc.dg/tg-tests.h index 134bc82..0cf1f64 100644 --- a/gcc/testsuite/gcc.dg/tg-tests.h +++ b/gcc/testsuite/gcc.dg/tg-tests.h @@ -11,7 +11,6 @@ void __attribute__ ((__noinline__)) foo_1 (float f, double d, long double ld, int res_unord, int res_isnan, int res_isinf, int res_isinf_sign, int res_isfin, int res_isnorm, - int res_iszero, int res_issubnorm, int res_signbit, int classification) { if (__builtin_isunordered (f, 0) != res_unord) @@ -81,29 +80,6 @@ foo_1 (float f, double d, long double ld, if (__builtin_finitel (ld) != res_isfin) __builtin_abort (); -/* On CPUs which flush denormals to zero these tests can never work one - denormals for the floating point version of the implementation. The integer - versions would work fine but we can't detect which version we have here. */ -#ifdef UNSAFE -if (!res_issubnorm) { -#endif - if (__builtin_iszero (f) != res_iszero) - __builtin_abort (); - if (__builtin_iszero (d) != res_iszero) - __builtin_abort (); - if (__builtin_iszero (ld) != res_iszero) - __builtin_abort (); - - if (__builtin_issubnormal (f) != res_issubnorm) - __builtin_abort (); - if (__builtin_issubnormal (d) != res_issubnorm) - __builtin_abort (); - if (__builtin_issubnormal (ld) != res_issubnorm) - __builtin_abort (); -#ifdef UNSAFE -} -#endif - /* Sign bit of zeros and nans is not preserved in unsafe math mode. */ #ifdef UNSAFE if (!res_isnan && f != 0 && d != 0 && ld != 0) @@ -139,13 +115,12 @@ if (!res_issubnorm) { void __attribute__ ((__noinline__)) foo (float f, double d, long double ld, int res_unord, int res_isnan, int res_isinf, - int res_isfin, int res_isnorm, int res_iszero, - int res_issubnorm, int classification) + int res_isfin, int res_isnorm, int classification) { - foo_1 (f, d, ld, res_unord, res_isnan, res_isinf, res_isinf, res_isfin, res_isnorm, res_iszero, res_issubnorm, 0, classification); + foo_1 (f, d, ld, res_unord, res_isnan, res_isinf, res_isinf, res_isfin, res_isnorm, 0, classification); /* Try all the values negated as well. All will have the sign bit set, except for the nan. */ - foo_1 (-f, -d, -ld, res_unord, res_isnan, res_isinf, -res_isinf, res_isfin, res_isnorm, res_iszero, res_issubnorm, 1, classification); + foo_1 (-f, -d, -ld, res_unord, res_isnan, res_isinf, -res_isinf, res_isfin, res_isnorm, 1, classification); } int __attribute__ ((__noinline__)) @@ -157,35 +132,35 @@ main_tests (void) /* Test NaN. */ f = __builtin_nanf(""); d = __builtin_nan(""); ld = __builtin_nanl(""); - foo(f, d, ld, /*unord=*/ 1, /*isnan=*/ 1, /*isinf=*/ 0, /*isfin=*/ 0, /*isnorm=*/ 0, /*iszero=*/0, /*issubnorm=*/0, FP_NAN); + foo(f, d, ld, /*unord=*/ 1, /*isnan=*/ 1, /*isinf=*/ 0, /*isfin=*/ 0, /*isnorm=*/ 0, FP_NAN); /* Test infinity. */ f = __builtin_inff(); d = __builtin_inf(); ld = __builtin_infl(); - foo(f, d, ld, /*unord=*/ 0, /*isnan=*/ 0, /*isinf=*/ 1, /*isfin=*/ 0, /*isnorm=*/ 0, /*iszero=*/0, /*issubnorm=*/0, FP_INFINITE); + foo(f, d, ld, /*unord=*/ 0, /*isnan=*/ 0, /*isinf=*/ 1, /*isfin=*/ 0, /*isnorm=*/ 0, FP_INFINITE); /* Test zero. */ f = 0; d = 0; ld = 0; - foo(f, d, ld, /*unord=*/ 0, /*isnan=*/ 0, /*isinf=*/ 0, /*isfin=*/ 1, /*isnorm=*/ 0, /*iszero=*/1, /*issubnorm=*/0, FP_ZERO); + foo(f, d, ld, /*unord=*/ 0, /*isnan=*/ 0, /*isinf=*/ 0, /*isfin=*/ 1, /*isnorm=*/ 0, FP_ZERO); /* Test one. */ f = 1; d = 1; ld = 1; - foo(f, d, ld, /*unord=*/ 0, /*isnan=*/ 0, /*isinf=*/ 0, /*isfin=*/ 1, /*isnorm=*/ 1, /*iszero=*/0, /*issubnorm=*/0, FP_NORMAL); + foo(f, d, ld, /*unord=*/ 0, /*isnan=*/ 0, /*isinf=*/ 0, /*isfin=*/ 1, /*isnorm=*/ 1, FP_NORMAL); /* Test minimum values. */ f = __FLT_MIN__; d = __DBL_MIN__; ld = __LDBL_MIN__; - foo(f, d, ld, /*unord=*/ 0, /*isnan=*/ 0, /*isinf=*/ 0, /*isfin=*/ 1, /*isnorm=*/ 1, /*iszero=*/0, /*issubnorm=*/0, FP_NORMAL); + foo(f, d, ld, /*unord=*/ 0, /*isnan=*/ 0, /*isinf=*/ 0, /*isfin=*/ 1, /*isnorm=*/ 1, FP_NORMAL); /* Test subnormal values. */ f = __FLT_MIN__/2; d = __DBL_MIN__/2; ld = __LDBL_MIN__/2; - foo(f, d, ld, /*unord=*/ 0, /*isnan=*/ 0, /*isinf=*/ 0, /*isfin=*/ 1, /*isnorm=*/ 0, /*iszero=*/0, /*issubnorm=*/1, FP_SUBNORMAL); + foo(f, d, ld, /*unord=*/ 0, /*isnan=*/ 0, /*isinf=*/ 0, /*isfin=*/ 1, /*isnorm=*/ 0, FP_SUBNORMAL); /* Test maximum values. */ f = __FLT_MAX__; d = __DBL_MAX__; ld = __LDBL_MAX__; - foo(f, d, ld, /*unord=*/ 0, /*isnan=*/ 0, /*isinf=*/ 0, /*isfin=*/ 1, /*isnorm=*/ 1, /*iszero=*/0, /*issubnorm=*/0, FP_NORMAL); + foo(f, d, ld, /*unord=*/ 0, /*isnan=*/ 0, /*isinf=*/ 0, /*isfin=*/ 1, /*isnorm=*/ 1, FP_NORMAL); /* Test overflow values. */ f = __FLT_MAX__*2; d = __DBL_MAX__*2; ld = __LDBL_MAX__*2; - foo(f, d, ld, /*unord=*/ 0, /*isnan=*/ 0, /*isinf=*/ 1, /*isfin=*/ 0, /*isnorm=*/ 0, /*iszero=*/0, /*issubnorm=*/0, FP_INFINITE); + foo(f, d, ld, /*unord=*/ 0, /*isnan=*/ 0, /*isinf=*/ 1, /*isfin=*/ 0, /*isnorm=*/ 0, FP_INFINITE); return 0; } diff --git a/gcc/testsuite/gcc.dg/torture/float128-tg-4.c b/gcc/testsuite/gcc.dg/torture/float128-tg-4.c deleted file mode 100644 index ec9d3ad..0000000 --- a/gcc/testsuite/gcc.dg/torture/float128-tg-4.c +++ /dev/null @@ -1,11 +0,0 @@ -/* Test _Float128 type-generic built-in functions: __builtin_iszero, - __builtin_issubnormal. */ -/* { dg-do run } */ -/* { dg-options "" } */ -/* { dg-add-options float128 } */ -/* { dg-add-options ieee } */ -/* { dg-require-effective-target float128_runtime } */ - -#define WIDTH 128 -#define EXT 0 -#include "floatn-tg-4.h" diff --git a/gcc/testsuite/gcc.dg/torture/float128x-tg-4.c b/gcc/testsuite/gcc.dg/torture/float128x-tg-4.c deleted file mode 100644 index 0ede861..0000000 --- a/gcc/testsuite/gcc.dg/torture/float128x-tg-4.c +++ /dev/null @@ -1,11 +0,0 @@ -/* Test _Float128x type-generic built-in functions: __builtin_iszero, - __builtin_issubnormal. */ -/* { dg-do run } */ -/* { dg-options "" } */ -/* { dg-add-options float128x } */ -/* { dg-add-options ieee } */ -/* { dg-require-effective-target float128x_runtime } */ - -#define WIDTH 128 -#define EXT 1 -#include "floatn-tg-4.h" diff --git a/gcc/testsuite/gcc.dg/torture/float16-tg-4.c b/gcc/testsuite/gcc.dg/torture/float16-tg-4.c deleted file mode 100644 index 007c4c2..0000000 --- a/gcc/testsuite/gcc.dg/torture/float16-tg-4.c +++ /dev/null @@ -1,11 +0,0 @@ -/* Test _Float16 type-generic built-in functions: __builtin_iszero, - __builtin_issubnormal. */ -/* { dg-do run } */ -/* { dg-options "" } */ -/* { dg-add-options float16 } */ -/* { dg-add-options ieee } */ -/* { dg-require-effective-target float16_runtime } */ - -#define WIDTH 16 -#define EXT 0 -#include "floatn-tg-4.h" diff --git a/gcc/testsuite/gcc.dg/torture/float32-tg-4.c b/gcc/testsuite/gcc.dg/torture/float32-tg-4.c deleted file mode 100644 index c7f8353..0000000 --- a/gcc/testsuite/gcc.dg/torture/float32-tg-4.c +++ /dev/null @@ -1,11 +0,0 @@ -/* Test _Float32 type-generic built-in functions: __builtin_f__builtin_iszero, - __builtin_issubnormal. */ -/* { dg-do run } */ -/* { dg-options "" } */ -/* { dg-add-options float32 } */ -/* { dg-add-options ieee } */ -/* { dg-require-effective-target float32_runtime } */ - -#define WIDTH 32 -#define EXT 0 -#include "floatn-tg-4.h" diff --git a/gcc/testsuite/gcc.dg/torture/float32x-tg-4.c b/gcc/testsuite/gcc.dg/torture/float32x-tg-4.c deleted file mode 100644 index 0d7a592..0000000 --- a/gcc/testsuite/gcc.dg/torture/float32x-tg-4.c +++ /dev/null @@ -1,11 +0,0 @@ -/* Test _Float32x type-generic built-in functions: __builtin_iszero, - __builtin_issubnormal. */ -/* { dg-do run } */ -/* { dg-options "" } */ -/* { dg-add-options float32x } */ -/* { dg-add-options ieee } */ -/* { dg-require-effective-target float32x_runtime } */ - -#define WIDTH 32 -#define EXT 1 -#include "floatn-tg-4.h" diff --git a/gcc/testsuite/gcc.dg/torture/float64-tg-4.c b/gcc/testsuite/gcc.dg/torture/float64-tg-4.c deleted file mode 100644 index bb25a22..0000000 --- a/gcc/testsuite/gcc.dg/torture/float64-tg-4.c +++ /dev/null @@ -1,11 +0,0 @@ -/* Test _Float64 type-generic built-in functions: __builtin_iszero, - __builtin_issubnormal */ -/* { dg-do run } */ -/* { dg-options "" } */ -/* { dg-add-options float64 } */ -/* { dg-add-options ieee } */ -/* { dg-require-effective-target float64_runtime } */ - -#define WIDTH 64 -#define EXT 0 -#include "floatn-tg-4.h" diff --git a/gcc/testsuite/gcc.dg/torture/float64x-tg-4.c b/gcc/testsuite/gcc.dg/torture/float64x-tg-4.c deleted file mode 100644 index 82305d9..0000000 --- a/gcc/testsuite/gcc.dg/torture/float64x-tg-4.c +++ /dev/null @@ -1,11 +0,0 @@ -/* Test _Float64x type-generic built-in functions: __builtin_iszero, - __builtin_issubnormal. */ -/* { dg-do run } */ -/* { dg-options "" } */ -/* { dg-add-options float64x } */ -/* { dg-add-options ieee } */ -/* { dg-require-effective-target float64x_runtime } */ - -#define WIDTH 64 -#define EXT 1 -#include "floatn-tg-4.h" diff --git a/gcc/testsuite/gcc.dg/torture/floatn-tg-4.h b/gcc/testsuite/gcc.dg/torture/floatn-tg-4.h deleted file mode 100644 index aa3448c..0000000 --- a/gcc/testsuite/gcc.dg/torture/floatn-tg-4.h +++ /dev/null @@ -1,99 +0,0 @@ -/* Tests for _FloatN / _FloatNx types: compile and execution tests for - type-generic built-in functions: __builtin_iszero, __builtin_issubnormal. - Before including this file, define WIDTH as the value N; define EXT to 1 - for _FloatNx and 0 for _FloatN. */ - -#define __STDC_WANT_IEC_60559_TYPES_EXT__ -#include <float.h> - -#define CONCATX(X, Y) X ## Y -#define CONCAT(X, Y) CONCATX (X, Y) -#define CONCAT3(X, Y, Z) CONCAT (CONCAT (X, Y), Z) -#define CONCAT4(W, X, Y, Z) CONCAT (CONCAT (CONCAT (W, X), Y), Z) - -#if EXT -# define TYPE CONCAT3 (_Float, WIDTH, x) -# define CST(C) CONCAT4 (C, f, WIDTH, x) -# define MAX CONCAT3 (FLT, WIDTH, X_MAX) -# define MIN CONCAT3 (FLT, WIDTH, X_MIN) -# define TRUE_MIN CONCAT3 (FLT, WIDTH, X_TRUE_MIN) -#else -# define TYPE CONCAT (_Float, WIDTH) -# define CST(C) CONCAT3 (C, f, WIDTH) -# define MAX CONCAT3 (FLT, WIDTH, _MAX) -# define MIN CONCAT3 (FLT, WIDTH, _MIN) -# define TRUE_MIN CONCAT3 (FLT, WIDTH, _TRUE_MIN) -#endif - -extern void exit (int); -extern void abort (void); - -volatile TYPE inf = __builtin_inf (), nanval = __builtin_nan (""); -volatile TYPE neginf = -__builtin_inf (), negnanval = -__builtin_nan (""); -volatile TYPE zero = CST (0.0), negzero = -CST (0.0), one = CST (1.0); -volatile TYPE max = MAX, negmax = -MAX, min = MIN, negmin = -MIN; -volatile TYPE true_min = TRUE_MIN, negtrue_min = -TRUE_MIN; -volatile TYPE sub_norm = MIN / 2.0; - -int -main (void) -{ - if (__builtin_iszero (inf) == 1) - abort (); - if (__builtin_iszero (nanval) == 1) - abort (); - if (__builtin_iszero (neginf) == 1) - abort (); - if (__builtin_iszero (negnanval) == 1) - abort (); - if (__builtin_iszero (zero) != 1) - abort (); - if (__builtin_iszero (negzero) != 1) - abort (); - if (__builtin_iszero (one) == 1) - abort (); - if (__builtin_iszero (max) == 1) - abort (); - if (__builtin_iszero (negmax) == 1) - abort (); - if (__builtin_iszero (min) == 1) - abort (); - if (__builtin_iszero (negmin) == 1) - abort (); - if (__builtin_iszero (true_min) == 1) - abort (); - if (__builtin_iszero (negtrue_min) == 1) - abort (); - if (__builtin_iszero (sub_norm) == 1) - abort (); - - if (__builtin_issubnormal (inf) == 1) - abort (); - if (__builtin_issubnormal (nanval) == 1) - abort (); - if (__builtin_issubnormal (neginf) == 1) - abort (); - if (__builtin_issubnormal (negnanval) == 1) - abort (); - if (__builtin_issubnormal (zero) == 1) - abort (); - if (__builtin_issubnormal (negzero) == 1) - abort (); - if (__builtin_issubnormal (one) == 1) - abort (); - if (__builtin_issubnormal (max) == 1) - abort (); - if (__builtin_issubnormal (negmax) == 1) - abort (); - if (__builtin_issubnormal (min) == 1) - abort (); - if (__builtin_issubnormal (negmin) == 1) - abort (); - if (__builtin_issubnormal (true_min) != 1) - abort (); - if (__builtin_issubnormal (negtrue_min) != 1) - abort (); - if (__builtin_issubnormal (sub_norm) != 1) - abort (); - exit (0); -} diff --git a/gcc/testsuite/gcc.target/aarch64/builtin-fpclassify.c b/gcc/testsuite/gcc.target/aarch64/builtin-fpclassify.c deleted file mode 100644 index 3a1bf956..0000000 --- a/gcc/testsuite/gcc.target/aarch64/builtin-fpclassify.c +++ /dev/null @@ -1,22 +0,0 @@ -/* This file checks the code generation for the new __builtin_fpclassify. - because checking the exact assembly isn't very useful, we'll just be checking - for the presence of certain instructions and the omition of others. */ -/* { dg-options "-O2" } */ -/* { dg-do compile } */ -/* { dg-final { scan-assembler-not "\[ \t\]?fabs\[ \t\]?" } } */ -/* { dg-final { scan-assembler-not "\[ \t\]?fcmp\[ \t\]?" } } */ -/* { dg-final { scan-assembler-not "\[ \t\]?fcmpe\[ \t\]?" } } */ -/* { dg-final { scan-assembler "\[ \t\]?ubfx\[ \t\]?" } } */ - -#include <stdio.h> -#include <math.h> - -/* - fp_nan = args[0]; - fp_infinite = args[1]; - fp_normal = args[2]; - fp_subnormal = args[3]; - fp_zero = args[4]; -*/ - -int f(double x) { return __builtin_fpclassify(0, 1, 4, 3, 2, x); } |