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 }