Mercurial > hg > CbC > CbC_gcc
comparison gcc/fold-const-call.c @ 145:1830386684a0
gcc-9.2.0
author | anatofuz |
---|---|
date | Thu, 13 Feb 2020 11:34:05 +0900 |
parents | 84e7813d76e9 |
children |
comparison
equal
deleted
inserted
replaced
131:84e7813d76e9 | 145:1830386684a0 |
---|---|
1 /* Constant folding for calls to built-in and internal functions. | 1 /* Constant folding for calls to built-in and internal functions. |
2 Copyright (C) 1988-2018 Free Software Foundation, Inc. | 2 Copyright (C) 1988-2020 Free Software Foundation, Inc. |
3 | 3 |
4 This file is part of GCC. | 4 This file is part of GCC. |
5 | 5 |
6 GCC is free software; you can redistribute it and/or modify it under | 6 GCC is free software; you can redistribute it and/or modify it under |
7 the terms of the GNU General Public License as published by the Free | 7 the terms of the GNU General Public License as published by the Free |
28 #include "fold-const-call.h" | 28 #include "fold-const-call.h" |
29 #include "case-cfn-macros.h" | 29 #include "case-cfn-macros.h" |
30 #include "tm.h" /* For C[LT]Z_DEFINED_AT_ZERO. */ | 30 #include "tm.h" /* For C[LT]Z_DEFINED_AT_ZERO. */ |
31 #include "builtins.h" | 31 #include "builtins.h" |
32 #include "gimple-expr.h" | 32 #include "gimple-expr.h" |
33 #include "tree-vector-builder.h" | |
33 | 34 |
34 /* Functions that test for certain constant types, abstracting away the | 35 /* Functions that test for certain constant types, abstracting away the |
35 decision about whether to check for overflow. */ | 36 decision about whether to check for overflow. */ |
36 | 37 |
37 static inline bool | 38 static inline bool |
96 || mpfr_underflow_p () | 97 || mpfr_underflow_p () |
97 || (flag_rounding_math && inexact)) | 98 || (flag_rounding_math && inexact)) |
98 return false; | 99 return false; |
99 | 100 |
100 REAL_VALUE_TYPE tmp; | 101 REAL_VALUE_TYPE tmp; |
101 real_from_mpfr (&tmp, m, format, GMP_RNDN); | 102 real_from_mpfr (&tmp, m, format, MPFR_RNDN); |
102 | 103 |
103 /* Proceed iff GCC's REAL_VALUE_TYPE can hold the MPFR values. | 104 /* Proceed iff GCC's REAL_VALUE_TYPE can hold the MPFR values. |
104 If the REAL_VALUE_TYPE is zero but the mpft_t is not, then we | 105 If the REAL_VALUE_TYPE is zero but the mpft_t is not, then we |
105 underflowed in the conversion. */ | 106 underflowed in the conversion. */ |
106 if (!real_isfinite (&tmp) | 107 if (!real_isfinite (&tmp) |
127 format, which only happens when the target base equals two. */ | 128 format, which only happens when the target base equals two. */ |
128 if (format->b != 2 || !real_isfinite (arg)) | 129 if (format->b != 2 || !real_isfinite (arg)) |
129 return false; | 130 return false; |
130 | 131 |
131 int prec = format->p; | 132 int prec = format->p; |
132 mp_rnd_t rnd = format->round_towards_zero ? GMP_RNDZ : GMP_RNDN; | 133 mpfr_rnd_t rnd = format->round_towards_zero ? MPFR_RNDZ : MPFR_RNDN; |
133 mpfr_t m; | 134 mpfr_t m; |
134 | 135 |
135 mpfr_init2 (m, prec); | 136 mpfr_init2 (m, prec); |
136 mpfr_from_real (m, arg, GMP_RNDN); | 137 mpfr_from_real (m, arg, MPFR_RNDN); |
137 mpfr_clear_flags (); | 138 mpfr_clear_flags (); |
138 bool inexact = func (m, m, rnd); | 139 bool inexact = func (m, m, rnd); |
139 bool ok = do_mpfr_ckconv (result, m, inexact, format); | 140 bool ok = do_mpfr_ckconv (result, m, inexact, format); |
140 mpfr_clear (m); | 141 mpfr_clear (m); |
141 | 142 |
157 format, which only happens when the target base equals two. */ | 158 format, which only happens when the target base equals two. */ |
158 if (format->b != 2 || !real_isfinite (arg)) | 159 if (format->b != 2 || !real_isfinite (arg)) |
159 return false; | 160 return false; |
160 | 161 |
161 int prec = format->p; | 162 int prec = format->p; |
162 mp_rnd_t rnd = format->round_towards_zero ? GMP_RNDZ : GMP_RNDN; | 163 mpfr_rnd_t rnd = format->round_towards_zero ? MPFR_RNDZ : MPFR_RNDN; |
163 mpfr_t m, ms, mc; | 164 mpfr_t m, ms, mc; |
164 | 165 |
165 mpfr_inits2 (prec, m, ms, mc, NULL); | 166 mpfr_inits2 (prec, m, ms, mc, NULL); |
166 mpfr_from_real (m, arg, GMP_RNDN); | 167 mpfr_from_real (m, arg, MPFR_RNDN); |
167 mpfr_clear_flags (); | 168 mpfr_clear_flags (); |
168 bool inexact = mpfr_sin_cos (ms, mc, m, rnd); | 169 bool inexact = mpfr_sin_cos (ms, mc, m, rnd); |
169 bool ok = (do_mpfr_ckconv (result_sin, ms, inexact, format) | 170 bool ok = (do_mpfr_ckconv (result_sin, ms, inexact, format) |
170 && do_mpfr_ckconv (result_cos, mc, inexact, format)); | 171 && do_mpfr_ckconv (result_cos, mc, inexact, format)); |
171 mpfr_clears (m, ms, mc, NULL); | 172 mpfr_clears (m, ms, mc, NULL); |
190 format, which only happens when the target base equals two. */ | 191 format, which only happens when the target base equals two. */ |
191 if (format->b != 2 || !real_isfinite (arg0) || !real_isfinite (arg1)) | 192 if (format->b != 2 || !real_isfinite (arg0) || !real_isfinite (arg1)) |
192 return false; | 193 return false; |
193 | 194 |
194 int prec = format->p; | 195 int prec = format->p; |
195 mp_rnd_t rnd = format->round_towards_zero ? GMP_RNDZ : GMP_RNDN; | 196 mpfr_rnd_t rnd = format->round_towards_zero ? MPFR_RNDZ : MPFR_RNDN; |
196 mpfr_t m0, m1; | 197 mpfr_t m0, m1; |
197 | 198 |
198 mpfr_inits2 (prec, m0, m1, NULL); | 199 mpfr_inits2 (prec, m0, m1, NULL); |
199 mpfr_from_real (m0, arg0, GMP_RNDN); | 200 mpfr_from_real (m0, arg0, MPFR_RNDN); |
200 mpfr_from_real (m1, arg1, GMP_RNDN); | 201 mpfr_from_real (m1, arg1, MPFR_RNDN); |
201 mpfr_clear_flags (); | 202 mpfr_clear_flags (); |
202 bool inexact = func (m0, m0, m1, rnd); | 203 bool inexact = func (m0, m0, m1, rnd); |
203 bool ok = do_mpfr_ckconv (result, m0, inexact, format); | 204 bool ok = do_mpfr_ckconv (result, m0, inexact, format); |
204 mpfr_clears (m0, m1, NULL); | 205 mpfr_clears (m0, m1, NULL); |
205 | 206 |
213 in format FORMAT, given that FUNC is the MPFR implementation of f. | 214 in format FORMAT, given that FUNC is the MPFR implementation of f. |
214 Return true on success. */ | 215 Return true on success. */ |
215 | 216 |
216 static bool | 217 static bool |
217 do_mpfr_arg2 (real_value *result, | 218 do_mpfr_arg2 (real_value *result, |
218 int (*func) (mpfr_ptr, long, mpfr_srcptr, mp_rnd_t), | 219 int (*func) (mpfr_ptr, long, mpfr_srcptr, mpfr_rnd_t), |
219 const wide_int_ref &arg0, const real_value *arg1, | 220 const wide_int_ref &arg0, const real_value *arg1, |
220 const real_format *format) | 221 const real_format *format) |
221 { | 222 { |
222 if (format->b != 2 || !real_isfinite (arg1)) | 223 if (format->b != 2 || !real_isfinite (arg1)) |
223 return false; | 224 return false; |
224 | 225 |
225 int prec = format->p; | 226 int prec = format->p; |
226 mp_rnd_t rnd = format->round_towards_zero ? GMP_RNDZ : GMP_RNDN; | 227 mpfr_rnd_t rnd = format->round_towards_zero ? MPFR_RNDZ : MPFR_RNDN; |
227 mpfr_t m; | 228 mpfr_t m; |
228 | 229 |
229 mpfr_init2 (m, prec); | 230 mpfr_init2 (m, prec); |
230 mpfr_from_real (m, arg1, GMP_RNDN); | 231 mpfr_from_real (m, arg1, MPFR_RNDN); |
231 mpfr_clear_flags (); | 232 mpfr_clear_flags (); |
232 bool inexact = func (m, arg0.to_shwi (), m, rnd); | 233 bool inexact = func (m, arg0.to_shwi (), m, rnd); |
233 bool ok = do_mpfr_ckconv (result, m, inexact, format); | 234 bool ok = do_mpfr_ckconv (result, m, inexact, format); |
234 mpfr_clear (m); | 235 mpfr_clear (m); |
235 | 236 |
257 || !real_isfinite (arg1) | 258 || !real_isfinite (arg1) |
258 || !real_isfinite (arg2)) | 259 || !real_isfinite (arg2)) |
259 return false; | 260 return false; |
260 | 261 |
261 int prec = format->p; | 262 int prec = format->p; |
262 mp_rnd_t rnd = format->round_towards_zero ? GMP_RNDZ : GMP_RNDN; | 263 mpfr_rnd_t rnd = format->round_towards_zero ? MPFR_RNDZ : MPFR_RNDN; |
263 mpfr_t m0, m1, m2; | 264 mpfr_t m0, m1, m2; |
264 | 265 |
265 mpfr_inits2 (prec, m0, m1, m2, NULL); | 266 mpfr_inits2 (prec, m0, m1, m2, NULL); |
266 mpfr_from_real (m0, arg0, GMP_RNDN); | 267 mpfr_from_real (m0, arg0, MPFR_RNDN); |
267 mpfr_from_real (m1, arg1, GMP_RNDN); | 268 mpfr_from_real (m1, arg1, MPFR_RNDN); |
268 mpfr_from_real (m2, arg2, GMP_RNDN); | 269 mpfr_from_real (m2, arg2, MPFR_RNDN); |
269 mpfr_clear_flags (); | 270 mpfr_clear_flags (); |
270 bool inexact = func (m0, m0, m1, m2, rnd); | 271 bool inexact = func (m0, m0, m1, m2, rnd); |
271 bool ok = do_mpfr_ckconv (result, m0, inexact, format); | 272 bool ok = do_mpfr_ckconv (result, m0, inexact, format); |
272 mpfr_clears (m0, m1, m2, NULL); | 273 mpfr_clears (m0, m1, m2, NULL); |
273 | 274 |
293 || mpfr_underflow_p () | 294 || mpfr_underflow_p () |
294 || (flag_rounding_math && inexact)) | 295 || (flag_rounding_math && inexact)) |
295 return false; | 296 return false; |
296 | 297 |
297 REAL_VALUE_TYPE tmp_real, tmp_imag; | 298 REAL_VALUE_TYPE tmp_real, tmp_imag; |
298 real_from_mpfr (&tmp_real, mpc_realref (m), format, GMP_RNDN); | 299 real_from_mpfr (&tmp_real, mpc_realref (m), format, MPFR_RNDN); |
299 real_from_mpfr (&tmp_imag, mpc_imagref (m), format, GMP_RNDN); | 300 real_from_mpfr (&tmp_imag, mpc_imagref (m), format, MPFR_RNDN); |
300 | 301 |
301 /* Proceed iff GCC's REAL_VALUE_TYPE can hold the MPFR values. | 302 /* Proceed iff GCC's REAL_VALUE_TYPE can hold the MPFR values. |
302 If the REAL_VALUE_TYPE is zero but the mpft_t is not, then we | 303 If the REAL_VALUE_TYPE is zero but the mpft_t is not, then we |
303 underflowed in the conversion. */ | 304 underflowed in the conversion. */ |
304 if (!real_isfinite (&tmp_real) | 305 if (!real_isfinite (&tmp_real) |
338 int prec = format->p; | 339 int prec = format->p; |
339 mpc_rnd_t crnd = format->round_towards_zero ? MPC_RNDZZ : MPC_RNDNN; | 340 mpc_rnd_t crnd = format->round_towards_zero ? MPC_RNDZZ : MPC_RNDNN; |
340 mpc_t m; | 341 mpc_t m; |
341 | 342 |
342 mpc_init2 (m, prec); | 343 mpc_init2 (m, prec); |
343 mpfr_from_real (mpc_realref (m), arg_real, GMP_RNDN); | 344 mpfr_from_real (mpc_realref (m), arg_real, MPFR_RNDN); |
344 mpfr_from_real (mpc_imagref (m), arg_imag, GMP_RNDN); | 345 mpfr_from_real (mpc_imagref (m), arg_imag, MPFR_RNDN); |
345 mpfr_clear_flags (); | 346 mpfr_clear_flags (); |
346 bool inexact = func (m, m, crnd); | 347 bool inexact = func (m, m, crnd); |
347 bool ok = do_mpc_ckconv (result_real, result_imag, m, inexact, format); | 348 bool ok = do_mpc_ckconv (result_real, result_imag, m, inexact, format); |
348 mpc_clear (m); | 349 mpc_clear (m); |
349 | 350 |
375 mpc_rnd_t crnd = format->round_towards_zero ? MPC_RNDZZ : MPC_RNDNN; | 376 mpc_rnd_t crnd = format->round_towards_zero ? MPC_RNDZZ : MPC_RNDNN; |
376 mpc_t m0, m1; | 377 mpc_t m0, m1; |
377 | 378 |
378 mpc_init2 (m0, prec); | 379 mpc_init2 (m0, prec); |
379 mpc_init2 (m1, prec); | 380 mpc_init2 (m1, prec); |
380 mpfr_from_real (mpc_realref (m0), arg0_real, GMP_RNDN); | 381 mpfr_from_real (mpc_realref (m0), arg0_real, MPFR_RNDN); |
381 mpfr_from_real (mpc_imagref (m0), arg0_imag, GMP_RNDN); | 382 mpfr_from_real (mpc_imagref (m0), arg0_imag, MPFR_RNDN); |
382 mpfr_from_real (mpc_realref (m1), arg1_real, GMP_RNDN); | 383 mpfr_from_real (mpc_realref (m1), arg1_real, MPFR_RNDN); |
383 mpfr_from_real (mpc_imagref (m1), arg1_imag, GMP_RNDN); | 384 mpfr_from_real (mpc_imagref (m1), arg1_imag, MPFR_RNDN); |
384 mpfr_clear_flags (); | 385 mpfr_clear_flags (); |
385 bool inexact = func (m0, m0, m1, crnd); | 386 bool inexact = func (m0, m0, m1, crnd); |
386 bool ok = do_mpc_ckconv (result_real, result_imag, m0, inexact, format); | 387 bool ok = do_mpc_ckconv (result_real, result_imag, m0, inexact, format); |
387 mpc_clear (m0); | 388 mpc_clear (m0); |
388 mpc_clear (m1); | 389 mpc_clear (m1); |
643 return NULL_TREE; | 644 return NULL_TREE; |
644 } | 645 } |
645 return res; | 646 return res; |
646 } | 647 } |
647 | 648 |
649 /* Fold a call to IFN_VEC_CONVERT (ARG) returning TYPE. */ | |
650 | |
651 static tree | |
652 fold_const_vec_convert (tree ret_type, tree arg) | |
653 { | |
654 enum tree_code code = NOP_EXPR; | |
655 tree arg_type = TREE_TYPE (arg); | |
656 if (TREE_CODE (arg) != VECTOR_CST) | |
657 return NULL_TREE; | |
658 | |
659 gcc_checking_assert (VECTOR_TYPE_P (ret_type) && VECTOR_TYPE_P (arg_type)); | |
660 | |
661 if (INTEGRAL_TYPE_P (TREE_TYPE (ret_type)) | |
662 && SCALAR_FLOAT_TYPE_P (TREE_TYPE (arg_type))) | |
663 code = FIX_TRUNC_EXPR; | |
664 else if (INTEGRAL_TYPE_P (TREE_TYPE (arg_type)) | |
665 && SCALAR_FLOAT_TYPE_P (TREE_TYPE (ret_type))) | |
666 code = FLOAT_EXPR; | |
667 | |
668 /* We can't handle steps directly when extending, since the | |
669 values need to wrap at the original precision first. */ | |
670 bool step_ok_p | |
671 = (INTEGRAL_TYPE_P (TREE_TYPE (ret_type)) | |
672 && INTEGRAL_TYPE_P (TREE_TYPE (arg_type)) | |
673 && (TYPE_PRECISION (TREE_TYPE (ret_type)) | |
674 <= TYPE_PRECISION (TREE_TYPE (arg_type)))); | |
675 tree_vector_builder elts; | |
676 if (!elts.new_unary_operation (ret_type, arg, step_ok_p)) | |
677 return NULL_TREE; | |
678 | |
679 unsigned int count = elts.encoded_nelts (); | |
680 for (unsigned int i = 0; i < count; ++i) | |
681 { | |
682 tree elt = fold_unary (code, TREE_TYPE (ret_type), | |
683 VECTOR_CST_ELT (arg, i)); | |
684 if (elt == NULL_TREE || !CONSTANT_CLASS_P (elt)) | |
685 return NULL_TREE; | |
686 elts.quick_push (elt); | |
687 } | |
688 | |
689 return elts.build (); | |
690 } | |
691 | |
692 /* Try to evaluate: | |
693 | |
694 IFN_WHILE_ULT (ARG0, ARG1, (TYPE) { ... }) | |
695 | |
696 Return the value on success and null on failure. */ | |
697 | |
698 static tree | |
699 fold_while_ult (tree type, poly_uint64 arg0, poly_uint64 arg1) | |
700 { | |
701 if (known_ge (arg0, arg1)) | |
702 return build_zero_cst (type); | |
703 | |
704 if (maybe_ge (arg0, arg1)) | |
705 return NULL_TREE; | |
706 | |
707 poly_uint64 diff = arg1 - arg0; | |
708 poly_uint64 nelts = TYPE_VECTOR_SUBPARTS (type); | |
709 if (known_ge (diff, nelts)) | |
710 return build_all_ones_cst (type); | |
711 | |
712 unsigned HOST_WIDE_INT const_diff; | |
713 if (known_le (diff, nelts) && diff.is_constant (&const_diff)) | |
714 { | |
715 tree minus_one = build_minus_one_cst (TREE_TYPE (type)); | |
716 tree zero = build_zero_cst (TREE_TYPE (type)); | |
717 return build_vector_a_then_b (type, const_diff, minus_one, zero); | |
718 } | |
719 return NULL_TREE; | |
720 } | |
721 | |
648 /* Try to evaluate: | 722 /* Try to evaluate: |
649 | 723 |
650 *RESULT = FN (*ARG) | 724 *RESULT = FN (*ARG) |
651 | 725 |
652 in format FORMAT. Return true on success. */ | 726 in format FORMAT. Return true on success. */ |
760 return (real_compare (GT_EXPR, arg, &dconst0) | 834 return (real_compare (GT_EXPR, arg, &dconst0) |
761 && do_mpfr_arg1 (result, mpfr_y1, arg, format)); | 835 && do_mpfr_arg1 (result, mpfr_y1, arg, format)); |
762 | 836 |
763 CASE_CFN_FLOOR: | 837 CASE_CFN_FLOOR: |
764 CASE_CFN_FLOOR_FN: | 838 CASE_CFN_FLOOR_FN: |
765 if (!REAL_VALUE_ISNAN (*arg) || !flag_errno_math) | 839 if (!REAL_VALUE_ISSIGNALING_NAN (*arg)) |
766 { | 840 { |
767 real_floor (result, format, arg); | 841 real_floor (result, format, arg); |
768 return true; | 842 return true; |
769 } | 843 } |
770 return false; | 844 return false; |
771 | 845 |
772 CASE_CFN_CEIL: | 846 CASE_CFN_CEIL: |
773 CASE_CFN_CEIL_FN: | 847 CASE_CFN_CEIL_FN: |
774 if (!REAL_VALUE_ISNAN (*arg) || !flag_errno_math) | 848 if (!REAL_VALUE_ISSIGNALING_NAN (*arg)) |
775 { | 849 { |
776 real_ceil (result, format, arg); | 850 real_ceil (result, format, arg); |
777 return true; | 851 return true; |
778 } | 852 } |
779 return false; | 853 return false; |
780 | 854 |
781 CASE_CFN_TRUNC: | 855 CASE_CFN_TRUNC: |
782 CASE_CFN_TRUNC_FN: | 856 CASE_CFN_TRUNC_FN: |
783 real_trunc (result, format, arg); | 857 if (!REAL_VALUE_ISSIGNALING_NAN (*arg)) |
784 return true; | 858 { |
859 real_trunc (result, format, arg); | |
860 return true; | |
861 } | |
862 return false; | |
785 | 863 |
786 CASE_CFN_ROUND: | 864 CASE_CFN_ROUND: |
787 CASE_CFN_ROUND_FN: | 865 CASE_CFN_ROUND_FN: |
788 if (!REAL_VALUE_ISNAN (*arg) || !flag_errno_math) | 866 if (!REAL_VALUE_ISSIGNALING_NAN (*arg)) |
789 { | 867 { |
790 real_round (result, format, arg); | 868 real_round (result, format, arg); |
869 return true; | |
870 } | |
871 return false; | |
872 | |
873 CASE_CFN_ROUNDEVEN: | |
874 CASE_CFN_ROUNDEVEN_FN: | |
875 if (!REAL_VALUE_ISSIGNALING_NAN (*arg)) | |
876 { | |
877 real_roundeven (result, format, arg); | |
791 return true; | 878 return true; |
792 } | 879 } |
793 return false; | 880 return false; |
794 | 881 |
795 CASE_CFN_LOGB: | 882 CASE_CFN_LOGB: |
1229 case CFN_REDUC_IOR: | 1316 case CFN_REDUC_IOR: |
1230 return fold_const_reduction (type, arg, BIT_IOR_EXPR); | 1317 return fold_const_reduction (type, arg, BIT_IOR_EXPR); |
1231 | 1318 |
1232 case CFN_REDUC_XOR: | 1319 case CFN_REDUC_XOR: |
1233 return fold_const_reduction (type, arg, BIT_XOR_EXPR); | 1320 return fold_const_reduction (type, arg, BIT_XOR_EXPR); |
1321 | |
1322 case CFN_VEC_CONVERT: | |
1323 return fold_const_vec_convert (type, arg); | |
1234 | 1324 |
1235 default: | 1325 default: |
1236 return fold_const_call_1 (fn, type, arg); | 1326 return fold_const_call_1 (fn, type, arg); |
1237 } | 1327 } |
1238 } | 1328 } |
1733 return fold_convert (type, | 1823 return fold_convert (type, |
1734 fold_build_pointer_plus_hwi (arg0, r - p0)); | 1824 fold_build_pointer_plus_hwi (arg0, r - p0)); |
1735 } | 1825 } |
1736 return NULL_TREE; | 1826 return NULL_TREE; |
1737 | 1827 |
1828 case CFN_WHILE_ULT: | |
1829 { | |
1830 poly_uint64 parg0, parg1; | |
1831 if (poly_int_tree_p (arg0, &parg0) && poly_int_tree_p (arg1, &parg1)) | |
1832 return fold_while_ult (type, parg0, parg1); | |
1833 return NULL_TREE; | |
1834 } | |
1835 | |
1738 default: | 1836 default: |
1739 return fold_const_call_1 (fn, type, arg0, arg1, arg2); | 1837 return fold_const_call_1 (fn, type, arg0, arg1, arg2); |
1740 } | 1838 } |
1741 } | 1839 } |