Mercurial > hg > CbC > CbC_gcc
comparison gcc/builtins.c @ 55:77e2b8dfacca gcc-4.4.5
update it from 4.4.3 to 4.5.0
author | ryoma <e075725@ie.u-ryukyu.ac.jp> |
---|---|
date | Fri, 12 Feb 2010 23:39:51 +0900 |
parents | 3bfb6c00c1e0 |
children | b7f97abdc517 |
comparison
equal
deleted
inserted
replaced
52:c156f1bd5cd9 | 55:77e2b8dfacca |
---|---|
56 #endif | 56 #endif |
57 | 57 |
58 #ifndef PAD_VARARGS_DOWN | 58 #ifndef PAD_VARARGS_DOWN |
59 #define PAD_VARARGS_DOWN BYTES_BIG_ENDIAN | 59 #define PAD_VARARGS_DOWN BYTES_BIG_ENDIAN |
60 #endif | 60 #endif |
61 static tree do_mpc_arg1 (tree, tree, int (*)(mpc_ptr, mpc_srcptr, mpc_rnd_t)); | |
61 | 62 |
62 /* Define the names of the builtin function types and codes. */ | 63 /* Define the names of the builtin function types and codes. */ |
63 const char *const built_in_class_names[4] | 64 const char *const built_in_class_names[4] |
64 = {"NOT_BUILT_IN", "BUILT_IN_FRONTEND", "BUILT_IN_MD", "BUILT_IN_NORMAL"}; | 65 = {"NOT_BUILT_IN", "BUILT_IN_FRONTEND", "BUILT_IN_MD", "BUILT_IN_NORMAL"}; |
65 | 66 |
107 static rtx expand_builtin_args_info (tree); | 108 static rtx expand_builtin_args_info (tree); |
108 static rtx expand_builtin_next_arg (void); | 109 static rtx expand_builtin_next_arg (void); |
109 static rtx expand_builtin_va_start (tree); | 110 static rtx expand_builtin_va_start (tree); |
110 static rtx expand_builtin_va_end (tree); | 111 static rtx expand_builtin_va_end (tree); |
111 static rtx expand_builtin_va_copy (tree); | 112 static rtx expand_builtin_va_copy (tree); |
112 static rtx expand_builtin_memchr (tree, rtx, enum machine_mode); | |
113 static rtx expand_builtin_memcmp (tree, rtx, enum machine_mode); | 113 static rtx expand_builtin_memcmp (tree, rtx, enum machine_mode); |
114 static rtx expand_builtin_strcmp (tree, rtx, enum machine_mode); | 114 static rtx expand_builtin_strcmp (tree, rtx); |
115 static rtx expand_builtin_strncmp (tree, rtx, enum machine_mode); | 115 static rtx expand_builtin_strncmp (tree, rtx, enum machine_mode); |
116 static rtx builtin_memcpy_read_str (void *, HOST_WIDE_INT, enum machine_mode); | 116 static rtx builtin_memcpy_read_str (void *, HOST_WIDE_INT, enum machine_mode); |
117 static rtx expand_builtin_strcat (tree, tree, rtx, enum machine_mode); | 117 static rtx expand_builtin_memcpy (tree, rtx); |
118 static rtx expand_builtin_strncat (tree, rtx, enum machine_mode); | |
119 static rtx expand_builtin_strspn (tree, rtx, enum machine_mode); | |
120 static rtx expand_builtin_strcspn (tree, rtx, enum machine_mode); | |
121 static rtx expand_builtin_memcpy (tree, rtx, enum machine_mode); | |
122 static rtx expand_builtin_mempcpy (tree, rtx, enum machine_mode); | 118 static rtx expand_builtin_mempcpy (tree, rtx, enum machine_mode); |
123 static rtx expand_builtin_mempcpy_args (tree, tree, tree, tree, rtx, | 119 static rtx expand_builtin_mempcpy_args (tree, tree, tree, rtx, |
124 enum machine_mode, int); | 120 enum machine_mode, int); |
125 static rtx expand_builtin_memmove (tree, rtx, enum machine_mode, int); | 121 static rtx expand_builtin_strcpy (tree, rtx); |
126 static rtx expand_builtin_memmove_args (tree, tree, tree, tree, rtx, | 122 static rtx expand_builtin_strcpy_args (tree, tree, rtx); |
127 enum machine_mode, int); | |
128 static rtx expand_builtin_bcopy (tree, int); | |
129 static rtx expand_builtin_strcpy (tree, tree, rtx, enum machine_mode); | |
130 static rtx expand_builtin_strcpy_args (tree, tree, tree, rtx, enum machine_mode); | |
131 static rtx expand_builtin_stpcpy (tree, rtx, enum machine_mode); | 123 static rtx expand_builtin_stpcpy (tree, rtx, enum machine_mode); |
132 static rtx expand_builtin_strncpy (tree, rtx, enum machine_mode); | 124 static rtx expand_builtin_strncpy (tree, rtx); |
133 static rtx builtin_memset_gen_str (void *, HOST_WIDE_INT, enum machine_mode); | 125 static rtx builtin_memset_gen_str (void *, HOST_WIDE_INT, enum machine_mode); |
134 static rtx expand_builtin_memset (tree, rtx, enum machine_mode); | 126 static rtx expand_builtin_memset (tree, rtx, enum machine_mode); |
135 static rtx expand_builtin_memset_args (tree, tree, tree, rtx, enum machine_mode, tree); | 127 static rtx expand_builtin_memset_args (tree, tree, tree, rtx, enum machine_mode, tree); |
136 static rtx expand_builtin_bzero (tree); | 128 static rtx expand_builtin_bzero (tree); |
137 static rtx expand_builtin_strlen (tree, rtx, enum machine_mode); | 129 static rtx expand_builtin_strlen (tree, rtx, enum machine_mode); |
138 static rtx expand_builtin_strstr (tree, rtx, enum machine_mode); | |
139 static rtx expand_builtin_strpbrk (tree, rtx, enum machine_mode); | |
140 static rtx expand_builtin_strchr (tree, rtx, enum machine_mode); | |
141 static rtx expand_builtin_strrchr (tree, rtx, enum machine_mode); | |
142 static rtx expand_builtin_alloca (tree, rtx); | 130 static rtx expand_builtin_alloca (tree, rtx); |
143 static rtx expand_builtin_unop (enum machine_mode, tree, rtx, rtx, optab); | 131 static rtx expand_builtin_unop (enum machine_mode, tree, rtx, rtx, optab); |
144 static rtx expand_builtin_frame_address (tree, tree); | 132 static rtx expand_builtin_frame_address (tree, tree); |
145 static rtx expand_builtin_fputs (tree, rtx, bool); | 133 static tree stabilize_va_list_loc (location_t, tree, int); |
146 static rtx expand_builtin_printf (tree, rtx, enum machine_mode, bool); | |
147 static rtx expand_builtin_fprintf (tree, rtx, enum machine_mode, bool); | |
148 static rtx expand_builtin_sprintf (tree, rtx, enum machine_mode); | |
149 static tree stabilize_va_list (tree, int); | |
150 static rtx expand_builtin_expect (tree, rtx); | 134 static rtx expand_builtin_expect (tree, rtx); |
151 static tree fold_builtin_constant_p (tree); | 135 static tree fold_builtin_constant_p (tree); |
152 static tree fold_builtin_expect (tree, tree); | 136 static tree fold_builtin_expect (location_t, tree, tree); |
153 static tree fold_builtin_classify_type (tree); | 137 static tree fold_builtin_classify_type (tree); |
154 static tree fold_builtin_strlen (tree, tree); | 138 static tree fold_builtin_strlen (location_t, tree); |
155 static tree fold_builtin_inf (tree, int); | 139 static tree fold_builtin_inf (location_t, tree, int); |
156 static tree fold_builtin_nan (tree, tree, int); | 140 static tree fold_builtin_nan (tree, tree, int); |
157 static tree rewrite_call_expr (tree, int, tree, int, ...); | 141 static tree rewrite_call_expr (location_t, tree, int, tree, int, ...); |
158 static bool validate_arg (const_tree, enum tree_code code); | 142 static bool validate_arg (const_tree, enum tree_code code); |
159 static bool integer_valued_real_p (tree); | 143 static bool integer_valued_real_p (tree); |
160 static tree fold_trunc_transparent_mathfn (tree, tree); | 144 static tree fold_trunc_transparent_mathfn (location_t, tree, tree); |
161 static bool readonly_data_expr (tree); | 145 static bool readonly_data_expr (tree); |
162 static rtx expand_builtin_fabs (tree, rtx, rtx); | 146 static rtx expand_builtin_fabs (tree, rtx, rtx); |
163 static rtx expand_builtin_signbit (tree, rtx); | 147 static rtx expand_builtin_signbit (tree, rtx); |
164 static tree fold_builtin_sqrt (tree, tree); | 148 static tree fold_builtin_sqrt (location_t, tree, tree); |
165 static tree fold_builtin_cbrt (tree, tree); | 149 static tree fold_builtin_cbrt (location_t, tree, tree); |
166 static tree fold_builtin_pow (tree, tree, tree, tree); | 150 static tree fold_builtin_pow (location_t, tree, tree, tree, tree); |
167 static tree fold_builtin_powi (tree, tree, tree, tree); | 151 static tree fold_builtin_powi (location_t, tree, tree, tree, tree); |
168 static tree fold_builtin_cos (tree, tree, tree); | 152 static tree fold_builtin_cos (location_t, tree, tree, tree); |
169 static tree fold_builtin_cosh (tree, tree, tree); | 153 static tree fold_builtin_cosh (location_t, tree, tree, tree); |
170 static tree fold_builtin_tan (tree, tree); | 154 static tree fold_builtin_tan (tree, tree); |
171 static tree fold_builtin_trunc (tree, tree); | 155 static tree fold_builtin_trunc (location_t, tree, tree); |
172 static tree fold_builtin_floor (tree, tree); | 156 static tree fold_builtin_floor (location_t, tree, tree); |
173 static tree fold_builtin_ceil (tree, tree); | 157 static tree fold_builtin_ceil (location_t, tree, tree); |
174 static tree fold_builtin_round (tree, tree); | 158 static tree fold_builtin_round (location_t, tree, tree); |
175 static tree fold_builtin_int_roundingfn (tree, tree); | 159 static tree fold_builtin_int_roundingfn (location_t, tree, tree); |
176 static tree fold_builtin_bitop (tree, tree); | 160 static tree fold_builtin_bitop (tree, tree); |
177 static tree fold_builtin_memory_op (tree, tree, tree, tree, bool, int); | 161 static tree fold_builtin_memory_op (location_t, tree, tree, tree, tree, bool, int); |
178 static tree fold_builtin_strchr (tree, tree, tree); | 162 static tree fold_builtin_strchr (location_t, tree, tree, tree); |
179 static tree fold_builtin_memchr (tree, tree, tree, tree); | 163 static tree fold_builtin_memchr (location_t, tree, tree, tree, tree); |
180 static tree fold_builtin_memcmp (tree, tree, tree); | 164 static tree fold_builtin_memcmp (location_t, tree, tree, tree); |
181 static tree fold_builtin_strcmp (tree, tree); | 165 static tree fold_builtin_strcmp (location_t, tree, tree); |
182 static tree fold_builtin_strncmp (tree, tree, tree); | 166 static tree fold_builtin_strncmp (location_t, tree, tree, tree); |
183 static tree fold_builtin_signbit (tree, tree); | 167 static tree fold_builtin_signbit (location_t, tree, tree); |
184 static tree fold_builtin_copysign (tree, tree, tree, tree); | 168 static tree fold_builtin_copysign (location_t, tree, tree, tree, tree); |
185 static tree fold_builtin_isascii (tree); | 169 static tree fold_builtin_isascii (location_t, tree); |
186 static tree fold_builtin_toascii (tree); | 170 static tree fold_builtin_toascii (location_t, tree); |
187 static tree fold_builtin_isdigit (tree); | 171 static tree fold_builtin_isdigit (location_t, tree); |
188 static tree fold_builtin_fabs (tree, tree); | 172 static tree fold_builtin_fabs (location_t, tree, tree); |
189 static tree fold_builtin_abs (tree, tree); | 173 static tree fold_builtin_abs (location_t, tree, tree); |
190 static tree fold_builtin_unordered_cmp (tree, tree, tree, enum tree_code, | 174 static tree fold_builtin_unordered_cmp (location_t, tree, tree, tree, enum tree_code, |
191 enum tree_code); | 175 enum tree_code); |
192 static tree fold_builtin_n (tree, tree *, int, bool); | 176 static tree fold_builtin_n (location_t, tree, tree *, int, bool); |
193 static tree fold_builtin_0 (tree, bool); | 177 static tree fold_builtin_0 (location_t, tree, bool); |
194 static tree fold_builtin_1 (tree, tree, bool); | 178 static tree fold_builtin_1 (location_t, tree, tree, bool); |
195 static tree fold_builtin_2 (tree, tree, tree, bool); | 179 static tree fold_builtin_2 (location_t, tree, tree, tree, bool); |
196 static tree fold_builtin_3 (tree, tree, tree, tree, bool); | 180 static tree fold_builtin_3 (location_t, tree, tree, tree, tree, bool); |
197 static tree fold_builtin_4 (tree, tree, tree, tree, tree, bool); | 181 static tree fold_builtin_4 (location_t, tree, tree, tree, tree, tree, bool); |
198 static tree fold_builtin_varargs (tree, tree, bool); | 182 static tree fold_builtin_varargs (location_t, tree, tree, bool); |
199 | 183 |
200 static tree fold_builtin_strpbrk (tree, tree, tree); | 184 static tree fold_builtin_strpbrk (location_t, tree, tree, tree); |
201 static tree fold_builtin_strstr (tree, tree, tree); | 185 static tree fold_builtin_strstr (location_t, tree, tree, tree); |
202 static tree fold_builtin_strrchr (tree, tree, tree); | 186 static tree fold_builtin_strrchr (location_t, tree, tree, tree); |
203 static tree fold_builtin_strcat (tree, tree); | 187 static tree fold_builtin_strcat (location_t, tree, tree); |
204 static tree fold_builtin_strncat (tree, tree, tree); | 188 static tree fold_builtin_strncat (location_t, tree, tree, tree); |
205 static tree fold_builtin_strspn (tree, tree); | 189 static tree fold_builtin_strspn (location_t, tree, tree); |
206 static tree fold_builtin_strcspn (tree, tree); | 190 static tree fold_builtin_strcspn (location_t, tree, tree); |
207 static tree fold_builtin_sprintf (tree, tree, tree, int); | 191 static tree fold_builtin_sprintf (location_t, tree, tree, tree, int); |
208 | 192 |
209 static rtx expand_builtin_object_size (tree); | 193 static rtx expand_builtin_object_size (tree); |
210 static rtx expand_builtin_memory_chk (tree, rtx, enum machine_mode, | 194 static rtx expand_builtin_memory_chk (tree, rtx, enum machine_mode, |
211 enum built_in_function); | 195 enum built_in_function); |
212 static void maybe_emit_chk_warning (tree, enum built_in_function); | 196 static void maybe_emit_chk_warning (tree, enum built_in_function); |
213 static void maybe_emit_sprintf_chk_warning (tree, enum built_in_function); | 197 static void maybe_emit_sprintf_chk_warning (tree, enum built_in_function); |
214 static void maybe_emit_free_warning (tree); | 198 static void maybe_emit_free_warning (tree); |
215 static tree fold_builtin_object_size (tree, tree); | 199 static tree fold_builtin_object_size (tree, tree); |
216 static tree fold_builtin_strcat_chk (tree, tree, tree, tree); | 200 static tree fold_builtin_strcat_chk (location_t, tree, tree, tree, tree); |
217 static tree fold_builtin_strncat_chk (tree, tree, tree, tree, tree); | 201 static tree fold_builtin_strncat_chk (location_t, tree, tree, tree, tree, tree); |
218 static tree fold_builtin_sprintf_chk (tree, enum built_in_function); | 202 static tree fold_builtin_sprintf_chk (location_t, tree, enum built_in_function); |
219 static tree fold_builtin_printf (tree, tree, tree, bool, enum built_in_function); | 203 static tree fold_builtin_printf (location_t, tree, tree, tree, bool, enum built_in_function); |
220 static tree fold_builtin_fprintf (tree, tree, tree, tree, bool, | 204 static tree fold_builtin_fprintf (location_t, tree, tree, tree, tree, bool, |
221 enum built_in_function); | 205 enum built_in_function); |
222 static bool init_target_chars (void); | 206 static bool init_target_chars (void); |
223 | 207 |
224 static unsigned HOST_WIDE_INT target_newline; | 208 static unsigned HOST_WIDE_INT target_newline; |
225 static unsigned HOST_WIDE_INT target_percent; | 209 static unsigned HOST_WIDE_INT target_percent; |
239 int (*)(mpfr_ptr, long, mpfr_srcptr, mp_rnd_t), | 223 int (*)(mpfr_ptr, long, mpfr_srcptr, mp_rnd_t), |
240 const REAL_VALUE_TYPE *, bool); | 224 const REAL_VALUE_TYPE *, bool); |
241 static tree do_mpfr_remquo (tree, tree, tree); | 225 static tree do_mpfr_remquo (tree, tree, tree); |
242 static tree do_mpfr_lgamma_r (tree, tree, tree); | 226 static tree do_mpfr_lgamma_r (tree, tree, tree); |
243 | 227 |
244 /* Return true if NODE should be considered for inline expansion regardless | 228 /* Return true if NAME starts with __builtin_ or __sync_. */ |
245 of the optimization level. This means whenever a function is invoked with | 229 |
246 its "internal" name, which normally contains the prefix "__builtin". */ | 230 bool |
247 | 231 is_builtin_name (const char *name) |
248 static bool called_as_built_in (tree node) | 232 { |
249 { | |
250 const char *name = IDENTIFIER_POINTER (DECL_NAME (node)); | |
251 if (strncmp (name, "__builtin_", 10) == 0) | 233 if (strncmp (name, "__builtin_", 10) == 0) |
252 return true; | 234 return true; |
253 if (strncmp (name, "__sync_", 7) == 0) | 235 if (strncmp (name, "__sync_", 7) == 0) |
254 return true; | 236 return true; |
255 return false; | 237 return false; |
256 } | 238 } |
257 | 239 |
240 | |
241 /* Return true if DECL is a function symbol representing a built-in. */ | |
242 | |
243 bool | |
244 is_builtin_fn (tree decl) | |
245 { | |
246 return TREE_CODE (decl) == FUNCTION_DECL && DECL_BUILT_IN (decl); | |
247 } | |
248 | |
249 | |
250 /* Return true if NODE should be considered for inline expansion regardless | |
251 of the optimization level. This means whenever a function is invoked with | |
252 its "internal" name, which normally contains the prefix "__builtin". */ | |
253 | |
254 static bool | |
255 called_as_built_in (tree node) | |
256 { | |
257 /* Note that we must use DECL_NAME, not DECL_ASSEMBLER_NAME_SET_P since | |
258 we want the name used to call the function, not the name it | |
259 will have. */ | |
260 const char *name = IDENTIFIER_POINTER (DECL_NAME (node)); | |
261 return is_builtin_name (name); | |
262 } | |
263 | |
258 /* Return the alignment in bits of EXP, an object. | 264 /* Return the alignment in bits of EXP, an object. |
259 Don't return more than MAX_ALIGN no matter what, ALIGN is the inital | 265 Don't return more than MAX_ALIGN no matter what, ALIGN is the inital |
260 guessed alignment e.g. from type alignment. */ | 266 guessed alignment e.g. from type alignment. */ |
261 | 267 |
262 int | 268 int |
267 inner = max_align; | 273 inner = max_align; |
268 if (handled_component_p (exp)) | 274 if (handled_component_p (exp)) |
269 { | 275 { |
270 HOST_WIDE_INT bitsize, bitpos; | 276 HOST_WIDE_INT bitsize, bitpos; |
271 tree offset; | 277 tree offset; |
272 enum machine_mode mode; | 278 enum machine_mode mode; |
273 int unsignedp, volatilep; | 279 int unsignedp, volatilep; |
274 | 280 |
275 exp = get_inner_reference (exp, &bitsize, &bitpos, &offset, | 281 exp = get_inner_reference (exp, &bitsize, &bitpos, &offset, |
276 &mode, &unsignedp, &volatilep, true); | 282 &mode, &unsignedp, &volatilep, true); |
277 if (bitpos) | 283 if (bitpos) |
315 break; | 321 break; |
316 } | 322 } |
317 offset = next_offset; | 323 offset = next_offset; |
318 } | 324 } |
319 } | 325 } |
326 if (TREE_CODE (exp) == CONST_DECL) | |
327 exp = DECL_INITIAL (exp); | |
320 if (DECL_P (exp)) | 328 if (DECL_P (exp)) |
321 align = MIN (inner, DECL_ALIGN (exp)); | 329 align = MIN (inner, DECL_ALIGN (exp)); |
322 #ifdef CONSTANT_ALIGNMENT | 330 #ifdef CONSTANT_ALIGNMENT |
323 else if (CONSTANT_CLASS_P (exp)) | 331 else if (CONSTANT_CLASS_P (exp)) |
324 align = MIN (inner, (unsigned)CONSTANT_ALIGNMENT (exp, align)); | 332 align = MIN (inner, (unsigned)CONSTANT_ALIGNMENT (exp, align)); |
329 else | 337 else |
330 align = MIN (align, inner); | 338 align = MIN (align, inner); |
331 return MIN (align, max_align); | 339 return MIN (align, max_align); |
332 } | 340 } |
333 | 341 |
342 /* Returns true iff we can trust that alignment information has been | |
343 calculated properly. */ | |
344 | |
345 bool | |
346 can_trust_pointer_alignment (void) | |
347 { | |
348 /* We rely on TER to compute accurate alignment information. */ | |
349 return (optimize && flag_tree_ter); | |
350 } | |
351 | |
334 /* Return the alignment in bits of EXP, a pointer valued expression. | 352 /* Return the alignment in bits of EXP, a pointer valued expression. |
335 But don't return more than MAX_ALIGN no matter what. | 353 But don't return more than MAX_ALIGN no matter what. |
336 The alignment returned is, by default, the alignment of the thing that | 354 The alignment returned is, by default, the alignment of the thing that |
337 EXP points to. If it is not a POINTER_TYPE, 0 is returned. | 355 EXP points to. If it is not a POINTER_TYPE, 0 is returned. |
338 | 356 |
342 int | 360 int |
343 get_pointer_alignment (tree exp, unsigned int max_align) | 361 get_pointer_alignment (tree exp, unsigned int max_align) |
344 { | 362 { |
345 unsigned int align, inner; | 363 unsigned int align, inner; |
346 | 364 |
347 /* We rely on TER to compute accurate alignment information. */ | 365 if (!can_trust_pointer_alignment ()) |
348 if (!(optimize && flag_tree_ter)) | |
349 return 0; | 366 return 0; |
350 | 367 |
351 if (!POINTER_TYPE_P (TREE_TYPE (exp))) | 368 if (!POINTER_TYPE_P (TREE_TYPE (exp))) |
352 return 0; | 369 return 0; |
353 | 370 |
455 within the bounds of the string; otherwise, the programmer deserves | 472 within the bounds of the string; otherwise, the programmer deserves |
456 what he gets. Subtract the offset from the length of the string, | 473 what he gets. Subtract the offset from the length of the string, |
457 and return that. This would perhaps not be valid if we were dealing | 474 and return that. This would perhaps not be valid if we were dealing |
458 with named arrays in addition to literal string constants. */ | 475 with named arrays in addition to literal string constants. */ |
459 | 476 |
460 return size_diffop (size_int (max), offset_node); | 477 return size_diffop_loc (input_location, size_int (max), offset_node); |
461 } | 478 } |
462 | 479 |
463 /* We have a known offset into the string. Start searching there for | 480 /* We have a known offset into the string. Start searching there for |
464 a null character if we can represent it as a single HOST_WIDE_INT. */ | 481 a null character if we can represent it as a single HOST_WIDE_INT. */ |
465 if (offset_node == 0) | 482 if (offset_node == 0) |
731 also called directly by the SJLJ exception handling code. */ | 748 also called directly by the SJLJ exception handling code. */ |
732 | 749 |
733 void | 750 void |
734 expand_builtin_setjmp_receiver (rtx receiver_label ATTRIBUTE_UNUSED) | 751 expand_builtin_setjmp_receiver (rtx receiver_label ATTRIBUTE_UNUSED) |
735 { | 752 { |
753 rtx chain; | |
754 | |
736 /* Clobber the FP when we get here, so we have to make sure it's | 755 /* Clobber the FP when we get here, so we have to make sure it's |
737 marked as used by this function. */ | 756 marked as used by this function. */ |
738 emit_use (hard_frame_pointer_rtx); | 757 emit_use (hard_frame_pointer_rtx); |
739 | 758 |
740 /* Mark the static chain as clobbered here so life information | 759 /* Mark the static chain as clobbered here so life information |
741 doesn't get messed up for it. */ | 760 doesn't get messed up for it. */ |
742 emit_clobber (static_chain_rtx); | 761 chain = targetm.calls.static_chain (current_function_decl, true); |
762 if (chain && REG_P (chain)) | |
763 emit_clobber (chain); | |
743 | 764 |
744 /* Now put in the code to restore the frame pointer, and argument | 765 /* Now put in the code to restore the frame pointer, and argument |
745 pointer, if needed. */ | 766 pointer, if needed. */ |
746 #ifdef HAVE_nonlocal_goto | 767 #ifdef HAVE_nonlocal_goto |
747 if (! HAVE_nonlocal_goto) | 768 if (! HAVE_nonlocal_goto) |
803 expand_builtin_longjmp (rtx buf_addr, rtx value) | 824 expand_builtin_longjmp (rtx buf_addr, rtx value) |
804 { | 825 { |
805 rtx fp, lab, stack, insn, last; | 826 rtx fp, lab, stack, insn, last; |
806 enum machine_mode sa_mode = STACK_SAVEAREA_MODE (SAVE_NONLOCAL); | 827 enum machine_mode sa_mode = STACK_SAVEAREA_MODE (SAVE_NONLOCAL); |
807 | 828 |
808 /* DRAP is needed for stack realign if longjmp is expanded to current | 829 /* DRAP is needed for stack realign if longjmp is expanded to current |
809 function */ | 830 function */ |
810 if (SUPPORTS_STACK_ALIGNMENT) | 831 if (SUPPORTS_STACK_ALIGNMENT) |
811 crtl->need_drap = true; | 832 crtl->need_drap = true; |
812 | 833 |
813 if (setjmp_alias_set == -1) | 834 if (setjmp_alias_set == -1) |
815 | 836 |
816 buf_addr = convert_memory_address (Pmode, buf_addr); | 837 buf_addr = convert_memory_address (Pmode, buf_addr); |
817 | 838 |
818 buf_addr = force_reg (Pmode, buf_addr); | 839 buf_addr = force_reg (Pmode, buf_addr); |
819 | 840 |
820 /* We used to store value in static_chain_rtx, but that fails if pointers | 841 /* We require that the user must pass a second argument of 1, because |
821 are smaller than integers. We instead require that the user must pass | 842 that is what builtin_setjmp will return. */ |
822 a second argument of 1, because that is what builtin_setjmp will | |
823 return. This also makes EH slightly more efficient, since we are no | |
824 longer copying around a value that we don't care about. */ | |
825 gcc_assert (value == const1_rtx); | 843 gcc_assert (value == const1_rtx); |
826 | 844 |
827 last = get_last_insn (); | 845 last = get_last_insn (); |
828 #ifdef HAVE_builtin_longjmp | 846 #ifdef HAVE_builtin_longjmp |
829 if (HAVE_builtin_longjmp) | 847 if (HAVE_builtin_longjmp) |
1154 inner = TREE_OPERAND (inner, 0); | 1172 inner = TREE_OPERAND (inner, 0); |
1155 | 1173 |
1156 gcc_assert (TREE_CODE (inner) == COMPONENT_REF); | 1174 gcc_assert (TREE_CODE (inner) == COMPONENT_REF); |
1157 | 1175 |
1158 if (MEM_OFFSET (mem) | 1176 if (MEM_OFFSET (mem) |
1159 && GET_CODE (MEM_OFFSET (mem)) == CONST_INT) | 1177 && CONST_INT_P (MEM_OFFSET (mem))) |
1160 offset = INTVAL (MEM_OFFSET (mem)); | 1178 offset = INTVAL (MEM_OFFSET (mem)); |
1161 | 1179 |
1162 if (offset >= 0 && len && host_integerp (len, 0)) | 1180 if (offset >= 0 && len && host_integerp (len, 0)) |
1163 length = tree_low_cst (len, 0); | 1181 length = tree_low_cst (len, 0); |
1164 | 1182 |
1236 register is not used for returning values. If the machine has | 1254 register is not used for returning values. If the machine has |
1237 register windows, this gives only the outbound registers. | 1255 register windows, this gives only the outbound registers. |
1238 INCOMING_REGNO gives the corresponding inbound register. */ | 1256 INCOMING_REGNO gives the corresponding inbound register. */ |
1239 static enum machine_mode apply_result_mode[FIRST_PSEUDO_REGISTER]; | 1257 static enum machine_mode apply_result_mode[FIRST_PSEUDO_REGISTER]; |
1240 | 1258 |
1241 /* For each register that may be used for calling a function, this | |
1242 gives the offset of that register into the block returned by | |
1243 __builtin_apply_args. 0 indicates that the register is not | |
1244 used for calling a function. */ | |
1245 static int apply_args_reg_offset[FIRST_PSEUDO_REGISTER]; | |
1246 | |
1247 /* Return the size required for the block returned by __builtin_apply_args, | 1259 /* Return the size required for the block returned by __builtin_apply_args, |
1248 and initialize apply_args_mode. */ | 1260 and initialize apply_args_mode. */ |
1249 | 1261 |
1250 static int | 1262 static int |
1251 apply_args_size (void) | 1263 apply_args_size (void) |
1274 gcc_assert (mode != VOIDmode); | 1286 gcc_assert (mode != VOIDmode); |
1275 | 1287 |
1276 align = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT; | 1288 align = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT; |
1277 if (size % align != 0) | 1289 if (size % align != 0) |
1278 size = CEIL (size, align) * align; | 1290 size = CEIL (size, align) * align; |
1279 apply_args_reg_offset[regno] = size; | |
1280 size += GET_MODE_SIZE (mode); | 1291 size += GET_MODE_SIZE (mode); |
1281 apply_args_mode[regno] = mode; | 1292 apply_args_mode[regno] = mode; |
1282 } | 1293 } |
1283 else | 1294 else |
1284 { | 1295 { |
1285 apply_args_mode[regno] = VOIDmode; | 1296 apply_args_mode[regno] = VOIDmode; |
1286 apply_args_reg_offset[regno] = 0; | |
1287 } | 1297 } |
1288 } | 1298 } |
1289 return size; | 1299 return size; |
1290 } | 1300 } |
1291 | 1301 |
1517 if (SUPPORTS_STACK_ALIGNMENT) | 1527 if (SUPPORTS_STACK_ALIGNMENT) |
1518 crtl->need_drap = true; | 1528 crtl->need_drap = true; |
1519 | 1529 |
1520 dest = virtual_outgoing_args_rtx; | 1530 dest = virtual_outgoing_args_rtx; |
1521 #ifndef STACK_GROWS_DOWNWARD | 1531 #ifndef STACK_GROWS_DOWNWARD |
1522 if (GET_CODE (argsize) == CONST_INT) | 1532 if (CONST_INT_P (argsize)) |
1523 dest = plus_constant (dest, -INTVAL (argsize)); | 1533 dest = plus_constant (dest, -INTVAL (argsize)); |
1524 else | 1534 else |
1525 dest = gen_rtx_PLUS (Pmode, dest, negate_rtx (Pmode, argsize)); | 1535 dest = gen_rtx_PLUS (Pmode, dest, negate_rtx (Pmode, argsize)); |
1526 #endif | 1536 #endif |
1527 dest = gen_rtx_MEM (BLKmode, dest); | 1537 dest = gen_rtx_MEM (BLKmode, dest); |
1566 use_reg (&call_fusage, struct_value); | 1576 use_reg (&call_fusage, struct_value); |
1567 size += GET_MODE_SIZE (Pmode); | 1577 size += GET_MODE_SIZE (Pmode); |
1568 } | 1578 } |
1569 | 1579 |
1570 /* All arguments and registers used for the call are set up by now! */ | 1580 /* All arguments and registers used for the call are set up by now! */ |
1571 function = prepare_call_address (function, NULL, &call_fusage, 0, 0); | 1581 function = prepare_call_address (NULL, function, NULL, &call_fusage, 0, 0); |
1572 | 1582 |
1573 /* Ensure address is valid. SYMBOL_REF is already valid, so no need, | 1583 /* Ensure address is valid. SYMBOL_REF is already valid, so no need, |
1574 and we don't want to load it into a register as an optimization, | 1584 and we don't want to load it into a register as an optimization, |
1575 because prepare_call_address already did it if it should be done. */ | 1585 because prepare_call_address already did it if it should be done. */ |
1576 if (GET_CODE (function) != SYMBOL_REF) | 1586 if (GET_CODE (function) != SYMBOL_REF) |
1861 { | 1871 { |
1862 rtx lab = gen_label_rtx (); | 1872 rtx lab = gen_label_rtx (); |
1863 | 1873 |
1864 /* Test the result; if it is NaN, set errno=EDOM because | 1874 /* Test the result; if it is NaN, set errno=EDOM because |
1865 the argument was not in the domain. */ | 1875 the argument was not in the domain. */ |
1866 emit_cmp_and_jump_insns (target, target, EQ, 0, GET_MODE (target), | 1876 do_compare_rtx_and_jump (target, target, EQ, 0, GET_MODE (target), |
1867 0, lab); | 1877 NULL_RTX, NULL_RTX, lab); |
1868 | 1878 |
1869 #ifdef TARGET_EDOM | 1879 #ifdef TARGET_EDOM |
1870 /* If this built-in doesn't throw an exception, set errno directly. */ | 1880 /* If this built-in doesn't throw an exception, set errno directly. */ |
1871 if (TREE_NOTHROW (TREE_OPERAND (CALL_EXPR_FN (exp), 0))) | 1881 if (TREE_NOTHROW (TREE_OPERAND (CALL_EXPR_FN (exp), 0))) |
1872 { | 1882 { |
1901 | 1911 |
1902 static rtx | 1912 static rtx |
1903 expand_builtin_mathfn (tree exp, rtx target, rtx subtarget) | 1913 expand_builtin_mathfn (tree exp, rtx target, rtx subtarget) |
1904 { | 1914 { |
1905 optab builtin_optab; | 1915 optab builtin_optab; |
1906 rtx op0, insns, before_call; | 1916 rtx op0, insns; |
1907 tree fndecl = get_callee_fndecl (exp); | 1917 tree fndecl = get_callee_fndecl (exp); |
1908 enum machine_mode mode; | 1918 enum machine_mode mode; |
1909 bool errno_set = false; | 1919 bool errno_set = false; |
1910 tree arg; | 1920 tree arg; |
1911 | 1921 |
1960 if (flag_trapping_math) | 1970 if (flag_trapping_math) |
1961 break; | 1971 break; |
1962 /* Else fallthrough and expand as rint. */ | 1972 /* Else fallthrough and expand as rint. */ |
1963 CASE_FLT_FN (BUILT_IN_RINT): | 1973 CASE_FLT_FN (BUILT_IN_RINT): |
1964 builtin_optab = rint_optab; break; | 1974 builtin_optab = rint_optab; break; |
1975 CASE_FLT_FN (BUILT_IN_SIGNIFICAND): | |
1976 builtin_optab = significand_optab; break; | |
1965 default: | 1977 default: |
1966 gcc_unreachable (); | 1978 gcc_unreachable (); |
1967 } | 1979 } |
1968 | 1980 |
1969 /* Make a suitable register to place result in. */ | 1981 /* Make a suitable register to place result in. */ |
2005 /* If we were unable to expand via the builtin, stop the sequence | 2017 /* If we were unable to expand via the builtin, stop the sequence |
2006 (without outputting the insns) and call to the library function | 2018 (without outputting the insns) and call to the library function |
2007 with the stabilized argument list. */ | 2019 with the stabilized argument list. */ |
2008 end_sequence (); | 2020 end_sequence (); |
2009 } | 2021 } |
2010 | |
2011 before_call = get_last_insn (); | |
2012 | 2022 |
2013 return expand_call (exp, target, target == const0_rtx); | 2023 return expand_call (exp, target, target == const0_rtx); |
2014 } | 2024 } |
2015 | 2025 |
2016 /* Expand a call to the builtin binary math functions (pow and atan2). | 2026 /* Expand a call to the builtin binary math functions (pow and atan2). |
2221 target = expand_call (exp, target, target == const0_rtx); | 2231 target = expand_call (exp, target, target == const0_rtx); |
2222 | 2232 |
2223 return target; | 2233 return target; |
2224 } | 2234 } |
2225 | 2235 |
2236 /* Given an interclass math builtin decl FNDECL and it's argument ARG | |
2237 return an RTL instruction code that implements the functionality. | |
2238 If that isn't possible or available return CODE_FOR_nothing. */ | |
2239 | |
2240 static enum insn_code | |
2241 interclass_mathfn_icode (tree arg, tree fndecl) | |
2242 { | |
2243 bool errno_set = false; | |
2244 optab builtin_optab = 0; | |
2245 enum machine_mode mode; | |
2246 | |
2247 switch (DECL_FUNCTION_CODE (fndecl)) | |
2248 { | |
2249 CASE_FLT_FN (BUILT_IN_ILOGB): | |
2250 errno_set = true; builtin_optab = ilogb_optab; break; | |
2251 CASE_FLT_FN (BUILT_IN_ISINF): | |
2252 builtin_optab = isinf_optab; break; | |
2253 case BUILT_IN_ISNORMAL: | |
2254 case BUILT_IN_ISFINITE: | |
2255 CASE_FLT_FN (BUILT_IN_FINITE): | |
2256 case BUILT_IN_FINITED32: | |
2257 case BUILT_IN_FINITED64: | |
2258 case BUILT_IN_FINITED128: | |
2259 case BUILT_IN_ISINFD32: | |
2260 case BUILT_IN_ISINFD64: | |
2261 case BUILT_IN_ISINFD128: | |
2262 /* These builtins have no optabs (yet). */ | |
2263 break; | |
2264 default: | |
2265 gcc_unreachable (); | |
2266 } | |
2267 | |
2268 /* There's no easy way to detect the case we need to set EDOM. */ | |
2269 if (flag_errno_math && errno_set) | |
2270 return CODE_FOR_nothing; | |
2271 | |
2272 /* Optab mode depends on the mode of the input argument. */ | |
2273 mode = TYPE_MODE (TREE_TYPE (arg)); | |
2274 | |
2275 if (builtin_optab) | |
2276 return optab_handler (builtin_optab, mode)->insn_code; | |
2277 return CODE_FOR_nothing; | |
2278 } | |
2279 | |
2226 /* Expand a call to one of the builtin math functions that operate on | 2280 /* Expand a call to one of the builtin math functions that operate on |
2227 floating point argument and output an integer result (ilogb, isinf, | 2281 floating point argument and output an integer result (ilogb, isinf, |
2228 isnan, etc). | 2282 isnan, etc). |
2229 Return 0 if a normal call should be emitted rather than expanding the | 2283 Return 0 if a normal call should be emitted rather than expanding the |
2230 function in-line. EXP is the expression that is a call to the builtin | 2284 function in-line. EXP is the expression that is a call to the builtin |
2232 SUBTARGET may be used as the target for computing one of EXP's operands. */ | 2286 SUBTARGET may be used as the target for computing one of EXP's operands. */ |
2233 | 2287 |
2234 static rtx | 2288 static rtx |
2235 expand_builtin_interclass_mathfn (tree exp, rtx target, rtx subtarget) | 2289 expand_builtin_interclass_mathfn (tree exp, rtx target, rtx subtarget) |
2236 { | 2290 { |
2237 optab builtin_optab = 0; | |
2238 enum insn_code icode = CODE_FOR_nothing; | 2291 enum insn_code icode = CODE_FOR_nothing; |
2239 rtx op0; | 2292 rtx op0; |
2240 tree fndecl = get_callee_fndecl (exp); | 2293 tree fndecl = get_callee_fndecl (exp); |
2241 enum machine_mode mode; | 2294 enum machine_mode mode; |
2242 bool errno_set = false; | |
2243 tree arg; | 2295 tree arg; |
2244 | 2296 |
2245 if (!validate_arglist (exp, REAL_TYPE, VOID_TYPE)) | 2297 if (!validate_arglist (exp, REAL_TYPE, VOID_TYPE)) |
2246 return NULL_RTX; | 2298 return NULL_RTX; |
2247 | 2299 |
2248 arg = CALL_EXPR_ARG (exp, 0); | 2300 arg = CALL_EXPR_ARG (exp, 0); |
2249 | 2301 icode = interclass_mathfn_icode (arg, fndecl); |
2250 switch (DECL_FUNCTION_CODE (fndecl)) | |
2251 { | |
2252 CASE_FLT_FN (BUILT_IN_ILOGB): | |
2253 errno_set = true; builtin_optab = ilogb_optab; break; | |
2254 CASE_FLT_FN (BUILT_IN_ISINF): | |
2255 builtin_optab = isinf_optab; break; | |
2256 case BUILT_IN_ISNORMAL: | |
2257 case BUILT_IN_ISFINITE: | |
2258 CASE_FLT_FN (BUILT_IN_FINITE): | |
2259 /* These builtins have no optabs (yet). */ | |
2260 break; | |
2261 default: | |
2262 gcc_unreachable (); | |
2263 } | |
2264 | |
2265 /* There's no easy way to detect the case we need to set EDOM. */ | |
2266 if (flag_errno_math && errno_set) | |
2267 return NULL_RTX; | |
2268 | |
2269 /* Optab mode depends on the mode of the input argument. */ | |
2270 mode = TYPE_MODE (TREE_TYPE (arg)); | 2302 mode = TYPE_MODE (TREE_TYPE (arg)); |
2271 | 2303 |
2272 if (builtin_optab) | |
2273 icode = optab_handler (builtin_optab, mode)->insn_code; | |
2274 | |
2275 /* Before working hard, check whether the instruction is available. */ | |
2276 if (icode != CODE_FOR_nothing) | 2304 if (icode != CODE_FOR_nothing) |
2277 { | 2305 { |
2278 /* Make a suitable register to place result in. */ | 2306 /* Make a suitable register to place result in. */ |
2279 if (!target | 2307 if (!target |
2280 || GET_MODE (target) != TYPE_MODE (TREE_TYPE (exp))) | 2308 || GET_MODE (target) != TYPE_MODE (TREE_TYPE (exp))) |
2297 Set TARGET to wherever the result comes back. */ | 2325 Set TARGET to wherever the result comes back. */ |
2298 emit_unop_insn (icode, target, op0, UNKNOWN); | 2326 emit_unop_insn (icode, target, op0, UNKNOWN); |
2299 return target; | 2327 return target; |
2300 } | 2328 } |
2301 | 2329 |
2302 /* If there is no optab, try generic code. */ | 2330 return NULL_RTX; |
2303 switch (DECL_FUNCTION_CODE (fndecl)) | |
2304 { | |
2305 tree result; | |
2306 | |
2307 CASE_FLT_FN (BUILT_IN_ISINF): | |
2308 { | |
2309 /* isinf(x) -> isgreater(fabs(x),DBL_MAX). */ | |
2310 tree const isgr_fn = built_in_decls[BUILT_IN_ISGREATER]; | |
2311 tree const type = TREE_TYPE (arg); | |
2312 REAL_VALUE_TYPE r; | |
2313 char buf[128]; | |
2314 | |
2315 get_max_float (REAL_MODE_FORMAT (mode), buf, sizeof (buf)); | |
2316 real_from_string (&r, buf); | |
2317 result = build_call_expr (isgr_fn, 2, | |
2318 fold_build1 (ABS_EXPR, type, arg), | |
2319 build_real (type, r)); | |
2320 return expand_expr (result, target, VOIDmode, EXPAND_NORMAL); | |
2321 } | |
2322 CASE_FLT_FN (BUILT_IN_FINITE): | |
2323 case BUILT_IN_ISFINITE: | |
2324 { | |
2325 /* isfinite(x) -> islessequal(fabs(x),DBL_MAX). */ | |
2326 tree const isle_fn = built_in_decls[BUILT_IN_ISLESSEQUAL]; | |
2327 tree const type = TREE_TYPE (arg); | |
2328 REAL_VALUE_TYPE r; | |
2329 char buf[128]; | |
2330 | |
2331 get_max_float (REAL_MODE_FORMAT (mode), buf, sizeof (buf)); | |
2332 real_from_string (&r, buf); | |
2333 result = build_call_expr (isle_fn, 2, | |
2334 fold_build1 (ABS_EXPR, type, arg), | |
2335 build_real (type, r)); | |
2336 return expand_expr (result, target, VOIDmode, EXPAND_NORMAL); | |
2337 } | |
2338 case BUILT_IN_ISNORMAL: | |
2339 { | |
2340 /* isnormal(x) -> isgreaterequal(fabs(x),DBL_MIN) & | |
2341 islessequal(fabs(x),DBL_MAX). */ | |
2342 tree const isle_fn = built_in_decls[BUILT_IN_ISLESSEQUAL]; | |
2343 tree const isge_fn = built_in_decls[BUILT_IN_ISGREATEREQUAL]; | |
2344 tree const type = TREE_TYPE (arg); | |
2345 REAL_VALUE_TYPE rmax, rmin; | |
2346 char buf[128]; | |
2347 | |
2348 get_max_float (REAL_MODE_FORMAT (mode), buf, sizeof (buf)); | |
2349 real_from_string (&rmax, buf); | |
2350 sprintf (buf, "0x1p%d", REAL_MODE_FORMAT (mode)->emin - 1); | |
2351 real_from_string (&rmin, buf); | |
2352 arg = builtin_save_expr (fold_build1 (ABS_EXPR, type, arg)); | |
2353 result = build_call_expr (isle_fn, 2, arg, | |
2354 build_real (type, rmax)); | |
2355 result = fold_build2 (BIT_AND_EXPR, integer_type_node, result, | |
2356 build_call_expr (isge_fn, 2, arg, | |
2357 build_real (type, rmin))); | |
2358 return expand_expr (result, target, VOIDmode, EXPAND_NORMAL); | |
2359 } | |
2360 default: | |
2361 break; | |
2362 } | |
2363 | |
2364 target = expand_call (exp, target, target == const0_rtx); | |
2365 | |
2366 return target; | |
2367 } | 2331 } |
2368 | 2332 |
2369 /* Expand a call to the builtin sincos math function. | 2333 /* Expand a call to the builtin sincos math function. |
2370 Return NULL_RTX if a normal call should be emitted rather than expanding the | 2334 Return NULL_RTX if a normal call should be emitted rather than expanding the |
2371 function in-line. EXP is the expression that is a call to the builtin | 2335 function in-line. EXP is the expression that is a call to the builtin |
2376 { | 2340 { |
2377 rtx op0, op1, op2, target1, target2; | 2341 rtx op0, op1, op2, target1, target2; |
2378 enum machine_mode mode; | 2342 enum machine_mode mode; |
2379 tree arg, sinp, cosp; | 2343 tree arg, sinp, cosp; |
2380 int result; | 2344 int result; |
2345 location_t loc = EXPR_LOCATION (exp); | |
2381 | 2346 |
2382 if (!validate_arglist (exp, REAL_TYPE, | 2347 if (!validate_arglist (exp, REAL_TYPE, |
2383 POINTER_TYPE, POINTER_TYPE, VOID_TYPE)) | 2348 POINTER_TYPE, POINTER_TYPE, VOID_TYPE)) |
2384 return NULL_RTX; | 2349 return NULL_RTX; |
2385 | 2350 |
2396 | 2361 |
2397 target1 = gen_reg_rtx (mode); | 2362 target1 = gen_reg_rtx (mode); |
2398 target2 = gen_reg_rtx (mode); | 2363 target2 = gen_reg_rtx (mode); |
2399 | 2364 |
2400 op0 = expand_normal (arg); | 2365 op0 = expand_normal (arg); |
2401 op1 = expand_normal (build_fold_indirect_ref (sinp)); | 2366 op1 = expand_normal (build_fold_indirect_ref_loc (loc, sinp)); |
2402 op2 = expand_normal (build_fold_indirect_ref (cosp)); | 2367 op2 = expand_normal (build_fold_indirect_ref_loc (loc, cosp)); |
2403 | 2368 |
2404 /* Compute into target1 and target2. | 2369 /* Compute into target1 and target2. |
2405 Set TARGET to wherever the result comes back. */ | 2370 Set TARGET to wherever the result comes back. */ |
2406 result = expand_twoval_unop (sincos_optab, op0, target2, target1, 0); | 2371 result = expand_twoval_unop (sincos_optab, op0, target2, target1, 0); |
2407 gcc_assert (result); | 2372 gcc_assert (result); |
2424 { | 2389 { |
2425 tree fndecl = get_callee_fndecl (exp); | 2390 tree fndecl = get_callee_fndecl (exp); |
2426 tree arg, type; | 2391 tree arg, type; |
2427 enum machine_mode mode; | 2392 enum machine_mode mode; |
2428 rtx op0, op1, op2; | 2393 rtx op0, op1, op2; |
2394 location_t loc = EXPR_LOCATION (exp); | |
2429 | 2395 |
2430 if (!validate_arglist (exp, REAL_TYPE, VOID_TYPE)) | 2396 if (!validate_arglist (exp, REAL_TYPE, VOID_TYPE)) |
2431 return NULL_RTX; | 2397 return NULL_RTX; |
2432 | 2398 |
2433 arg = CALL_EXPR_ARG (exp, 0); | 2399 arg = CALL_EXPR_ARG (exp, 0); |
2459 fn = built_in_decls[BUILT_IN_SINCOS]; | 2425 fn = built_in_decls[BUILT_IN_SINCOS]; |
2460 else if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CEXPIL) | 2426 else if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CEXPIL) |
2461 fn = built_in_decls[BUILT_IN_SINCOSL]; | 2427 fn = built_in_decls[BUILT_IN_SINCOSL]; |
2462 else | 2428 else |
2463 gcc_unreachable (); | 2429 gcc_unreachable (); |
2464 | 2430 |
2465 op1 = assign_temp (TREE_TYPE (arg), 0, 1, 1); | 2431 op1 = assign_temp (TREE_TYPE (arg), 0, 1, 1); |
2466 op2 = assign_temp (TREE_TYPE (arg), 0, 1, 1); | 2432 op2 = assign_temp (TREE_TYPE (arg), 0, 1, 1); |
2467 op1a = copy_to_mode_reg (Pmode, XEXP (op1, 0)); | 2433 op1a = copy_to_mode_reg (Pmode, XEXP (op1, 0)); |
2468 op2a = copy_to_mode_reg (Pmode, XEXP (op2, 0)); | 2434 op2a = copy_to_mode_reg (Pmode, XEXP (op2, 0)); |
2469 top1 = make_tree (build_pointer_type (TREE_TYPE (arg)), op1a); | 2435 top1 = make_tree (build_pointer_type (TREE_TYPE (arg)), op1a); |
2505 | 2471 |
2506 fntype = build_function_type_list (ctype, ctype, NULL_TREE); | 2472 fntype = build_function_type_list (ctype, ctype, NULL_TREE); |
2507 fn = build_fn_decl (name, fntype); | 2473 fn = build_fn_decl (name, fntype); |
2508 } | 2474 } |
2509 | 2475 |
2510 narg = fold_build2 (COMPLEX_EXPR, ctype, | 2476 narg = fold_build2_loc (loc, COMPLEX_EXPR, ctype, |
2511 build_real (type, dconst0), arg); | 2477 build_real (type, dconst0), arg); |
2512 | 2478 |
2513 /* Make sure not to fold the cexp call again. */ | 2479 /* Make sure not to fold the cexp call again. */ |
2514 call = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (fn)), fn); | 2480 call = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (fn)), fn); |
2515 return expand_expr (build_call_nary (ctype, call, 1, narg), | 2481 return expand_expr (build_call_nary (ctype, call, 1, narg), |
2516 target, VOIDmode, EXPAND_NORMAL); | 2482 target, VOIDmode, EXPAND_NORMAL); |
2517 } | 2483 } |
2518 | 2484 |
2519 /* Now build the proper return type. */ | 2485 /* Now build the proper return type. */ |
2520 return expand_expr (build2 (COMPLEX_EXPR, build_complex_type (type), | 2486 return expand_expr (build2 (COMPLEX_EXPR, build_complex_type (type), |
2521 make_tree (TREE_TYPE (arg), op2), | 2487 make_tree (TREE_TYPE (arg), op2), |
2522 make_tree (TREE_TYPE (arg), op1)), | 2488 make_tree (TREE_TYPE (arg), op1)), |
2523 target, VOIDmode, EXPAND_NORMAL); | 2489 target, VOIDmode, EXPAND_NORMAL); |
2524 } | 2490 } |
2491 | |
2492 /* Conveniently construct a function call expression. FNDECL names the | |
2493 function to be called, N is the number of arguments, and the "..." | |
2494 parameters are the argument expressions. Unlike build_call_exr | |
2495 this doesn't fold the call, hence it will always return a CALL_EXPR. */ | |
2496 | |
2497 static tree | |
2498 build_call_nofold_loc (location_t loc, tree fndecl, int n, ...) | |
2499 { | |
2500 va_list ap; | |
2501 tree fntype = TREE_TYPE (fndecl); | |
2502 tree fn = build1 (ADDR_EXPR, build_pointer_type (fntype), fndecl); | |
2503 | |
2504 va_start (ap, n); | |
2505 fn = build_call_valist (TREE_TYPE (fntype), fn, n, ap); | |
2506 va_end (ap); | |
2507 SET_EXPR_LOCATION (fn, loc); | |
2508 return fn; | |
2509 } | |
2510 #define build_call_nofold(...) \ | |
2511 build_call_nofold_loc (UNKNOWN_LOCATION, __VA_ARGS__) | |
2525 | 2512 |
2526 /* Expand a call to one of the builtin rounding functions gcc defines | 2513 /* Expand a call to one of the builtin rounding functions gcc defines |
2527 as an extension (lfloor and lceil). As these are gcc extensions we | 2514 as an extension (lfloor and lceil). As these are gcc extensions we |
2528 do not need to worry about setting errno to EDOM. | 2515 do not need to worry about setting errno to EDOM. |
2529 If expanding via optab fails, lower expression to (int)(floor(x)). | 2516 If expanding via optab fails, lower expression to (int)(floor(x)). |
2637 fntype = build_function_type_list (TREE_TYPE (arg), | 2624 fntype = build_function_type_list (TREE_TYPE (arg), |
2638 TREE_TYPE (arg), NULL_TREE); | 2625 TREE_TYPE (arg), NULL_TREE); |
2639 fallback_fndecl = build_fn_decl (name, fntype); | 2626 fallback_fndecl = build_fn_decl (name, fntype); |
2640 } | 2627 } |
2641 | 2628 |
2642 exp = build_call_expr (fallback_fndecl, 1, arg); | 2629 exp = build_call_nofold (fallback_fndecl, 1, arg); |
2643 | 2630 |
2644 tmp = expand_normal (exp); | 2631 tmp = expand_normal (exp); |
2645 | 2632 |
2646 /* Truncate the result of floating point optab to integer | 2633 /* Truncate the result of floating point optab to integer |
2647 via expand_fix (). */ | 2634 via expand_fix (). */ |
2670 if (flag_errno_math) | 2657 if (flag_errno_math) |
2671 return NULL_RTX; | 2658 return NULL_RTX; |
2672 | 2659 |
2673 if (!validate_arglist (exp, REAL_TYPE, VOID_TYPE)) | 2660 if (!validate_arglist (exp, REAL_TYPE, VOID_TYPE)) |
2674 gcc_unreachable (); | 2661 gcc_unreachable (); |
2675 | 2662 |
2676 arg = CALL_EXPR_ARG (exp, 0); | 2663 arg = CALL_EXPR_ARG (exp, 0); |
2677 | 2664 |
2678 switch (DECL_FUNCTION_CODE (fndecl)) | 2665 switch (DECL_FUNCTION_CODE (fndecl)) |
2679 { | 2666 { |
2680 CASE_FLT_FN (BUILT_IN_LRINT): | 2667 CASE_FLT_FN (BUILT_IN_LRINT): |
2901 function needs to be kept in sync with powi_cost above. */ | 2888 function needs to be kept in sync with powi_cost above. */ |
2902 | 2889 |
2903 static rtx | 2890 static rtx |
2904 expand_powi (rtx x, enum machine_mode mode, HOST_WIDE_INT n) | 2891 expand_powi (rtx x, enum machine_mode mode, HOST_WIDE_INT n) |
2905 { | 2892 { |
2906 unsigned HOST_WIDE_INT val; | |
2907 rtx cache[POWI_TABLE_SIZE]; | 2893 rtx cache[POWI_TABLE_SIZE]; |
2908 rtx result; | 2894 rtx result; |
2909 | 2895 |
2910 if (n == 0) | 2896 if (n == 0) |
2911 return CONST1_RTX (mode); | 2897 return CONST1_RTX (mode); |
2912 | |
2913 val = (n < 0) ? -n : n; | |
2914 | 2898 |
2915 memset (cache, 0, sizeof (cache)); | 2899 memset (cache, 0, sizeof (cache)); |
2916 cache[1] = x; | 2900 cache[1] = x; |
2917 | 2901 |
2918 result = expand_powi_1 (mode, (n < 0) ? -n : n, cache); | 2902 result = expand_powi_1 (mode, (n < 0) ? -n : n, cache); |
2987 && ((flag_unsafe_math_optimizations | 2971 && ((flag_unsafe_math_optimizations |
2988 && optimize_insn_for_speed_p () | 2972 && optimize_insn_for_speed_p () |
2989 && powi_cost (n/2) <= POWI_MAX_MULTS) | 2973 && powi_cost (n/2) <= POWI_MAX_MULTS) |
2990 || n == 1)) | 2974 || n == 1)) |
2991 { | 2975 { |
2992 tree call_expr = build_call_expr (fn, 1, narg0); | 2976 tree call_expr = build_call_nofold (fn, 1, narg0); |
2993 /* Use expand_expr in case the newly built call expression | 2977 /* Use expand_expr in case the newly built call expression |
2994 was folded to a non-call. */ | 2978 was folded to a non-call. */ |
2995 op = expand_expr (call_expr, subtarget, mode, EXPAND_NORMAL); | 2979 op = expand_expr (call_expr, subtarget, mode, EXPAND_NORMAL); |
2996 if (n != 1) | 2980 if (n != 1) |
2997 { | 2981 { |
3032 if (real_identical (&c2, &c) | 3016 if (real_identical (&c2, &c) |
3033 && ((optimize_insn_for_speed_p () | 3017 && ((optimize_insn_for_speed_p () |
3034 && powi_cost (n/3) <= POWI_MAX_MULTS) | 3018 && powi_cost (n/3) <= POWI_MAX_MULTS) |
3035 || n == 1)) | 3019 || n == 1)) |
3036 { | 3020 { |
3037 tree call_expr = build_call_expr (fn, 1,narg0); | 3021 tree call_expr = build_call_nofold (fn, 1,narg0); |
3038 op = expand_builtin (call_expr, NULL_RTX, subtarget, mode, 0); | 3022 op = expand_builtin (call_expr, NULL_RTX, subtarget, mode, 0); |
3039 if (abs (n) % 3 == 2) | 3023 if (abs (n) % 3 == 2) |
3040 op = expand_simple_binop (mode, MULT, op, op, op, | 3024 op = expand_simple_binop (mode, MULT, op, op, op, |
3041 0, OPTAB_LIB_WIDEN); | 3025 0, OPTAB_LIB_WIDEN); |
3042 if (n != 1) | 3026 if (n != 1) |
3121 op0, mode, op1, mode2); | 3105 op0, mode, op1, mode2); |
3122 | 3106 |
3123 return target; | 3107 return target; |
3124 } | 3108 } |
3125 | 3109 |
3126 /* Expand expression EXP which is a call to the strlen builtin. Return | 3110 /* Expand expression EXP which is a call to the strlen builtin. Return |
3127 NULL_RTX if we failed the caller should emit a normal call, otherwise | 3111 NULL_RTX if we failed the caller should emit a normal call, otherwise |
3128 try to get the result in TARGET, if convenient. */ | 3112 try to get the result in TARGET, if convenient. */ |
3129 | 3113 |
3130 static rtx | 3114 static rtx |
3131 expand_builtin_strlen (tree exp, rtx target, | 3115 expand_builtin_strlen (tree exp, rtx target, |
3230 | 3214 |
3231 return target; | 3215 return target; |
3232 } | 3216 } |
3233 } | 3217 } |
3234 | 3218 |
3235 /* Expand a call to the strstr builtin. Return NULL_RTX if we failed the | |
3236 caller should emit a normal call, otherwise try to get the result | |
3237 in TARGET, if convenient (and in mode MODE if that's convenient). */ | |
3238 | |
3239 static rtx | |
3240 expand_builtin_strstr (tree exp, rtx target, enum machine_mode mode) | |
3241 { | |
3242 if (validate_arglist (exp, POINTER_TYPE, POINTER_TYPE, VOID_TYPE)) | |
3243 { | |
3244 tree type = TREE_TYPE (exp); | |
3245 tree result = fold_builtin_strstr (CALL_EXPR_ARG (exp, 0), | |
3246 CALL_EXPR_ARG (exp, 1), type); | |
3247 if (result) | |
3248 return expand_expr (result, target, mode, EXPAND_NORMAL); | |
3249 } | |
3250 return NULL_RTX; | |
3251 } | |
3252 | |
3253 /* Expand a call to the strchr builtin. Return NULL_RTX if we failed the | |
3254 caller should emit a normal call, otherwise try to get the result | |
3255 in TARGET, if convenient (and in mode MODE if that's convenient). */ | |
3256 | |
3257 static rtx | |
3258 expand_builtin_strchr (tree exp, rtx target, enum machine_mode mode) | |
3259 { | |
3260 if (validate_arglist (exp, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE)) | |
3261 { | |
3262 tree type = TREE_TYPE (exp); | |
3263 tree result = fold_builtin_strchr (CALL_EXPR_ARG (exp, 0), | |
3264 CALL_EXPR_ARG (exp, 1), type); | |
3265 if (result) | |
3266 return expand_expr (result, target, mode, EXPAND_NORMAL); | |
3267 | |
3268 /* FIXME: Should use strchrM optab so that ports can optimize this. */ | |
3269 } | |
3270 return NULL_RTX; | |
3271 } | |
3272 | |
3273 /* Expand a call to the strrchr builtin. Return NULL_RTX if we failed the | |
3274 caller should emit a normal call, otherwise try to get the result | |
3275 in TARGET, if convenient (and in mode MODE if that's convenient). */ | |
3276 | |
3277 static rtx | |
3278 expand_builtin_strrchr (tree exp, rtx target, enum machine_mode mode) | |
3279 { | |
3280 if (validate_arglist (exp, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE)) | |
3281 { | |
3282 tree type = TREE_TYPE (exp); | |
3283 tree result = fold_builtin_strrchr (CALL_EXPR_ARG (exp, 0), | |
3284 CALL_EXPR_ARG (exp, 1), type); | |
3285 if (result) | |
3286 return expand_expr (result, target, mode, EXPAND_NORMAL); | |
3287 } | |
3288 return NULL_RTX; | |
3289 } | |
3290 | |
3291 /* Expand a call to the strpbrk builtin. Return NULL_RTX if we failed the | |
3292 caller should emit a normal call, otherwise try to get the result | |
3293 in TARGET, if convenient (and in mode MODE if that's convenient). */ | |
3294 | |
3295 static rtx | |
3296 expand_builtin_strpbrk (tree exp, rtx target, enum machine_mode mode) | |
3297 { | |
3298 if (validate_arglist (exp, POINTER_TYPE, POINTER_TYPE, VOID_TYPE)) | |
3299 { | |
3300 tree type = TREE_TYPE (exp); | |
3301 tree result = fold_builtin_strpbrk (CALL_EXPR_ARG (exp, 0), | |
3302 CALL_EXPR_ARG (exp, 1), type); | |
3303 if (result) | |
3304 return expand_expr (result, target, mode, EXPAND_NORMAL); | |
3305 } | |
3306 return NULL_RTX; | |
3307 } | |
3308 | |
3309 /* Callback routine for store_by_pieces. Read GET_MODE_BITSIZE (MODE) | 3219 /* Callback routine for store_by_pieces. Read GET_MODE_BITSIZE (MODE) |
3310 bytes from constant string DATA + OFFSET and return it as target | 3220 bytes from constant string DATA + OFFSET and return it as target |
3311 constant. */ | 3221 constant. */ |
3312 | 3222 |
3313 static rtx | 3223 static rtx |
3327 Return NULL_RTX if we failed, the caller should emit a normal call, | 3237 Return NULL_RTX if we failed, the caller should emit a normal call, |
3328 otherwise try to get the result in TARGET, if convenient (and in | 3238 otherwise try to get the result in TARGET, if convenient (and in |
3329 mode MODE if that's convenient). */ | 3239 mode MODE if that's convenient). */ |
3330 | 3240 |
3331 static rtx | 3241 static rtx |
3332 expand_builtin_memcpy (tree exp, rtx target, enum machine_mode mode) | 3242 expand_builtin_memcpy (tree exp, rtx target) |
3333 { | 3243 { |
3334 tree fndecl = get_callee_fndecl (exp); | |
3335 | |
3336 if (!validate_arglist (exp, | 3244 if (!validate_arglist (exp, |
3337 POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE)) | 3245 POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE)) |
3338 return NULL_RTX; | 3246 return NULL_RTX; |
3339 else | 3247 else |
3340 { | 3248 { |
3344 const char *src_str; | 3252 const char *src_str; |
3345 unsigned int src_align = get_pointer_alignment (src, BIGGEST_ALIGNMENT); | 3253 unsigned int src_align = get_pointer_alignment (src, BIGGEST_ALIGNMENT); |
3346 unsigned int dest_align | 3254 unsigned int dest_align |
3347 = get_pointer_alignment (dest, BIGGEST_ALIGNMENT); | 3255 = get_pointer_alignment (dest, BIGGEST_ALIGNMENT); |
3348 rtx dest_mem, src_mem, dest_addr, len_rtx; | 3256 rtx dest_mem, src_mem, dest_addr, len_rtx; |
3349 tree result = fold_builtin_memory_op (dest, src, len, | |
3350 TREE_TYPE (TREE_TYPE (fndecl)), | |
3351 false, /*endp=*/0); | |
3352 HOST_WIDE_INT expected_size = -1; | 3257 HOST_WIDE_INT expected_size = -1; |
3353 unsigned int expected_align = 0; | 3258 unsigned int expected_align = 0; |
3354 tree_ann_common_t ann; | |
3355 | |
3356 if (result) | |
3357 { | |
3358 while (TREE_CODE (result) == COMPOUND_EXPR) | |
3359 { | |
3360 expand_expr (TREE_OPERAND (result, 0), const0_rtx, VOIDmode, | |
3361 EXPAND_NORMAL); | |
3362 result = TREE_OPERAND (result, 1); | |
3363 } | |
3364 return expand_expr (result, target, mode, EXPAND_NORMAL); | |
3365 } | |
3366 | 3259 |
3367 /* If DEST is not a pointer type, call the normal function. */ | 3260 /* If DEST is not a pointer type, call the normal function. */ |
3368 if (dest_align == 0) | 3261 if (dest_align == 0) |
3369 return NULL_RTX; | 3262 return NULL_RTX; |
3370 | 3263 |
3371 /* If either SRC is not a pointer type, don't do this | 3264 /* If either SRC is not a pointer type, don't do this |
3372 operation in-line. */ | 3265 operation in-line. */ |
3373 if (src_align == 0) | 3266 if (src_align == 0) |
3374 return NULL_RTX; | 3267 return NULL_RTX; |
3375 | 3268 |
3376 ann = tree_common_ann (exp); | 3269 if (currently_expanding_gimple_stmt) |
3377 if (ann) | 3270 stringop_block_profile (currently_expanding_gimple_stmt, |
3378 stringop_block_profile (ann->stmt, &expected_align, &expected_size); | 3271 &expected_align, &expected_size); |
3379 | 3272 |
3380 if (expected_align < dest_align) | 3273 if (expected_align < dest_align) |
3381 expected_align = dest_align; | 3274 expected_align = dest_align; |
3382 dest_mem = get_memory_rtx (dest, len); | 3275 dest_mem = get_memory_rtx (dest, len); |
3383 set_mem_align (dest_mem, dest_align); | 3276 set_mem_align (dest_mem, dest_align); |
3386 | 3279 |
3387 /* If SRC is a string constant and block move would be done | 3280 /* If SRC is a string constant and block move would be done |
3388 by pieces, we can avoid loading the string from memory | 3281 by pieces, we can avoid loading the string from memory |
3389 and only stored the computed constants. */ | 3282 and only stored the computed constants. */ |
3390 if (src_str | 3283 if (src_str |
3391 && GET_CODE (len_rtx) == CONST_INT | 3284 && CONST_INT_P (len_rtx) |
3392 && (unsigned HOST_WIDE_INT) INTVAL (len_rtx) <= strlen (src_str) + 1 | 3285 && (unsigned HOST_WIDE_INT) INTVAL (len_rtx) <= strlen (src_str) + 1 |
3393 && can_store_by_pieces (INTVAL (len_rtx), builtin_memcpy_read_str, | 3286 && can_store_by_pieces (INTVAL (len_rtx), builtin_memcpy_read_str, |
3394 CONST_CAST (char *, src_str), | 3287 CONST_CAST (char *, src_str), |
3395 dest_align, false)) | 3288 dest_align, false)) |
3396 { | 3289 { |
3397 dest_mem = store_by_pieces (dest_mem, INTVAL (len_rtx), | 3290 dest_mem = store_by_pieces (dest_mem, INTVAL (len_rtx), |
3398 builtin_memcpy_read_str, | 3291 builtin_memcpy_read_str, |
3399 CONST_CAST (char *, src_str), | 3292 CONST_CAST (char *, src_str), |
3400 dest_align, false, 0); | 3293 dest_align, false, 0); |
3401 dest_mem = force_operand (XEXP (dest_mem, 0), NULL_RTX); | 3294 dest_mem = force_operand (XEXP (dest_mem, 0), target); |
3402 dest_mem = convert_memory_address (ptr_mode, dest_mem); | 3295 dest_mem = convert_memory_address (ptr_mode, dest_mem); |
3403 return dest_mem; | 3296 return dest_mem; |
3404 } | 3297 } |
3405 | 3298 |
3406 src_mem = get_memory_rtx (src, len); | 3299 src_mem = get_memory_rtx (src, len); |
3412 ? BLOCK_OP_TAILCALL : BLOCK_OP_NORMAL, | 3305 ? BLOCK_OP_TAILCALL : BLOCK_OP_NORMAL, |
3413 expected_align, expected_size); | 3306 expected_align, expected_size); |
3414 | 3307 |
3415 if (dest_addr == 0) | 3308 if (dest_addr == 0) |
3416 { | 3309 { |
3417 dest_addr = force_operand (XEXP (dest_mem, 0), NULL_RTX); | 3310 dest_addr = force_operand (XEXP (dest_mem, 0), target); |
3418 dest_addr = convert_memory_address (ptr_mode, dest_addr); | 3311 dest_addr = convert_memory_address (ptr_mode, dest_addr); |
3419 } | 3312 } |
3420 return dest_addr; | 3313 return dest_addr; |
3421 } | 3314 } |
3422 } | 3315 } |
3439 { | 3332 { |
3440 tree dest = CALL_EXPR_ARG (exp, 0); | 3333 tree dest = CALL_EXPR_ARG (exp, 0); |
3441 tree src = CALL_EXPR_ARG (exp, 1); | 3334 tree src = CALL_EXPR_ARG (exp, 1); |
3442 tree len = CALL_EXPR_ARG (exp, 2); | 3335 tree len = CALL_EXPR_ARG (exp, 2); |
3443 return expand_builtin_mempcpy_args (dest, src, len, | 3336 return expand_builtin_mempcpy_args (dest, src, len, |
3444 TREE_TYPE (exp), | |
3445 target, mode, /*endp=*/ 1); | 3337 target, mode, /*endp=*/ 1); |
3446 } | 3338 } |
3447 } | 3339 } |
3448 | 3340 |
3449 /* Helper function to do the actual work for expand_builtin_mempcpy. The | 3341 /* Helper function to do the actual work for expand_builtin_mempcpy. The |
3450 arguments to the builtin_mempcpy call DEST, SRC, and LEN are broken out | 3342 arguments to the builtin_mempcpy call DEST, SRC, and LEN are broken out |
3451 so that this can also be called without constructing an actual CALL_EXPR. | 3343 so that this can also be called without constructing an actual CALL_EXPR. |
3452 TYPE is the return type of the call. The other arguments and return value | 3344 The other arguments and return value are the same as for |
3453 are the same as for expand_builtin_mempcpy. */ | 3345 expand_builtin_mempcpy. */ |
3454 | 3346 |
3455 static rtx | 3347 static rtx |
3456 expand_builtin_mempcpy_args (tree dest, tree src, tree len, tree type, | 3348 expand_builtin_mempcpy_args (tree dest, tree src, tree len, |
3457 rtx target, enum machine_mode mode, int endp) | 3349 rtx target, enum machine_mode mode, int endp) |
3458 { | 3350 { |
3459 /* If return value is ignored, transform mempcpy into memcpy. */ | 3351 /* If return value is ignored, transform mempcpy into memcpy. */ |
3460 if (target == const0_rtx && implicit_built_in_decls[BUILT_IN_MEMCPY]) | 3352 if (target == const0_rtx && implicit_built_in_decls[BUILT_IN_MEMCPY]) |
3461 { | 3353 { |
3462 tree fn = implicit_built_in_decls[BUILT_IN_MEMCPY]; | 3354 tree fn = implicit_built_in_decls[BUILT_IN_MEMCPY]; |
3463 tree result = build_call_expr (fn, 3, dest, src, len); | 3355 tree result = build_call_nofold (fn, 3, dest, src, len); |
3464 | |
3465 while (TREE_CODE (result) == COMPOUND_EXPR) | |
3466 { | |
3467 expand_expr (TREE_OPERAND (result, 0), const0_rtx, VOIDmode, | |
3468 EXPAND_NORMAL); | |
3469 result = TREE_OPERAND (result, 1); | |
3470 } | |
3471 return expand_expr (result, target, mode, EXPAND_NORMAL); | 3356 return expand_expr (result, target, mode, EXPAND_NORMAL); |
3472 } | 3357 } |
3473 else | 3358 else |
3474 { | 3359 { |
3475 const char *src_str; | 3360 const char *src_str; |
3476 unsigned int src_align = get_pointer_alignment (src, BIGGEST_ALIGNMENT); | 3361 unsigned int src_align = get_pointer_alignment (src, BIGGEST_ALIGNMENT); |
3477 unsigned int dest_align | 3362 unsigned int dest_align |
3478 = get_pointer_alignment (dest, BIGGEST_ALIGNMENT); | 3363 = get_pointer_alignment (dest, BIGGEST_ALIGNMENT); |
3479 rtx dest_mem, src_mem, len_rtx; | 3364 rtx dest_mem, src_mem, len_rtx; |
3480 tree result = fold_builtin_memory_op (dest, src, len, type, false, endp); | |
3481 | |
3482 if (result) | |
3483 { | |
3484 while (TREE_CODE (result) == COMPOUND_EXPR) | |
3485 { | |
3486 expand_expr (TREE_OPERAND (result, 0), const0_rtx, VOIDmode, | |
3487 EXPAND_NORMAL); | |
3488 result = TREE_OPERAND (result, 1); | |
3489 } | |
3490 return expand_expr (result, target, mode, EXPAND_NORMAL); | |
3491 } | |
3492 | 3365 |
3493 /* If either SRC or DEST is not a pointer type, don't do this | 3366 /* If either SRC or DEST is not a pointer type, don't do this |
3494 operation in-line. */ | 3367 operation in-line. */ |
3495 if (dest_align == 0 || src_align == 0) | 3368 if (dest_align == 0 || src_align == 0) |
3496 return NULL_RTX; | 3369 return NULL_RTX; |
3504 | 3377 |
3505 /* If SRC is a string constant and block move would be done | 3378 /* If SRC is a string constant and block move would be done |
3506 by pieces, we can avoid loading the string from memory | 3379 by pieces, we can avoid loading the string from memory |
3507 and only stored the computed constants. */ | 3380 and only stored the computed constants. */ |
3508 if (src_str | 3381 if (src_str |
3509 && GET_CODE (len_rtx) == CONST_INT | 3382 && CONST_INT_P (len_rtx) |
3510 && (unsigned HOST_WIDE_INT) INTVAL (len_rtx) <= strlen (src_str) + 1 | 3383 && (unsigned HOST_WIDE_INT) INTVAL (len_rtx) <= strlen (src_str) + 1 |
3511 && can_store_by_pieces (INTVAL (len_rtx), builtin_memcpy_read_str, | 3384 && can_store_by_pieces (INTVAL (len_rtx), builtin_memcpy_read_str, |
3512 CONST_CAST (char *, src_str), | 3385 CONST_CAST (char *, src_str), |
3513 dest_align, false)) | 3386 dest_align, false)) |
3514 { | 3387 { |
3521 dest_mem = force_operand (XEXP (dest_mem, 0), NULL_RTX); | 3394 dest_mem = force_operand (XEXP (dest_mem, 0), NULL_RTX); |
3522 dest_mem = convert_memory_address (ptr_mode, dest_mem); | 3395 dest_mem = convert_memory_address (ptr_mode, dest_mem); |
3523 return dest_mem; | 3396 return dest_mem; |
3524 } | 3397 } |
3525 | 3398 |
3526 if (GET_CODE (len_rtx) == CONST_INT | 3399 if (CONST_INT_P (len_rtx) |
3527 && can_move_by_pieces (INTVAL (len_rtx), | 3400 && can_move_by_pieces (INTVAL (len_rtx), |
3528 MIN (dest_align, src_align))) | 3401 MIN (dest_align, src_align))) |
3529 { | 3402 { |
3530 dest_mem = get_memory_rtx (dest, len); | 3403 dest_mem = get_memory_rtx (dest, len); |
3531 set_mem_align (dest_mem, dest_align); | 3404 set_mem_align (dest_mem, dest_align); |
3540 | 3413 |
3541 return NULL_RTX; | 3414 return NULL_RTX; |
3542 } | 3415 } |
3543 } | 3416 } |
3544 | 3417 |
3545 /* Expand expression EXP, which is a call to the memmove builtin. Return | |
3546 NULL_RTX if we failed; the caller should emit a normal call. */ | |
3547 | |
3548 static rtx | |
3549 expand_builtin_memmove (tree exp, rtx target, enum machine_mode mode, int ignore) | |
3550 { | |
3551 if (!validate_arglist (exp, | |
3552 POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE)) | |
3553 return NULL_RTX; | |
3554 else | |
3555 { | |
3556 tree dest = CALL_EXPR_ARG (exp, 0); | |
3557 tree src = CALL_EXPR_ARG (exp, 1); | |
3558 tree len = CALL_EXPR_ARG (exp, 2); | |
3559 return expand_builtin_memmove_args (dest, src, len, TREE_TYPE (exp), | |
3560 target, mode, ignore); | |
3561 } | |
3562 } | |
3563 | |
3564 /* Helper function to do the actual work for expand_builtin_memmove. The | |
3565 arguments to the builtin_memmove call DEST, SRC, and LEN are broken out | |
3566 so that this can also be called without constructing an actual CALL_EXPR. | |
3567 TYPE is the return type of the call. The other arguments and return value | |
3568 are the same as for expand_builtin_memmove. */ | |
3569 | |
3570 static rtx | |
3571 expand_builtin_memmove_args (tree dest, tree src, tree len, | |
3572 tree type, rtx target, enum machine_mode mode, | |
3573 int ignore) | |
3574 { | |
3575 tree result = fold_builtin_memory_op (dest, src, len, type, ignore, /*endp=*/3); | |
3576 | |
3577 if (result) | |
3578 { | |
3579 STRIP_TYPE_NOPS (result); | |
3580 while (TREE_CODE (result) == COMPOUND_EXPR) | |
3581 { | |
3582 expand_expr (TREE_OPERAND (result, 0), const0_rtx, VOIDmode, | |
3583 EXPAND_NORMAL); | |
3584 result = TREE_OPERAND (result, 1); | |
3585 } | |
3586 return expand_expr (result, target, mode, EXPAND_NORMAL); | |
3587 } | |
3588 | |
3589 /* Otherwise, call the normal function. */ | |
3590 return NULL_RTX; | |
3591 } | |
3592 | |
3593 /* Expand expression EXP, which is a call to the bcopy builtin. Return | |
3594 NULL_RTX if we failed the caller should emit a normal call. */ | |
3595 | |
3596 static rtx | |
3597 expand_builtin_bcopy (tree exp, int ignore) | |
3598 { | |
3599 tree type = TREE_TYPE (exp); | |
3600 tree src, dest, size; | |
3601 | |
3602 if (!validate_arglist (exp, | |
3603 POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE)) | |
3604 return NULL_RTX; | |
3605 | |
3606 src = CALL_EXPR_ARG (exp, 0); | |
3607 dest = CALL_EXPR_ARG (exp, 1); | |
3608 size = CALL_EXPR_ARG (exp, 2); | |
3609 | |
3610 /* Transform bcopy(ptr x, ptr y, int z) to memmove(ptr y, ptr x, size_t z). | |
3611 This is done this way so that if it isn't expanded inline, we fall | |
3612 back to calling bcopy instead of memmove. */ | |
3613 return expand_builtin_memmove_args (dest, src, | |
3614 fold_convert (sizetype, size), | |
3615 type, const0_rtx, VOIDmode, | |
3616 ignore); | |
3617 } | |
3618 | |
3619 #ifndef HAVE_movstr | 3418 #ifndef HAVE_movstr |
3620 # define HAVE_movstr 0 | 3419 # define HAVE_movstr 0 |
3621 # define CODE_FOR_movstr CODE_FOR_nothing | 3420 # define CODE_FOR_movstr CODE_FOR_nothing |
3622 #endif | 3421 #endif |
3623 | 3422 |
3681 } | 3480 } |
3682 | 3481 |
3683 return target; | 3482 return target; |
3684 } | 3483 } |
3685 | 3484 |
3686 /* Expand expression EXP, which is a call to the strcpy builtin. Return | 3485 /* Expand expression EXP, which is a call to the strcpy builtin. Return |
3687 NULL_RTX if we failed the caller should emit a normal call, otherwise | 3486 NULL_RTX if we failed the caller should emit a normal call, otherwise |
3688 try to get the result in TARGET, if convenient (and in mode MODE if that's | 3487 try to get the result in TARGET, if convenient (and in mode MODE if that's |
3689 convenient). */ | 3488 convenient). */ |
3690 | 3489 |
3691 static rtx | 3490 static rtx |
3692 expand_builtin_strcpy (tree fndecl, tree exp, rtx target, enum machine_mode mode) | 3491 expand_builtin_strcpy (tree exp, rtx target) |
3693 { | 3492 { |
3694 if (validate_arglist (exp, POINTER_TYPE, POINTER_TYPE, VOID_TYPE)) | 3493 if (validate_arglist (exp, POINTER_TYPE, POINTER_TYPE, VOID_TYPE)) |
3695 { | 3494 { |
3696 tree dest = CALL_EXPR_ARG (exp, 0); | 3495 tree dest = CALL_EXPR_ARG (exp, 0); |
3697 tree src = CALL_EXPR_ARG (exp, 1); | 3496 tree src = CALL_EXPR_ARG (exp, 1); |
3698 return expand_builtin_strcpy_args (fndecl, dest, src, target, mode); | 3497 return expand_builtin_strcpy_args (dest, src, target); |
3699 } | 3498 } |
3700 return NULL_RTX; | 3499 return NULL_RTX; |
3701 } | 3500 } |
3702 | 3501 |
3703 /* Helper function to do the actual work for expand_builtin_strcpy. The | 3502 /* Helper function to do the actual work for expand_builtin_strcpy. The |
3705 so that this can also be called without constructing an actual CALL_EXPR. | 3504 so that this can also be called without constructing an actual CALL_EXPR. |
3706 The other arguments and return value are the same as for | 3505 The other arguments and return value are the same as for |
3707 expand_builtin_strcpy. */ | 3506 expand_builtin_strcpy. */ |
3708 | 3507 |
3709 static rtx | 3508 static rtx |
3710 expand_builtin_strcpy_args (tree fndecl, tree dest, tree src, | 3509 expand_builtin_strcpy_args (tree dest, tree src, rtx target) |
3711 rtx target, enum machine_mode mode) | 3510 { |
3712 { | |
3713 tree result = fold_builtin_strcpy (fndecl, dest, src, 0); | |
3714 if (result) | |
3715 { | |
3716 while (TREE_CODE (result) == COMPOUND_EXPR) | |
3717 { | |
3718 expand_expr (TREE_OPERAND (result, 0), const0_rtx, VOIDmode, | |
3719 EXPAND_NORMAL); | |
3720 result = TREE_OPERAND (result, 1); | |
3721 } | |
3722 return expand_expr (result, target, mode, EXPAND_NORMAL); | |
3723 } | |
3724 return expand_movstr (dest, src, target, /*endp=*/0); | 3511 return expand_movstr (dest, src, target, /*endp=*/0); |
3725 | |
3726 } | 3512 } |
3727 | 3513 |
3728 /* Expand a call EXP to the stpcpy builtin. | 3514 /* Expand a call EXP to the stpcpy builtin. |
3729 Return NULL_RTX if we failed the caller should emit a normal call, | 3515 Return NULL_RTX if we failed the caller should emit a normal call, |
3730 otherwise try to get the result in TARGET, if convenient (and in | 3516 otherwise try to get the result in TARGET, if convenient (and in |
3732 | 3518 |
3733 static rtx | 3519 static rtx |
3734 expand_builtin_stpcpy (tree exp, rtx target, enum machine_mode mode) | 3520 expand_builtin_stpcpy (tree exp, rtx target, enum machine_mode mode) |
3735 { | 3521 { |
3736 tree dst, src; | 3522 tree dst, src; |
3523 location_t loc = EXPR_LOCATION (exp); | |
3737 | 3524 |
3738 if (!validate_arglist (exp, POINTER_TYPE, POINTER_TYPE, VOID_TYPE)) | 3525 if (!validate_arglist (exp, POINTER_TYPE, POINTER_TYPE, VOID_TYPE)) |
3739 return NULL_RTX; | 3526 return NULL_RTX; |
3740 | 3527 |
3741 dst = CALL_EXPR_ARG (exp, 0); | 3528 dst = CALL_EXPR_ARG (exp, 0); |
3743 | 3530 |
3744 /* If return value is ignored, transform stpcpy into strcpy. */ | 3531 /* If return value is ignored, transform stpcpy into strcpy. */ |
3745 if (target == const0_rtx && implicit_built_in_decls[BUILT_IN_STRCPY]) | 3532 if (target == const0_rtx && implicit_built_in_decls[BUILT_IN_STRCPY]) |
3746 { | 3533 { |
3747 tree fn = implicit_built_in_decls[BUILT_IN_STRCPY]; | 3534 tree fn = implicit_built_in_decls[BUILT_IN_STRCPY]; |
3748 tree result = build_call_expr (fn, 2, dst, src); | 3535 tree result = build_call_nofold (fn, 2, dst, src); |
3749 | |
3750 STRIP_NOPS (result); | |
3751 while (TREE_CODE (result) == COMPOUND_EXPR) | |
3752 { | |
3753 expand_expr (TREE_OPERAND (result, 0), const0_rtx, VOIDmode, | |
3754 EXPAND_NORMAL); | |
3755 result = TREE_OPERAND (result, 1); | |
3756 } | |
3757 return expand_expr (result, target, mode, EXPAND_NORMAL); | 3536 return expand_expr (result, target, mode, EXPAND_NORMAL); |
3758 } | 3537 } |
3759 else | 3538 else |
3760 { | 3539 { |
3761 tree len, lenp1; | 3540 tree len, lenp1; |
3766 because the latter will potentially produce pessimized code | 3545 because the latter will potentially produce pessimized code |
3767 when used to produce the return value. */ | 3546 when used to produce the return value. */ |
3768 if (! c_getstr (src) || ! (len = c_strlen (src, 0))) | 3547 if (! c_getstr (src) || ! (len = c_strlen (src, 0))) |
3769 return expand_movstr (dst, src, target, /*endp=*/2); | 3548 return expand_movstr (dst, src, target, /*endp=*/2); |
3770 | 3549 |
3771 lenp1 = size_binop (PLUS_EXPR, len, ssize_int (1)); | 3550 lenp1 = size_binop_loc (loc, PLUS_EXPR, len, ssize_int (1)); |
3772 ret = expand_builtin_mempcpy_args (dst, src, lenp1, TREE_TYPE (exp), | 3551 ret = expand_builtin_mempcpy_args (dst, src, lenp1, |
3773 target, mode, /*endp=*/2); | 3552 target, mode, /*endp=*/2); |
3774 | 3553 |
3775 if (ret) | 3554 if (ret) |
3776 return ret; | 3555 return ret; |
3777 | 3556 |
3778 if (TREE_CODE (len) == INTEGER_CST) | 3557 if (TREE_CODE (len) == INTEGER_CST) |
3779 { | 3558 { |
3780 rtx len_rtx = expand_normal (len); | 3559 rtx len_rtx = expand_normal (len); |
3781 | 3560 |
3782 if (GET_CODE (len_rtx) == CONST_INT) | 3561 if (CONST_INT_P (len_rtx)) |
3783 { | 3562 { |
3784 ret = expand_builtin_strcpy_args (get_callee_fndecl (exp), | 3563 ret = expand_builtin_strcpy_args (dst, src, target); |
3785 dst, src, target, mode); | |
3786 | 3564 |
3787 if (ret) | 3565 if (ret) |
3788 { | 3566 { |
3789 if (! target) | 3567 if (! target) |
3790 { | 3568 { |
3823 return const0_rtx; | 3601 return const0_rtx; |
3824 | 3602 |
3825 return c_readstr (str + offset, mode); | 3603 return c_readstr (str + offset, mode); |
3826 } | 3604 } |
3827 | 3605 |
3828 /* Expand expression EXP, which is a call to the strncpy builtin. Return | 3606 /* Expand expression EXP, which is a call to the strncpy builtin. Return |
3829 NULL_RTX if we failed the caller should emit a normal call. */ | 3607 NULL_RTX if we failed the caller should emit a normal call. */ |
3830 | 3608 |
3831 static rtx | 3609 static rtx |
3832 expand_builtin_strncpy (tree exp, rtx target, enum machine_mode mode) | 3610 expand_builtin_strncpy (tree exp, rtx target) |
3833 { | 3611 { |
3834 tree fndecl = get_callee_fndecl (exp); | 3612 location_t loc = EXPR_LOCATION (exp); |
3835 | 3613 |
3836 if (validate_arglist (exp, | 3614 if (validate_arglist (exp, |
3837 POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE)) | 3615 POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE)) |
3838 { | 3616 { |
3839 tree dest = CALL_EXPR_ARG (exp, 0); | 3617 tree dest = CALL_EXPR_ARG (exp, 0); |
3840 tree src = CALL_EXPR_ARG (exp, 1); | 3618 tree src = CALL_EXPR_ARG (exp, 1); |
3841 tree len = CALL_EXPR_ARG (exp, 2); | 3619 tree len = CALL_EXPR_ARG (exp, 2); |
3842 tree slen = c_strlen (src, 1); | 3620 tree slen = c_strlen (src, 1); |
3843 tree result = fold_builtin_strncpy (fndecl, dest, src, len, slen); | |
3844 | |
3845 if (result) | |
3846 { | |
3847 while (TREE_CODE (result) == COMPOUND_EXPR) | |
3848 { | |
3849 expand_expr (TREE_OPERAND (result, 0), const0_rtx, VOIDmode, | |
3850 EXPAND_NORMAL); | |
3851 result = TREE_OPERAND (result, 1); | |
3852 } | |
3853 return expand_expr (result, target, mode, EXPAND_NORMAL); | |
3854 } | |
3855 | 3621 |
3856 /* We must be passed a constant len and src parameter. */ | 3622 /* We must be passed a constant len and src parameter. */ |
3857 if (!host_integerp (len, 1) || !slen || !host_integerp (slen, 1)) | 3623 if (!host_integerp (len, 1) || !slen || !host_integerp (slen, 1)) |
3858 return NULL_RTX; | 3624 return NULL_RTX; |
3859 | 3625 |
3860 slen = size_binop (PLUS_EXPR, slen, ssize_int (1)); | 3626 slen = size_binop_loc (loc, PLUS_EXPR, slen, ssize_int (1)); |
3861 | 3627 |
3862 /* We're required to pad with trailing zeros if the requested | 3628 /* We're required to pad with trailing zeros if the requested |
3863 len is greater than strlen(s2)+1. In that case try to | 3629 len is greater than strlen(s2)+1. In that case try to |
3864 use store_by_pieces, if it fails, punt. */ | 3630 use store_by_pieces, if it fails, punt. */ |
3865 if (tree_int_cst_lt (slen, len)) | 3631 if (tree_int_cst_lt (slen, len)) |
3878 | 3644 |
3879 dest_mem = get_memory_rtx (dest, len); | 3645 dest_mem = get_memory_rtx (dest, len); |
3880 store_by_pieces (dest_mem, tree_low_cst (len, 1), | 3646 store_by_pieces (dest_mem, tree_low_cst (len, 1), |
3881 builtin_strncpy_read_str, | 3647 builtin_strncpy_read_str, |
3882 CONST_CAST (char *, p), dest_align, false, 0); | 3648 CONST_CAST (char *, p), dest_align, false, 0); |
3883 dest_mem = force_operand (XEXP (dest_mem, 0), NULL_RTX); | 3649 dest_mem = force_operand (XEXP (dest_mem, 0), target); |
3884 dest_mem = convert_memory_address (ptr_mode, dest_mem); | 3650 dest_mem = convert_memory_address (ptr_mode, dest_mem); |
3885 return dest_mem; | 3651 return dest_mem; |
3886 } | 3652 } |
3887 } | 3653 } |
3888 return NULL_RTX; | 3654 return NULL_RTX; |
3928 target = convert_to_mode (mode, (rtx) data, 1); | 3694 target = convert_to_mode (mode, (rtx) data, 1); |
3929 target = expand_mult (mode, target, coeff, NULL_RTX, 1); | 3695 target = expand_mult (mode, target, coeff, NULL_RTX, 1); |
3930 return force_reg (mode, target); | 3696 return force_reg (mode, target); |
3931 } | 3697 } |
3932 | 3698 |
3933 /* Expand expression EXP, which is a call to the memset builtin. Return | 3699 /* Expand expression EXP, which is a call to the memset builtin. Return |
3934 NULL_RTX if we failed the caller should emit a normal call, otherwise | 3700 NULL_RTX if we failed the caller should emit a normal call, otherwise |
3935 try to get the result in TARGET, if convenient (and in mode MODE if that's | 3701 try to get the result in TARGET, if convenient (and in mode MODE if that's |
3936 convenient). */ | 3702 convenient). */ |
3937 | 3703 |
3938 static rtx | 3704 static rtx |
3939 expand_builtin_memset (tree exp, rtx target, enum machine_mode mode) | 3705 expand_builtin_memset (tree exp, rtx target, enum machine_mode mode) |
3965 char c; | 3731 char c; |
3966 unsigned int dest_align; | 3732 unsigned int dest_align; |
3967 rtx dest_mem, dest_addr, len_rtx; | 3733 rtx dest_mem, dest_addr, len_rtx; |
3968 HOST_WIDE_INT expected_size = -1; | 3734 HOST_WIDE_INT expected_size = -1; |
3969 unsigned int expected_align = 0; | 3735 unsigned int expected_align = 0; |
3970 tree_ann_common_t ann; | |
3971 | 3736 |
3972 dest_align = get_pointer_alignment (dest, BIGGEST_ALIGNMENT); | 3737 dest_align = get_pointer_alignment (dest, BIGGEST_ALIGNMENT); |
3973 | 3738 |
3974 /* If DEST is not a pointer type, don't do this operation in-line. */ | 3739 /* If DEST is not a pointer type, don't do this operation in-line. */ |
3975 if (dest_align == 0) | 3740 if (dest_align == 0) |
3976 return NULL_RTX; | 3741 return NULL_RTX; |
3977 | 3742 |
3978 ann = tree_common_ann (orig_exp); | 3743 if (currently_expanding_gimple_stmt) |
3979 if (ann) | 3744 stringop_block_profile (currently_expanding_gimple_stmt, |
3980 stringop_block_profile (ann->stmt, &expected_align, &expected_size); | 3745 &expected_align, &expected_size); |
3981 | 3746 |
3982 if (expected_align < dest_align) | 3747 if (expected_align < dest_align) |
3983 expected_align = dest_align; | 3748 expected_align = dest_align; |
3984 | 3749 |
3985 /* If the LEN parameter is zero, return DEST. */ | 3750 /* If the LEN parameter is zero, return DEST. */ |
4023 } | 3788 } |
4024 else if (!set_storage_via_setmem (dest_mem, len_rtx, val_rtx, | 3789 else if (!set_storage_via_setmem (dest_mem, len_rtx, val_rtx, |
4025 dest_align, expected_align, | 3790 dest_align, expected_align, |
4026 expected_size)) | 3791 expected_size)) |
4027 goto do_libcall; | 3792 goto do_libcall; |
4028 | 3793 |
4029 dest_mem = force_operand (XEXP (dest_mem, 0), NULL_RTX); | 3794 dest_mem = force_operand (XEXP (dest_mem, 0), NULL_RTX); |
4030 dest_mem = convert_memory_address (ptr_mode, dest_mem); | 3795 dest_mem = convert_memory_address (ptr_mode, dest_mem); |
4031 return dest_mem; | 3796 return dest_mem; |
4032 } | 3797 } |
4033 | 3798 |
4044 builtin_memset_read_str, &c, dest_align, true, 0); | 3809 builtin_memset_read_str, &c, dest_align, true, 0); |
4045 else if (!set_storage_via_setmem (dest_mem, len_rtx, GEN_INT (c), | 3810 else if (!set_storage_via_setmem (dest_mem, len_rtx, GEN_INT (c), |
4046 dest_align, expected_align, | 3811 dest_align, expected_align, |
4047 expected_size)) | 3812 expected_size)) |
4048 goto do_libcall; | 3813 goto do_libcall; |
4049 | 3814 |
4050 dest_mem = force_operand (XEXP (dest_mem, 0), NULL_RTX); | 3815 dest_mem = force_operand (XEXP (dest_mem, 0), NULL_RTX); |
4051 dest_mem = convert_memory_address (ptr_mode, dest_mem); | 3816 dest_mem = convert_memory_address (ptr_mode, dest_mem); |
4052 return dest_mem; | 3817 return dest_mem; |
4053 } | 3818 } |
4054 | 3819 |
4068 | 3833 |
4069 do_libcall: | 3834 do_libcall: |
4070 fndecl = get_callee_fndecl (orig_exp); | 3835 fndecl = get_callee_fndecl (orig_exp); |
4071 fcode = DECL_FUNCTION_CODE (fndecl); | 3836 fcode = DECL_FUNCTION_CODE (fndecl); |
4072 if (fcode == BUILT_IN_MEMSET) | 3837 if (fcode == BUILT_IN_MEMSET) |
4073 fn = build_call_expr (fndecl, 3, dest, val, len); | 3838 fn = build_call_nofold (fndecl, 3, dest, val, len); |
4074 else if (fcode == BUILT_IN_BZERO) | 3839 else if (fcode == BUILT_IN_BZERO) |
4075 fn = build_call_expr (fndecl, 2, dest, len); | 3840 fn = build_call_nofold (fndecl, 2, dest, len); |
4076 else | 3841 else |
4077 gcc_unreachable (); | 3842 gcc_unreachable (); |
4078 if (TREE_CODE (fn) == CALL_EXPR) | 3843 gcc_assert (TREE_CODE (fn) == CALL_EXPR); |
4079 CALL_EXPR_TAILCALL (fn) = CALL_EXPR_TAILCALL (orig_exp); | 3844 CALL_EXPR_TAILCALL (fn) = CALL_EXPR_TAILCALL (orig_exp); |
4080 return expand_call (fn, target, target == const0_rtx); | 3845 return expand_call (fn, target, target == const0_rtx); |
4081 } | 3846 } |
4082 | 3847 |
4083 /* Expand expression EXP, which is a call to the bzero builtin. Return | 3848 /* Expand expression EXP, which is a call to the bzero builtin. Return |
4084 NULL_RTX if we failed the caller should emit a normal call. */ | 3849 NULL_RTX if we failed the caller should emit a normal call. */ |
4085 | 3850 |
4086 static rtx | 3851 static rtx |
4087 expand_builtin_bzero (tree exp) | 3852 expand_builtin_bzero (tree exp) |
4088 { | 3853 { |
4089 tree dest, size; | 3854 tree dest, size; |
3855 location_t loc = EXPR_LOCATION (exp); | |
4090 | 3856 |
4091 if (!validate_arglist (exp, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE)) | 3857 if (!validate_arglist (exp, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE)) |
4092 return NULL_RTX; | 3858 return NULL_RTX; |
4093 | 3859 |
4094 dest = CALL_EXPR_ARG (exp, 0); | 3860 dest = CALL_EXPR_ARG (exp, 0); |
4098 memset(ptr x, int 0, size_t y). This is done this way | 3864 memset(ptr x, int 0, size_t y). This is done this way |
4099 so that if it isn't expanded inline, we fallback to | 3865 so that if it isn't expanded inline, we fallback to |
4100 calling bzero instead of memset. */ | 3866 calling bzero instead of memset. */ |
4101 | 3867 |
4102 return expand_builtin_memset_args (dest, integer_zero_node, | 3868 return expand_builtin_memset_args (dest, integer_zero_node, |
4103 fold_convert (sizetype, size), | 3869 fold_convert_loc (loc, sizetype, size), |
4104 const0_rtx, VOIDmode, exp); | 3870 const0_rtx, VOIDmode, exp); |
4105 } | |
4106 | |
4107 /* Expand a call to the memchr builtin. Return NULL_RTX if we failed the | |
4108 caller should emit a normal call, otherwise try to get the result | |
4109 in TARGET, if convenient (and in mode MODE if that's convenient). */ | |
4110 | |
4111 static rtx | |
4112 expand_builtin_memchr (tree exp, rtx target, enum machine_mode mode) | |
4113 { | |
4114 if (validate_arglist (exp, POINTER_TYPE, INTEGER_TYPE, | |
4115 INTEGER_TYPE, VOID_TYPE)) | |
4116 { | |
4117 tree type = TREE_TYPE (exp); | |
4118 tree result = fold_builtin_memchr (CALL_EXPR_ARG (exp, 0), | |
4119 CALL_EXPR_ARG (exp, 1), | |
4120 CALL_EXPR_ARG (exp, 2), type); | |
4121 if (result) | |
4122 return expand_expr (result, target, mode, EXPAND_NORMAL); | |
4123 } | |
4124 return NULL_RTX; | |
4125 } | 3871 } |
4126 | 3872 |
4127 /* Expand expression EXP, which is a call to the memcmp built-in function. | 3873 /* Expand expression EXP, which is a call to the memcmp built-in function. |
4128 Return NULL_RTX if we failed and the | 3874 Return NULL_RTX if we failed and the |
4129 caller should emit a normal call, otherwise try to get the result in | 3875 caller should emit a normal call, otherwise try to get the result in |
4130 TARGET, if convenient (and in mode MODE, if that's convenient). */ | 3876 TARGET, if convenient (and in mode MODE, if that's convenient). */ |
4131 | 3877 |
4132 static rtx | 3878 static rtx |
4133 expand_builtin_memcmp (tree exp, rtx target, enum machine_mode mode) | 3879 expand_builtin_memcmp (tree exp, ATTRIBUTE_UNUSED rtx target, |
4134 { | 3880 ATTRIBUTE_UNUSED enum machine_mode mode) |
3881 { | |
3882 location_t loc ATTRIBUTE_UNUSED = EXPR_LOCATION (exp); | |
3883 | |
4135 if (!validate_arglist (exp, | 3884 if (!validate_arglist (exp, |
4136 POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE)) | 3885 POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE)) |
4137 return NULL_RTX; | 3886 return NULL_RTX; |
4138 else | |
4139 { | |
4140 tree result = fold_builtin_memcmp (CALL_EXPR_ARG (exp, 0), | |
4141 CALL_EXPR_ARG (exp, 1), | |
4142 CALL_EXPR_ARG (exp, 2)); | |
4143 if (result) | |
4144 return expand_expr (result, target, mode, EXPAND_NORMAL); | |
4145 } | |
4146 | 3887 |
4147 #if defined HAVE_cmpmemsi || defined HAVE_cmpstrnsi | 3888 #if defined HAVE_cmpmemsi || defined HAVE_cmpstrnsi |
4148 { | 3889 { |
4149 rtx arg1_rtx, arg2_rtx, arg3_rtx; | 3890 rtx arg1_rtx, arg2_rtx, arg3_rtx; |
4150 rtx result; | 3891 rtx result; |
4182 && REGNO (result) >= FIRST_PSEUDO_REGISTER)) | 3923 && REGNO (result) >= FIRST_PSEUDO_REGISTER)) |
4183 result = gen_reg_rtx (insn_mode); | 3924 result = gen_reg_rtx (insn_mode); |
4184 | 3925 |
4185 arg1_rtx = get_memory_rtx (arg1, len); | 3926 arg1_rtx = get_memory_rtx (arg1, len); |
4186 arg2_rtx = get_memory_rtx (arg2, len); | 3927 arg2_rtx = get_memory_rtx (arg2, len); |
4187 arg3_rtx = expand_normal (fold_convert (sizetype, len)); | 3928 arg3_rtx = expand_normal (fold_convert_loc (loc, sizetype, len)); |
4188 | 3929 |
4189 /* Set MEM_SIZE as appropriate. */ | 3930 /* Set MEM_SIZE as appropriate. */ |
4190 if (GET_CODE (arg3_rtx) == CONST_INT) | 3931 if (CONST_INT_P (arg3_rtx)) |
4191 { | 3932 { |
4192 set_mem_size (arg1_rtx, arg3_rtx); | 3933 set_mem_size (arg1_rtx, arg3_rtx); |
4193 set_mem_size (arg2_rtx, arg3_rtx); | 3934 set_mem_size (arg2_rtx, arg3_rtx); |
4194 } | 3935 } |
4195 | 3936 |
4238 /* Expand expression EXP, which is a call to the strcmp builtin. Return NULL_RTX | 3979 /* Expand expression EXP, which is a call to the strcmp builtin. Return NULL_RTX |
4239 if we failed the caller should emit a normal call, otherwise try to get | 3980 if we failed the caller should emit a normal call, otherwise try to get |
4240 the result in TARGET, if convenient. */ | 3981 the result in TARGET, if convenient. */ |
4241 | 3982 |
4242 static rtx | 3983 static rtx |
4243 expand_builtin_strcmp (tree exp, rtx target, enum machine_mode mode) | 3984 expand_builtin_strcmp (tree exp, ATTRIBUTE_UNUSED rtx target) |
4244 { | 3985 { |
4245 if (!validate_arglist (exp, POINTER_TYPE, POINTER_TYPE, VOID_TYPE)) | 3986 if (!validate_arglist (exp, POINTER_TYPE, POINTER_TYPE, VOID_TYPE)) |
4246 return NULL_RTX; | 3987 return NULL_RTX; |
4247 else | |
4248 { | |
4249 tree result = fold_builtin_strcmp (CALL_EXPR_ARG (exp, 0), | |
4250 CALL_EXPR_ARG (exp, 1)); | |
4251 if (result) | |
4252 return expand_expr (result, target, mode, EXPAND_NORMAL); | |
4253 } | |
4254 | 3988 |
4255 #if defined HAVE_cmpstrsi || defined HAVE_cmpstrnsi | 3989 #if defined HAVE_cmpstrsi || defined HAVE_cmpstrnsi |
4256 if (cmpstr_optab[SImode] != CODE_FOR_nothing | 3990 if (cmpstr_optab[SImode] != CODE_FOR_nothing |
4257 || cmpstrn_optab[SImode] != CODE_FOR_nothing) | 3991 || cmpstrn_optab[SImode] != CODE_FOR_nothing) |
4258 { | 3992 { |
4355 } | 4089 } |
4356 #endif | 4090 #endif |
4357 | 4091 |
4358 if (insn) | 4092 if (insn) |
4359 { | 4093 { |
4094 enum machine_mode mode; | |
4360 emit_insn (insn); | 4095 emit_insn (insn); |
4361 | 4096 |
4362 /* Return the value in the proper mode for this function. */ | 4097 /* Return the value in the proper mode for this function. */ |
4363 mode = TYPE_MODE (TREE_TYPE (exp)); | 4098 mode = TYPE_MODE (TREE_TYPE (exp)); |
4364 if (GET_MODE (result) == mode) | 4099 if (GET_MODE (result) == mode) |
4373 list to avoid re-evaluating the function's arguments twice. */ | 4108 list to avoid re-evaluating the function's arguments twice. */ |
4374 #ifdef HAVE_cmpstrnsi | 4109 #ifdef HAVE_cmpstrnsi |
4375 do_libcall: | 4110 do_libcall: |
4376 #endif | 4111 #endif |
4377 fndecl = get_callee_fndecl (exp); | 4112 fndecl = get_callee_fndecl (exp); |
4378 fn = build_call_expr (fndecl, 2, arg1, arg2); | 4113 fn = build_call_nofold (fndecl, 2, arg1, arg2); |
4379 if (TREE_CODE (fn) == CALL_EXPR) | 4114 gcc_assert (TREE_CODE (fn) == CALL_EXPR); |
4380 CALL_EXPR_TAILCALL (fn) = CALL_EXPR_TAILCALL (exp); | 4115 CALL_EXPR_TAILCALL (fn) = CALL_EXPR_TAILCALL (exp); |
4381 return expand_call (fn, target, target == const0_rtx); | 4116 return expand_call (fn, target, target == const0_rtx); |
4382 } | 4117 } |
4383 #endif | 4118 #endif |
4384 return NULL_RTX; | 4119 return NULL_RTX; |
4385 } | 4120 } |
4386 | 4121 |
4387 /* Expand expression EXP, which is a call to the strncmp builtin. Return | 4122 /* Expand expression EXP, which is a call to the strncmp builtin. Return |
4388 NULL_RTX if we failed the caller should emit a normal call, otherwise try to get | 4123 NULL_RTX if we failed the caller should emit a normal call, otherwise try to get |
4389 the result in TARGET, if convenient. */ | 4124 the result in TARGET, if convenient. */ |
4390 | 4125 |
4391 static rtx | 4126 static rtx |
4392 expand_builtin_strncmp (tree exp, rtx target, enum machine_mode mode) | 4127 expand_builtin_strncmp (tree exp, ATTRIBUTE_UNUSED rtx target, |
4393 { | 4128 ATTRIBUTE_UNUSED enum machine_mode mode) |
4129 { | |
4130 location_t loc ATTRIBUTE_UNUSED = EXPR_LOCATION (exp); | |
4131 | |
4394 if (!validate_arglist (exp, | 4132 if (!validate_arglist (exp, |
4395 POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE)) | 4133 POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE)) |
4396 return NULL_RTX; | 4134 return NULL_RTX; |
4397 else | |
4398 { | |
4399 tree result = fold_builtin_strncmp (CALL_EXPR_ARG (exp, 0), | |
4400 CALL_EXPR_ARG (exp, 1), | |
4401 CALL_EXPR_ARG (exp, 2)); | |
4402 if (result) | |
4403 return expand_expr (result, target, mode, EXPAND_NORMAL); | |
4404 } | |
4405 | 4135 |
4406 /* If c_strlen can determine an expression for one of the string | 4136 /* If c_strlen can determine an expression for one of the string |
4407 lengths, and it doesn't have side effects, then emit cmpstrnsi | 4137 lengths, and it doesn't have side effects, then emit cmpstrnsi |
4408 using length MIN(strlen(string)+1, arg3). */ | 4138 using length MIN(strlen(string)+1, arg3). */ |
4409 #ifdef HAVE_cmpstrnsi | 4139 #ifdef HAVE_cmpstrnsi |
4426 | 4156 |
4427 len1 = c_strlen (arg1, 1); | 4157 len1 = c_strlen (arg1, 1); |
4428 len2 = c_strlen (arg2, 1); | 4158 len2 = c_strlen (arg2, 1); |
4429 | 4159 |
4430 if (len1) | 4160 if (len1) |
4431 len1 = size_binop (PLUS_EXPR, ssize_int (1), len1); | 4161 len1 = size_binop_loc (loc, PLUS_EXPR, ssize_int (1), len1); |
4432 if (len2) | 4162 if (len2) |
4433 len2 = size_binop (PLUS_EXPR, ssize_int (1), len2); | 4163 len2 = size_binop_loc (loc, PLUS_EXPR, ssize_int (1), len2); |
4434 | 4164 |
4435 /* If we don't have a constant length for the first, use the length | 4165 /* If we don't have a constant length for the first, use the length |
4436 of the second, if we know it. We don't require a constant for | 4166 of the second, if we know it. We don't require a constant for |
4437 this case; some cost analysis could be done if both are available | 4167 this case; some cost analysis could be done if both are available |
4438 but neither is constant. For now, assume they're equally cheap, | 4168 but neither is constant. For now, assume they're equally cheap, |
4459 /* If both arguments have side effects, we cannot optimize. */ | 4189 /* If both arguments have side effects, we cannot optimize. */ |
4460 if (!len || TREE_SIDE_EFFECTS (len)) | 4190 if (!len || TREE_SIDE_EFFECTS (len)) |
4461 return NULL_RTX; | 4191 return NULL_RTX; |
4462 | 4192 |
4463 /* The actual new length parameter is MIN(len,arg3). */ | 4193 /* The actual new length parameter is MIN(len,arg3). */ |
4464 len = fold_build2 (MIN_EXPR, TREE_TYPE (len), len, | 4194 len = fold_build2_loc (loc, MIN_EXPR, TREE_TYPE (len), len, |
4465 fold_convert (TREE_TYPE (len), arg3)); | 4195 fold_convert_loc (loc, TREE_TYPE (len), arg3)); |
4466 | 4196 |
4467 /* If we don't have POINTER_TYPE, call the function. */ | 4197 /* If we don't have POINTER_TYPE, call the function. */ |
4468 if (arg1_align == 0 || arg2_align == 0) | 4198 if (arg1_align == 0 || arg2_align == 0) |
4469 return NULL_RTX; | 4199 return NULL_RTX; |
4470 | 4200 |
4500 } | 4230 } |
4501 | 4231 |
4502 /* Expand the library call ourselves using a stabilized argument | 4232 /* Expand the library call ourselves using a stabilized argument |
4503 list to avoid re-evaluating the function's arguments twice. */ | 4233 list to avoid re-evaluating the function's arguments twice. */ |
4504 fndecl = get_callee_fndecl (exp); | 4234 fndecl = get_callee_fndecl (exp); |
4505 fn = build_call_expr (fndecl, 3, arg1, arg2, len); | 4235 fn = build_call_nofold (fndecl, 3, arg1, arg2, len); |
4506 if (TREE_CODE (fn) == CALL_EXPR) | 4236 gcc_assert (TREE_CODE (fn) == CALL_EXPR); |
4507 CALL_EXPR_TAILCALL (fn) = CALL_EXPR_TAILCALL (exp); | 4237 CALL_EXPR_TAILCALL (fn) = CALL_EXPR_TAILCALL (exp); |
4508 return expand_call (fn, target, target == const0_rtx); | 4238 return expand_call (fn, target, target == const0_rtx); |
4509 } | 4239 } |
4510 #endif | 4240 #endif |
4511 return NULL_RTX; | |
4512 } | |
4513 | |
4514 /* Expand expression EXP, which is a call to the strcat builtin. | |
4515 Return NULL_RTX if we failed the caller should emit a normal call, | |
4516 otherwise try to get the result in TARGET, if convenient. */ | |
4517 | |
4518 static rtx | |
4519 expand_builtin_strcat (tree fndecl, tree exp, rtx target, enum machine_mode mode) | |
4520 { | |
4521 if (!validate_arglist (exp, POINTER_TYPE, POINTER_TYPE, VOID_TYPE)) | |
4522 return NULL_RTX; | |
4523 else | |
4524 { | |
4525 tree dst = CALL_EXPR_ARG (exp, 0); | |
4526 tree src = CALL_EXPR_ARG (exp, 1); | |
4527 const char *p = c_getstr (src); | |
4528 | |
4529 /* If the string length is zero, return the dst parameter. */ | |
4530 if (p && *p == '\0') | |
4531 return expand_expr (dst, target, mode, EXPAND_NORMAL); | |
4532 | |
4533 if (optimize_insn_for_speed_p ()) | |
4534 { | |
4535 /* See if we can store by pieces into (dst + strlen(dst)). */ | |
4536 tree newsrc, newdst, | |
4537 strlen_fn = implicit_built_in_decls[BUILT_IN_STRLEN]; | |
4538 rtx insns; | |
4539 | |
4540 /* Stabilize the argument list. */ | |
4541 newsrc = builtin_save_expr (src); | |
4542 dst = builtin_save_expr (dst); | |
4543 | |
4544 start_sequence (); | |
4545 | |
4546 /* Create strlen (dst). */ | |
4547 newdst = build_call_expr (strlen_fn, 1, dst); | |
4548 /* Create (dst p+ strlen (dst)). */ | |
4549 | |
4550 newdst = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (dst), dst, newdst); | |
4551 newdst = builtin_save_expr (newdst); | |
4552 | |
4553 if (!expand_builtin_strcpy_args (fndecl, newdst, newsrc, target, mode)) | |
4554 { | |
4555 end_sequence (); /* Stop sequence. */ | |
4556 return NULL_RTX; | |
4557 } | |
4558 | |
4559 /* Output the entire sequence. */ | |
4560 insns = get_insns (); | |
4561 end_sequence (); | |
4562 emit_insn (insns); | |
4563 | |
4564 return expand_expr (dst, target, mode, EXPAND_NORMAL); | |
4565 } | |
4566 | |
4567 return NULL_RTX; | |
4568 } | |
4569 } | |
4570 | |
4571 /* Expand expression EXP, which is a call to the strncat builtin. | |
4572 Return NULL_RTX if we failed the caller should emit a normal call, | |
4573 otherwise try to get the result in TARGET, if convenient. */ | |
4574 | |
4575 static rtx | |
4576 expand_builtin_strncat (tree exp, rtx target, enum machine_mode mode) | |
4577 { | |
4578 if (validate_arglist (exp, | |
4579 POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE)) | |
4580 { | |
4581 tree result = fold_builtin_strncat (CALL_EXPR_ARG (exp, 0), | |
4582 CALL_EXPR_ARG (exp, 1), | |
4583 CALL_EXPR_ARG (exp, 2)); | |
4584 if (result) | |
4585 return expand_expr (result, target, mode, EXPAND_NORMAL); | |
4586 } | |
4587 return NULL_RTX; | |
4588 } | |
4589 | |
4590 /* Expand expression EXP, which is a call to the strspn builtin. | |
4591 Return NULL_RTX if we failed the caller should emit a normal call, | |
4592 otherwise try to get the result in TARGET, if convenient. */ | |
4593 | |
4594 static rtx | |
4595 expand_builtin_strspn (tree exp, rtx target, enum machine_mode mode) | |
4596 { | |
4597 if (validate_arglist (exp, POINTER_TYPE, POINTER_TYPE, VOID_TYPE)) | |
4598 { | |
4599 tree result = fold_builtin_strspn (CALL_EXPR_ARG (exp, 0), | |
4600 CALL_EXPR_ARG (exp, 1)); | |
4601 if (result) | |
4602 return expand_expr (result, target, mode, EXPAND_NORMAL); | |
4603 } | |
4604 return NULL_RTX; | |
4605 } | |
4606 | |
4607 /* Expand expression EXP, which is a call to the strcspn builtin. | |
4608 Return NULL_RTX if we failed the caller should emit a normal call, | |
4609 otherwise try to get the result in TARGET, if convenient. */ | |
4610 | |
4611 static rtx | |
4612 expand_builtin_strcspn (tree exp, rtx target, enum machine_mode mode) | |
4613 { | |
4614 if (validate_arglist (exp, POINTER_TYPE, POINTER_TYPE, VOID_TYPE)) | |
4615 { | |
4616 tree result = fold_builtin_strcspn (CALL_EXPR_ARG (exp, 0), | |
4617 CALL_EXPR_ARG (exp, 1)); | |
4618 if (result) | |
4619 return expand_expr (result, target, mode, EXPAND_NORMAL); | |
4620 } | |
4621 return NULL_RTX; | 4241 return NULL_RTX; |
4622 } | 4242 } |
4623 | 4243 |
4624 /* Expand a call to __builtin_saveregs, generating the result in TARGET, | 4244 /* Expand a call to __builtin_saveregs, generating the result in TARGET, |
4625 if that's convenient. */ | 4245 if that's convenient. */ |
4705 | 4325 |
4706 /* Make it easier for the backends by protecting the valist argument | 4326 /* Make it easier for the backends by protecting the valist argument |
4707 from multiple evaluations. */ | 4327 from multiple evaluations. */ |
4708 | 4328 |
4709 static tree | 4329 static tree |
4710 stabilize_va_list (tree valist, int needs_lvalue) | 4330 stabilize_va_list_loc (location_t loc, tree valist, int needs_lvalue) |
4711 { | 4331 { |
4712 tree vatype = targetm.canonical_va_list_type (TREE_TYPE (valist)); | 4332 tree vatype = targetm.canonical_va_list_type (TREE_TYPE (valist)); |
4713 | 4333 |
4714 gcc_assert (vatype != NULL_TREE); | 4334 gcc_assert (vatype != NULL_TREE); |
4715 | 4335 |
4723 (an actual TARGET_CANONICAL_VA_LIST_TYPE (valist)). | 4343 (an actual TARGET_CANONICAL_VA_LIST_TYPE (valist)). |
4724 So fix it. */ | 4344 So fix it. */ |
4725 if (TREE_CODE (TREE_TYPE (valist)) == ARRAY_TYPE) | 4345 if (TREE_CODE (TREE_TYPE (valist)) == ARRAY_TYPE) |
4726 { | 4346 { |
4727 tree p1 = build_pointer_type (TREE_TYPE (vatype)); | 4347 tree p1 = build_pointer_type (TREE_TYPE (vatype)); |
4728 valist = build_fold_addr_expr_with_type (valist, p1); | 4348 valist = build_fold_addr_expr_with_type_loc (loc, valist, p1); |
4729 } | 4349 } |
4730 } | 4350 } |
4731 else | 4351 else |
4732 { | 4352 { |
4733 tree pt; | 4353 tree pt; |
4736 { | 4356 { |
4737 if (! TREE_SIDE_EFFECTS (valist)) | 4357 if (! TREE_SIDE_EFFECTS (valist)) |
4738 return valist; | 4358 return valist; |
4739 | 4359 |
4740 pt = build_pointer_type (vatype); | 4360 pt = build_pointer_type (vatype); |
4741 valist = fold_build1 (ADDR_EXPR, pt, valist); | 4361 valist = fold_build1_loc (loc, ADDR_EXPR, pt, valist); |
4742 TREE_SIDE_EFFECTS (valist) = 1; | 4362 TREE_SIDE_EFFECTS (valist) = 1; |
4743 } | 4363 } |
4744 | 4364 |
4745 if (TREE_SIDE_EFFECTS (valist)) | 4365 if (TREE_SIDE_EFFECTS (valist)) |
4746 valist = save_expr (valist); | 4366 valist = save_expr (valist); |
4747 valist = build_fold_indirect_ref (valist); | 4367 valist = build_fold_indirect_ref_loc (loc, valist); |
4748 } | 4368 } |
4749 | 4369 |
4750 return valist; | 4370 return valist; |
4751 } | 4371 } |
4752 | 4372 |
4816 static rtx | 4436 static rtx |
4817 expand_builtin_va_start (tree exp) | 4437 expand_builtin_va_start (tree exp) |
4818 { | 4438 { |
4819 rtx nextarg; | 4439 rtx nextarg; |
4820 tree valist; | 4440 tree valist; |
4441 location_t loc = EXPR_LOCATION (exp); | |
4821 | 4442 |
4822 if (call_expr_nargs (exp) < 2) | 4443 if (call_expr_nargs (exp) < 2) |
4823 { | 4444 { |
4824 error ("too few arguments to function %<va_start%>"); | 4445 error_at (loc, "too few arguments to function %<va_start%>"); |
4825 return const0_rtx; | 4446 return const0_rtx; |
4826 } | 4447 } |
4827 | 4448 |
4828 if (fold_builtin_next_arg (exp, true)) | 4449 if (fold_builtin_next_arg (exp, true)) |
4829 return const0_rtx; | 4450 return const0_rtx; |
4830 | 4451 |
4831 nextarg = expand_builtin_next_arg (); | 4452 nextarg = expand_builtin_next_arg (); |
4832 valist = stabilize_va_list (CALL_EXPR_ARG (exp, 0), 1); | 4453 valist = stabilize_va_list_loc (loc, CALL_EXPR_ARG (exp, 0), 1); |
4833 | 4454 |
4834 if (targetm.expand_builtin_va_start) | 4455 if (targetm.expand_builtin_va_start) |
4835 targetm.expand_builtin_va_start (valist, nextarg); | 4456 targetm.expand_builtin_va_start (valist, nextarg); |
4836 else | 4457 else |
4837 std_expand_builtin_va_start (valist, nextarg); | 4458 std_expand_builtin_va_start (valist, nextarg); |
4880 requires greater alignment, we must perform dynamic alignment. */ | 4501 requires greater alignment, we must perform dynamic alignment. */ |
4881 if (boundary > align | 4502 if (boundary > align |
4882 && !integer_zerop (TYPE_SIZE (type))) | 4503 && !integer_zerop (TYPE_SIZE (type))) |
4883 { | 4504 { |
4884 t = build2 (MODIFY_EXPR, TREE_TYPE (valist), valist_tmp, | 4505 t = build2 (MODIFY_EXPR, TREE_TYPE (valist), valist_tmp, |
4885 fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (valist), | 4506 fold_build2 (POINTER_PLUS_EXPR, |
4507 TREE_TYPE (valist), | |
4886 valist_tmp, size_int (boundary - 1))); | 4508 valist_tmp, size_int (boundary - 1))); |
4887 gimplify_and_add (t, pre_p); | 4509 gimplify_and_add (t, pre_p); |
4888 | 4510 |
4889 t = fold_convert (sizetype, valist_tmp); | 4511 t = fold_convert (sizetype, valist_tmp); |
4890 t = build2 (MODIFY_EXPR, TREE_TYPE (valist), valist_tmp, | 4512 t = build2 (MODIFY_EXPR, TREE_TYPE (valist), valist_tmp, |
4916 /* Get AP. */ | 4538 /* Get AP. */ |
4917 addr = valist_tmp; | 4539 addr = valist_tmp; |
4918 if (PAD_VARARGS_DOWN && !integer_zerop (rounded_size)) | 4540 if (PAD_VARARGS_DOWN && !integer_zerop (rounded_size)) |
4919 { | 4541 { |
4920 /* Small args are padded downward. */ | 4542 /* Small args are padded downward. */ |
4921 t = fold_build2 (GT_EXPR, sizetype, rounded_size, size_int (align)); | 4543 t = fold_build2_loc (input_location, GT_EXPR, sizetype, |
4544 rounded_size, size_int (align)); | |
4922 t = fold_build3 (COND_EXPR, sizetype, t, size_zero_node, | 4545 t = fold_build3 (COND_EXPR, sizetype, t, size_zero_node, |
4923 size_binop (MINUS_EXPR, rounded_size, type_size)); | 4546 size_binop (MINUS_EXPR, rounded_size, type_size)); |
4924 addr = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (addr), addr, t); | 4547 addr = fold_build2 (POINTER_PLUS_EXPR, |
4548 TREE_TYPE (addr), addr, t); | |
4925 } | 4549 } |
4926 | 4550 |
4927 /* Compute new value for AP. */ | 4551 /* Compute new value for AP. */ |
4928 t = build2 (POINTER_PLUS_EXPR, TREE_TYPE (valist), valist_tmp, rounded_size); | 4552 t = build2 (POINTER_PLUS_EXPR, TREE_TYPE (valist), valist_tmp, rounded_size); |
4929 t = build2 (MODIFY_EXPR, TREE_TYPE (valist), valist, t); | 4553 t = build2 (MODIFY_EXPR, TREE_TYPE (valist), valist, t); |
4940 /* Build an indirect-ref expression over the given TREE, which represents a | 4564 /* Build an indirect-ref expression over the given TREE, which represents a |
4941 piece of a va_arg() expansion. */ | 4565 piece of a va_arg() expansion. */ |
4942 tree | 4566 tree |
4943 build_va_arg_indirect_ref (tree addr) | 4567 build_va_arg_indirect_ref (tree addr) |
4944 { | 4568 { |
4945 addr = build_fold_indirect_ref (addr); | 4569 addr = build_fold_indirect_ref_loc (EXPR_LOCATION (addr), addr); |
4946 | 4570 |
4947 if (flag_mudflap) /* Don't instrument va_arg INDIRECT_REF. */ | 4571 if (flag_mudflap) /* Don't instrument va_arg INDIRECT_REF. */ |
4948 mf_mark (addr); | 4572 mf_mark (addr); |
4949 | 4573 |
4950 return addr; | 4574 return addr; |
4968 { | 4592 { |
4969 tree promoted_type, have_va_type; | 4593 tree promoted_type, have_va_type; |
4970 tree valist = TREE_OPERAND (*expr_p, 0); | 4594 tree valist = TREE_OPERAND (*expr_p, 0); |
4971 tree type = TREE_TYPE (*expr_p); | 4595 tree type = TREE_TYPE (*expr_p); |
4972 tree t; | 4596 tree t; |
4597 location_t loc = EXPR_LOCATION (*expr_p); | |
4973 | 4598 |
4974 /* Verify that valist is of the proper type. */ | 4599 /* Verify that valist is of the proper type. */ |
4975 have_va_type = TREE_TYPE (valist); | 4600 have_va_type = TREE_TYPE (valist); |
4976 if (have_va_type == error_mark_node) | 4601 if (have_va_type == error_mark_node) |
4977 return GS_ERROR; | 4602 return GS_ERROR; |
4978 have_va_type = targetm.canonical_va_list_type (have_va_type); | 4603 have_va_type = targetm.canonical_va_list_type (have_va_type); |
4979 | 4604 |
4980 if (have_va_type == NULL_TREE) | 4605 if (have_va_type == NULL_TREE) |
4981 { | 4606 { |
4982 error ("first argument to %<va_arg%> not of type %<va_list%>"); | 4607 error_at (loc, "first argument to %<va_arg%> not of type %<va_list%>"); |
4983 return GS_ERROR; | 4608 return GS_ERROR; |
4984 } | 4609 } |
4985 | 4610 |
4986 /* Generate a diagnostic for requesting data of a type that cannot | 4611 /* Generate a diagnostic for requesting data of a type that cannot |
4987 be passed through `...' due to type promotion at the call site. */ | 4612 be passed through `...' due to type promotion at the call site. */ |
4992 bool warned; | 4617 bool warned; |
4993 | 4618 |
4994 /* Unfortunately, this is merely undefined, rather than a constraint | 4619 /* Unfortunately, this is merely undefined, rather than a constraint |
4995 violation, so we cannot make this an error. If this call is never | 4620 violation, so we cannot make this an error. If this call is never |
4996 executed, the program is still strictly conforming. */ | 4621 executed, the program is still strictly conforming. */ |
4997 warned = warning (0, "%qT is promoted to %qT when passed through %<...%>", | 4622 warned = warning_at (loc, 0, |
4998 type, promoted_type); | 4623 "%qT is promoted to %qT when passed through %<...%>", |
4624 type, promoted_type); | |
4999 if (!gave_help && warned) | 4625 if (!gave_help && warned) |
5000 { | 4626 { |
5001 gave_help = true; | 4627 gave_help = true; |
5002 inform (input_location, "(so you should pass %qT not %qT to %<va_arg%>)", | 4628 inform (loc, "(so you should pass %qT not %qT to %<va_arg%>)", |
5003 promoted_type, type); | 4629 promoted_type, type); |
5004 } | 4630 } |
5005 | 4631 |
5006 /* We can, however, treat "undefined" any way we please. | 4632 /* We can, however, treat "undefined" any way we please. |
5007 Call abort to encourage the user to fix the program. */ | 4633 Call abort to encourage the user to fix the program. */ |
5008 if (warned) | 4634 if (warned) |
5009 inform (input_location, "if this code is reached, the program will abort"); | 4635 inform (loc, "if this code is reached, the program will abort"); |
5010 /* Before the abort, allow the evaluation of the va_list | 4636 /* Before the abort, allow the evaluation of the va_list |
5011 expression to exit or longjmp. */ | 4637 expression to exit or longjmp. */ |
5012 gimplify_and_add (valist, pre_p); | 4638 gimplify_and_add (valist, pre_p); |
5013 t = build_call_expr (implicit_built_in_decls[BUILT_IN_TRAP], 0); | 4639 t = build_call_expr_loc (loc, |
4640 implicit_built_in_decls[BUILT_IN_TRAP], 0); | |
5014 gimplify_and_add (t, pre_p); | 4641 gimplify_and_add (t, pre_p); |
5015 | 4642 |
5016 /* This is dead code, but go ahead and finish so that the | 4643 /* This is dead code, but go ahead and finish so that the |
5017 mode of the result comes out right. */ | 4644 mode of the result comes out right. */ |
5018 *expr_p = dummy_object (type); | 4645 *expr_p = dummy_object (type); |
5029 actually been given an array (an actual TARGET_FN_ABI_VA_LIST). | 4656 actually been given an array (an actual TARGET_FN_ABI_VA_LIST). |
5030 So fix it. */ | 4657 So fix it. */ |
5031 if (TREE_CODE (TREE_TYPE (valist)) == ARRAY_TYPE) | 4658 if (TREE_CODE (TREE_TYPE (valist)) == ARRAY_TYPE) |
5032 { | 4659 { |
5033 tree p1 = build_pointer_type (TREE_TYPE (have_va_type)); | 4660 tree p1 = build_pointer_type (TREE_TYPE (have_va_type)); |
5034 valist = build_fold_addr_expr_with_type (valist, p1); | 4661 valist = fold_convert_loc (loc, p1, |
4662 build_fold_addr_expr_loc (loc, valist)); | |
5035 } | 4663 } |
5036 | 4664 |
5037 gimplify_expr (&valist, pre_p, post_p, is_gimple_val, fb_rvalue); | 4665 gimplify_expr (&valist, pre_p, post_p, is_gimple_val, fb_rvalue); |
5038 } | 4666 } |
5039 else | 4667 else |
5070 | 4698 |
5071 static rtx | 4699 static rtx |
5072 expand_builtin_va_copy (tree exp) | 4700 expand_builtin_va_copy (tree exp) |
5073 { | 4701 { |
5074 tree dst, src, t; | 4702 tree dst, src, t; |
4703 location_t loc = EXPR_LOCATION (exp); | |
5075 | 4704 |
5076 dst = CALL_EXPR_ARG (exp, 0); | 4705 dst = CALL_EXPR_ARG (exp, 0); |
5077 src = CALL_EXPR_ARG (exp, 1); | 4706 src = CALL_EXPR_ARG (exp, 1); |
5078 | 4707 |
5079 dst = stabilize_va_list (dst, 1); | 4708 dst = stabilize_va_list_loc (loc, dst, 1); |
5080 src = stabilize_va_list (src, 0); | 4709 src = stabilize_va_list_loc (loc, src, 0); |
5081 | 4710 |
5082 gcc_assert (cfun != NULL && cfun->decl != NULL_TREE); | 4711 gcc_assert (cfun != NULL && cfun->decl != NULL_TREE); |
5083 | 4712 |
5084 if (TREE_CODE (targetm.fn_abi_va_list (cfun->decl)) != ARRAY_TYPE) | 4713 if (TREE_CODE (targetm.fn_abi_va_list (cfun->decl)) != ARRAY_TYPE) |
5085 { | 4714 { |
5170 expand_builtin_alloca (tree exp, rtx target) | 4799 expand_builtin_alloca (tree exp, rtx target) |
5171 { | 4800 { |
5172 rtx op0; | 4801 rtx op0; |
5173 rtx result; | 4802 rtx result; |
5174 | 4803 |
5175 /* In -fmudflap-instrumented code, alloca() and __builtin_alloca() | 4804 /* Emit normal call if marked not-inlineable. */ |
5176 should always expand to function calls. These can be intercepted | 4805 if (CALL_CANNOT_INLINE_P (exp)) |
5177 in libmudflap. */ | |
5178 if (flag_mudflap) | |
5179 return NULL_RTX; | 4806 return NULL_RTX; |
5180 | 4807 |
5181 if (!validate_arglist (exp, INTEGER_TYPE, VOID_TYPE)) | 4808 if (!validate_arglist (exp, INTEGER_TYPE, VOID_TYPE)) |
5182 return NULL_RTX; | 4809 return NULL_RTX; |
5183 | 4810 |
5239 gcc_assert (target); | 4866 gcc_assert (target); |
5240 | 4867 |
5241 return convert_to_mode (target_mode, target, 0); | 4868 return convert_to_mode (target_mode, target, 0); |
5242 } | 4869 } |
5243 | 4870 |
5244 /* If the string passed to fputs is a constant and is one character | 4871 /* Expand a call to __builtin_expect. We just return our argument |
5245 long, we attempt to transform this call into __builtin_fputc(). */ | |
5246 | |
5247 static rtx | |
5248 expand_builtin_fputs (tree exp, rtx target, bool unlocked) | |
5249 { | |
5250 /* Verify the arguments in the original call. */ | |
5251 if (validate_arglist (exp, POINTER_TYPE, POINTER_TYPE, VOID_TYPE)) | |
5252 { | |
5253 tree result = fold_builtin_fputs (CALL_EXPR_ARG (exp, 0), | |
5254 CALL_EXPR_ARG (exp, 1), | |
5255 (target == const0_rtx), | |
5256 unlocked, NULL_TREE); | |
5257 if (result) | |
5258 return expand_expr (result, target, VOIDmode, EXPAND_NORMAL); | |
5259 } | |
5260 return NULL_RTX; | |
5261 } | |
5262 | |
5263 /* Expand a call to __builtin_expect. We just return our argument | |
5264 as the builtin_expect semantic should've been already executed by | 4872 as the builtin_expect semantic should've been already executed by |
5265 tree branch prediction pass. */ | 4873 tree branch prediction pass. */ |
5266 | 4874 |
5267 static rtx | 4875 static rtx |
5268 expand_builtin_expect (tree exp, rtx target) | 4876 expand_builtin_expect (tree exp, rtx target) |
5269 { | 4877 { |
5270 tree arg, c; | 4878 tree arg; |
5271 | 4879 |
5272 if (call_expr_nargs (exp) < 2) | 4880 if (call_expr_nargs (exp) < 2) |
5273 return const0_rtx; | 4881 return const0_rtx; |
5274 arg = CALL_EXPR_ARG (exp, 0); | 4882 arg = CALL_EXPR_ARG (exp, 0); |
5275 c = CALL_EXPR_ARG (exp, 1); | |
5276 | 4883 |
5277 target = expand_expr (arg, target, VOIDmode, EXPAND_NORMAL); | 4884 target = expand_expr (arg, target, VOIDmode, EXPAND_NORMAL); |
5278 /* When guessing was done, the hints should be already stripped away. */ | 4885 /* When guessing was done, the hints should be already stripped away. */ |
5279 gcc_assert (!flag_guess_branch_prob | 4886 gcc_assert (!flag_guess_branch_prob |
5280 || optimize == 0 || errorcount || sorrycount); | 4887 || optimize == 0 || errorcount || sorrycount); |
5288 if (HAVE_trap) | 4895 if (HAVE_trap) |
5289 emit_insn (gen_trap ()); | 4896 emit_insn (gen_trap ()); |
5290 else | 4897 else |
5291 #endif | 4898 #endif |
5292 emit_library_call (abort_libfunc, LCT_NORETURN, VOIDmode, 0); | 4899 emit_library_call (abort_libfunc, LCT_NORETURN, VOIDmode, 0); |
4900 emit_barrier (); | |
4901 } | |
4902 | |
4903 /* Expand a call to __builtin_unreachable. We do nothing except emit | |
4904 a barrier saying that control flow will not pass here. | |
4905 | |
4906 It is the responsibility of the program being compiled to ensure | |
4907 that control flow does never reach __builtin_unreachable. */ | |
4908 static void | |
4909 expand_builtin_unreachable (void) | |
4910 { | |
5293 emit_barrier (); | 4911 emit_barrier (); |
5294 } | 4912 } |
5295 | 4913 |
5296 /* Expand EXP, a call to fabs, fabsf or fabsl. | 4914 /* Expand EXP, a call to fabs, fabsf or fabsl. |
5297 Return NULL_RTX if a normal call should be emitted rather than expanding | 4915 Return NULL_RTX if a normal call should be emitted rather than expanding |
5358 type = build_pointer_type (elem); | 4976 type = build_pointer_type (elem); |
5359 t = build1 (ADDR_EXPR, type, | 4977 t = build1 (ADDR_EXPR, type, |
5360 build4 (ARRAY_REF, elem, | 4978 build4 (ARRAY_REF, elem, |
5361 t, integer_zero_node, NULL_TREE, NULL_TREE)); | 4979 t, integer_zero_node, NULL_TREE, NULL_TREE)); |
5362 return t; | 4980 return t; |
5363 } | |
5364 | |
5365 /* Expand EXP, a call to printf or printf_unlocked. | |
5366 Return NULL_RTX if a normal call should be emitted rather than transforming | |
5367 the function inline. If convenient, the result should be placed in | |
5368 TARGET with mode MODE. UNLOCKED indicates this is a printf_unlocked | |
5369 call. */ | |
5370 static rtx | |
5371 expand_builtin_printf (tree exp, rtx target, enum machine_mode mode, | |
5372 bool unlocked) | |
5373 { | |
5374 /* If we're using an unlocked function, assume the other unlocked | |
5375 functions exist explicitly. */ | |
5376 tree const fn_putchar = unlocked ? built_in_decls[BUILT_IN_PUTCHAR_UNLOCKED] | |
5377 : implicit_built_in_decls[BUILT_IN_PUTCHAR]; | |
5378 tree const fn_puts = unlocked ? built_in_decls[BUILT_IN_PUTS_UNLOCKED] | |
5379 : implicit_built_in_decls[BUILT_IN_PUTS]; | |
5380 const char *fmt_str; | |
5381 tree fn = 0; | |
5382 tree fmt, arg; | |
5383 int nargs = call_expr_nargs (exp); | |
5384 | |
5385 /* If the return value is used, don't do the transformation. */ | |
5386 if (target != const0_rtx) | |
5387 return NULL_RTX; | |
5388 | |
5389 /* Verify the required arguments in the original call. */ | |
5390 if (nargs == 0) | |
5391 return NULL_RTX; | |
5392 fmt = CALL_EXPR_ARG (exp, 0); | |
5393 if (! POINTER_TYPE_P (TREE_TYPE (fmt))) | |
5394 return NULL_RTX; | |
5395 | |
5396 /* Check whether the format is a literal string constant. */ | |
5397 fmt_str = c_getstr (fmt); | |
5398 if (fmt_str == NULL) | |
5399 return NULL_RTX; | |
5400 | |
5401 if (!init_target_chars ()) | |
5402 return NULL_RTX; | |
5403 | |
5404 /* If the format specifier was "%s\n", call __builtin_puts(arg). */ | |
5405 if (strcmp (fmt_str, target_percent_s_newline) == 0) | |
5406 { | |
5407 if ((nargs != 2) | |
5408 || ! POINTER_TYPE_P (TREE_TYPE (CALL_EXPR_ARG (exp, 1)))) | |
5409 return NULL_RTX; | |
5410 if (fn_puts) | |
5411 fn = build_call_expr (fn_puts, 1, CALL_EXPR_ARG (exp, 1)); | |
5412 } | |
5413 /* If the format specifier was "%c", call __builtin_putchar(arg). */ | |
5414 else if (strcmp (fmt_str, target_percent_c) == 0) | |
5415 { | |
5416 if ((nargs != 2) | |
5417 || TREE_CODE (TREE_TYPE (CALL_EXPR_ARG (exp, 1))) != INTEGER_TYPE) | |
5418 return NULL_RTX; | |
5419 if (fn_putchar) | |
5420 fn = build_call_expr (fn_putchar, 1, CALL_EXPR_ARG (exp, 1)); | |
5421 } | |
5422 else | |
5423 { | |
5424 /* We can't handle anything else with % args or %% ... yet. */ | |
5425 if (strchr (fmt_str, target_percent)) | |
5426 return NULL_RTX; | |
5427 | |
5428 if (nargs > 1) | |
5429 return NULL_RTX; | |
5430 | |
5431 /* If the format specifier was "", printf does nothing. */ | |
5432 if (fmt_str[0] == '\0') | |
5433 return const0_rtx; | |
5434 /* If the format specifier has length of 1, call putchar. */ | |
5435 if (fmt_str[1] == '\0') | |
5436 { | |
5437 /* Given printf("c"), (where c is any one character,) | |
5438 convert "c"[0] to an int and pass that to the replacement | |
5439 function. */ | |
5440 arg = build_int_cst (NULL_TREE, fmt_str[0]); | |
5441 if (fn_putchar) | |
5442 fn = build_call_expr (fn_putchar, 1, arg); | |
5443 } | |
5444 else | |
5445 { | |
5446 /* If the format specifier was "string\n", call puts("string"). */ | |
5447 size_t len = strlen (fmt_str); | |
5448 if ((unsigned char)fmt_str[len - 1] == target_newline) | |
5449 { | |
5450 /* Create a NUL-terminated string that's one char shorter | |
5451 than the original, stripping off the trailing '\n'. */ | |
5452 char *newstr = XALLOCAVEC (char, len); | |
5453 memcpy (newstr, fmt_str, len - 1); | |
5454 newstr[len - 1] = 0; | |
5455 arg = build_string_literal (len, newstr); | |
5456 if (fn_puts) | |
5457 fn = build_call_expr (fn_puts, 1, arg); | |
5458 } | |
5459 else | |
5460 /* We'd like to arrange to call fputs(string,stdout) here, | |
5461 but we need stdout and don't have a way to get it yet. */ | |
5462 return NULL_RTX; | |
5463 } | |
5464 } | |
5465 | |
5466 if (!fn) | |
5467 return NULL_RTX; | |
5468 if (TREE_CODE (fn) == CALL_EXPR) | |
5469 CALL_EXPR_TAILCALL (fn) = CALL_EXPR_TAILCALL (exp); | |
5470 return expand_expr (fn, target, mode, EXPAND_NORMAL); | |
5471 } | |
5472 | |
5473 /* Expand EXP, a call to fprintf or fprintf_unlocked. | |
5474 Return NULL_RTX if a normal call should be emitted rather than transforming | |
5475 the function inline. If convenient, the result should be placed in | |
5476 TARGET with mode MODE. UNLOCKED indicates this is a fprintf_unlocked | |
5477 call. */ | |
5478 static rtx | |
5479 expand_builtin_fprintf (tree exp, rtx target, enum machine_mode mode, | |
5480 bool unlocked) | |
5481 { | |
5482 /* If we're using an unlocked function, assume the other unlocked | |
5483 functions exist explicitly. */ | |
5484 tree const fn_fputc = unlocked ? built_in_decls[BUILT_IN_FPUTC_UNLOCKED] | |
5485 : implicit_built_in_decls[BUILT_IN_FPUTC]; | |
5486 tree const fn_fputs = unlocked ? built_in_decls[BUILT_IN_FPUTS_UNLOCKED] | |
5487 : implicit_built_in_decls[BUILT_IN_FPUTS]; | |
5488 const char *fmt_str; | |
5489 tree fn = 0; | |
5490 tree fmt, fp, arg; | |
5491 int nargs = call_expr_nargs (exp); | |
5492 | |
5493 /* If the return value is used, don't do the transformation. */ | |
5494 if (target != const0_rtx) | |
5495 return NULL_RTX; | |
5496 | |
5497 /* Verify the required arguments in the original call. */ | |
5498 if (nargs < 2) | |
5499 return NULL_RTX; | |
5500 fp = CALL_EXPR_ARG (exp, 0); | |
5501 if (! POINTER_TYPE_P (TREE_TYPE (fp))) | |
5502 return NULL_RTX; | |
5503 fmt = CALL_EXPR_ARG (exp, 1); | |
5504 if (! POINTER_TYPE_P (TREE_TYPE (fmt))) | |
5505 return NULL_RTX; | |
5506 | |
5507 /* Check whether the format is a literal string constant. */ | |
5508 fmt_str = c_getstr (fmt); | |
5509 if (fmt_str == NULL) | |
5510 return NULL_RTX; | |
5511 | |
5512 if (!init_target_chars ()) | |
5513 return NULL_RTX; | |
5514 | |
5515 /* If the format specifier was "%s", call __builtin_fputs(arg,fp). */ | |
5516 if (strcmp (fmt_str, target_percent_s) == 0) | |
5517 { | |
5518 if ((nargs != 3) | |
5519 || ! POINTER_TYPE_P (TREE_TYPE (CALL_EXPR_ARG (exp, 2)))) | |
5520 return NULL_RTX; | |
5521 arg = CALL_EXPR_ARG (exp, 2); | |
5522 if (fn_fputs) | |
5523 fn = build_call_expr (fn_fputs, 2, arg, fp); | |
5524 } | |
5525 /* If the format specifier was "%c", call __builtin_fputc(arg,fp). */ | |
5526 else if (strcmp (fmt_str, target_percent_c) == 0) | |
5527 { | |
5528 if ((nargs != 3) | |
5529 || TREE_CODE (TREE_TYPE (CALL_EXPR_ARG (exp, 2))) != INTEGER_TYPE) | |
5530 return NULL_RTX; | |
5531 arg = CALL_EXPR_ARG (exp, 2); | |
5532 if (fn_fputc) | |
5533 fn = build_call_expr (fn_fputc, 2, arg, fp); | |
5534 } | |
5535 else | |
5536 { | |
5537 /* We can't handle anything else with % args or %% ... yet. */ | |
5538 if (strchr (fmt_str, target_percent)) | |
5539 return NULL_RTX; | |
5540 | |
5541 if (nargs > 2) | |
5542 return NULL_RTX; | |
5543 | |
5544 /* If the format specifier was "", fprintf does nothing. */ | |
5545 if (fmt_str[0] == '\0') | |
5546 { | |
5547 /* Evaluate and ignore FILE* argument for side-effects. */ | |
5548 expand_expr (fp, const0_rtx, VOIDmode, EXPAND_NORMAL); | |
5549 return const0_rtx; | |
5550 } | |
5551 | |
5552 /* When "string" doesn't contain %, replace all cases of | |
5553 fprintf(stream,string) with fputs(string,stream). The fputs | |
5554 builtin will take care of special cases like length == 1. */ | |
5555 if (fn_fputs) | |
5556 fn = build_call_expr (fn_fputs, 2, fmt, fp); | |
5557 } | |
5558 | |
5559 if (!fn) | |
5560 return NULL_RTX; | |
5561 if (TREE_CODE (fn) == CALL_EXPR) | |
5562 CALL_EXPR_TAILCALL (fn) = CALL_EXPR_TAILCALL (exp); | |
5563 return expand_expr (fn, target, mode, EXPAND_NORMAL); | |
5564 } | |
5565 | |
5566 /* Expand a call EXP to sprintf. Return NULL_RTX if | |
5567 a normal call should be emitted rather than expanding the function | |
5568 inline. If convenient, the result should be placed in TARGET with | |
5569 mode MODE. */ | |
5570 | |
5571 static rtx | |
5572 expand_builtin_sprintf (tree exp, rtx target, enum machine_mode mode) | |
5573 { | |
5574 tree dest, fmt; | |
5575 const char *fmt_str; | |
5576 int nargs = call_expr_nargs (exp); | |
5577 | |
5578 /* Verify the required arguments in the original call. */ | |
5579 if (nargs < 2) | |
5580 return NULL_RTX; | |
5581 dest = CALL_EXPR_ARG (exp, 0); | |
5582 if (! POINTER_TYPE_P (TREE_TYPE (dest))) | |
5583 return NULL_RTX; | |
5584 fmt = CALL_EXPR_ARG (exp, 0); | |
5585 if (! POINTER_TYPE_P (TREE_TYPE (fmt))) | |
5586 return NULL_RTX; | |
5587 | |
5588 /* Check whether the format is a literal string constant. */ | |
5589 fmt_str = c_getstr (fmt); | |
5590 if (fmt_str == NULL) | |
5591 return NULL_RTX; | |
5592 | |
5593 if (!init_target_chars ()) | |
5594 return NULL_RTX; | |
5595 | |
5596 /* If the format doesn't contain % args or %%, use strcpy. */ | |
5597 if (strchr (fmt_str, target_percent) == 0) | |
5598 { | |
5599 tree fn = implicit_built_in_decls[BUILT_IN_STRCPY]; | |
5600 tree exp; | |
5601 | |
5602 if ((nargs > 2) || ! fn) | |
5603 return NULL_RTX; | |
5604 expand_expr (build_call_expr (fn, 2, dest, fmt), | |
5605 const0_rtx, VOIDmode, EXPAND_NORMAL); | |
5606 if (target == const0_rtx) | |
5607 return const0_rtx; | |
5608 exp = build_int_cst (NULL_TREE, strlen (fmt_str)); | |
5609 return expand_expr (exp, target, mode, EXPAND_NORMAL); | |
5610 } | |
5611 /* If the format is "%s", use strcpy if the result isn't used. */ | |
5612 else if (strcmp (fmt_str, target_percent_s) == 0) | |
5613 { | |
5614 tree fn, arg, len; | |
5615 fn = implicit_built_in_decls[BUILT_IN_STRCPY]; | |
5616 | |
5617 if (! fn) | |
5618 return NULL_RTX; | |
5619 if (nargs != 3) | |
5620 return NULL_RTX; | |
5621 arg = CALL_EXPR_ARG (exp, 2); | |
5622 if (! POINTER_TYPE_P (TREE_TYPE (arg))) | |
5623 return NULL_RTX; | |
5624 | |
5625 if (target != const0_rtx) | |
5626 { | |
5627 len = c_strlen (arg, 1); | |
5628 if (! len || TREE_CODE (len) != INTEGER_CST) | |
5629 return NULL_RTX; | |
5630 } | |
5631 else | |
5632 len = NULL_TREE; | |
5633 | |
5634 expand_expr (build_call_expr (fn, 2, dest, arg), | |
5635 const0_rtx, VOIDmode, EXPAND_NORMAL); | |
5636 | |
5637 if (target == const0_rtx) | |
5638 return const0_rtx; | |
5639 return expand_expr (len, target, mode, EXPAND_NORMAL); | |
5640 } | |
5641 | |
5642 return NULL_RTX; | |
5643 } | 4981 } |
5644 | 4982 |
5645 /* Expand a call to either the entry or exit function profiler. */ | 4983 /* Expand a call to either the entry or exit function profiler. */ |
5646 | 4984 |
5647 static rtx | 4985 static rtx |
5746 | 5084 |
5747 static rtx | 5085 static rtx |
5748 expand_builtin_init_trampoline (tree exp) | 5086 expand_builtin_init_trampoline (tree exp) |
5749 { | 5087 { |
5750 tree t_tramp, t_func, t_chain; | 5088 tree t_tramp, t_func, t_chain; |
5751 rtx r_tramp, r_func, r_chain; | 5089 rtx m_tramp, r_tramp, r_chain, tmp; |
5752 #ifdef TRAMPOLINE_TEMPLATE | |
5753 rtx blktramp; | |
5754 #endif | |
5755 | 5090 |
5756 if (!validate_arglist (exp, POINTER_TYPE, POINTER_TYPE, | 5091 if (!validate_arglist (exp, POINTER_TYPE, POINTER_TYPE, |
5757 POINTER_TYPE, VOID_TYPE)) | 5092 POINTER_TYPE, VOID_TYPE)) |
5758 return NULL_RTX; | 5093 return NULL_RTX; |
5759 | 5094 |
5760 t_tramp = CALL_EXPR_ARG (exp, 0); | 5095 t_tramp = CALL_EXPR_ARG (exp, 0); |
5761 t_func = CALL_EXPR_ARG (exp, 1); | 5096 t_func = CALL_EXPR_ARG (exp, 1); |
5762 t_chain = CALL_EXPR_ARG (exp, 2); | 5097 t_chain = CALL_EXPR_ARG (exp, 2); |
5763 | 5098 |
5764 r_tramp = expand_normal (t_tramp); | 5099 r_tramp = expand_normal (t_tramp); |
5765 r_func = expand_normal (t_func); | 5100 m_tramp = gen_rtx_MEM (BLKmode, r_tramp); |
5101 MEM_NOTRAP_P (m_tramp) = 1; | |
5102 | |
5103 /* The TRAMP argument should be the address of a field within the | |
5104 local function's FRAME decl. Let's see if we can fill in the | |
5105 to fill in the MEM_ATTRs for this memory. */ | |
5106 if (TREE_CODE (t_tramp) == ADDR_EXPR) | |
5107 set_mem_attributes_minus_bitpos (m_tramp, TREE_OPERAND (t_tramp, 0), | |
5108 true, 0); | |
5109 | |
5110 tmp = round_trampoline_addr (r_tramp); | |
5111 if (tmp != r_tramp) | |
5112 { | |
5113 m_tramp = change_address (m_tramp, BLKmode, tmp); | |
5114 set_mem_align (m_tramp, TRAMPOLINE_ALIGNMENT); | |
5115 set_mem_size (m_tramp, GEN_INT (TRAMPOLINE_SIZE)); | |
5116 } | |
5117 | |
5118 /* The FUNC argument should be the address of the nested function. | |
5119 Extract the actual function decl to pass to the hook. */ | |
5120 gcc_assert (TREE_CODE (t_func) == ADDR_EXPR); | |
5121 t_func = TREE_OPERAND (t_func, 0); | |
5122 gcc_assert (TREE_CODE (t_func) == FUNCTION_DECL); | |
5123 | |
5766 r_chain = expand_normal (t_chain); | 5124 r_chain = expand_normal (t_chain); |
5767 | 5125 |
5768 /* Generate insns to initialize the trampoline. */ | 5126 /* Generate insns to initialize the trampoline. */ |
5769 r_tramp = round_trampoline_addr (r_tramp); | 5127 targetm.calls.trampoline_init (m_tramp, t_func, r_chain); |
5770 #ifdef TRAMPOLINE_TEMPLATE | 5128 |
5771 blktramp = gen_rtx_MEM (BLKmode, r_tramp); | |
5772 set_mem_align (blktramp, TRAMPOLINE_ALIGNMENT); | |
5773 emit_block_move (blktramp, assemble_trampoline_template (), | |
5774 GEN_INT (TRAMPOLINE_SIZE), BLOCK_OP_NORMAL); | |
5775 #endif | |
5776 trampolines_created = 1; | 5129 trampolines_created = 1; |
5777 INITIALIZE_TRAMPOLINE (r_tramp, r_func, r_chain); | |
5778 | |
5779 return const0_rtx; | 5130 return const0_rtx; |
5780 } | 5131 } |
5781 | 5132 |
5782 static rtx | 5133 static rtx |
5783 expand_builtin_adjust_trampoline (tree exp) | 5134 expand_builtin_adjust_trampoline (tree exp) |
5787 if (!validate_arglist (exp, POINTER_TYPE, VOID_TYPE)) | 5138 if (!validate_arglist (exp, POINTER_TYPE, VOID_TYPE)) |
5788 return NULL_RTX; | 5139 return NULL_RTX; |
5789 | 5140 |
5790 tramp = expand_normal (CALL_EXPR_ARG (exp, 0)); | 5141 tramp = expand_normal (CALL_EXPR_ARG (exp, 0)); |
5791 tramp = round_trampoline_addr (tramp); | 5142 tramp = round_trampoline_addr (tramp); |
5792 #ifdef TRAMPOLINE_ADJUST_ADDRESS | 5143 if (targetm.calls.trampoline_adjust_address) |
5793 TRAMPOLINE_ADJUST_ADDRESS (tramp); | 5144 tramp = targetm.calls.trampoline_adjust_address (tramp); |
5794 #endif | |
5795 | 5145 |
5796 return tramp; | 5146 return tramp; |
5797 } | 5147 } |
5798 | 5148 |
5799 /* Expand the call EXP to the built-in signbit, signbitf or signbitl | 5149 /* Expand the call EXP to the built-in signbit, signbitf or signbitl |
5813 HOST_WIDE_INT hi, lo; | 5163 HOST_WIDE_INT hi, lo; |
5814 tree arg; | 5164 tree arg; |
5815 int word, bitpos; | 5165 int word, bitpos; |
5816 enum insn_code icode; | 5166 enum insn_code icode; |
5817 rtx temp; | 5167 rtx temp; |
5168 location_t loc = EXPR_LOCATION (exp); | |
5818 | 5169 |
5819 if (!validate_arglist (exp, REAL_TYPE, VOID_TYPE)) | 5170 if (!validate_arglist (exp, REAL_TYPE, VOID_TYPE)) |
5820 return NULL_RTX; | 5171 return NULL_RTX; |
5821 | 5172 |
5822 arg = CALL_EXPR_ARG (exp, 0); | 5173 arg = CALL_EXPR_ARG (exp, 0); |
5846 { | 5197 { |
5847 /* But we can't do this if the format supports signed zero. */ | 5198 /* But we can't do this if the format supports signed zero. */ |
5848 if (fmt->has_signed_zero && HONOR_SIGNED_ZEROS (fmode)) | 5199 if (fmt->has_signed_zero && HONOR_SIGNED_ZEROS (fmode)) |
5849 return NULL_RTX; | 5200 return NULL_RTX; |
5850 | 5201 |
5851 arg = fold_build2 (LT_EXPR, TREE_TYPE (exp), arg, | 5202 arg = fold_build2_loc (loc, LT_EXPR, TREE_TYPE (exp), arg, |
5852 build_real (TREE_TYPE (arg), dconst0)); | 5203 build_real (TREE_TYPE (arg), dconst0)); |
5853 return expand_expr (arg, target, VOIDmode, EXPAND_NORMAL); | 5204 return expand_expr (arg, target, VOIDmode, EXPAND_NORMAL); |
5854 } | 5205 } |
5855 | 5206 |
5856 if (GET_MODE_SIZE (fmode) <= UNITS_PER_WORD) | 5207 if (GET_MODE_SIZE (fmode) <= UNITS_PER_WORD) |
5966 | 5317 |
5967 default: | 5318 default: |
5968 gcc_unreachable (); | 5319 gcc_unreachable (); |
5969 } | 5320 } |
5970 | 5321 |
5971 decl = build_decl (FUNCTION_DECL, id, TREE_TYPE (fn)); | 5322 decl = build_decl (DECL_SOURCE_LOCATION (fn), |
5323 FUNCTION_DECL, id, TREE_TYPE (fn)); | |
5972 DECL_EXTERNAL (decl) = 1; | 5324 DECL_EXTERNAL (decl) = 1; |
5973 TREE_PUBLIC (decl) = 1; | 5325 TREE_PUBLIC (decl) = 1; |
5974 DECL_ARTIFICIAL (decl) = 1; | 5326 DECL_ARTIFICIAL (decl) = 1; |
5975 TREE_NOTHROW (decl) = 1; | 5327 TREE_NOTHROW (decl) = 1; |
5976 DECL_VISIBILITY (decl) = VISIBILITY_DEFAULT; | 5328 DECL_VISIBILITY (decl) = VISIBILITY_DEFAULT; |
5977 DECL_VISIBILITY_SPECIFIED (decl) = 1; | 5329 DECL_VISIBILITY_SPECIFIED (decl) = 1; |
5978 call = rewrite_call_expr (exp, 0, decl, 0); | 5330 call = rewrite_call_expr (EXPR_LOCATION (exp), exp, 0, decl, 0); |
5979 return expand_call (call, target, ignore); | 5331 return expand_call (call, target, ignore); |
5980 } | 5332 } |
5981 | 5333 |
5982 | 5334 |
5983 | 5335 |
5984 /* Reconstitute a mode for a __sync intrinsic operation. Since the type of | 5336 /* Reconstitute a mode for a __sync intrinsic operation. Since the type of |
5985 the pointer in these functions is void*, the tree optimizers may remove | 5337 the pointer in these functions is void*, the tree optimizers may remove |
5986 casts. The mode computed in expand_builtin isn't reliable either, due | 5338 casts. The mode computed in expand_builtin isn't reliable either, due |
6003 static rtx | 5355 static rtx |
6004 get_builtin_sync_mem (tree loc, enum machine_mode mode) | 5356 get_builtin_sync_mem (tree loc, enum machine_mode mode) |
6005 { | 5357 { |
6006 rtx addr, mem; | 5358 rtx addr, mem; |
6007 | 5359 |
6008 addr = expand_expr (loc, NULL_RTX, Pmode, EXPAND_SUM); | 5360 addr = expand_expr (loc, NULL_RTX, ptr_mode, EXPAND_SUM); |
5361 addr = convert_memory_address (Pmode, addr); | |
6009 | 5362 |
6010 /* Note that we explicitly do not want any alias information for this | 5363 /* Note that we explicitly do not want any alias information for this |
6011 memory, so that we kill all other live memories. Otherwise we don't | 5364 memory, so that we kill all other live memories. Otherwise we don't |
6012 satisfy the full barrier semantics of the intrinsic. */ | 5365 satisfy the full barrier semantics of the intrinsic. */ |
6013 mem = validize_mem (gen_rtx_MEM (mode, addr)); | 5366 mem = validize_mem (gen_rtx_MEM (mode, addr)); |
6032 enum rtx_code code, bool after, | 5385 enum rtx_code code, bool after, |
6033 rtx target, bool ignore) | 5386 rtx target, bool ignore) |
6034 { | 5387 { |
6035 rtx val, mem; | 5388 rtx val, mem; |
6036 enum machine_mode old_mode; | 5389 enum machine_mode old_mode; |
5390 location_t loc = EXPR_LOCATION (exp); | |
6037 | 5391 |
6038 if (code == NOT && warn_sync_nand) | 5392 if (code == NOT && warn_sync_nand) |
6039 { | 5393 { |
6040 tree fndecl = get_callee_fndecl (exp); | 5394 tree fndecl = get_callee_fndecl (exp); |
6041 enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl); | 5395 enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl); |
6052 | 5406 |
6053 if (warned_f_a_n) | 5407 if (warned_f_a_n) |
6054 break; | 5408 break; |
6055 | 5409 |
6056 fndecl = implicit_built_in_decls[BUILT_IN_FETCH_AND_NAND_N]; | 5410 fndecl = implicit_built_in_decls[BUILT_IN_FETCH_AND_NAND_N]; |
6057 inform (input_location, | 5411 inform (loc, "%qD changed semantics in GCC 4.4", fndecl); |
6058 "%qD changed semantics in GCC 4.4", fndecl); | |
6059 warned_f_a_n = true; | 5412 warned_f_a_n = true; |
6060 break; | 5413 break; |
6061 | 5414 |
6062 case BUILT_IN_NAND_AND_FETCH_1: | 5415 case BUILT_IN_NAND_AND_FETCH_1: |
6063 case BUILT_IN_NAND_AND_FETCH_2: | 5416 case BUILT_IN_NAND_AND_FETCH_2: |
6067 | 5420 |
6068 if (warned_n_a_f) | 5421 if (warned_n_a_f) |
6069 break; | 5422 break; |
6070 | 5423 |
6071 fndecl = implicit_built_in_decls[BUILT_IN_NAND_AND_FETCH_N]; | 5424 fndecl = implicit_built_in_decls[BUILT_IN_NAND_AND_FETCH_N]; |
6072 inform (input_location, | 5425 inform (loc, "%qD changed semantics in GCC 4.4", fndecl); |
6073 "%qD changed semantics in GCC 4.4", fndecl); | |
6074 warned_n_a_f = true; | 5426 warned_n_a_f = true; |
6075 break; | 5427 break; |
6076 | 5428 |
6077 default: | 5429 default: |
6078 gcc_unreachable (); | 5430 gcc_unreachable (); |
6137 } | 5489 } |
6138 | 5490 |
6139 /* Expand the __sync_lock_test_and_set intrinsic. Note that the most | 5491 /* Expand the __sync_lock_test_and_set intrinsic. Note that the most |
6140 general form is actually an atomic exchange, and some targets only | 5492 general form is actually an atomic exchange, and some targets only |
6141 support a reduced form with the second argument being a constant 1. | 5493 support a reduced form with the second argument being a constant 1. |
6142 EXP is the CALL_EXPR; TARGET is an optional place for us to store | 5494 EXP is the CALL_EXPR; TARGET is an optional place for us to store |
6143 the results. */ | 5495 the results. */ |
6144 | 5496 |
6145 static rtx | 5497 static rtx |
6146 expand_builtin_lock_test_and_set (enum machine_mode mode, tree exp, | 5498 expand_builtin_lock_test_and_set (enum machine_mode mode, tree exp, |
6147 rtx target) | 5499 rtx target) |
6165 /* Expand the __sync_synchronize intrinsic. */ | 5517 /* Expand the __sync_synchronize intrinsic. */ |
6166 | 5518 |
6167 static void | 5519 static void |
6168 expand_builtin_synchronize (void) | 5520 expand_builtin_synchronize (void) |
6169 { | 5521 { |
6170 tree x; | 5522 gimple x; |
5523 VEC (tree, gc) *v_clobbers; | |
6171 | 5524 |
6172 #ifdef HAVE_memory_barrier | 5525 #ifdef HAVE_memory_barrier |
6173 if (HAVE_memory_barrier) | 5526 if (HAVE_memory_barrier) |
6174 { | 5527 { |
6175 emit_insn (gen_memory_barrier ()); | 5528 emit_insn (gen_memory_barrier ()); |
6183 return; | 5536 return; |
6184 } | 5537 } |
6185 | 5538 |
6186 /* If no explicit memory barrier instruction is available, create an | 5539 /* If no explicit memory barrier instruction is available, create an |
6187 empty asm stmt with a memory clobber. */ | 5540 empty asm stmt with a memory clobber. */ |
6188 x = build4 (ASM_EXPR, void_type_node, build_string (0, ""), NULL, NULL, | 5541 v_clobbers = VEC_alloc (tree, gc, 1); |
6189 tree_cons (NULL, build_string (6, "memory"), NULL)); | 5542 VEC_quick_push (tree, v_clobbers, |
6190 ASM_VOLATILE_P (x) = 1; | 5543 tree_cons (NULL, build_string (6, "memory"), NULL)); |
6191 expand_asm_expr (x); | 5544 x = gimple_build_asm_vec ("", NULL, NULL, v_clobbers, NULL); |
5545 gimple_asm_set_volatile (x, true); | |
5546 expand_asm_stmt (x); | |
6192 } | 5547 } |
6193 | 5548 |
6194 /* Expand the __sync_lock_release intrinsic. EXP is the CALL_EXPR. */ | 5549 /* Expand the __sync_lock_release intrinsic. EXP is the CALL_EXPR. */ |
6195 | 5550 |
6196 static void | 5551 static void |
6311 CASE_FLT_FN (BUILT_IN_LOG1P): | 5666 CASE_FLT_FN (BUILT_IN_LOG1P): |
6312 CASE_FLT_FN (BUILT_IN_TAN): | 5667 CASE_FLT_FN (BUILT_IN_TAN): |
6313 CASE_FLT_FN (BUILT_IN_ASIN): | 5668 CASE_FLT_FN (BUILT_IN_ASIN): |
6314 CASE_FLT_FN (BUILT_IN_ACOS): | 5669 CASE_FLT_FN (BUILT_IN_ACOS): |
6315 CASE_FLT_FN (BUILT_IN_ATAN): | 5670 CASE_FLT_FN (BUILT_IN_ATAN): |
5671 CASE_FLT_FN (BUILT_IN_SIGNIFICAND): | |
6316 /* Treat these like sqrt only if unsafe math optimizations are allowed, | 5672 /* Treat these like sqrt only if unsafe math optimizations are allowed, |
6317 because of possible accuracy problems. */ | 5673 because of possible accuracy problems. */ |
6318 if (! flag_unsafe_math_optimizations) | 5674 if (! flag_unsafe_math_optimizations) |
6319 break; | 5675 break; |
6320 CASE_FLT_FN (BUILT_IN_SQRT): | 5676 CASE_FLT_FN (BUILT_IN_SQRT): |
6563 if (target) | 5919 if (target) |
6564 return target; | 5920 return target; |
6565 break; | 5921 break; |
6566 | 5922 |
6567 case BUILT_IN_STRCPY: | 5923 case BUILT_IN_STRCPY: |
6568 target = expand_builtin_strcpy (fndecl, exp, target, mode); | 5924 target = expand_builtin_strcpy (exp, target); |
6569 if (target) | 5925 if (target) |
6570 return target; | 5926 return target; |
6571 break; | 5927 break; |
6572 | 5928 |
6573 case BUILT_IN_STRNCPY: | 5929 case BUILT_IN_STRNCPY: |
6574 target = expand_builtin_strncpy (exp, target, mode); | 5930 target = expand_builtin_strncpy (exp, target); |
6575 if (target) | 5931 if (target) |
6576 return target; | 5932 return target; |
6577 break; | 5933 break; |
6578 | 5934 |
6579 case BUILT_IN_STPCPY: | 5935 case BUILT_IN_STPCPY: |
6580 target = expand_builtin_stpcpy (exp, target, mode); | 5936 target = expand_builtin_stpcpy (exp, target, mode); |
6581 if (target) | 5937 if (target) |
6582 return target; | 5938 return target; |
6583 break; | 5939 break; |
6584 | 5940 |
6585 case BUILT_IN_STRCAT: | |
6586 target = expand_builtin_strcat (fndecl, exp, target, mode); | |
6587 if (target) | |
6588 return target; | |
6589 break; | |
6590 | |
6591 case BUILT_IN_STRNCAT: | |
6592 target = expand_builtin_strncat (exp, target, mode); | |
6593 if (target) | |
6594 return target; | |
6595 break; | |
6596 | |
6597 case BUILT_IN_STRSPN: | |
6598 target = expand_builtin_strspn (exp, target, mode); | |
6599 if (target) | |
6600 return target; | |
6601 break; | |
6602 | |
6603 case BUILT_IN_STRCSPN: | |
6604 target = expand_builtin_strcspn (exp, target, mode); | |
6605 if (target) | |
6606 return target; | |
6607 break; | |
6608 | |
6609 case BUILT_IN_STRSTR: | |
6610 target = expand_builtin_strstr (exp, target, mode); | |
6611 if (target) | |
6612 return target; | |
6613 break; | |
6614 | |
6615 case BUILT_IN_STRPBRK: | |
6616 target = expand_builtin_strpbrk (exp, target, mode); | |
6617 if (target) | |
6618 return target; | |
6619 break; | |
6620 | |
6621 case BUILT_IN_INDEX: | |
6622 case BUILT_IN_STRCHR: | |
6623 target = expand_builtin_strchr (exp, target, mode); | |
6624 if (target) | |
6625 return target; | |
6626 break; | |
6627 | |
6628 case BUILT_IN_RINDEX: | |
6629 case BUILT_IN_STRRCHR: | |
6630 target = expand_builtin_strrchr (exp, target, mode); | |
6631 if (target) | |
6632 return target; | |
6633 break; | |
6634 | |
6635 case BUILT_IN_MEMCPY: | 5941 case BUILT_IN_MEMCPY: |
6636 target = expand_builtin_memcpy (exp, target, mode); | 5942 target = expand_builtin_memcpy (exp, target); |
6637 if (target) | 5943 if (target) |
6638 return target; | 5944 return target; |
6639 break; | 5945 break; |
6640 | 5946 |
6641 case BUILT_IN_MEMPCPY: | 5947 case BUILT_IN_MEMPCPY: |
6642 target = expand_builtin_mempcpy (exp, target, mode); | 5948 target = expand_builtin_mempcpy (exp, target, mode); |
6643 if (target) | 5949 if (target) |
6644 return target; | 5950 return target; |
6645 break; | 5951 break; |
6646 | 5952 |
6647 case BUILT_IN_MEMMOVE: | |
6648 target = expand_builtin_memmove (exp, target, mode, ignore); | |
6649 if (target) | |
6650 return target; | |
6651 break; | |
6652 | |
6653 case BUILT_IN_BCOPY: | |
6654 target = expand_builtin_bcopy (exp, ignore); | |
6655 if (target) | |
6656 return target; | |
6657 break; | |
6658 | |
6659 case BUILT_IN_MEMSET: | 5953 case BUILT_IN_MEMSET: |
6660 target = expand_builtin_memset (exp, target, mode); | 5954 target = expand_builtin_memset (exp, target, mode); |
6661 if (target) | 5955 if (target) |
6662 return target; | 5956 return target; |
6663 break; | 5957 break; |
6667 if (target) | 5961 if (target) |
6668 return target; | 5962 return target; |
6669 break; | 5963 break; |
6670 | 5964 |
6671 case BUILT_IN_STRCMP: | 5965 case BUILT_IN_STRCMP: |
6672 target = expand_builtin_strcmp (exp, target, mode); | 5966 target = expand_builtin_strcmp (exp, target); |
6673 if (target) | 5967 if (target) |
6674 return target; | 5968 return target; |
6675 break; | 5969 break; |
6676 | 5970 |
6677 case BUILT_IN_STRNCMP: | 5971 case BUILT_IN_STRNCMP: |
6678 target = expand_builtin_strncmp (exp, target, mode); | 5972 target = expand_builtin_strncmp (exp, target, mode); |
6679 if (target) | |
6680 return target; | |
6681 break; | |
6682 | |
6683 case BUILT_IN_MEMCHR: | |
6684 target = expand_builtin_memchr (exp, target, mode); | |
6685 if (target) | 5973 if (target) |
6686 return target; | 5974 return target; |
6687 break; | 5975 break; |
6688 | 5976 |
6689 case BUILT_IN_BCMP: | 5977 case BUILT_IN_BCMP: |
6788 | 6076 |
6789 case BUILT_IN_TRAP: | 6077 case BUILT_IN_TRAP: |
6790 expand_builtin_trap (); | 6078 expand_builtin_trap (); |
6791 return const0_rtx; | 6079 return const0_rtx; |
6792 | 6080 |
6793 case BUILT_IN_PRINTF: | 6081 case BUILT_IN_UNREACHABLE: |
6794 target = expand_builtin_printf (exp, target, mode, false); | 6082 expand_builtin_unreachable (); |
6795 if (target) | 6083 return const0_rtx; |
6796 return target; | |
6797 break; | |
6798 | |
6799 case BUILT_IN_PRINTF_UNLOCKED: | |
6800 target = expand_builtin_printf (exp, target, mode, true); | |
6801 if (target) | |
6802 return target; | |
6803 break; | |
6804 | |
6805 case BUILT_IN_FPUTS: | |
6806 target = expand_builtin_fputs (exp, target, false); | |
6807 if (target) | |
6808 return target; | |
6809 break; | |
6810 case BUILT_IN_FPUTS_UNLOCKED: | |
6811 target = expand_builtin_fputs (exp, target, true); | |
6812 if (target) | |
6813 return target; | |
6814 break; | |
6815 | |
6816 case BUILT_IN_FPRINTF: | |
6817 target = expand_builtin_fprintf (exp, target, mode, false); | |
6818 if (target) | |
6819 return target; | |
6820 break; | |
6821 | |
6822 case BUILT_IN_FPRINTF_UNLOCKED: | |
6823 target = expand_builtin_fprintf (exp, target, mode, true); | |
6824 if (target) | |
6825 return target; | |
6826 break; | |
6827 | |
6828 case BUILT_IN_SPRINTF: | |
6829 target = expand_builtin_sprintf (exp, target, mode); | |
6830 if (target) | |
6831 return target; | |
6832 break; | |
6833 | 6084 |
6834 CASE_FLT_FN (BUILT_IN_SIGNBIT): | 6085 CASE_FLT_FN (BUILT_IN_SIGNBIT): |
6835 case BUILT_IN_SIGNBITD32: | 6086 case BUILT_IN_SIGNBITD32: |
6836 case BUILT_IN_SIGNBITD64: | 6087 case BUILT_IN_SIGNBITD64: |
6837 case BUILT_IN_SIGNBITD128: | 6088 case BUILT_IN_SIGNBITD128: |
6865 case BUILT_IN_EH_RETURN_DATA_REGNO: | 6116 case BUILT_IN_EH_RETURN_DATA_REGNO: |
6866 return expand_builtin_eh_return_data_regno (exp); | 6117 return expand_builtin_eh_return_data_regno (exp); |
6867 #endif | 6118 #endif |
6868 case BUILT_IN_EXTEND_POINTER: | 6119 case BUILT_IN_EXTEND_POINTER: |
6869 return expand_builtin_extend_pointer (CALL_EXPR_ARG (exp, 0)); | 6120 return expand_builtin_extend_pointer (CALL_EXPR_ARG (exp, 0)); |
6121 case BUILT_IN_EH_POINTER: | |
6122 return expand_builtin_eh_pointer (exp); | |
6123 case BUILT_IN_EH_FILTER: | |
6124 return expand_builtin_eh_filter (exp); | |
6125 case BUILT_IN_EH_COPY_VALUES: | |
6126 return expand_builtin_eh_copy_values (exp); | |
6870 | 6127 |
6871 case BUILT_IN_VA_START: | 6128 case BUILT_IN_VA_START: |
6872 return expand_builtin_va_start (exp); | 6129 return expand_builtin_va_start (exp); |
6873 case BUILT_IN_VA_END: | 6130 case BUILT_IN_VA_END: |
6874 return expand_builtin_va_end (exp); | 6131 return expand_builtin_va_end (exp); |
7175 return DECL_FUNCTION_CODE (fndecl); | 6432 return DECL_FUNCTION_CODE (fndecl); |
7176 } | 6433 } |
7177 | 6434 |
7178 if (! more_const_call_expr_args_p (&iter)) | 6435 if (! more_const_call_expr_args_p (&iter)) |
7179 return END_BUILTINS; | 6436 return END_BUILTINS; |
7180 | 6437 |
7181 arg = next_const_call_expr_arg (&iter); | 6438 arg = next_const_call_expr_arg (&iter); |
7182 argtype = TREE_TYPE (arg); | 6439 argtype = TREE_TYPE (arg); |
7183 | 6440 |
7184 if (SCALAR_FLOAT_TYPE_P (parmtype)) | 6441 if (SCALAR_FLOAT_TYPE_P (parmtype)) |
7185 { | 6442 { |
7254 | 6511 |
7255 /* Create builtin_expect with PRED and EXPECTED as its arguments and | 6512 /* Create builtin_expect with PRED and EXPECTED as its arguments and |
7256 return it as a truthvalue. */ | 6513 return it as a truthvalue. */ |
7257 | 6514 |
7258 static tree | 6515 static tree |
7259 build_builtin_expect_predicate (tree pred, tree expected) | 6516 build_builtin_expect_predicate (location_t loc, tree pred, tree expected) |
7260 { | 6517 { |
7261 tree fn, arg_types, pred_type, expected_type, call_expr, ret_type; | 6518 tree fn, arg_types, pred_type, expected_type, call_expr, ret_type; |
7262 | 6519 |
7263 fn = built_in_decls[BUILT_IN_EXPECT]; | 6520 fn = built_in_decls[BUILT_IN_EXPECT]; |
7264 arg_types = TYPE_ARG_TYPES (TREE_TYPE (fn)); | 6521 arg_types = TYPE_ARG_TYPES (TREE_TYPE (fn)); |
7265 ret_type = TREE_TYPE (TREE_TYPE (fn)); | 6522 ret_type = TREE_TYPE (TREE_TYPE (fn)); |
7266 pred_type = TREE_VALUE (arg_types); | 6523 pred_type = TREE_VALUE (arg_types); |
7267 expected_type = TREE_VALUE (TREE_CHAIN (arg_types)); | 6524 expected_type = TREE_VALUE (TREE_CHAIN (arg_types)); |
7268 | 6525 |
7269 pred = fold_convert (pred_type, pred); | 6526 pred = fold_convert_loc (loc, pred_type, pred); |
7270 expected = fold_convert (expected_type, expected); | 6527 expected = fold_convert_loc (loc, expected_type, expected); |
7271 call_expr = build_call_expr (fn, 2, pred, expected); | 6528 call_expr = build_call_expr_loc (loc, fn, 2, pred, expected); |
7272 | 6529 |
7273 return build2 (NE_EXPR, TREE_TYPE (pred), call_expr, | 6530 return build2 (NE_EXPR, TREE_TYPE (pred), call_expr, |
7274 build_int_cst (ret_type, 0)); | 6531 build_int_cst (ret_type, 0)); |
7275 } | 6532 } |
7276 | 6533 |
7277 /* Fold a call to builtin_expect with arguments ARG0 and ARG1. Return | 6534 /* Fold a call to builtin_expect with arguments ARG0 and ARG1. Return |
7278 NULL_TREE if no simplification is possible. */ | 6535 NULL_TREE if no simplification is possible. */ |
7279 | 6536 |
7280 static tree | 6537 static tree |
7281 fold_builtin_expect (tree arg0, tree arg1) | 6538 fold_builtin_expect (location_t loc, tree arg0, tree arg1) |
7282 { | 6539 { |
7283 tree inner, fndecl; | 6540 tree inner, fndecl; |
7284 enum tree_code code; | 6541 enum tree_code code; |
7285 | 6542 |
7286 /* If this is a builtin_expect within a builtin_expect keep the | 6543 /* If this is a builtin_expect within a builtin_expect keep the |
7309 if (code == TRUTH_ANDIF_EXPR || code == TRUTH_ORIF_EXPR) | 6566 if (code == TRUTH_ANDIF_EXPR || code == TRUTH_ORIF_EXPR) |
7310 { | 6567 { |
7311 tree op0 = TREE_OPERAND (inner, 0); | 6568 tree op0 = TREE_OPERAND (inner, 0); |
7312 tree op1 = TREE_OPERAND (inner, 1); | 6569 tree op1 = TREE_OPERAND (inner, 1); |
7313 | 6570 |
7314 op0 = build_builtin_expect_predicate (op0, arg1); | 6571 op0 = build_builtin_expect_predicate (loc, op0, arg1); |
7315 op1 = build_builtin_expect_predicate (op1, arg1); | 6572 op1 = build_builtin_expect_predicate (loc, op1, arg1); |
7316 inner = build2 (code, TREE_TYPE (inner), op0, op1); | 6573 inner = build2 (code, TREE_TYPE (inner), op0, op1); |
7317 | 6574 |
7318 return fold_convert (TREE_TYPE (arg0), inner); | 6575 return fold_convert_loc (loc, TREE_TYPE (arg0), inner); |
7319 } | 6576 } |
7320 | 6577 |
7321 /* If the argument isn't invariant then there's nothing else we can do. */ | 6578 /* If the argument isn't invariant then there's nothing else we can do. */ |
7322 if (!TREE_CONSTANT (arg0)) | 6579 if (!TREE_CONSTANT (arg0)) |
7323 return NULL_TREE; | 6580 return NULL_TREE; |
7357 } | 6614 } |
7358 | 6615 |
7359 /* Fold a call to __builtin_strlen with argument ARG. */ | 6616 /* Fold a call to __builtin_strlen with argument ARG. */ |
7360 | 6617 |
7361 static tree | 6618 static tree |
7362 fold_builtin_strlen (tree type, tree arg) | 6619 fold_builtin_strlen (location_t loc, tree arg) |
7363 { | 6620 { |
7364 if (!validate_arg (arg, POINTER_TYPE)) | 6621 if (!validate_arg (arg, POINTER_TYPE)) |
7365 return NULL_TREE; | 6622 return NULL_TREE; |
7366 else | 6623 else |
7367 { | 6624 { |
7368 tree len = c_strlen (arg, 0); | 6625 tree len = c_strlen (arg, 0); |
7369 | 6626 |
7370 if (len) | 6627 if (len) |
7371 return fold_convert (type, len); | 6628 { |
6629 /* Convert from the internal "sizetype" type to "size_t". */ | |
6630 if (size_type_node) | |
6631 len = fold_convert_loc (loc, size_type_node, len); | |
6632 return len; | |
6633 } | |
7372 | 6634 |
7373 return NULL_TREE; | 6635 return NULL_TREE; |
7374 } | 6636 } |
7375 } | 6637 } |
7376 | 6638 |
7377 /* Fold a call to __builtin_inf or __builtin_huge_val. */ | 6639 /* Fold a call to __builtin_inf or __builtin_huge_val. */ |
7378 | 6640 |
7379 static tree | 6641 static tree |
7380 fold_builtin_inf (tree type, int warn) | 6642 fold_builtin_inf (location_t loc, tree type, int warn) |
7381 { | 6643 { |
7382 REAL_VALUE_TYPE real; | 6644 REAL_VALUE_TYPE real; |
7383 | 6645 |
7384 /* __builtin_inff is intended to be usable to define INFINITY on all | 6646 /* __builtin_inff is intended to be usable to define INFINITY on all |
7385 targets. If an infinity is not available, INFINITY expands "to a | 6647 targets. If an infinity is not available, INFINITY expands "to a |
7387 time", footnote "In this case, using INFINITY will violate the | 6649 time", footnote "In this case, using INFINITY will violate the |
7388 constraint in 6.4.4 and thus require a diagnostic." (C99 7.12#4). | 6650 constraint in 6.4.4 and thus require a diagnostic." (C99 7.12#4). |
7389 Thus we pedwarn to ensure this constraint violation is | 6651 Thus we pedwarn to ensure this constraint violation is |
7390 diagnosed. */ | 6652 diagnosed. */ |
7391 if (!MODE_HAS_INFINITIES (TYPE_MODE (type)) && warn) | 6653 if (!MODE_HAS_INFINITIES (TYPE_MODE (type)) && warn) |
7392 pedwarn (input_location, 0, "target format does not support infinity"); | 6654 pedwarn (loc, 0, "target format does not support infinity"); |
7393 | 6655 |
7394 real_inf (&real); | 6656 real_inf (&real); |
7395 return build_real (type, real); | 6657 return build_real (type, real); |
7396 } | 6658 } |
7397 | 6659 |
7490 /* FNDECL is assumed to be a builtin where truncation can be propagated | 6752 /* FNDECL is assumed to be a builtin where truncation can be propagated |
7491 across (for instance floor((double)f) == (double)floorf (f). | 6753 across (for instance floor((double)f) == (double)floorf (f). |
7492 Do the transformation for a call with argument ARG. */ | 6754 Do the transformation for a call with argument ARG. */ |
7493 | 6755 |
7494 static tree | 6756 static tree |
7495 fold_trunc_transparent_mathfn (tree fndecl, tree arg) | 6757 fold_trunc_transparent_mathfn (location_t loc, tree fndecl, tree arg) |
7496 { | 6758 { |
7497 enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl); | 6759 enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl); |
7498 | 6760 |
7499 if (!validate_arg (arg, REAL_TYPE)) | 6761 if (!validate_arg (arg, REAL_TYPE)) |
7500 return NULL_TREE; | 6762 return NULL_TREE; |
7515 tree newtype = TREE_TYPE (arg0); | 6777 tree newtype = TREE_TYPE (arg0); |
7516 tree decl; | 6778 tree decl; |
7517 | 6779 |
7518 if (TYPE_PRECISION (newtype) < TYPE_PRECISION (ftype) | 6780 if (TYPE_PRECISION (newtype) < TYPE_PRECISION (ftype) |
7519 && (decl = mathfn_built_in (newtype, fcode))) | 6781 && (decl = mathfn_built_in (newtype, fcode))) |
7520 return fold_convert (ftype, | 6782 return fold_convert_loc (loc, ftype, |
7521 build_call_expr (decl, 1, | 6783 build_call_expr_loc (loc, decl, 1, |
7522 fold_convert (newtype, arg0))); | 6784 fold_convert_loc (loc, |
6785 newtype, | |
6786 arg0))); | |
7523 } | 6787 } |
7524 return NULL_TREE; | 6788 return NULL_TREE; |
7525 } | 6789 } |
7526 | 6790 |
7527 /* FNDECL is assumed to be builtin which can narrow the FP type of | 6791 /* FNDECL is assumed to be builtin which can narrow the FP type of |
7528 the argument, for instance lround((double)f) -> lroundf (f). | 6792 the argument, for instance lround((double)f) -> lroundf (f). |
7529 Do the transformation for a call with argument ARG. */ | 6793 Do the transformation for a call with argument ARG. */ |
7530 | 6794 |
7531 static tree | 6795 static tree |
7532 fold_fixed_mathfn (tree fndecl, tree arg) | 6796 fold_fixed_mathfn (location_t loc, tree fndecl, tree arg) |
7533 { | 6797 { |
7534 enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl); | 6798 enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl); |
7535 | 6799 |
7536 if (!validate_arg (arg, REAL_TYPE)) | 6800 if (!validate_arg (arg, REAL_TYPE)) |
7537 return NULL_TREE; | 6801 return NULL_TREE; |
7538 | 6802 |
7539 /* If argument is already integer valued, and we don't need to worry | 6803 /* If argument is already integer valued, and we don't need to worry |
7540 about setting errno, there's no need to perform rounding. */ | 6804 about setting errno, there's no need to perform rounding. */ |
7541 if (! flag_errno_math && integer_valued_real_p (arg)) | 6805 if (! flag_errno_math && integer_valued_real_p (arg)) |
7542 return fold_build1 (FIX_TRUNC_EXPR, TREE_TYPE (TREE_TYPE (fndecl)), arg); | 6806 return fold_build1_loc (loc, FIX_TRUNC_EXPR, |
6807 TREE_TYPE (TREE_TYPE (fndecl)), arg); | |
7543 | 6808 |
7544 if (optimize) | 6809 if (optimize) |
7545 { | 6810 { |
7546 tree ftype = TREE_TYPE (arg); | 6811 tree ftype = TREE_TYPE (arg); |
7547 tree arg0 = strip_float_extensions (arg); | 6812 tree arg0 = strip_float_extensions (arg); |
7548 tree newtype = TREE_TYPE (arg0); | 6813 tree newtype = TREE_TYPE (arg0); |
7549 tree decl; | 6814 tree decl; |
7550 | 6815 |
7551 if (TYPE_PRECISION (newtype) < TYPE_PRECISION (ftype) | 6816 if (TYPE_PRECISION (newtype) < TYPE_PRECISION (ftype) |
7552 && (decl = mathfn_built_in (newtype, fcode))) | 6817 && (decl = mathfn_built_in (newtype, fcode))) |
7553 return build_call_expr (decl, 1, fold_convert (newtype, arg0)); | 6818 return build_call_expr_loc (loc, decl, 1, |
6819 fold_convert_loc (loc, newtype, arg0)); | |
7554 } | 6820 } |
7555 | 6821 |
7556 /* Canonicalize llround (x) to lround (x) on LP64 targets where | 6822 /* Canonicalize llround (x) to lround (x) on LP64 targets where |
7557 sizeof (long long) == sizeof (long). */ | 6823 sizeof (long long) == sizeof (long). */ |
7558 if (TYPE_PRECISION (long_long_integer_type_node) | 6824 if (TYPE_PRECISION (long_long_integer_type_node) |
7581 break; | 6847 break; |
7582 } | 6848 } |
7583 | 6849 |
7584 if (newfn) | 6850 if (newfn) |
7585 { | 6851 { |
7586 tree newcall = build_call_expr(newfn, 1, arg); | 6852 tree newcall = build_call_expr_loc (loc, newfn, 1, arg); |
7587 return fold_convert (TREE_TYPE (TREE_TYPE (fndecl)), newcall); | 6853 return fold_convert_loc (loc, |
6854 TREE_TYPE (TREE_TYPE (fndecl)), newcall); | |
7588 } | 6855 } |
7589 } | 6856 } |
7590 | 6857 |
7591 return NULL_TREE; | 6858 return NULL_TREE; |
7592 } | 6859 } |
7593 | 6860 |
7594 /* Fold call to builtin cabs, cabsf or cabsl with argument ARG. TYPE is the | 6861 /* Fold call to builtin cabs, cabsf or cabsl with argument ARG. TYPE is the |
7595 return type. Return NULL_TREE if no simplification can be made. */ | 6862 return type. Return NULL_TREE if no simplification can be made. */ |
7596 | 6863 |
7597 static tree | 6864 static tree |
7598 fold_builtin_cabs (tree arg, tree type, tree fndecl) | 6865 fold_builtin_cabs (location_t loc, tree arg, tree type, tree fndecl) |
7599 { | 6866 { |
7600 tree res; | 6867 tree res; |
7601 | 6868 |
7602 if (TREE_CODE (TREE_TYPE (arg)) != COMPLEX_TYPE | 6869 if (!validate_arg (arg, COMPLEX_TYPE) |
7603 || TREE_CODE (TREE_TYPE (TREE_TYPE (arg))) != REAL_TYPE) | 6870 || TREE_CODE (TREE_TYPE (TREE_TYPE (arg))) != REAL_TYPE) |
7604 return NULL_TREE; | 6871 return NULL_TREE; |
7605 | 6872 |
7606 /* Calculate the result when the argument is a constant. */ | 6873 /* Calculate the result when the argument is a constant. */ |
7607 if (TREE_CODE (arg) == COMPLEX_CST | 6874 if (TREE_CODE (arg) == COMPLEX_CST |
7608 && (res = do_mpfr_arg2 (TREE_REALPART (arg), TREE_IMAGPART (arg), | 6875 && (res = do_mpfr_arg2 (TREE_REALPART (arg), TREE_IMAGPART (arg), |
7609 type, mpfr_hypot))) | 6876 type, mpfr_hypot))) |
7610 return res; | 6877 return res; |
7611 | 6878 |
7612 if (TREE_CODE (arg) == COMPLEX_EXPR) | 6879 if (TREE_CODE (arg) == COMPLEX_EXPR) |
7613 { | 6880 { |
7614 tree real = TREE_OPERAND (arg, 0); | 6881 tree real = TREE_OPERAND (arg, 0); |
7615 tree imag = TREE_OPERAND (arg, 1); | 6882 tree imag = TREE_OPERAND (arg, 1); |
7616 | 6883 |
7617 /* If either part is zero, cabs is fabs of the other. */ | 6884 /* If either part is zero, cabs is fabs of the other. */ |
7618 if (real_zerop (real)) | 6885 if (real_zerop (real)) |
7619 return fold_build1 (ABS_EXPR, type, imag); | 6886 return fold_build1_loc (loc, ABS_EXPR, type, imag); |
7620 if (real_zerop (imag)) | 6887 if (real_zerop (imag)) |
7621 return fold_build1 (ABS_EXPR, type, real); | 6888 return fold_build1_loc (loc, ABS_EXPR, type, real); |
7622 | 6889 |
7623 /* cabs(x+xi) -> fabs(x)*sqrt(2). */ | 6890 /* cabs(x+xi) -> fabs(x)*sqrt(2). */ |
7624 if (flag_unsafe_math_optimizations | 6891 if (flag_unsafe_math_optimizations |
7625 && operand_equal_p (real, imag, OEP_PURE_SAME)) | 6892 && operand_equal_p (real, imag, OEP_PURE_SAME)) |
7626 { | 6893 { |
7627 const REAL_VALUE_TYPE sqrt2_trunc | 6894 const REAL_VALUE_TYPE sqrt2_trunc |
7628 = real_value_truncate (TYPE_MODE (type), dconst_sqrt2 ()); | 6895 = real_value_truncate (TYPE_MODE (type), dconst_sqrt2 ()); |
7629 STRIP_NOPS (real); | 6896 STRIP_NOPS (real); |
7630 return fold_build2 (MULT_EXPR, type, | 6897 return fold_build2_loc (loc, MULT_EXPR, type, |
7631 fold_build1 (ABS_EXPR, type, real), | 6898 fold_build1_loc (loc, ABS_EXPR, type, real), |
7632 build_real (type, sqrt2_trunc)); | 6899 build_real (type, sqrt2_trunc)); |
7633 } | 6900 } |
7634 } | 6901 } |
7635 | 6902 |
7636 /* Optimize cabs(-z) and cabs(conj(z)) as cabs(z). */ | 6903 /* Optimize cabs(-z) and cabs(conj(z)) as cabs(z). */ |
7637 if (TREE_CODE (arg) == NEGATE_EXPR | 6904 if (TREE_CODE (arg) == NEGATE_EXPR |
7638 || TREE_CODE (arg) == CONJ_EXPR) | 6905 || TREE_CODE (arg) == CONJ_EXPR) |
7639 return build_call_expr (fndecl, 1, TREE_OPERAND (arg, 0)); | 6906 return build_call_expr_loc (loc, fndecl, 1, TREE_OPERAND (arg, 0)); |
7640 | 6907 |
7641 /* Don't do this when optimizing for size. */ | 6908 /* Don't do this when optimizing for size. */ |
7642 if (flag_unsafe_math_optimizations | 6909 if (flag_unsafe_math_optimizations |
7643 && optimize && optimize_function_for_speed_p (cfun)) | 6910 && optimize && optimize_function_for_speed_p (cfun)) |
7644 { | 6911 { |
7648 { | 6915 { |
7649 tree rpart, ipart, result; | 6916 tree rpart, ipart, result; |
7650 | 6917 |
7651 arg = builtin_save_expr (arg); | 6918 arg = builtin_save_expr (arg); |
7652 | 6919 |
7653 rpart = fold_build1 (REALPART_EXPR, type, arg); | 6920 rpart = fold_build1_loc (loc, REALPART_EXPR, type, arg); |
7654 ipart = fold_build1 (IMAGPART_EXPR, type, arg); | 6921 ipart = fold_build1_loc (loc, IMAGPART_EXPR, type, arg); |
7655 | 6922 |
7656 rpart = builtin_save_expr (rpart); | 6923 rpart = builtin_save_expr (rpart); |
7657 ipart = builtin_save_expr (ipart); | 6924 ipart = builtin_save_expr (ipart); |
7658 | 6925 |
7659 result = fold_build2 (PLUS_EXPR, type, | 6926 result = fold_build2_loc (loc, PLUS_EXPR, type, |
7660 fold_build2 (MULT_EXPR, type, | 6927 fold_build2_loc (loc, MULT_EXPR, type, |
7661 rpart, rpart), | 6928 rpart, rpart), |
7662 fold_build2 (MULT_EXPR, type, | 6929 fold_build2_loc (loc, MULT_EXPR, type, |
7663 ipart, ipart)); | 6930 ipart, ipart)); |
7664 | 6931 |
7665 return build_call_expr (sqrtfn, 1, result); | 6932 return build_call_expr_loc (loc, sqrtfn, 1, result); |
7666 } | 6933 } |
7667 } | 6934 } |
7668 | 6935 |
7669 return NULL_TREE; | 6936 return NULL_TREE; |
7670 } | 6937 } |
7671 | 6938 |
7672 /* Fold a builtin function call to sqrt, sqrtf, or sqrtl with argument ARG. | 6939 /* Fold a builtin function call to sqrt, sqrtf, or sqrtl with argument ARG. |
7673 Return NULL_TREE if no simplification can be made. */ | 6940 Return NULL_TREE if no simplification can be made. */ |
7674 | 6941 |
7675 static tree | 6942 static tree |
7676 fold_builtin_sqrt (tree arg, tree type) | 6943 fold_builtin_sqrt (location_t loc, tree arg, tree type) |
7677 { | 6944 { |
7678 | 6945 |
7679 enum built_in_function fcode; | 6946 enum built_in_function fcode; |
7680 tree res; | 6947 tree res; |
7681 | 6948 |
7683 return NULL_TREE; | 6950 return NULL_TREE; |
7684 | 6951 |
7685 /* Calculate the result when the argument is a constant. */ | 6952 /* Calculate the result when the argument is a constant. */ |
7686 if ((res = do_mpfr_arg1 (arg, type, mpfr_sqrt, &dconst0, NULL, true))) | 6953 if ((res = do_mpfr_arg1 (arg, type, mpfr_sqrt, &dconst0, NULL, true))) |
7687 return res; | 6954 return res; |
7688 | 6955 |
7689 /* Optimize sqrt(expN(x)) = expN(x*0.5). */ | 6956 /* Optimize sqrt(expN(x)) = expN(x*0.5). */ |
7690 fcode = builtin_mathfn_code (arg); | 6957 fcode = builtin_mathfn_code (arg); |
7691 if (flag_unsafe_math_optimizations && BUILTIN_EXPONENT_P (fcode)) | 6958 if (flag_unsafe_math_optimizations && BUILTIN_EXPONENT_P (fcode)) |
7692 { | 6959 { |
7693 tree expfn = TREE_OPERAND (CALL_EXPR_FN (arg), 0); | 6960 tree expfn = TREE_OPERAND (CALL_EXPR_FN (arg), 0); |
7694 arg = fold_build2 (MULT_EXPR, type, | 6961 arg = fold_build2_loc (loc, MULT_EXPR, type, |
7695 CALL_EXPR_ARG (arg, 0), | 6962 CALL_EXPR_ARG (arg, 0), |
7696 build_real (type, dconsthalf)); | 6963 build_real (type, dconsthalf)); |
7697 return build_call_expr (expfn, 1, arg); | 6964 return build_call_expr_loc (loc, expfn, 1, arg); |
7698 } | 6965 } |
7699 | 6966 |
7700 /* Optimize sqrt(Nroot(x)) -> pow(x,1/(2*N)). */ | 6967 /* Optimize sqrt(Nroot(x)) -> pow(x,1/(2*N)). */ |
7701 if (flag_unsafe_math_optimizations && BUILTIN_ROOT_P (fcode)) | 6968 if (flag_unsafe_math_optimizations && BUILTIN_ROOT_P (fcode)) |
7702 { | 6969 { |
7717 | 6984 |
7718 /* Adjust for the outer root. */ | 6985 /* Adjust for the outer root. */ |
7719 SET_REAL_EXP (&dconstroot, REAL_EXP (&dconstroot) - 1); | 6986 SET_REAL_EXP (&dconstroot, REAL_EXP (&dconstroot) - 1); |
7720 dconstroot = real_value_truncate (TYPE_MODE (type), dconstroot); | 6987 dconstroot = real_value_truncate (TYPE_MODE (type), dconstroot); |
7721 tree_root = build_real (type, dconstroot); | 6988 tree_root = build_real (type, dconstroot); |
7722 return build_call_expr (powfn, 2, arg0, tree_root); | 6989 return build_call_expr_loc (loc, powfn, 2, arg0, tree_root); |
7723 } | 6990 } |
7724 } | 6991 } |
7725 | 6992 |
7726 /* Optimize sqrt(pow(x,y)) = pow(|x|,y*0.5). */ | 6993 /* Optimize sqrt(pow(x,y)) = pow(|x|,y*0.5). */ |
7727 if (flag_unsafe_math_optimizations | 6994 if (flag_unsafe_math_optimizations |
7733 tree arg0 = CALL_EXPR_ARG (arg, 0); | 7000 tree arg0 = CALL_EXPR_ARG (arg, 0); |
7734 tree arg1 = CALL_EXPR_ARG (arg, 1); | 7001 tree arg1 = CALL_EXPR_ARG (arg, 1); |
7735 tree narg1; | 7002 tree narg1; |
7736 if (!tree_expr_nonnegative_p (arg0)) | 7003 if (!tree_expr_nonnegative_p (arg0)) |
7737 arg0 = build1 (ABS_EXPR, type, arg0); | 7004 arg0 = build1 (ABS_EXPR, type, arg0); |
7738 narg1 = fold_build2 (MULT_EXPR, type, arg1, | 7005 narg1 = fold_build2_loc (loc, MULT_EXPR, type, arg1, |
7739 build_real (type, dconsthalf)); | 7006 build_real (type, dconsthalf)); |
7740 return build_call_expr (powfn, 2, arg0, narg1); | 7007 return build_call_expr_loc (loc, powfn, 2, arg0, narg1); |
7741 } | 7008 } |
7742 | 7009 |
7743 return NULL_TREE; | 7010 return NULL_TREE; |
7744 } | 7011 } |
7745 | 7012 |
7746 /* Fold a builtin function call to cbrt, cbrtf, or cbrtl with argument ARG. | 7013 /* Fold a builtin function call to cbrt, cbrtf, or cbrtl with argument ARG. |
7747 Return NULL_TREE if no simplification can be made. */ | 7014 Return NULL_TREE if no simplification can be made. */ |
7748 | 7015 |
7749 static tree | 7016 static tree |
7750 fold_builtin_cbrt (tree arg, tree type) | 7017 fold_builtin_cbrt (location_t loc, tree arg, tree type) |
7751 { | 7018 { |
7752 const enum built_in_function fcode = builtin_mathfn_code (arg); | 7019 const enum built_in_function fcode = builtin_mathfn_code (arg); |
7753 tree res; | 7020 tree res; |
7754 | 7021 |
7755 if (!validate_arg (arg, REAL_TYPE)) | 7022 if (!validate_arg (arg, REAL_TYPE)) |
7765 if (BUILTIN_EXPONENT_P (fcode)) | 7032 if (BUILTIN_EXPONENT_P (fcode)) |
7766 { | 7033 { |
7767 tree expfn = TREE_OPERAND (CALL_EXPR_FN (arg), 0); | 7034 tree expfn = TREE_OPERAND (CALL_EXPR_FN (arg), 0); |
7768 const REAL_VALUE_TYPE third_trunc = | 7035 const REAL_VALUE_TYPE third_trunc = |
7769 real_value_truncate (TYPE_MODE (type), dconst_third ()); | 7036 real_value_truncate (TYPE_MODE (type), dconst_third ()); |
7770 arg = fold_build2 (MULT_EXPR, type, | 7037 arg = fold_build2_loc (loc, MULT_EXPR, type, |
7771 CALL_EXPR_ARG (arg, 0), | 7038 CALL_EXPR_ARG (arg, 0), |
7772 build_real (type, third_trunc)); | 7039 build_real (type, third_trunc)); |
7773 return build_call_expr (expfn, 1, arg); | 7040 return build_call_expr_loc (loc, expfn, 1, arg); |
7774 } | 7041 } |
7775 | 7042 |
7776 /* Optimize cbrt(sqrt(x)) -> pow(x,1/6). */ | 7043 /* Optimize cbrt(sqrt(x)) -> pow(x,1/6). */ |
7777 if (BUILTIN_SQRT_P (fcode)) | 7044 if (BUILTIN_SQRT_P (fcode)) |
7778 { | 7045 { |
7785 REAL_VALUE_TYPE dconstroot = dconst_third (); | 7052 REAL_VALUE_TYPE dconstroot = dconst_third (); |
7786 | 7053 |
7787 SET_REAL_EXP (&dconstroot, REAL_EXP (&dconstroot) - 1); | 7054 SET_REAL_EXP (&dconstroot, REAL_EXP (&dconstroot) - 1); |
7788 dconstroot = real_value_truncate (TYPE_MODE (type), dconstroot); | 7055 dconstroot = real_value_truncate (TYPE_MODE (type), dconstroot); |
7789 tree_root = build_real (type, dconstroot); | 7056 tree_root = build_real (type, dconstroot); |
7790 return build_call_expr (powfn, 2, arg0, tree_root); | 7057 return build_call_expr_loc (loc, powfn, 2, arg0, tree_root); |
7791 } | 7058 } |
7792 } | 7059 } |
7793 | 7060 |
7794 /* Optimize cbrt(cbrt(x)) -> pow(x,1/9) iff x is nonnegative. */ | 7061 /* Optimize cbrt(cbrt(x)) -> pow(x,1/9) iff x is nonnegative. */ |
7795 if (BUILTIN_CBRT_P (fcode)) | 7062 if (BUILTIN_CBRT_P (fcode)) |
7806 | 7073 |
7807 real_arithmetic (&dconstroot, MULT_EXPR, | 7074 real_arithmetic (&dconstroot, MULT_EXPR, |
7808 dconst_third_ptr (), dconst_third_ptr ()); | 7075 dconst_third_ptr (), dconst_third_ptr ()); |
7809 dconstroot = real_value_truncate (TYPE_MODE (type), dconstroot); | 7076 dconstroot = real_value_truncate (TYPE_MODE (type), dconstroot); |
7810 tree_root = build_real (type, dconstroot); | 7077 tree_root = build_real (type, dconstroot); |
7811 return build_call_expr (powfn, 2, arg0, tree_root); | 7078 return build_call_expr_loc (loc, powfn, 2, arg0, tree_root); |
7812 } | 7079 } |
7813 } | 7080 } |
7814 } | 7081 } |
7815 | 7082 |
7816 /* Optimize cbrt(pow(x,y)) -> pow(x,y/3) iff x is nonnegative. */ | 7083 /* Optimize cbrt(pow(x,y)) -> pow(x,y/3) iff x is nonnegative. */ |
7817 if (fcode == BUILT_IN_POW | 7084 if (fcode == BUILT_IN_POW |
7818 || fcode == BUILT_IN_POWF | 7085 || fcode == BUILT_IN_POWF |
7819 || fcode == BUILT_IN_POWL) | 7086 || fcode == BUILT_IN_POWL) |
7820 { | 7087 { |
7821 tree arg00 = CALL_EXPR_ARG (arg, 0); | 7088 tree arg00 = CALL_EXPR_ARG (arg, 0); |
7822 tree arg01 = CALL_EXPR_ARG (arg, 1); | 7089 tree arg01 = CALL_EXPR_ARG (arg, 1); |
7823 if (tree_expr_nonnegative_p (arg00)) | 7090 if (tree_expr_nonnegative_p (arg00)) |
7824 { | 7091 { |
7825 tree powfn = TREE_OPERAND (CALL_EXPR_FN (arg), 0); | 7092 tree powfn = TREE_OPERAND (CALL_EXPR_FN (arg), 0); |
7826 const REAL_VALUE_TYPE dconstroot | 7093 const REAL_VALUE_TYPE dconstroot |
7827 = real_value_truncate (TYPE_MODE (type), dconst_third ()); | 7094 = real_value_truncate (TYPE_MODE (type), dconst_third ()); |
7828 tree narg01 = fold_build2 (MULT_EXPR, type, arg01, | 7095 tree narg01 = fold_build2_loc (loc, MULT_EXPR, type, arg01, |
7829 build_real (type, dconstroot)); | 7096 build_real (type, dconstroot)); |
7830 return build_call_expr (powfn, 2, arg00, narg01); | 7097 return build_call_expr_loc (loc, powfn, 2, arg00, narg01); |
7831 } | 7098 } |
7832 } | 7099 } |
7833 } | 7100 } |
7834 return NULL_TREE; | 7101 return NULL_TREE; |
7835 } | 7102 } |
7837 /* Fold function call to builtin cos, cosf, or cosl with argument ARG. | 7104 /* Fold function call to builtin cos, cosf, or cosl with argument ARG. |
7838 TYPE is the type of the return value. Return NULL_TREE if no | 7105 TYPE is the type of the return value. Return NULL_TREE if no |
7839 simplification can be made. */ | 7106 simplification can be made. */ |
7840 | 7107 |
7841 static tree | 7108 static tree |
7842 fold_builtin_cos (tree arg, tree type, tree fndecl) | 7109 fold_builtin_cos (location_t loc, |
7110 tree arg, tree type, tree fndecl) | |
7843 { | 7111 { |
7844 tree res, narg; | 7112 tree res, narg; |
7845 | 7113 |
7846 if (!validate_arg (arg, REAL_TYPE)) | 7114 if (!validate_arg (arg, REAL_TYPE)) |
7847 return NULL_TREE; | 7115 return NULL_TREE; |
7848 | 7116 |
7849 /* Calculate the result when the argument is a constant. */ | 7117 /* Calculate the result when the argument is a constant. */ |
7850 if ((res = do_mpfr_arg1 (arg, type, mpfr_cos, NULL, NULL, 0))) | 7118 if ((res = do_mpfr_arg1 (arg, type, mpfr_cos, NULL, NULL, 0))) |
7851 return res; | 7119 return res; |
7852 | 7120 |
7853 /* Optimize cos(-x) into cos (x). */ | 7121 /* Optimize cos(-x) into cos (x). */ |
7854 if ((narg = fold_strip_sign_ops (arg))) | 7122 if ((narg = fold_strip_sign_ops (arg))) |
7855 return build_call_expr (fndecl, 1, narg); | 7123 return build_call_expr_loc (loc, fndecl, 1, narg); |
7856 | 7124 |
7857 return NULL_TREE; | 7125 return NULL_TREE; |
7858 } | 7126 } |
7859 | 7127 |
7860 /* Fold function call to builtin cosh, coshf, or coshl with argument ARG. | 7128 /* Fold function call to builtin cosh, coshf, or coshl with argument ARG. |
7861 Return NULL_TREE if no simplification can be made. */ | 7129 Return NULL_TREE if no simplification can be made. */ |
7862 | 7130 |
7863 static tree | 7131 static tree |
7864 fold_builtin_cosh (tree arg, tree type, tree fndecl) | 7132 fold_builtin_cosh (location_t loc, tree arg, tree type, tree fndecl) |
7865 { | 7133 { |
7866 if (validate_arg (arg, REAL_TYPE)) | 7134 if (validate_arg (arg, REAL_TYPE)) |
7867 { | 7135 { |
7868 tree res, narg; | 7136 tree res, narg; |
7869 | 7137 |
7870 /* Calculate the result when the argument is a constant. */ | 7138 /* Calculate the result when the argument is a constant. */ |
7871 if ((res = do_mpfr_arg1 (arg, type, mpfr_cosh, NULL, NULL, 0))) | 7139 if ((res = do_mpfr_arg1 (arg, type, mpfr_cosh, NULL, NULL, 0))) |
7872 return res; | 7140 return res; |
7873 | 7141 |
7874 /* Optimize cosh(-x) into cosh (x). */ | 7142 /* Optimize cosh(-x) into cosh (x). */ |
7875 if ((narg = fold_strip_sign_ops (arg))) | 7143 if ((narg = fold_strip_sign_ops (arg))) |
7876 return build_call_expr (fndecl, 1, narg); | 7144 return build_call_expr_loc (loc, fndecl, 1, narg); |
7877 } | 7145 } |
7878 | 7146 |
7147 return NULL_TREE; | |
7148 } | |
7149 | |
7150 /* Fold function call to builtin ccos (or ccosh if HYPER is TRUE) with | |
7151 argument ARG. TYPE is the type of the return value. Return | |
7152 NULL_TREE if no simplification can be made. */ | |
7153 | |
7154 static tree | |
7155 fold_builtin_ccos (location_t loc, tree arg, tree type, tree fndecl, | |
7156 bool hyper) | |
7157 { | |
7158 if (validate_arg (arg, COMPLEX_TYPE) | |
7159 && TREE_CODE (TREE_TYPE (TREE_TYPE (arg))) == REAL_TYPE) | |
7160 { | |
7161 tree tmp; | |
7162 | |
7163 /* Calculate the result when the argument is a constant. */ | |
7164 if ((tmp = do_mpc_arg1 (arg, type, (hyper ? mpc_cosh : mpc_cos)))) | |
7165 return tmp; | |
7166 | |
7167 /* Optimize fn(-x) into fn(x). */ | |
7168 if ((tmp = fold_strip_sign_ops (arg))) | |
7169 return build_call_expr_loc (loc, fndecl, 1, tmp); | |
7170 } | |
7171 | |
7879 return NULL_TREE; | 7172 return NULL_TREE; |
7880 } | 7173 } |
7881 | 7174 |
7882 /* Fold function call to builtin tan, tanf, or tanl with argument ARG. | 7175 /* Fold function call to builtin tan, tanf, or tanl with argument ARG. |
7883 Return NULL_TREE if no simplification can be made. */ | 7176 Return NULL_TREE if no simplification can be made. */ |
7892 return NULL_TREE; | 7185 return NULL_TREE; |
7893 | 7186 |
7894 /* Calculate the result when the argument is a constant. */ | 7187 /* Calculate the result when the argument is a constant. */ |
7895 if ((res = do_mpfr_arg1 (arg, type, mpfr_tan, NULL, NULL, 0))) | 7188 if ((res = do_mpfr_arg1 (arg, type, mpfr_tan, NULL, NULL, 0))) |
7896 return res; | 7189 return res; |
7897 | 7190 |
7898 /* Optimize tan(atan(x)) = x. */ | 7191 /* Optimize tan(atan(x)) = x. */ |
7899 fcode = builtin_mathfn_code (arg); | 7192 fcode = builtin_mathfn_code (arg); |
7900 if (flag_unsafe_math_optimizations | 7193 if (flag_unsafe_math_optimizations |
7901 && (fcode == BUILT_IN_ATAN | 7194 && (fcode == BUILT_IN_ATAN |
7902 || fcode == BUILT_IN_ATANF | 7195 || fcode == BUILT_IN_ATANF |
7908 | 7201 |
7909 /* Fold function call to builtin sincos, sincosf, or sincosl. Return | 7202 /* Fold function call to builtin sincos, sincosf, or sincosl. Return |
7910 NULL_TREE if no simplification can be made. */ | 7203 NULL_TREE if no simplification can be made. */ |
7911 | 7204 |
7912 static tree | 7205 static tree |
7913 fold_builtin_sincos (tree arg0, tree arg1, tree arg2) | 7206 fold_builtin_sincos (location_t loc, |
7207 tree arg0, tree arg1, tree arg2) | |
7914 { | 7208 { |
7915 tree type; | 7209 tree type; |
7916 tree res, fn, call; | 7210 tree res, fn, call; |
7917 | 7211 |
7918 if (!validate_arg (arg0, REAL_TYPE) | 7212 if (!validate_arg (arg0, REAL_TYPE) |
7931 return NULL_TREE; | 7225 return NULL_TREE; |
7932 fn = mathfn_built_in (type, BUILT_IN_CEXPI); | 7226 fn = mathfn_built_in (type, BUILT_IN_CEXPI); |
7933 if (!fn) | 7227 if (!fn) |
7934 return NULL_TREE; | 7228 return NULL_TREE; |
7935 | 7229 |
7936 call = build_call_expr (fn, 1, arg0); | 7230 call = build_call_expr_loc (loc, fn, 1, arg0); |
7937 call = builtin_save_expr (call); | 7231 call = builtin_save_expr (call); |
7938 | 7232 |
7939 return build2 (COMPOUND_EXPR, type, | 7233 return build2 (COMPOUND_EXPR, void_type_node, |
7940 build2 (MODIFY_EXPR, void_type_node, | 7234 build2 (MODIFY_EXPR, void_type_node, |
7941 build_fold_indirect_ref (arg1), | 7235 build_fold_indirect_ref_loc (loc, arg1), |
7942 build1 (IMAGPART_EXPR, type, call)), | 7236 build1 (IMAGPART_EXPR, type, call)), |
7943 build2 (MODIFY_EXPR, void_type_node, | 7237 build2 (MODIFY_EXPR, void_type_node, |
7944 build_fold_indirect_ref (arg2), | 7238 build_fold_indirect_ref_loc (loc, arg2), |
7945 build1 (REALPART_EXPR, type, call))); | 7239 build1 (REALPART_EXPR, type, call))); |
7946 } | 7240 } |
7947 | 7241 |
7948 /* Fold function call to builtin cexp, cexpf, or cexpl. Return | 7242 /* Fold function call to builtin cexp, cexpf, or cexpl. Return |
7949 NULL_TREE if no simplification can be made. */ | 7243 NULL_TREE if no simplification can be made. */ |
7950 | 7244 |
7951 static tree | 7245 static tree |
7952 fold_builtin_cexp (tree arg0, tree type) | 7246 fold_builtin_cexp (location_t loc, tree arg0, tree type) |
7953 { | 7247 { |
7954 tree rtype; | 7248 tree rtype; |
7955 tree realp, imagp, ifn; | 7249 tree realp, imagp, ifn; |
7956 | 7250 tree res; |
7957 if (!validate_arg (arg0, COMPLEX_TYPE)) | 7251 |
7958 return NULL_TREE; | 7252 if (!validate_arg (arg0, COMPLEX_TYPE) |
7253 || TREE_CODE (TREE_TYPE (TREE_TYPE (arg0))) != REAL_TYPE) | |
7254 return NULL_TREE; | |
7255 | |
7256 /* Calculate the result when the argument is a constant. */ | |
7257 if ((res = do_mpc_arg1 (arg0, type, mpc_exp))) | |
7258 return res; | |
7959 | 7259 |
7960 rtype = TREE_TYPE (TREE_TYPE (arg0)); | 7260 rtype = TREE_TYPE (TREE_TYPE (arg0)); |
7961 | 7261 |
7962 /* In case we can figure out the real part of arg0 and it is constant zero | 7262 /* In case we can figure out the real part of arg0 and it is constant zero |
7963 fold to cexpi. */ | 7263 fold to cexpi. */ |
7965 return NULL_TREE; | 7265 return NULL_TREE; |
7966 ifn = mathfn_built_in (rtype, BUILT_IN_CEXPI); | 7266 ifn = mathfn_built_in (rtype, BUILT_IN_CEXPI); |
7967 if (!ifn) | 7267 if (!ifn) |
7968 return NULL_TREE; | 7268 return NULL_TREE; |
7969 | 7269 |
7970 if ((realp = fold_unary (REALPART_EXPR, rtype, arg0)) | 7270 if ((realp = fold_unary_loc (loc, REALPART_EXPR, rtype, arg0)) |
7971 && real_zerop (realp)) | 7271 && real_zerop (realp)) |
7972 { | 7272 { |
7973 tree narg = fold_build1 (IMAGPART_EXPR, rtype, arg0); | 7273 tree narg = fold_build1_loc (loc, IMAGPART_EXPR, rtype, arg0); |
7974 return build_call_expr (ifn, 1, narg); | 7274 return build_call_expr_loc (loc, ifn, 1, narg); |
7975 } | 7275 } |
7976 | 7276 |
7977 /* In case we can easily decompose real and imaginary parts split cexp | 7277 /* In case we can easily decompose real and imaginary parts split cexp |
7978 to exp (r) * cexpi (i). */ | 7278 to exp (r) * cexpi (i). */ |
7979 if (flag_unsafe_math_optimizations | 7279 if (flag_unsafe_math_optimizations |
7983 | 7283 |
7984 rfn = mathfn_built_in (rtype, BUILT_IN_EXP); | 7284 rfn = mathfn_built_in (rtype, BUILT_IN_EXP); |
7985 if (!rfn) | 7285 if (!rfn) |
7986 return NULL_TREE; | 7286 return NULL_TREE; |
7987 | 7287 |
7988 imagp = fold_unary (IMAGPART_EXPR, rtype, arg0); | 7288 imagp = fold_unary_loc (loc, IMAGPART_EXPR, rtype, arg0); |
7989 if (!imagp) | 7289 if (!imagp) |
7990 return NULL_TREE; | 7290 return NULL_TREE; |
7991 | 7291 |
7992 icall = build_call_expr (ifn, 1, imagp); | 7292 icall = build_call_expr_loc (loc, ifn, 1, imagp); |
7993 icall = builtin_save_expr (icall); | 7293 icall = builtin_save_expr (icall); |
7994 rcall = build_call_expr (rfn, 1, realp); | 7294 rcall = build_call_expr_loc (loc, rfn, 1, realp); |
7995 rcall = builtin_save_expr (rcall); | 7295 rcall = builtin_save_expr (rcall); |
7996 return fold_build2 (COMPLEX_EXPR, type, | 7296 return fold_build2_loc (loc, COMPLEX_EXPR, type, |
7997 fold_build2 (MULT_EXPR, rtype, | 7297 fold_build2_loc (loc, MULT_EXPR, rtype, |
7998 rcall, | 7298 rcall, |
7999 fold_build1 (REALPART_EXPR, rtype, icall)), | 7299 fold_build1_loc (loc, REALPART_EXPR, |
8000 fold_build2 (MULT_EXPR, rtype, | 7300 rtype, icall)), |
7301 fold_build2_loc (loc, MULT_EXPR, rtype, | |
8001 rcall, | 7302 rcall, |
8002 fold_build1 (IMAGPART_EXPR, rtype, icall))); | 7303 fold_build1_loc (loc, IMAGPART_EXPR, |
7304 rtype, icall))); | |
8003 } | 7305 } |
8004 | 7306 |
8005 return NULL_TREE; | 7307 return NULL_TREE; |
8006 } | 7308 } |
8007 | 7309 |
8008 /* Fold function call to builtin trunc, truncf or truncl with argument ARG. | 7310 /* Fold function call to builtin trunc, truncf or truncl with argument ARG. |
8009 Return NULL_TREE if no simplification can be made. */ | 7311 Return NULL_TREE if no simplification can be made. */ |
8010 | 7312 |
8011 static tree | 7313 static tree |
8012 fold_builtin_trunc (tree fndecl, tree arg) | 7314 fold_builtin_trunc (location_t loc, tree fndecl, tree arg) |
8013 { | 7315 { |
8014 if (!validate_arg (arg, REAL_TYPE)) | 7316 if (!validate_arg (arg, REAL_TYPE)) |
8015 return NULL_TREE; | 7317 return NULL_TREE; |
8016 | 7318 |
8017 /* Optimize trunc of constant value. */ | 7319 /* Optimize trunc of constant value. */ |
8023 x = TREE_REAL_CST (arg); | 7325 x = TREE_REAL_CST (arg); |
8024 real_trunc (&r, TYPE_MODE (type), &x); | 7326 real_trunc (&r, TYPE_MODE (type), &x); |
8025 return build_real (type, r); | 7327 return build_real (type, r); |
8026 } | 7328 } |
8027 | 7329 |
8028 return fold_trunc_transparent_mathfn (fndecl, arg); | 7330 return fold_trunc_transparent_mathfn (loc, fndecl, arg); |
8029 } | 7331 } |
8030 | 7332 |
8031 /* Fold function call to builtin floor, floorf or floorl with argument ARG. | 7333 /* Fold function call to builtin floor, floorf or floorl with argument ARG. |
8032 Return NULL_TREE if no simplification can be made. */ | 7334 Return NULL_TREE if no simplification can be made. */ |
8033 | 7335 |
8034 static tree | 7336 static tree |
8035 fold_builtin_floor (tree fndecl, tree arg) | 7337 fold_builtin_floor (location_t loc, tree fndecl, tree arg) |
8036 { | 7338 { |
8037 if (!validate_arg (arg, REAL_TYPE)) | 7339 if (!validate_arg (arg, REAL_TYPE)) |
8038 return NULL_TREE; | 7340 return NULL_TREE; |
8039 | 7341 |
8040 /* Optimize floor of constant value. */ | 7342 /* Optimize floor of constant value. */ |
8056 /* Fold floor (x) where x is nonnegative to trunc (x). */ | 7358 /* Fold floor (x) where x is nonnegative to trunc (x). */ |
8057 if (tree_expr_nonnegative_p (arg)) | 7359 if (tree_expr_nonnegative_p (arg)) |
8058 { | 7360 { |
8059 tree truncfn = mathfn_built_in (TREE_TYPE (arg), BUILT_IN_TRUNC); | 7361 tree truncfn = mathfn_built_in (TREE_TYPE (arg), BUILT_IN_TRUNC); |
8060 if (truncfn) | 7362 if (truncfn) |
8061 return build_call_expr (truncfn, 1, arg); | 7363 return build_call_expr_loc (loc, truncfn, 1, arg); |
8062 } | 7364 } |
8063 | 7365 |
8064 return fold_trunc_transparent_mathfn (fndecl, arg); | 7366 return fold_trunc_transparent_mathfn (loc, fndecl, arg); |
8065 } | 7367 } |
8066 | 7368 |
8067 /* Fold function call to builtin ceil, ceilf or ceill with argument ARG. | 7369 /* Fold function call to builtin ceil, ceilf or ceill with argument ARG. |
8068 Return NULL_TREE if no simplification can be made. */ | 7370 Return NULL_TREE if no simplification can be made. */ |
8069 | 7371 |
8070 static tree | 7372 static tree |
8071 fold_builtin_ceil (tree fndecl, tree arg) | 7373 fold_builtin_ceil (location_t loc, tree fndecl, tree arg) |
8072 { | 7374 { |
8073 if (!validate_arg (arg, REAL_TYPE)) | 7375 if (!validate_arg (arg, REAL_TYPE)) |
8074 return NULL_TREE; | 7376 return NULL_TREE; |
8075 | 7377 |
8076 /* Optimize ceil of constant value. */ | 7378 /* Optimize ceil of constant value. */ |
8087 real_ceil (&r, TYPE_MODE (type), &x); | 7389 real_ceil (&r, TYPE_MODE (type), &x); |
8088 return build_real (type, r); | 7390 return build_real (type, r); |
8089 } | 7391 } |
8090 } | 7392 } |
8091 | 7393 |
8092 return fold_trunc_transparent_mathfn (fndecl, arg); | 7394 return fold_trunc_transparent_mathfn (loc, fndecl, arg); |
8093 } | 7395 } |
8094 | 7396 |
8095 /* Fold function call to builtin round, roundf or roundl with argument ARG. | 7397 /* Fold function call to builtin round, roundf or roundl with argument ARG. |
8096 Return NULL_TREE if no simplification can be made. */ | 7398 Return NULL_TREE if no simplification can be made. */ |
8097 | 7399 |
8098 static tree | 7400 static tree |
8099 fold_builtin_round (tree fndecl, tree arg) | 7401 fold_builtin_round (location_t loc, tree fndecl, tree arg) |
8100 { | 7402 { |
8101 if (!validate_arg (arg, REAL_TYPE)) | 7403 if (!validate_arg (arg, REAL_TYPE)) |
8102 return NULL_TREE; | 7404 return NULL_TREE; |
8103 | 7405 |
8104 /* Optimize round of constant value. */ | 7406 /* Optimize round of constant value. */ |
8115 real_round (&r, TYPE_MODE (type), &x); | 7417 real_round (&r, TYPE_MODE (type), &x); |
8116 return build_real (type, r); | 7418 return build_real (type, r); |
8117 } | 7419 } |
8118 } | 7420 } |
8119 | 7421 |
8120 return fold_trunc_transparent_mathfn (fndecl, arg); | 7422 return fold_trunc_transparent_mathfn (loc, fndecl, arg); |
8121 } | 7423 } |
8122 | 7424 |
8123 /* Fold function call to builtin lround, lroundf or lroundl (or the | 7425 /* Fold function call to builtin lround, lroundf or lroundl (or the |
8124 corresponding long long versions) and other rounding functions. ARG | 7426 corresponding long long versions) and other rounding functions. ARG |
8125 is the argument to the call. Return NULL_TREE if no simplification | 7427 is the argument to the call. Return NULL_TREE if no simplification |
8126 can be made. */ | 7428 can be made. */ |
8127 | 7429 |
8128 static tree | 7430 static tree |
8129 fold_builtin_int_roundingfn (tree fndecl, tree arg) | 7431 fold_builtin_int_roundingfn (location_t loc, tree fndecl, tree arg) |
8130 { | 7432 { |
8131 if (!validate_arg (arg, REAL_TYPE)) | 7433 if (!validate_arg (arg, REAL_TYPE)) |
8132 return NULL_TREE; | 7434 return NULL_TREE; |
8133 | 7435 |
8134 /* Optimize lround of constant value. */ | 7436 /* Optimize lround of constant value. */ |
8175 { | 7477 { |
8176 CASE_FLT_FN (BUILT_IN_LFLOOR): | 7478 CASE_FLT_FN (BUILT_IN_LFLOOR): |
8177 CASE_FLT_FN (BUILT_IN_LLFLOOR): | 7479 CASE_FLT_FN (BUILT_IN_LLFLOOR): |
8178 /* Fold lfloor (x) where x is nonnegative to FIX_TRUNC (x). */ | 7480 /* Fold lfloor (x) where x is nonnegative to FIX_TRUNC (x). */ |
8179 if (tree_expr_nonnegative_p (arg)) | 7481 if (tree_expr_nonnegative_p (arg)) |
8180 return fold_build1 (FIX_TRUNC_EXPR, TREE_TYPE (TREE_TYPE (fndecl)), | 7482 return fold_build1_loc (loc, FIX_TRUNC_EXPR, |
8181 arg); | 7483 TREE_TYPE (TREE_TYPE (fndecl)), arg); |
8182 break; | 7484 break; |
8183 default:; | 7485 default:; |
8184 } | 7486 } |
8185 | 7487 |
8186 return fold_fixed_mathfn (fndecl, arg); | 7488 return fold_fixed_mathfn (loc, fndecl, arg); |
8187 } | 7489 } |
8188 | 7490 |
8189 /* Fold function call to builtin ffs, clz, ctz, popcount and parity | 7491 /* Fold function call to builtin ffs, clz, ctz, popcount and parity |
8190 and their long and long long variants (i.e. ffsl and ffsll). ARG is | 7492 and their long and long long variants (i.e. ffsl and ffsll). ARG is |
8191 the argument to the call. Return NULL_TREE if no simplification can | 7493 the argument to the call. Return NULL_TREE if no simplification can |
8335 } | 7637 } |
8336 | 7638 |
8337 return NULL_TREE; | 7639 return NULL_TREE; |
8338 } | 7640 } |
8339 | 7641 |
8340 /* Return true if EXPR is the real constant contained in VALUE. */ | |
8341 | |
8342 static bool | |
8343 real_dconstp (tree expr, const REAL_VALUE_TYPE *value) | |
8344 { | |
8345 STRIP_NOPS (expr); | |
8346 | |
8347 return ((TREE_CODE (expr) == REAL_CST | |
8348 && !TREE_OVERFLOW (expr) | |
8349 && REAL_VALUES_EQUAL (TREE_REAL_CST (expr), *value)) | |
8350 || (TREE_CODE (expr) == COMPLEX_CST | |
8351 && real_dconstp (TREE_REALPART (expr), value) | |
8352 && real_zerop (TREE_IMAGPART (expr)))); | |
8353 } | |
8354 | |
8355 /* A subroutine of fold_builtin to fold the various logarithmic | 7642 /* A subroutine of fold_builtin to fold the various logarithmic |
8356 functions. Return NULL_TREE if no simplification can me made. | 7643 functions. Return NULL_TREE if no simplification can me made. |
8357 FUNC is the corresponding MPFR logarithm function. */ | 7644 FUNC is the corresponding MPFR logarithm function. */ |
8358 | 7645 |
8359 static tree | 7646 static tree |
8360 fold_builtin_logarithm (tree fndecl, tree arg, | 7647 fold_builtin_logarithm (location_t loc, tree fndecl, tree arg, |
8361 int (*func)(mpfr_ptr, mpfr_srcptr, mp_rnd_t)) | 7648 int (*func)(mpfr_ptr, mpfr_srcptr, mp_rnd_t)) |
8362 { | 7649 { |
8363 if (validate_arg (arg, REAL_TYPE)) | 7650 if (validate_arg (arg, REAL_TYPE)) |
8364 { | 7651 { |
8365 tree type = TREE_TYPE (TREE_TYPE (fndecl)); | 7652 tree type = TREE_TYPE (TREE_TYPE (fndecl)); |
8366 tree res; | 7653 tree res; |
8367 const enum built_in_function fcode = builtin_mathfn_code (arg); | 7654 const enum built_in_function fcode = builtin_mathfn_code (arg); |
8368 | |
8369 /* Optimize log(e) = 1.0. We're never passed an exact 'e', | |
8370 instead we'll look for 'e' truncated to MODE. So only do | |
8371 this if flag_unsafe_math_optimizations is set. */ | |
8372 if (flag_unsafe_math_optimizations && func == mpfr_log) | |
8373 { | |
8374 const REAL_VALUE_TYPE e_truncated = | |
8375 real_value_truncate (TYPE_MODE (type), dconst_e ()); | |
8376 if (real_dconstp (arg, &e_truncated)) | |
8377 return build_real (type, dconst1); | |
8378 } | |
8379 | 7655 |
8380 /* Calculate the result when the argument is a constant. */ | 7656 /* Calculate the result when the argument is a constant. */ |
8381 if ((res = do_mpfr_arg1 (arg, type, func, &dconst0, NULL, false))) | 7657 if ((res = do_mpfr_arg1 (arg, type, func, &dconst0, NULL, false))) |
8382 return res; | 7658 return res; |
8383 | 7659 |
8390 || (func == mpfr_log2 | 7666 || (func == mpfr_log2 |
8391 && (fcode == BUILT_IN_EXP2 | 7667 && (fcode == BUILT_IN_EXP2 |
8392 || fcode == BUILT_IN_EXP2F | 7668 || fcode == BUILT_IN_EXP2F |
8393 || fcode == BUILT_IN_EXP2L)) | 7669 || fcode == BUILT_IN_EXP2L)) |
8394 || (func == mpfr_log10 && (BUILTIN_EXP10_P (fcode))))) | 7670 || (func == mpfr_log10 && (BUILTIN_EXP10_P (fcode))))) |
8395 return fold_convert (type, CALL_EXPR_ARG (arg, 0)); | 7671 return fold_convert_loc (loc, type, CALL_EXPR_ARG (arg, 0)); |
8396 | 7672 |
8397 /* Optimize logN(func()) for various exponential functions. We | 7673 /* Optimize logN(func()) for various exponential functions. We |
8398 want to determine the value "x" and the power "exponent" in | 7674 want to determine the value "x" and the power "exponent" in |
8399 order to transform logN(x**exponent) into exponent*logN(x). */ | 7675 order to transform logN(x**exponent) into exponent*logN(x). */ |
8400 if (flag_unsafe_math_optimizations) | 7676 if (flag_unsafe_math_optimizations) |
8403 | 7679 |
8404 switch (fcode) | 7680 switch (fcode) |
8405 { | 7681 { |
8406 CASE_FLT_FN (BUILT_IN_EXP): | 7682 CASE_FLT_FN (BUILT_IN_EXP): |
8407 /* Prepare to do logN(exp(exponent) -> exponent*logN(e). */ | 7683 /* Prepare to do logN(exp(exponent) -> exponent*logN(e). */ |
8408 x = build_real (type, real_value_truncate (TYPE_MODE (type), | 7684 x = build_real (type, real_value_truncate (TYPE_MODE (type), |
8409 dconst_e ())); | 7685 dconst_e ())); |
8410 exponent = CALL_EXPR_ARG (arg, 0); | 7686 exponent = CALL_EXPR_ARG (arg, 0); |
8411 break; | 7687 break; |
8412 CASE_FLT_FN (BUILT_IN_EXP2): | 7688 CASE_FLT_FN (BUILT_IN_EXP2): |
8413 /* Prepare to do logN(exp2(exponent) -> exponent*logN(2). */ | 7689 /* Prepare to do logN(exp2(exponent) -> exponent*logN(2). */ |
8445 } | 7721 } |
8446 | 7722 |
8447 /* Now perform the optimization. */ | 7723 /* Now perform the optimization. */ |
8448 if (x && exponent) | 7724 if (x && exponent) |
8449 { | 7725 { |
8450 tree logfn = build_call_expr (fndecl, 1, x); | 7726 tree logfn = build_call_expr_loc (loc, fndecl, 1, x); |
8451 return fold_build2 (MULT_EXPR, type, exponent, logfn); | 7727 return fold_build2_loc (loc, MULT_EXPR, type, exponent, logfn); |
8452 } | 7728 } |
8453 } | 7729 } |
8454 } | 7730 } |
8455 | 7731 |
8456 return NULL_TREE; | 7732 return NULL_TREE; |
8458 | 7734 |
8459 /* Fold a builtin function call to hypot, hypotf, or hypotl. Return | 7735 /* Fold a builtin function call to hypot, hypotf, or hypotl. Return |
8460 NULL_TREE if no simplification can be made. */ | 7736 NULL_TREE if no simplification can be made. */ |
8461 | 7737 |
8462 static tree | 7738 static tree |
8463 fold_builtin_hypot (tree fndecl, tree arg0, tree arg1, tree type) | 7739 fold_builtin_hypot (location_t loc, tree fndecl, |
7740 tree arg0, tree arg1, tree type) | |
8464 { | 7741 { |
8465 tree res, narg0, narg1; | 7742 tree res, narg0, narg1; |
8466 | 7743 |
8467 if (!validate_arg (arg0, REAL_TYPE) | 7744 if (!validate_arg (arg0, REAL_TYPE) |
8468 || !validate_arg (arg1, REAL_TYPE)) | 7745 || !validate_arg (arg1, REAL_TYPE)) |
8469 return NULL_TREE; | 7746 return NULL_TREE; |
8470 | 7747 |
8471 /* Calculate the result when the argument is a constant. */ | 7748 /* Calculate the result when the argument is a constant. */ |
8472 if ((res = do_mpfr_arg2 (arg0, arg1, type, mpfr_hypot))) | 7749 if ((res = do_mpfr_arg2 (arg0, arg1, type, mpfr_hypot))) |
8473 return res; | 7750 return res; |
8474 | 7751 |
8475 /* If either argument to hypot has a negate or abs, strip that off. | 7752 /* If either argument to hypot has a negate or abs, strip that off. |
8476 E.g. hypot(-x,fabs(y)) -> hypot(x,y). */ | 7753 E.g. hypot(-x,fabs(y)) -> hypot(x,y). */ |
8477 narg0 = fold_strip_sign_ops (arg0); | 7754 narg0 = fold_strip_sign_ops (arg0); |
8478 narg1 = fold_strip_sign_ops (arg1); | 7755 narg1 = fold_strip_sign_ops (arg1); |
8479 if (narg0 || narg1) | 7756 if (narg0 || narg1) |
8480 { | 7757 { |
8481 return build_call_expr (fndecl, 2, narg0 ? narg0 : arg0, | 7758 return build_call_expr_loc (loc, fndecl, 2, narg0 ? narg0 : arg0, |
8482 narg1 ? narg1 : arg1); | 7759 narg1 ? narg1 : arg1); |
8483 } | 7760 } |
8484 | 7761 |
8485 /* If either argument is zero, hypot is fabs of the other. */ | 7762 /* If either argument is zero, hypot is fabs of the other. */ |
8486 if (real_zerop (arg0)) | 7763 if (real_zerop (arg0)) |
8487 return fold_build1 (ABS_EXPR, type, arg1); | 7764 return fold_build1_loc (loc, ABS_EXPR, type, arg1); |
8488 else if (real_zerop (arg1)) | 7765 else if (real_zerop (arg1)) |
8489 return fold_build1 (ABS_EXPR, type, arg0); | 7766 return fold_build1_loc (loc, ABS_EXPR, type, arg0); |
8490 | 7767 |
8491 /* hypot(x,x) -> fabs(x)*sqrt(2). */ | 7768 /* hypot(x,x) -> fabs(x)*sqrt(2). */ |
8492 if (flag_unsafe_math_optimizations | 7769 if (flag_unsafe_math_optimizations |
8493 && operand_equal_p (arg0, arg1, OEP_PURE_SAME)) | 7770 && operand_equal_p (arg0, arg1, OEP_PURE_SAME)) |
8494 { | 7771 { |
8495 const REAL_VALUE_TYPE sqrt2_trunc | 7772 const REAL_VALUE_TYPE sqrt2_trunc |
8496 = real_value_truncate (TYPE_MODE (type), dconst_sqrt2 ()); | 7773 = real_value_truncate (TYPE_MODE (type), dconst_sqrt2 ()); |
8497 return fold_build2 (MULT_EXPR, type, | 7774 return fold_build2_loc (loc, MULT_EXPR, type, |
8498 fold_build1 (ABS_EXPR, type, arg0), | 7775 fold_build1_loc (loc, ABS_EXPR, type, arg0), |
8499 build_real (type, sqrt2_trunc)); | 7776 build_real (type, sqrt2_trunc)); |
8500 } | 7777 } |
8501 | 7778 |
8502 return NULL_TREE; | 7779 return NULL_TREE; |
8503 } | 7780 } |
8504 | 7781 |
8505 | 7782 |
8506 /* Fold a builtin function call to pow, powf, or powl. Return | 7783 /* Fold a builtin function call to pow, powf, or powl. Return |
8507 NULL_TREE if no simplification can be made. */ | 7784 NULL_TREE if no simplification can be made. */ |
8508 static tree | 7785 static tree |
8509 fold_builtin_pow (tree fndecl, tree arg0, tree arg1, tree type) | 7786 fold_builtin_pow (location_t loc, tree fndecl, tree arg0, tree arg1, tree type) |
8510 { | 7787 { |
8511 tree res; | 7788 tree res; |
8512 | 7789 |
8513 if (!validate_arg (arg0, REAL_TYPE) | 7790 if (!validate_arg (arg0, REAL_TYPE) |
8514 || !validate_arg (arg1, REAL_TYPE)) | 7791 || !validate_arg (arg1, REAL_TYPE)) |
8518 if ((res = do_mpfr_arg2 (arg0, arg1, type, mpfr_pow))) | 7795 if ((res = do_mpfr_arg2 (arg0, arg1, type, mpfr_pow))) |
8519 return res; | 7796 return res; |
8520 | 7797 |
8521 /* Optimize pow(1.0,y) = 1.0. */ | 7798 /* Optimize pow(1.0,y) = 1.0. */ |
8522 if (real_onep (arg0)) | 7799 if (real_onep (arg0)) |
8523 return omit_one_operand (type, build_real (type, dconst1), arg1); | 7800 return omit_one_operand_loc (loc, type, build_real (type, dconst1), arg1); |
8524 | 7801 |
8525 if (TREE_CODE (arg1) == REAL_CST | 7802 if (TREE_CODE (arg1) == REAL_CST |
8526 && !TREE_OVERFLOW (arg1)) | 7803 && !TREE_OVERFLOW (arg1)) |
8527 { | 7804 { |
8528 REAL_VALUE_TYPE cint; | 7805 REAL_VALUE_TYPE cint; |
8531 | 7808 |
8532 c = TREE_REAL_CST (arg1); | 7809 c = TREE_REAL_CST (arg1); |
8533 | 7810 |
8534 /* Optimize pow(x,0.0) = 1.0. */ | 7811 /* Optimize pow(x,0.0) = 1.0. */ |
8535 if (REAL_VALUES_EQUAL (c, dconst0)) | 7812 if (REAL_VALUES_EQUAL (c, dconst0)) |
8536 return omit_one_operand (type, build_real (type, dconst1), | 7813 return omit_one_operand_loc (loc, type, build_real (type, dconst1), |
8537 arg0); | 7814 arg0); |
8538 | 7815 |
8539 /* Optimize pow(x,1.0) = x. */ | 7816 /* Optimize pow(x,1.0) = x. */ |
8540 if (REAL_VALUES_EQUAL (c, dconst1)) | 7817 if (REAL_VALUES_EQUAL (c, dconst1)) |
8541 return arg0; | 7818 return arg0; |
8542 | 7819 |
8543 /* Optimize pow(x,-1.0) = 1.0/x. */ | 7820 /* Optimize pow(x,-1.0) = 1.0/x. */ |
8544 if (REAL_VALUES_EQUAL (c, dconstm1)) | 7821 if (REAL_VALUES_EQUAL (c, dconstm1)) |
8545 return fold_build2 (RDIV_EXPR, type, | 7822 return fold_build2_loc (loc, RDIV_EXPR, type, |
8546 build_real (type, dconst1), arg0); | 7823 build_real (type, dconst1), arg0); |
8547 | 7824 |
8548 /* Optimize pow(x,0.5) = sqrt(x). */ | 7825 /* Optimize pow(x,0.5) = sqrt(x). */ |
8549 if (flag_unsafe_math_optimizations | 7826 if (flag_unsafe_math_optimizations |
8550 && REAL_VALUES_EQUAL (c, dconsthalf)) | 7827 && REAL_VALUES_EQUAL (c, dconsthalf)) |
8551 { | 7828 { |
8552 tree sqrtfn = mathfn_built_in (type, BUILT_IN_SQRT); | 7829 tree sqrtfn = mathfn_built_in (type, BUILT_IN_SQRT); |
8553 | 7830 |
8554 if (sqrtfn != NULL_TREE) | 7831 if (sqrtfn != NULL_TREE) |
8555 return build_call_expr (sqrtfn, 1, arg0); | 7832 return build_call_expr_loc (loc, sqrtfn, 1, arg0); |
8556 } | 7833 } |
8557 | 7834 |
8558 /* Optimize pow(x,1.0/3.0) = cbrt(x). */ | 7835 /* Optimize pow(x,1.0/3.0) = cbrt(x). */ |
8559 if (flag_unsafe_math_optimizations) | 7836 if (flag_unsafe_math_optimizations) |
8560 { | 7837 { |
8563 | 7840 |
8564 if (REAL_VALUES_EQUAL (c, dconstroot)) | 7841 if (REAL_VALUES_EQUAL (c, dconstroot)) |
8565 { | 7842 { |
8566 tree cbrtfn = mathfn_built_in (type, BUILT_IN_CBRT); | 7843 tree cbrtfn = mathfn_built_in (type, BUILT_IN_CBRT); |
8567 if (cbrtfn != NULL_TREE) | 7844 if (cbrtfn != NULL_TREE) |
8568 return build_call_expr (cbrtfn, 1, arg0); | 7845 return build_call_expr_loc (loc, cbrtfn, 1, arg0); |
8569 } | 7846 } |
8570 } | 7847 } |
8571 | 7848 |
8572 /* Check for an integer exponent. */ | 7849 /* Check for an integer exponent. */ |
8573 n = real_to_integer (&c); | 7850 n = real_to_integer (&c); |
8594 /* Strip sign ops from even integer powers. */ | 7871 /* Strip sign ops from even integer powers. */ |
8595 if ((n & 1) == 0 && flag_unsafe_math_optimizations) | 7872 if ((n & 1) == 0 && flag_unsafe_math_optimizations) |
8596 { | 7873 { |
8597 tree narg0 = fold_strip_sign_ops (arg0); | 7874 tree narg0 = fold_strip_sign_ops (arg0); |
8598 if (narg0) | 7875 if (narg0) |
8599 return build_call_expr (fndecl, 2, narg0, arg1); | 7876 return build_call_expr_loc (loc, fndecl, 2, narg0, arg1); |
8600 } | 7877 } |
8601 } | 7878 } |
8602 } | 7879 } |
8603 | 7880 |
8604 if (flag_unsafe_math_optimizations) | 7881 if (flag_unsafe_math_optimizations) |
8608 /* Optimize pow(expN(x),y) = expN(x*y). */ | 7885 /* Optimize pow(expN(x),y) = expN(x*y). */ |
8609 if (BUILTIN_EXPONENT_P (fcode)) | 7886 if (BUILTIN_EXPONENT_P (fcode)) |
8610 { | 7887 { |
8611 tree expfn = TREE_OPERAND (CALL_EXPR_FN (arg0), 0); | 7888 tree expfn = TREE_OPERAND (CALL_EXPR_FN (arg0), 0); |
8612 tree arg = CALL_EXPR_ARG (arg0, 0); | 7889 tree arg = CALL_EXPR_ARG (arg0, 0); |
8613 arg = fold_build2 (MULT_EXPR, type, arg, arg1); | 7890 arg = fold_build2_loc (loc, MULT_EXPR, type, arg, arg1); |
8614 return build_call_expr (expfn, 1, arg); | 7891 return build_call_expr_loc (loc, expfn, 1, arg); |
8615 } | 7892 } |
8616 | 7893 |
8617 /* Optimize pow(sqrt(x),y) = pow(x,y*0.5). */ | 7894 /* Optimize pow(sqrt(x),y) = pow(x,y*0.5). */ |
8618 if (BUILTIN_SQRT_P (fcode)) | 7895 if (BUILTIN_SQRT_P (fcode)) |
8619 { | 7896 { |
8620 tree narg0 = CALL_EXPR_ARG (arg0, 0); | 7897 tree narg0 = CALL_EXPR_ARG (arg0, 0); |
8621 tree narg1 = fold_build2 (MULT_EXPR, type, arg1, | 7898 tree narg1 = fold_build2_loc (loc, MULT_EXPR, type, arg1, |
8622 build_real (type, dconsthalf)); | 7899 build_real (type, dconsthalf)); |
8623 return build_call_expr (fndecl, 2, narg0, narg1); | 7900 return build_call_expr_loc (loc, fndecl, 2, narg0, narg1); |
8624 } | 7901 } |
8625 | 7902 |
8626 /* Optimize pow(cbrt(x),y) = pow(x,y/3) iff x is nonnegative. */ | 7903 /* Optimize pow(cbrt(x),y) = pow(x,y/3) iff x is nonnegative. */ |
8627 if (BUILTIN_CBRT_P (fcode)) | 7904 if (BUILTIN_CBRT_P (fcode)) |
8628 { | 7905 { |
8629 tree arg = CALL_EXPR_ARG (arg0, 0); | 7906 tree arg = CALL_EXPR_ARG (arg0, 0); |
8630 if (tree_expr_nonnegative_p (arg)) | 7907 if (tree_expr_nonnegative_p (arg)) |
8631 { | 7908 { |
8632 const REAL_VALUE_TYPE dconstroot | 7909 const REAL_VALUE_TYPE dconstroot |
8633 = real_value_truncate (TYPE_MODE (type), dconst_third ()); | 7910 = real_value_truncate (TYPE_MODE (type), dconst_third ()); |
8634 tree narg1 = fold_build2 (MULT_EXPR, type, arg1, | 7911 tree narg1 = fold_build2_loc (loc, MULT_EXPR, type, arg1, |
8635 build_real (type, dconstroot)); | 7912 build_real (type, dconstroot)); |
8636 return build_call_expr (fndecl, 2, arg, narg1); | 7913 return build_call_expr_loc (loc, fndecl, 2, arg, narg1); |
8637 } | 7914 } |
8638 } | 7915 } |
8639 | 7916 |
8640 /* Optimize pow(pow(x,y),z) = pow(x,y*z) iff x is nonnegative. */ | 7917 /* Optimize pow(pow(x,y),z) = pow(x,y*z) iff x is nonnegative. */ |
8641 if (fcode == BUILT_IN_POW | 7918 if (fcode == BUILT_IN_POW |
8644 { | 7921 { |
8645 tree arg00 = CALL_EXPR_ARG (arg0, 0); | 7922 tree arg00 = CALL_EXPR_ARG (arg0, 0); |
8646 if (tree_expr_nonnegative_p (arg00)) | 7923 if (tree_expr_nonnegative_p (arg00)) |
8647 { | 7924 { |
8648 tree arg01 = CALL_EXPR_ARG (arg0, 1); | 7925 tree arg01 = CALL_EXPR_ARG (arg0, 1); |
8649 tree narg1 = fold_build2 (MULT_EXPR, type, arg01, arg1); | 7926 tree narg1 = fold_build2_loc (loc, MULT_EXPR, type, arg01, arg1); |
8650 return build_call_expr (fndecl, 2, arg00, narg1); | 7927 return build_call_expr_loc (loc, fndecl, 2, arg00, narg1); |
8651 } | 7928 } |
8652 } | 7929 } |
8653 } | 7930 } |
8654 | 7931 |
8655 return NULL_TREE; | 7932 return NULL_TREE; |
8656 } | 7933 } |
8657 | 7934 |
8658 /* Fold a builtin function call to powi, powif, or powil with argument ARG. | 7935 /* Fold a builtin function call to powi, powif, or powil with argument ARG. |
8659 Return NULL_TREE if no simplification can be made. */ | 7936 Return NULL_TREE if no simplification can be made. */ |
8660 static tree | 7937 static tree |
8661 fold_builtin_powi (tree fndecl ATTRIBUTE_UNUSED, | 7938 fold_builtin_powi (location_t loc, tree fndecl ATTRIBUTE_UNUSED, |
8662 tree arg0, tree arg1, tree type) | 7939 tree arg0, tree arg1, tree type) |
8663 { | 7940 { |
8664 if (!validate_arg (arg0, REAL_TYPE) | 7941 if (!validate_arg (arg0, REAL_TYPE) |
8665 || !validate_arg (arg1, INTEGER_TYPE)) | 7942 || !validate_arg (arg1, INTEGER_TYPE)) |
8666 return NULL_TREE; | 7943 return NULL_TREE; |
8667 | 7944 |
8668 /* Optimize pow(1.0,y) = 1.0. */ | 7945 /* Optimize pow(1.0,y) = 1.0. */ |
8669 if (real_onep (arg0)) | 7946 if (real_onep (arg0)) |
8670 return omit_one_operand (type, build_real (type, dconst1), arg1); | 7947 return omit_one_operand_loc (loc, type, build_real (type, dconst1), arg1); |
8671 | 7948 |
8672 if (host_integerp (arg1, 0)) | 7949 if (host_integerp (arg1, 0)) |
8673 { | 7950 { |
8674 HOST_WIDE_INT c = TREE_INT_CST_LOW (arg1); | 7951 HOST_WIDE_INT c = TREE_INT_CST_LOW (arg1); |
8675 | 7952 |
8683 return build_real (type, x); | 7960 return build_real (type, x); |
8684 } | 7961 } |
8685 | 7962 |
8686 /* Optimize pow(x,0) = 1.0. */ | 7963 /* Optimize pow(x,0) = 1.0. */ |
8687 if (c == 0) | 7964 if (c == 0) |
8688 return omit_one_operand (type, build_real (type, dconst1), | 7965 return omit_one_operand_loc (loc, type, build_real (type, dconst1), |
8689 arg0); | 7966 arg0); |
8690 | 7967 |
8691 /* Optimize pow(x,1) = x. */ | 7968 /* Optimize pow(x,1) = x. */ |
8692 if (c == 1) | 7969 if (c == 1) |
8693 return arg0; | 7970 return arg0; |
8694 | 7971 |
8695 /* Optimize pow(x,-1) = 1.0/x. */ | 7972 /* Optimize pow(x,-1) = 1.0/x. */ |
8696 if (c == -1) | 7973 if (c == -1) |
8697 return fold_build2 (RDIV_EXPR, type, | 7974 return fold_build2_loc (loc, RDIV_EXPR, type, |
8698 build_real (type, dconst1), arg0); | 7975 build_real (type, dconst1), arg0); |
8699 } | 7976 } |
8700 | 7977 |
8701 return NULL_TREE; | 7978 return NULL_TREE; |
8702 } | 7979 } |
8704 /* A subroutine of fold_builtin to fold the various exponent | 7981 /* A subroutine of fold_builtin to fold the various exponent |
8705 functions. Return NULL_TREE if no simplification can be made. | 7982 functions. Return NULL_TREE if no simplification can be made. |
8706 FUNC is the corresponding MPFR exponent function. */ | 7983 FUNC is the corresponding MPFR exponent function. */ |
8707 | 7984 |
8708 static tree | 7985 static tree |
8709 fold_builtin_exponent (tree fndecl, tree arg, | 7986 fold_builtin_exponent (location_t loc, tree fndecl, tree arg, |
8710 int (*func)(mpfr_ptr, mpfr_srcptr, mp_rnd_t)) | 7987 int (*func)(mpfr_ptr, mpfr_srcptr, mp_rnd_t)) |
8711 { | 7988 { |
8712 if (validate_arg (arg, REAL_TYPE)) | 7989 if (validate_arg (arg, REAL_TYPE)) |
8713 { | 7990 { |
8714 tree type = TREE_TYPE (TREE_TYPE (fndecl)); | 7991 tree type = TREE_TYPE (TREE_TYPE (fndecl)); |
8715 tree res; | 7992 tree res; |
8716 | 7993 |
8717 /* Calculate the result when the argument is a constant. */ | 7994 /* Calculate the result when the argument is a constant. */ |
8718 if ((res = do_mpfr_arg1 (arg, type, func, NULL, NULL, 0))) | 7995 if ((res = do_mpfr_arg1 (arg, type, func, NULL, NULL, 0))) |
8719 return res; | 7996 return res; |
8720 | 7997 |
8721 /* Optimize expN(logN(x)) = x. */ | 7998 /* Optimize expN(logN(x)) = x. */ |
8733 || fcode == BUILT_IN_LOG2L)) | 8010 || fcode == BUILT_IN_LOG2L)) |
8734 || (func == mpfr_exp10 | 8011 || (func == mpfr_exp10 |
8735 && (fcode == BUILT_IN_LOG10 | 8012 && (fcode == BUILT_IN_LOG10 |
8736 || fcode == BUILT_IN_LOG10F | 8013 || fcode == BUILT_IN_LOG10F |
8737 || fcode == BUILT_IN_LOG10L))) | 8014 || fcode == BUILT_IN_LOG10L))) |
8738 return fold_convert (type, CALL_EXPR_ARG (arg, 0)); | 8015 return fold_convert_loc (loc, type, CALL_EXPR_ARG (arg, 0)); |
8739 } | 8016 } |
8740 } | 8017 } |
8741 | 8018 |
8742 return NULL_TREE; | 8019 return NULL_TREE; |
8743 } | 8020 } |
8755 | 8032 |
8756 /* Fold function call to builtin memset. Return | 8033 /* Fold function call to builtin memset. Return |
8757 NULL_TREE if no simplification can be made. */ | 8034 NULL_TREE if no simplification can be made. */ |
8758 | 8035 |
8759 static tree | 8036 static tree |
8760 fold_builtin_memset (tree dest, tree c, tree len, tree type, bool ignore) | 8037 fold_builtin_memset (location_t loc, tree dest, tree c, tree len, |
8761 { | 8038 tree type, bool ignore) |
8762 tree var, ret; | 8039 { |
8040 tree var, ret, etype; | |
8763 unsigned HOST_WIDE_INT length, cval; | 8041 unsigned HOST_WIDE_INT length, cval; |
8764 | 8042 |
8765 if (! validate_arg (dest, POINTER_TYPE) | 8043 if (! validate_arg (dest, POINTER_TYPE) |
8766 || ! validate_arg (c, INTEGER_TYPE) | 8044 || ! validate_arg (c, INTEGER_TYPE) |
8767 || ! validate_arg (len, INTEGER_TYPE)) | 8045 || ! validate_arg (len, INTEGER_TYPE)) |
8770 if (! host_integerp (len, 1)) | 8048 if (! host_integerp (len, 1)) |
8771 return NULL_TREE; | 8049 return NULL_TREE; |
8772 | 8050 |
8773 /* If the LEN parameter is zero, return DEST. */ | 8051 /* If the LEN parameter is zero, return DEST. */ |
8774 if (integer_zerop (len)) | 8052 if (integer_zerop (len)) |
8775 return omit_one_operand (type, dest, c); | 8053 return omit_one_operand_loc (loc, type, dest, c); |
8776 | 8054 |
8777 if (! host_integerp (c, 1) || TREE_SIDE_EFFECTS (dest)) | 8055 if (! host_integerp (c, 1) || TREE_SIDE_EFFECTS (dest)) |
8778 return NULL_TREE; | 8056 return NULL_TREE; |
8779 | 8057 |
8780 var = dest; | 8058 var = dest; |
8784 | 8062 |
8785 var = TREE_OPERAND (var, 0); | 8063 var = TREE_OPERAND (var, 0); |
8786 if (TREE_THIS_VOLATILE (var)) | 8064 if (TREE_THIS_VOLATILE (var)) |
8787 return NULL_TREE; | 8065 return NULL_TREE; |
8788 | 8066 |
8789 if (!INTEGRAL_TYPE_P (TREE_TYPE (var)) | 8067 etype = TREE_TYPE (var); |
8790 && !POINTER_TYPE_P (TREE_TYPE (var))) | 8068 if (TREE_CODE (etype) == ARRAY_TYPE) |
8069 etype = TREE_TYPE (etype); | |
8070 | |
8071 if (!INTEGRAL_TYPE_P (etype) | |
8072 && !POINTER_TYPE_P (etype)) | |
8791 return NULL_TREE; | 8073 return NULL_TREE; |
8792 | 8074 |
8793 if (! var_decl_component_p (var)) | 8075 if (! var_decl_component_p (var)) |
8794 return NULL_TREE; | 8076 return NULL_TREE; |
8795 | 8077 |
8796 length = tree_low_cst (len, 1); | 8078 length = tree_low_cst (len, 1); |
8797 if (GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (var))) != length | 8079 if (GET_MODE_SIZE (TYPE_MODE (etype)) != length |
8798 || get_pointer_alignment (dest, BIGGEST_ALIGNMENT) / BITS_PER_UNIT | 8080 || get_pointer_alignment (dest, BIGGEST_ALIGNMENT) / BITS_PER_UNIT |
8799 < (int) length) | 8081 < (int) length) |
8800 return NULL_TREE; | 8082 return NULL_TREE; |
8801 | 8083 |
8802 if (length > HOST_BITS_PER_WIDE_INT / BITS_PER_UNIT) | 8084 if (length > HOST_BITS_PER_WIDE_INT / BITS_PER_UNIT) |
8814 cval |= cval << 8; | 8096 cval |= cval << 8; |
8815 cval |= cval << 16; | 8097 cval |= cval << 16; |
8816 cval |= (cval << 31) << 1; | 8098 cval |= (cval << 31) << 1; |
8817 } | 8099 } |
8818 | 8100 |
8819 ret = build_int_cst_type (TREE_TYPE (var), cval); | 8101 ret = build_int_cst_type (etype, cval); |
8820 ret = build2 (MODIFY_EXPR, TREE_TYPE (var), var, ret); | 8102 var = build_fold_indirect_ref_loc (loc, |
8103 fold_convert_loc (loc, | |
8104 build_pointer_type (etype), | |
8105 dest)); | |
8106 ret = build2 (MODIFY_EXPR, etype, var, ret); | |
8821 if (ignore) | 8107 if (ignore) |
8822 return ret; | 8108 return ret; |
8823 | 8109 |
8824 return omit_one_operand (type, dest, ret); | 8110 return omit_one_operand_loc (loc, type, dest, ret); |
8825 } | 8111 } |
8826 | 8112 |
8827 /* Fold function call to builtin memset. Return | 8113 /* Fold function call to builtin memset. Return |
8828 NULL_TREE if no simplification can be made. */ | 8114 NULL_TREE if no simplification can be made. */ |
8829 | 8115 |
8830 static tree | 8116 static tree |
8831 fold_builtin_bzero (tree dest, tree size, bool ignore) | 8117 fold_builtin_bzero (location_t loc, tree dest, tree size, bool ignore) |
8832 { | 8118 { |
8833 if (! validate_arg (dest, POINTER_TYPE) | 8119 if (! validate_arg (dest, POINTER_TYPE) |
8834 || ! validate_arg (size, INTEGER_TYPE)) | 8120 || ! validate_arg (size, INTEGER_TYPE)) |
8835 return NULL_TREE; | 8121 return NULL_TREE; |
8836 | 8122 |
8840 /* New argument list transforming bzero(ptr x, int y) to | 8126 /* New argument list transforming bzero(ptr x, int y) to |
8841 memset(ptr x, int 0, size_t y). This is done this way | 8127 memset(ptr x, int 0, size_t y). This is done this way |
8842 so that if it isn't expanded inline, we fallback to | 8128 so that if it isn't expanded inline, we fallback to |
8843 calling bzero instead of memset. */ | 8129 calling bzero instead of memset. */ |
8844 | 8130 |
8845 return fold_builtin_memset (dest, integer_zero_node, | 8131 return fold_builtin_memset (loc, dest, integer_zero_node, |
8846 fold_convert (sizetype, size), | 8132 fold_convert_loc (loc, sizetype, size), |
8847 void_type_node, ignore); | 8133 void_type_node, ignore); |
8848 } | 8134 } |
8849 | 8135 |
8850 /* Fold function call to builtin mem{{,p}cpy,move}. Return | 8136 /* Fold function call to builtin mem{{,p}cpy,move}. Return |
8851 NULL_TREE if no simplification can be made. | 8137 NULL_TREE if no simplification can be made. |
8854 If ENDP is 2, return DEST+LEN-1 (like stpcpy). | 8140 If ENDP is 2, return DEST+LEN-1 (like stpcpy). |
8855 If ENDP is 3, return DEST, additionally *SRC and *DEST may overlap | 8141 If ENDP is 3, return DEST, additionally *SRC and *DEST may overlap |
8856 (memmove). */ | 8142 (memmove). */ |
8857 | 8143 |
8858 static tree | 8144 static tree |
8859 fold_builtin_memory_op (tree dest, tree src, tree len, tree type, bool ignore, int endp) | 8145 fold_builtin_memory_op (location_t loc, tree dest, tree src, |
8146 tree len, tree type, bool ignore, int endp) | |
8860 { | 8147 { |
8861 tree destvar, srcvar, expr; | 8148 tree destvar, srcvar, expr; |
8862 | 8149 |
8863 if (! validate_arg (dest, POINTER_TYPE) | 8150 if (! validate_arg (dest, POINTER_TYPE) |
8864 || ! validate_arg (src, POINTER_TYPE) | 8151 || ! validate_arg (src, POINTER_TYPE) |
8865 || ! validate_arg (len, INTEGER_TYPE)) | 8152 || ! validate_arg (len, INTEGER_TYPE)) |
8866 return NULL_TREE; | 8153 return NULL_TREE; |
8867 | 8154 |
8868 /* If the LEN parameter is zero, return DEST. */ | 8155 /* If the LEN parameter is zero, return DEST. */ |
8869 if (integer_zerop (len)) | 8156 if (integer_zerop (len)) |
8870 return omit_one_operand (type, dest, src); | 8157 return omit_one_operand_loc (loc, type, dest, src); |
8871 | 8158 |
8872 /* If SRC and DEST are the same (and not volatile), return | 8159 /* If SRC and DEST are the same (and not volatile), return |
8873 DEST{,+LEN,+LEN-1}. */ | 8160 DEST{,+LEN,+LEN-1}. */ |
8874 if (operand_equal_p (src, dest, 0)) | 8161 if (operand_equal_p (src, dest, 0)) |
8875 expr = len; | 8162 expr = len; |
8881 if (endp == 3) | 8168 if (endp == 3) |
8882 { | 8169 { |
8883 src_align = get_pointer_alignment (src, BIGGEST_ALIGNMENT); | 8170 src_align = get_pointer_alignment (src, BIGGEST_ALIGNMENT); |
8884 dest_align = get_pointer_alignment (dest, BIGGEST_ALIGNMENT); | 8171 dest_align = get_pointer_alignment (dest, BIGGEST_ALIGNMENT); |
8885 | 8172 |
8886 /* Both DEST and SRC must be pointer types. | 8173 /* Both DEST and SRC must be pointer types. |
8887 ??? This is what old code did. Is the testing for pointer types | 8174 ??? This is what old code did. Is the testing for pointer types |
8888 really mandatory? | 8175 really mandatory? |
8889 | 8176 |
8890 If either SRC is readonly or length is 1, we can use memcpy. */ | 8177 If either SRC is readonly or length is 1, we can use memcpy. */ |
8891 if (dest_align && src_align | 8178 if (!dest_align || !src_align) |
8892 && (readonly_data_expr (src) | 8179 return NULL_TREE; |
8893 || (host_integerp (len, 1) | 8180 if (readonly_data_expr (src) |
8894 && (MIN (src_align, dest_align) / BITS_PER_UNIT >= | 8181 || (host_integerp (len, 1) |
8895 tree_low_cst (len, 1))))) | 8182 && (MIN (src_align, dest_align) / BITS_PER_UNIT |
8183 >= tree_low_cst (len, 1)))) | |
8896 { | 8184 { |
8897 tree fn = implicit_built_in_decls[BUILT_IN_MEMCPY]; | 8185 tree fn = implicit_built_in_decls[BUILT_IN_MEMCPY]; |
8898 if (!fn) | 8186 if (!fn) |
8899 return NULL_TREE; | 8187 return NULL_TREE; |
8900 return build_call_expr (fn, 3, dest, src, len); | 8188 return build_call_expr_loc (loc, fn, 3, dest, src, len); |
8189 } | |
8190 | |
8191 /* If *src and *dest can't overlap, optimize into memcpy as well. */ | |
8192 srcvar = build_fold_indirect_ref_loc (loc, src); | |
8193 destvar = build_fold_indirect_ref_loc (loc, dest); | |
8194 if (srcvar | |
8195 && !TREE_THIS_VOLATILE (srcvar) | |
8196 && destvar | |
8197 && !TREE_THIS_VOLATILE (destvar)) | |
8198 { | |
8199 tree src_base, dest_base, fn; | |
8200 HOST_WIDE_INT src_offset = 0, dest_offset = 0; | |
8201 HOST_WIDE_INT size = -1; | |
8202 HOST_WIDE_INT maxsize = -1; | |
8203 | |
8204 src_base = srcvar; | |
8205 if (handled_component_p (src_base)) | |
8206 src_base = get_ref_base_and_extent (src_base, &src_offset, | |
8207 &size, &maxsize); | |
8208 dest_base = destvar; | |
8209 if (handled_component_p (dest_base)) | |
8210 dest_base = get_ref_base_and_extent (dest_base, &dest_offset, | |
8211 &size, &maxsize); | |
8212 if (host_integerp (len, 1)) | |
8213 { | |
8214 maxsize = tree_low_cst (len, 1); | |
8215 if (maxsize | |
8216 > INTTYPE_MAXIMUM (HOST_WIDE_INT) / BITS_PER_UNIT) | |
8217 maxsize = -1; | |
8218 else | |
8219 maxsize *= BITS_PER_UNIT; | |
8220 } | |
8221 else | |
8222 maxsize = -1; | |
8223 if (SSA_VAR_P (src_base) | |
8224 && SSA_VAR_P (dest_base)) | |
8225 { | |
8226 if (operand_equal_p (src_base, dest_base, 0) | |
8227 && ranges_overlap_p (src_offset, maxsize, | |
8228 dest_offset, maxsize)) | |
8229 return NULL_TREE; | |
8230 } | |
8231 else if (TREE_CODE (src_base) == INDIRECT_REF | |
8232 && TREE_CODE (dest_base) == INDIRECT_REF) | |
8233 { | |
8234 if (! operand_equal_p (TREE_OPERAND (src_base, 0), | |
8235 TREE_OPERAND (dest_base, 0), 0) | |
8236 || ranges_overlap_p (src_offset, maxsize, | |
8237 dest_offset, maxsize)) | |
8238 return NULL_TREE; | |
8239 } | |
8240 else | |
8241 return NULL_TREE; | |
8242 | |
8243 fn = implicit_built_in_decls[BUILT_IN_MEMCPY]; | |
8244 if (!fn) | |
8245 return NULL_TREE; | |
8246 return build_call_expr_loc (loc, fn, 3, dest, src, len); | |
8901 } | 8247 } |
8902 return NULL_TREE; | 8248 return NULL_TREE; |
8903 } | 8249 } |
8904 | 8250 |
8905 if (!host_integerp (len, 0)) | 8251 if (!host_integerp (len, 0)) |
8908 This logic lose for arguments like (type *)malloc (sizeof (type)), | 8254 This logic lose for arguments like (type *)malloc (sizeof (type)), |
8909 since we strip the casts of up to VOID return value from malloc. | 8255 since we strip the casts of up to VOID return value from malloc. |
8910 Perhaps we ought to inherit type from non-VOID argument here? */ | 8256 Perhaps we ought to inherit type from non-VOID argument here? */ |
8911 STRIP_NOPS (src); | 8257 STRIP_NOPS (src); |
8912 STRIP_NOPS (dest); | 8258 STRIP_NOPS (dest); |
8259 /* As we fold (void *)(p + CST) to (void *)p + CST undo this here. */ | |
8260 if (TREE_CODE (src) == POINTER_PLUS_EXPR) | |
8261 { | |
8262 tree tem = TREE_OPERAND (src, 0); | |
8263 STRIP_NOPS (tem); | |
8264 if (tem != TREE_OPERAND (src, 0)) | |
8265 src = build1 (NOP_EXPR, TREE_TYPE (tem), src); | |
8266 } | |
8267 if (TREE_CODE (dest) == POINTER_PLUS_EXPR) | |
8268 { | |
8269 tree tem = TREE_OPERAND (dest, 0); | |
8270 STRIP_NOPS (tem); | |
8271 if (tem != TREE_OPERAND (dest, 0)) | |
8272 dest = build1 (NOP_EXPR, TREE_TYPE (tem), dest); | |
8273 } | |
8913 srctype = TREE_TYPE (TREE_TYPE (src)); | 8274 srctype = TREE_TYPE (TREE_TYPE (src)); |
8275 if (srctype | |
8276 && TREE_CODE (srctype) == ARRAY_TYPE | |
8277 && !tree_int_cst_equal (TYPE_SIZE_UNIT (srctype), len)) | |
8278 { | |
8279 srctype = TREE_TYPE (srctype); | |
8280 STRIP_NOPS (src); | |
8281 src = build1 (NOP_EXPR, build_pointer_type (srctype), src); | |
8282 } | |
8914 desttype = TREE_TYPE (TREE_TYPE (dest)); | 8283 desttype = TREE_TYPE (TREE_TYPE (dest)); |
8284 if (desttype | |
8285 && TREE_CODE (desttype) == ARRAY_TYPE | |
8286 && !tree_int_cst_equal (TYPE_SIZE_UNIT (desttype), len)) | |
8287 { | |
8288 desttype = TREE_TYPE (desttype); | |
8289 STRIP_NOPS (dest); | |
8290 dest = build1 (NOP_EXPR, build_pointer_type (desttype), dest); | |
8291 } | |
8915 if (!srctype || !desttype | 8292 if (!srctype || !desttype |
8916 || !TYPE_SIZE_UNIT (srctype) | 8293 || !TYPE_SIZE_UNIT (srctype) |
8917 || !TYPE_SIZE_UNIT (desttype) | 8294 || !TYPE_SIZE_UNIT (desttype) |
8918 || TREE_CODE (TYPE_SIZE_UNIT (srctype)) != INTEGER_CST | 8295 || TREE_CODE (TYPE_SIZE_UNIT (srctype)) != INTEGER_CST |
8919 || TREE_CODE (TYPE_SIZE_UNIT (desttype)) != INTEGER_CST | 8296 || TREE_CODE (TYPE_SIZE_UNIT (desttype)) != INTEGER_CST |
8931 dest = builtin_save_expr (dest); | 8308 dest = builtin_save_expr (dest); |
8932 | 8309 |
8933 srcvar = NULL_TREE; | 8310 srcvar = NULL_TREE; |
8934 if (tree_int_cst_equal (TYPE_SIZE_UNIT (srctype), len)) | 8311 if (tree_int_cst_equal (TYPE_SIZE_UNIT (srctype), len)) |
8935 { | 8312 { |
8936 srcvar = build_fold_indirect_ref (src); | 8313 srcvar = build_fold_indirect_ref_loc (loc, src); |
8937 if (TREE_THIS_VOLATILE (srcvar)) | 8314 if (TREE_THIS_VOLATILE (srcvar)) |
8938 return NULL_TREE; | 8315 return NULL_TREE; |
8939 else if (!tree_int_cst_equal (lang_hooks.expr_size (srcvar), len)) | 8316 else if (!tree_int_cst_equal (tree_expr_size (srcvar), len)) |
8940 srcvar = NULL_TREE; | 8317 srcvar = NULL_TREE; |
8941 /* With memcpy, it is possible to bypass aliasing rules, so without | 8318 /* With memcpy, it is possible to bypass aliasing rules, so without |
8942 this check i.e. execute/20060930-2.c would be misoptimized, | 8319 this check i.e. execute/20060930-2.c would be misoptimized, |
8943 because it use conflicting alias set to hold argument for the | 8320 because it use conflicting alias set to hold argument for the |
8944 memcpy call. This check is probably unnecessary with | 8321 memcpy call. This check is probably unnecessary with |
8949 } | 8326 } |
8950 | 8327 |
8951 destvar = NULL_TREE; | 8328 destvar = NULL_TREE; |
8952 if (tree_int_cst_equal (TYPE_SIZE_UNIT (desttype), len)) | 8329 if (tree_int_cst_equal (TYPE_SIZE_UNIT (desttype), len)) |
8953 { | 8330 { |
8954 destvar = build_fold_indirect_ref (dest); | 8331 destvar = build_fold_indirect_ref_loc (loc, dest); |
8955 if (TREE_THIS_VOLATILE (destvar)) | 8332 if (TREE_THIS_VOLATILE (destvar)) |
8956 return NULL_TREE; | 8333 return NULL_TREE; |
8957 else if (!tree_int_cst_equal (lang_hooks.expr_size (destvar), len)) | 8334 else if (!tree_int_cst_equal (tree_expr_size (destvar), len)) |
8958 destvar = NULL_TREE; | 8335 destvar = NULL_TREE; |
8959 else if (!var_decl_component_p (destvar)) | 8336 else if (!var_decl_component_p (destvar)) |
8960 destvar = NULL_TREE; | 8337 destvar = NULL_TREE; |
8961 } | 8338 } |
8962 | 8339 |
8980 TYPE_ALIGN (srctype) = src_align; | 8357 TYPE_ALIGN (srctype) = src_align; |
8981 TYPE_USER_ALIGN (srctype) = 1; | 8358 TYPE_USER_ALIGN (srctype) = 1; |
8982 TYPE_PACKED (srctype) = 1; | 8359 TYPE_PACKED (srctype) = 1; |
8983 } | 8360 } |
8984 srcptype = build_pointer_type_for_mode (srctype, ptr_mode, true); | 8361 srcptype = build_pointer_type_for_mode (srctype, ptr_mode, true); |
8985 src = fold_convert (srcptype, src); | 8362 src = fold_convert_loc (loc, srcptype, src); |
8986 srcvar = build_fold_indirect_ref (src); | 8363 srcvar = build_fold_indirect_ref_loc (loc, src); |
8987 } | 8364 } |
8988 else if (destvar == NULL_TREE) | 8365 else if (destvar == NULL_TREE) |
8989 { | 8366 { |
8990 tree destptype; | 8367 tree destptype; |
8991 if (TREE_ADDRESSABLE (TREE_TYPE (srcvar))) | 8368 if (TREE_ADDRESSABLE (TREE_TYPE (srcvar))) |
9002 TYPE_ALIGN (desttype) = dest_align; | 8379 TYPE_ALIGN (desttype) = dest_align; |
9003 TYPE_USER_ALIGN (desttype) = 1; | 8380 TYPE_USER_ALIGN (desttype) = 1; |
9004 TYPE_PACKED (desttype) = 1; | 8381 TYPE_PACKED (desttype) = 1; |
9005 } | 8382 } |
9006 destptype = build_pointer_type_for_mode (desttype, ptr_mode, true); | 8383 destptype = build_pointer_type_for_mode (desttype, ptr_mode, true); |
9007 dest = fold_convert (destptype, dest); | 8384 dest = fold_convert_loc (loc, destptype, dest); |
9008 destvar = build_fold_indirect_ref (dest); | 8385 destvar = build_fold_indirect_ref_loc (loc, dest); |
9009 } | 8386 } |
9010 | 8387 |
9011 if (srctype == desttype | 8388 if (srctype == desttype |
9012 || (gimple_in_ssa_p (cfun) | 8389 || (gimple_in_ssa_p (cfun) |
9013 && useless_type_conversion_p (desttype, srctype))) | 8390 && useless_type_conversion_p (desttype, srctype))) |
9014 expr = srcvar; | 8391 expr = srcvar; |
9015 else if ((INTEGRAL_TYPE_P (TREE_TYPE (srcvar)) | 8392 else if ((INTEGRAL_TYPE_P (TREE_TYPE (srcvar)) |
9016 || POINTER_TYPE_P (TREE_TYPE (srcvar))) | 8393 || POINTER_TYPE_P (TREE_TYPE (srcvar))) |
9017 && (INTEGRAL_TYPE_P (TREE_TYPE (destvar)) | 8394 && (INTEGRAL_TYPE_P (TREE_TYPE (destvar)) |
9018 || POINTER_TYPE_P (TREE_TYPE (destvar)))) | 8395 || POINTER_TYPE_P (TREE_TYPE (destvar)))) |
9019 expr = fold_convert (TREE_TYPE (destvar), srcvar); | 8396 expr = fold_convert_loc (loc, TREE_TYPE (destvar), srcvar); |
9020 else | 8397 else |
9021 expr = fold_build1 (VIEW_CONVERT_EXPR, TREE_TYPE (destvar), srcvar); | 8398 expr = fold_build1_loc (loc, VIEW_CONVERT_EXPR, |
8399 TREE_TYPE (destvar), srcvar); | |
9022 expr = build2 (MODIFY_EXPR, TREE_TYPE (destvar), destvar, expr); | 8400 expr = build2 (MODIFY_EXPR, TREE_TYPE (destvar), destvar, expr); |
9023 } | 8401 } |
9024 | 8402 |
9025 if (ignore) | 8403 if (ignore) |
9026 return expr; | 8404 return expr; |
9027 | 8405 |
9028 if (endp == 0 || endp == 3) | 8406 if (endp == 0 || endp == 3) |
9029 return omit_one_operand (type, dest, expr); | 8407 return omit_one_operand_loc (loc, type, dest, expr); |
9030 | 8408 |
9031 if (expr == len) | 8409 if (expr == len) |
9032 expr = NULL_TREE; | 8410 expr = NULL_TREE; |
9033 | 8411 |
9034 if (endp == 2) | 8412 if (endp == 2) |
9035 len = fold_build2 (MINUS_EXPR, TREE_TYPE (len), len, | 8413 len = fold_build2_loc (loc, MINUS_EXPR, TREE_TYPE (len), len, |
9036 ssize_int (1)); | 8414 ssize_int (1)); |
9037 | 8415 |
9038 len = fold_convert (sizetype, len); | 8416 len = fold_convert_loc (loc, sizetype, len); |
9039 dest = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (dest), dest, len); | 8417 dest = fold_build2_loc (loc, POINTER_PLUS_EXPR, TREE_TYPE (dest), dest, len); |
9040 dest = fold_convert (type, dest); | 8418 dest = fold_convert_loc (loc, type, dest); |
9041 if (expr) | 8419 if (expr) |
9042 dest = omit_one_operand (type, dest, expr); | 8420 dest = omit_one_operand_loc (loc, type, dest, expr); |
9043 return dest; | 8421 return dest; |
9044 } | 8422 } |
9045 | 8423 |
9046 /* Fold function call to builtin strcpy with arguments DEST and SRC. | 8424 /* Fold function call to builtin strcpy with arguments DEST and SRC. |
9047 If LEN is not NULL, it represents the length of the string to be | 8425 If LEN is not NULL, it represents the length of the string to be |
9048 copied. Return NULL_TREE if no simplification can be made. */ | 8426 copied. Return NULL_TREE if no simplification can be made. */ |
9049 | 8427 |
9050 tree | 8428 tree |
9051 fold_builtin_strcpy (tree fndecl, tree dest, tree src, tree len) | 8429 fold_builtin_strcpy (location_t loc, tree fndecl, tree dest, tree src, tree len) |
9052 { | 8430 { |
9053 tree fn; | 8431 tree fn; |
9054 | 8432 |
9055 if (!validate_arg (dest, POINTER_TYPE) | 8433 if (!validate_arg (dest, POINTER_TYPE) |
9056 || !validate_arg (src, POINTER_TYPE)) | 8434 || !validate_arg (src, POINTER_TYPE)) |
9057 return NULL_TREE; | 8435 return NULL_TREE; |
9058 | 8436 |
9059 /* If SRC and DEST are the same (and not volatile), return DEST. */ | 8437 /* If SRC and DEST are the same (and not volatile), return DEST. */ |
9060 if (operand_equal_p (src, dest, 0)) | 8438 if (operand_equal_p (src, dest, 0)) |
9061 return fold_convert (TREE_TYPE (TREE_TYPE (fndecl)), dest); | 8439 return fold_convert_loc (loc, TREE_TYPE (TREE_TYPE (fndecl)), dest); |
9062 | 8440 |
9063 if (optimize_function_for_size_p (cfun)) | 8441 if (optimize_function_for_size_p (cfun)) |
9064 return NULL_TREE; | 8442 return NULL_TREE; |
9065 | 8443 |
9066 fn = implicit_built_in_decls[BUILT_IN_MEMCPY]; | 8444 fn = implicit_built_in_decls[BUILT_IN_MEMCPY]; |
9072 len = c_strlen (src, 1); | 8450 len = c_strlen (src, 1); |
9073 if (! len || TREE_SIDE_EFFECTS (len)) | 8451 if (! len || TREE_SIDE_EFFECTS (len)) |
9074 return NULL_TREE; | 8452 return NULL_TREE; |
9075 } | 8453 } |
9076 | 8454 |
9077 len = size_binop (PLUS_EXPR, len, ssize_int (1)); | 8455 len = size_binop_loc (loc, PLUS_EXPR, len, ssize_int (1)); |
9078 return fold_convert (TREE_TYPE (TREE_TYPE (fndecl)), | 8456 return fold_convert_loc (loc, TREE_TYPE (TREE_TYPE (fndecl)), |
9079 build_call_expr (fn, 3, dest, src, len)); | 8457 build_call_expr_loc (loc, fn, 3, dest, src, len)); |
8458 } | |
8459 | |
8460 /* Fold function call to builtin stpcpy with arguments DEST and SRC. | |
8461 Return NULL_TREE if no simplification can be made. */ | |
8462 | |
8463 static tree | |
8464 fold_builtin_stpcpy (location_t loc, tree fndecl, tree dest, tree src) | |
8465 { | |
8466 tree fn, len, lenp1, call, type; | |
8467 | |
8468 if (!validate_arg (dest, POINTER_TYPE) | |
8469 || !validate_arg (src, POINTER_TYPE)) | |
8470 return NULL_TREE; | |
8471 | |
8472 len = c_strlen (src, 1); | |
8473 if (!len | |
8474 || TREE_CODE (len) != INTEGER_CST) | |
8475 return NULL_TREE; | |
8476 | |
8477 if (optimize_function_for_size_p (cfun) | |
8478 /* If length is zero it's small enough. */ | |
8479 && !integer_zerop (len)) | |
8480 return NULL_TREE; | |
8481 | |
8482 fn = implicit_built_in_decls[BUILT_IN_MEMCPY]; | |
8483 if (!fn) | |
8484 return NULL_TREE; | |
8485 | |
8486 lenp1 = size_binop_loc (loc, PLUS_EXPR, len, ssize_int (1)); | |
8487 /* We use dest twice in building our expression. Save it from | |
8488 multiple expansions. */ | |
8489 dest = builtin_save_expr (dest); | |
8490 call = build_call_expr_loc (loc, fn, 3, dest, src, lenp1); | |
8491 | |
8492 type = TREE_TYPE (TREE_TYPE (fndecl)); | |
8493 len = fold_convert_loc (loc, sizetype, len); | |
8494 dest = fold_build2_loc (loc, POINTER_PLUS_EXPR, TREE_TYPE (dest), dest, len); | |
8495 dest = fold_convert_loc (loc, type, dest); | |
8496 dest = omit_one_operand_loc (loc, type, dest, call); | |
8497 return dest; | |
9080 } | 8498 } |
9081 | 8499 |
9082 /* Fold function call to builtin strncpy with arguments DEST, SRC, and LEN. | 8500 /* Fold function call to builtin strncpy with arguments DEST, SRC, and LEN. |
9083 If SLEN is not NULL, it represents the length of the source string. | 8501 If SLEN is not NULL, it represents the length of the source string. |
9084 Return NULL_TREE if no simplification can be made. */ | 8502 Return NULL_TREE if no simplification can be made. */ |
9085 | 8503 |
9086 tree | 8504 tree |
9087 fold_builtin_strncpy (tree fndecl, tree dest, tree src, tree len, tree slen) | 8505 fold_builtin_strncpy (location_t loc, tree fndecl, tree dest, |
8506 tree src, tree len, tree slen) | |
9088 { | 8507 { |
9089 tree fn; | 8508 tree fn; |
9090 | 8509 |
9091 if (!validate_arg (dest, POINTER_TYPE) | 8510 if (!validate_arg (dest, POINTER_TYPE) |
9092 || !validate_arg (src, POINTER_TYPE) | 8511 || !validate_arg (src, POINTER_TYPE) |
9093 || !validate_arg (len, INTEGER_TYPE)) | 8512 || !validate_arg (len, INTEGER_TYPE)) |
9094 return NULL_TREE; | 8513 return NULL_TREE; |
9095 | 8514 |
9096 /* If the LEN parameter is zero, return DEST. */ | 8515 /* If the LEN parameter is zero, return DEST. */ |
9097 if (integer_zerop (len)) | 8516 if (integer_zerop (len)) |
9098 return omit_one_operand (TREE_TYPE (TREE_TYPE (fndecl)), dest, src); | 8517 return omit_one_operand_loc (loc, TREE_TYPE (TREE_TYPE (fndecl)), dest, src); |
9099 | 8518 |
9100 /* We can't compare slen with len as constants below if len is not a | 8519 /* We can't compare slen with len as constants below if len is not a |
9101 constant. */ | 8520 constant. */ |
9102 if (len == 0 || TREE_CODE (len) != INTEGER_CST) | 8521 if (len == 0 || TREE_CODE (len) != INTEGER_CST) |
9103 return NULL_TREE; | 8522 return NULL_TREE; |
9107 | 8526 |
9108 /* Now, we must be passed a constant src ptr parameter. */ | 8527 /* Now, we must be passed a constant src ptr parameter. */ |
9109 if (slen == 0 || TREE_CODE (slen) != INTEGER_CST) | 8528 if (slen == 0 || TREE_CODE (slen) != INTEGER_CST) |
9110 return NULL_TREE; | 8529 return NULL_TREE; |
9111 | 8530 |
9112 slen = size_binop (PLUS_EXPR, slen, ssize_int (1)); | 8531 slen = size_binop_loc (loc, PLUS_EXPR, slen, ssize_int (1)); |
9113 | 8532 |
9114 /* We do not support simplification of this case, though we do | 8533 /* We do not support simplification of this case, though we do |
9115 support it when expanding trees into RTL. */ | 8534 support it when expanding trees into RTL. */ |
9116 /* FIXME: generate a call to __builtin_memset. */ | 8535 /* FIXME: generate a call to __builtin_memset. */ |
9117 if (tree_int_cst_lt (slen, len)) | 8536 if (tree_int_cst_lt (slen, len)) |
9119 | 8538 |
9120 /* OK transform into builtin memcpy. */ | 8539 /* OK transform into builtin memcpy. */ |
9121 fn = implicit_built_in_decls[BUILT_IN_MEMCPY]; | 8540 fn = implicit_built_in_decls[BUILT_IN_MEMCPY]; |
9122 if (!fn) | 8541 if (!fn) |
9123 return NULL_TREE; | 8542 return NULL_TREE; |
9124 return fold_convert (TREE_TYPE (TREE_TYPE (fndecl)), | 8543 return fold_convert_loc (loc, TREE_TYPE (TREE_TYPE (fndecl)), |
9125 build_call_expr (fn, 3, dest, src, len)); | 8544 build_call_expr_loc (loc, fn, 3, dest, src, len)); |
9126 } | 8545 } |
9127 | 8546 |
9128 /* Fold function call to builtin memchr. ARG1, ARG2 and LEN are the | 8547 /* Fold function call to builtin memchr. ARG1, ARG2 and LEN are the |
9129 arguments to the call, and TYPE is its return type. | 8548 arguments to the call, and TYPE is its return type. |
9130 Return NULL_TREE if no simplification can be made. */ | 8549 Return NULL_TREE if no simplification can be made. */ |
9131 | 8550 |
9132 static tree | 8551 static tree |
9133 fold_builtin_memchr (tree arg1, tree arg2, tree len, tree type) | 8552 fold_builtin_memchr (location_t loc, tree arg1, tree arg2, tree len, tree type) |
9134 { | 8553 { |
9135 if (!validate_arg (arg1, POINTER_TYPE) | 8554 if (!validate_arg (arg1, POINTER_TYPE) |
9136 || !validate_arg (arg2, INTEGER_TYPE) | 8555 || !validate_arg (arg2, INTEGER_TYPE) |
9137 || !validate_arg (len, INTEGER_TYPE)) | 8556 || !validate_arg (len, INTEGER_TYPE)) |
9138 return NULL_TREE; | 8557 return NULL_TREE; |
9157 r = (char *) memchr (p1, c, tree_low_cst (len, 1)); | 8576 r = (char *) memchr (p1, c, tree_low_cst (len, 1)); |
9158 | 8577 |
9159 if (r == NULL) | 8578 if (r == NULL) |
9160 return build_int_cst (TREE_TYPE (arg1), 0); | 8579 return build_int_cst (TREE_TYPE (arg1), 0); |
9161 | 8580 |
9162 tem = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (arg1), arg1, | 8581 tem = fold_build2_loc (loc, POINTER_PLUS_EXPR, TREE_TYPE (arg1), arg1, |
9163 size_int (r - p1)); | 8582 size_int (r - p1)); |
9164 return fold_convert (type, tem); | 8583 return fold_convert_loc (loc, type, tem); |
9165 } | 8584 } |
9166 return NULL_TREE; | 8585 return NULL_TREE; |
9167 } | 8586 } |
9168 } | 8587 } |
9169 | 8588 |
9170 /* Fold function call to builtin memcmp with arguments ARG1 and ARG2. | 8589 /* Fold function call to builtin memcmp with arguments ARG1 and ARG2. |
9171 Return NULL_TREE if no simplification can be made. */ | 8590 Return NULL_TREE if no simplification can be made. */ |
9172 | 8591 |
9173 static tree | 8592 static tree |
9174 fold_builtin_memcmp (tree arg1, tree arg2, tree len) | 8593 fold_builtin_memcmp (location_t loc, tree arg1, tree arg2, tree len) |
9175 { | 8594 { |
9176 const char *p1, *p2; | 8595 const char *p1, *p2; |
9177 | 8596 |
9178 if (!validate_arg (arg1, POINTER_TYPE) | 8597 if (!validate_arg (arg1, POINTER_TYPE) |
9179 || !validate_arg (arg2, POINTER_TYPE) | 8598 || !validate_arg (arg2, POINTER_TYPE) |
9180 || !validate_arg (len, INTEGER_TYPE)) | 8599 || !validate_arg (len, INTEGER_TYPE)) |
9181 return NULL_TREE; | 8600 return NULL_TREE; |
9182 | 8601 |
9183 /* If the LEN parameter is zero, return zero. */ | 8602 /* If the LEN parameter is zero, return zero. */ |
9184 if (integer_zerop (len)) | 8603 if (integer_zerop (len)) |
9185 return omit_two_operands (integer_type_node, integer_zero_node, | 8604 return omit_two_operands_loc (loc, integer_type_node, integer_zero_node, |
9186 arg1, arg2); | 8605 arg1, arg2); |
9187 | 8606 |
9188 /* If ARG1 and ARG2 are the same (and not volatile), return zero. */ | 8607 /* If ARG1 and ARG2 are the same (and not volatile), return zero. */ |
9189 if (operand_equal_p (arg1, arg2, 0)) | 8608 if (operand_equal_p (arg1, arg2, 0)) |
9190 return omit_one_operand (integer_type_node, integer_zero_node, len); | 8609 return omit_one_operand_loc (loc, integer_type_node, integer_zero_node, len); |
9191 | 8610 |
9192 p1 = c_getstr (arg1); | 8611 p1 = c_getstr (arg1); |
9193 p2 = c_getstr (arg2); | 8612 p2 = c_getstr (arg2); |
9194 | 8613 |
9195 /* If all arguments are constant, and the value of len is not greater | 8614 /* If all arguments are constant, and the value of len is not greater |
9214 { | 8633 { |
9215 tree cst_uchar_node = build_type_variant (unsigned_char_type_node, 1, 0); | 8634 tree cst_uchar_node = build_type_variant (unsigned_char_type_node, 1, 0); |
9216 tree cst_uchar_ptr_node | 8635 tree cst_uchar_ptr_node |
9217 = build_pointer_type_for_mode (cst_uchar_node, ptr_mode, true); | 8636 = build_pointer_type_for_mode (cst_uchar_node, ptr_mode, true); |
9218 | 8637 |
9219 tree ind1 = fold_convert (integer_type_node, | 8638 tree ind1 |
9220 build1 (INDIRECT_REF, cst_uchar_node, | 8639 = fold_convert_loc (loc, integer_type_node, |
9221 fold_convert (cst_uchar_ptr_node, | 8640 build1 (INDIRECT_REF, cst_uchar_node, |
8641 fold_convert_loc (loc, | |
8642 cst_uchar_ptr_node, | |
9222 arg1))); | 8643 arg1))); |
9223 tree ind2 = fold_convert (integer_type_node, | 8644 tree ind2 |
9224 build1 (INDIRECT_REF, cst_uchar_node, | 8645 = fold_convert_loc (loc, integer_type_node, |
9225 fold_convert (cst_uchar_ptr_node, | 8646 build1 (INDIRECT_REF, cst_uchar_node, |
8647 fold_convert_loc (loc, | |
8648 cst_uchar_ptr_node, | |
9226 arg2))); | 8649 arg2))); |
9227 return fold_build2 (MINUS_EXPR, integer_type_node, ind1, ind2); | 8650 return fold_build2_loc (loc, MINUS_EXPR, integer_type_node, ind1, ind2); |
9228 } | 8651 } |
9229 | 8652 |
9230 return NULL_TREE; | 8653 return NULL_TREE; |
9231 } | 8654 } |
9232 | 8655 |
9233 /* Fold function call to builtin strcmp with arguments ARG1 and ARG2. | 8656 /* Fold function call to builtin strcmp with arguments ARG1 and ARG2. |
9234 Return NULL_TREE if no simplification can be made. */ | 8657 Return NULL_TREE if no simplification can be made. */ |
9235 | 8658 |
9236 static tree | 8659 static tree |
9237 fold_builtin_strcmp (tree arg1, tree arg2) | 8660 fold_builtin_strcmp (location_t loc, tree arg1, tree arg2) |
9238 { | 8661 { |
9239 const char *p1, *p2; | 8662 const char *p1, *p2; |
9240 | 8663 |
9241 if (!validate_arg (arg1, POINTER_TYPE) | 8664 if (!validate_arg (arg1, POINTER_TYPE) |
9242 || !validate_arg (arg2, POINTER_TYPE)) | 8665 || !validate_arg (arg2, POINTER_TYPE)) |
9265 { | 8688 { |
9266 tree cst_uchar_node = build_type_variant (unsigned_char_type_node, 1, 0); | 8689 tree cst_uchar_node = build_type_variant (unsigned_char_type_node, 1, 0); |
9267 tree cst_uchar_ptr_node | 8690 tree cst_uchar_ptr_node |
9268 = build_pointer_type_for_mode (cst_uchar_node, ptr_mode, true); | 8691 = build_pointer_type_for_mode (cst_uchar_node, ptr_mode, true); |
9269 | 8692 |
9270 return fold_convert (integer_type_node, | 8693 return fold_convert_loc (loc, integer_type_node, |
9271 build1 (INDIRECT_REF, cst_uchar_node, | 8694 build1 (INDIRECT_REF, cst_uchar_node, |
9272 fold_convert (cst_uchar_ptr_node, | 8695 fold_convert_loc (loc, |
9273 arg1))); | 8696 cst_uchar_ptr_node, |
8697 arg1))); | |
9274 } | 8698 } |
9275 | 8699 |
9276 /* If the first arg is "", return -*(const unsigned char*)arg2. */ | 8700 /* If the first arg is "", return -*(const unsigned char*)arg2. */ |
9277 if (p1 && *p1 == '\0') | 8701 if (p1 && *p1 == '\0') |
9278 { | 8702 { |
9279 tree cst_uchar_node = build_type_variant (unsigned_char_type_node, 1, 0); | 8703 tree cst_uchar_node = build_type_variant (unsigned_char_type_node, 1, 0); |
9280 tree cst_uchar_ptr_node | 8704 tree cst_uchar_ptr_node |
9281 = build_pointer_type_for_mode (cst_uchar_node, ptr_mode, true); | 8705 = build_pointer_type_for_mode (cst_uchar_node, ptr_mode, true); |
9282 | 8706 |
9283 tree temp = fold_convert (integer_type_node, | 8707 tree temp |
9284 build1 (INDIRECT_REF, cst_uchar_node, | 8708 = fold_convert_loc (loc, integer_type_node, |
9285 fold_convert (cst_uchar_ptr_node, | 8709 build1 (INDIRECT_REF, cst_uchar_node, |
8710 fold_convert_loc (loc, | |
8711 cst_uchar_ptr_node, | |
9286 arg2))); | 8712 arg2))); |
9287 return fold_build1 (NEGATE_EXPR, integer_type_node, temp); | 8713 return fold_build1_loc (loc, NEGATE_EXPR, integer_type_node, temp); |
9288 } | 8714 } |
9289 | 8715 |
9290 return NULL_TREE; | 8716 return NULL_TREE; |
9291 } | 8717 } |
9292 | 8718 |
9293 /* Fold function call to builtin strncmp with arguments ARG1, ARG2, and LEN. | 8719 /* Fold function call to builtin strncmp with arguments ARG1, ARG2, and LEN. |
9294 Return NULL_TREE if no simplification can be made. */ | 8720 Return NULL_TREE if no simplification can be made. */ |
9295 | 8721 |
9296 static tree | 8722 static tree |
9297 fold_builtin_strncmp (tree arg1, tree arg2, tree len) | 8723 fold_builtin_strncmp (location_t loc, tree arg1, tree arg2, tree len) |
9298 { | 8724 { |
9299 const char *p1, *p2; | 8725 const char *p1, *p2; |
9300 | 8726 |
9301 if (!validate_arg (arg1, POINTER_TYPE) | 8727 if (!validate_arg (arg1, POINTER_TYPE) |
9302 || !validate_arg (arg2, POINTER_TYPE) | 8728 || !validate_arg (arg2, POINTER_TYPE) |
9303 || !validate_arg (len, INTEGER_TYPE)) | 8729 || !validate_arg (len, INTEGER_TYPE)) |
9304 return NULL_TREE; | 8730 return NULL_TREE; |
9305 | 8731 |
9306 /* If the LEN parameter is zero, return zero. */ | 8732 /* If the LEN parameter is zero, return zero. */ |
9307 if (integer_zerop (len)) | 8733 if (integer_zerop (len)) |
9308 return omit_two_operands (integer_type_node, integer_zero_node, | 8734 return omit_two_operands_loc (loc, integer_type_node, integer_zero_node, |
9309 arg1, arg2); | 8735 arg1, arg2); |
9310 | 8736 |
9311 /* If ARG1 and ARG2 are the same (and not volatile), return zero. */ | 8737 /* If ARG1 and ARG2 are the same (and not volatile), return zero. */ |
9312 if (operand_equal_p (arg1, arg2, 0)) | 8738 if (operand_equal_p (arg1, arg2, 0)) |
9313 return omit_one_operand (integer_type_node, integer_zero_node, len); | 8739 return omit_one_operand_loc (loc, integer_type_node, integer_zero_node, len); |
9314 | 8740 |
9315 p1 = c_getstr (arg1); | 8741 p1 = c_getstr (arg1); |
9316 p2 = c_getstr (arg2); | 8742 p2 = c_getstr (arg2); |
9317 | 8743 |
9318 if (host_integerp (len, 1) && p1 && p2) | 8744 if (host_integerp (len, 1) && p1 && p2) |
9334 { | 8760 { |
9335 tree cst_uchar_node = build_type_variant (unsigned_char_type_node, 1, 0); | 8761 tree cst_uchar_node = build_type_variant (unsigned_char_type_node, 1, 0); |
9336 tree cst_uchar_ptr_node | 8762 tree cst_uchar_ptr_node |
9337 = build_pointer_type_for_mode (cst_uchar_node, ptr_mode, true); | 8763 = build_pointer_type_for_mode (cst_uchar_node, ptr_mode, true); |
9338 | 8764 |
9339 return fold_convert (integer_type_node, | 8765 return fold_convert_loc (loc, integer_type_node, |
9340 build1 (INDIRECT_REF, cst_uchar_node, | 8766 build1 (INDIRECT_REF, cst_uchar_node, |
9341 fold_convert (cst_uchar_ptr_node, | 8767 fold_convert_loc (loc, |
9342 arg1))); | 8768 cst_uchar_ptr_node, |
8769 arg1))); | |
9343 } | 8770 } |
9344 | 8771 |
9345 /* If the first arg is "", and the length is greater than zero, | 8772 /* If the first arg is "", and the length is greater than zero, |
9346 return -*(const unsigned char*)arg2. */ | 8773 return -*(const unsigned char*)arg2. */ |
9347 if (p1 && *p1 == '\0' | 8774 if (p1 && *p1 == '\0' |
9350 { | 8777 { |
9351 tree cst_uchar_node = build_type_variant (unsigned_char_type_node, 1, 0); | 8778 tree cst_uchar_node = build_type_variant (unsigned_char_type_node, 1, 0); |
9352 tree cst_uchar_ptr_node | 8779 tree cst_uchar_ptr_node |
9353 = build_pointer_type_for_mode (cst_uchar_node, ptr_mode, true); | 8780 = build_pointer_type_for_mode (cst_uchar_node, ptr_mode, true); |
9354 | 8781 |
9355 tree temp = fold_convert (integer_type_node, | 8782 tree temp = fold_convert_loc (loc, integer_type_node, |
9356 build1 (INDIRECT_REF, cst_uchar_node, | 8783 build1 (INDIRECT_REF, cst_uchar_node, |
9357 fold_convert (cst_uchar_ptr_node, | 8784 fold_convert_loc (loc, |
9358 arg2))); | 8785 cst_uchar_ptr_node, |
9359 return fold_build1 (NEGATE_EXPR, integer_type_node, temp); | 8786 arg2))); |
8787 return fold_build1_loc (loc, NEGATE_EXPR, integer_type_node, temp); | |
9360 } | 8788 } |
9361 | 8789 |
9362 /* If len parameter is one, return an expression corresponding to | 8790 /* If len parameter is one, return an expression corresponding to |
9363 (*(const unsigned char*)arg1 - (const unsigned char*)arg2). */ | 8791 (*(const unsigned char*)arg1 - (const unsigned char*)arg2). */ |
9364 if (host_integerp (len, 1) && tree_low_cst (len, 1) == 1) | 8792 if (host_integerp (len, 1) && tree_low_cst (len, 1) == 1) |
9365 { | 8793 { |
9366 tree cst_uchar_node = build_type_variant (unsigned_char_type_node, 1, 0); | 8794 tree cst_uchar_node = build_type_variant (unsigned_char_type_node, 1, 0); |
9367 tree cst_uchar_ptr_node | 8795 tree cst_uchar_ptr_node |
9368 = build_pointer_type_for_mode (cst_uchar_node, ptr_mode, true); | 8796 = build_pointer_type_for_mode (cst_uchar_node, ptr_mode, true); |
9369 | 8797 |
9370 tree ind1 = fold_convert (integer_type_node, | 8798 tree ind1 = fold_convert_loc (loc, integer_type_node, |
9371 build1 (INDIRECT_REF, cst_uchar_node, | 8799 build1 (INDIRECT_REF, cst_uchar_node, |
9372 fold_convert (cst_uchar_ptr_node, | 8800 fold_convert_loc (loc, |
9373 arg1))); | 8801 cst_uchar_ptr_node, |
9374 tree ind2 = fold_convert (integer_type_node, | 8802 arg1))); |
9375 build1 (INDIRECT_REF, cst_uchar_node, | 8803 tree ind2 = fold_convert_loc (loc, integer_type_node, |
9376 fold_convert (cst_uchar_ptr_node, | 8804 build1 (INDIRECT_REF, cst_uchar_node, |
9377 arg2))); | 8805 fold_convert_loc (loc, |
9378 return fold_build2 (MINUS_EXPR, integer_type_node, ind1, ind2); | 8806 cst_uchar_ptr_node, |
8807 arg2))); | |
8808 return fold_build2_loc (loc, MINUS_EXPR, integer_type_node, ind1, ind2); | |
9379 } | 8809 } |
9380 | 8810 |
9381 return NULL_TREE; | 8811 return NULL_TREE; |
9382 } | 8812 } |
9383 | 8813 |
9384 /* Fold function call to builtin signbit, signbitf or signbitl with argument | 8814 /* Fold function call to builtin signbit, signbitf or signbitl with argument |
9385 ARG. Return NULL_TREE if no simplification can be made. */ | 8815 ARG. Return NULL_TREE if no simplification can be made. */ |
9386 | 8816 |
9387 static tree | 8817 static tree |
9388 fold_builtin_signbit (tree arg, tree type) | 8818 fold_builtin_signbit (location_t loc, tree arg, tree type) |
9389 { | 8819 { |
9390 tree temp; | 8820 tree temp; |
9391 | 8821 |
9392 if (!validate_arg (arg, REAL_TYPE)) | 8822 if (!validate_arg (arg, REAL_TYPE)) |
9393 return NULL_TREE; | 8823 return NULL_TREE; |
9398 { | 8828 { |
9399 REAL_VALUE_TYPE c; | 8829 REAL_VALUE_TYPE c; |
9400 | 8830 |
9401 c = TREE_REAL_CST (arg); | 8831 c = TREE_REAL_CST (arg); |
9402 temp = REAL_VALUE_NEGATIVE (c) ? integer_one_node : integer_zero_node; | 8832 temp = REAL_VALUE_NEGATIVE (c) ? integer_one_node : integer_zero_node; |
9403 return fold_convert (type, temp); | 8833 return fold_convert_loc (loc, type, temp); |
9404 } | 8834 } |
9405 | 8835 |
9406 /* If ARG is non-negative, the result is always zero. */ | 8836 /* If ARG is non-negative, the result is always zero. */ |
9407 if (tree_expr_nonnegative_p (arg)) | 8837 if (tree_expr_nonnegative_p (arg)) |
9408 return omit_one_operand (type, integer_zero_node, arg); | 8838 return omit_one_operand_loc (loc, type, integer_zero_node, arg); |
9409 | 8839 |
9410 /* If ARG's format doesn't have signed zeros, return "arg < 0.0". */ | 8840 /* If ARG's format doesn't have signed zeros, return "arg < 0.0". */ |
9411 if (!HONOR_SIGNED_ZEROS (TYPE_MODE (TREE_TYPE (arg)))) | 8841 if (!HONOR_SIGNED_ZEROS (TYPE_MODE (TREE_TYPE (arg)))) |
9412 return fold_build2 (LT_EXPR, type, arg, | 8842 return fold_build2_loc (loc, LT_EXPR, type, arg, |
9413 build_real (TREE_TYPE (arg), dconst0)); | 8843 build_real (TREE_TYPE (arg), dconst0)); |
9414 | 8844 |
9415 return NULL_TREE; | 8845 return NULL_TREE; |
9416 } | 8846 } |
9417 | 8847 |
9418 /* Fold function call to builtin copysign, copysignf or copysignl with | 8848 /* Fold function call to builtin copysign, copysignf or copysignl with |
9419 arguments ARG1 and ARG2. Return NULL_TREE if no simplification can | 8849 arguments ARG1 and ARG2. Return NULL_TREE if no simplification can |
9420 be made. */ | 8850 be made. */ |
9421 | 8851 |
9422 static tree | 8852 static tree |
9423 fold_builtin_copysign (tree fndecl, tree arg1, tree arg2, tree type) | 8853 fold_builtin_copysign (location_t loc, tree fndecl, |
8854 tree arg1, tree arg2, tree type) | |
9424 { | 8855 { |
9425 tree tem; | 8856 tree tem; |
9426 | 8857 |
9427 if (!validate_arg (arg1, REAL_TYPE) | 8858 if (!validate_arg (arg1, REAL_TYPE) |
9428 || !validate_arg (arg2, REAL_TYPE)) | 8859 || !validate_arg (arg2, REAL_TYPE)) |
9429 return NULL_TREE; | 8860 return NULL_TREE; |
9430 | 8861 |
9431 /* copysign(X,X) is X. */ | 8862 /* copysign(X,X) is X. */ |
9432 if (operand_equal_p (arg1, arg2, 0)) | 8863 if (operand_equal_p (arg1, arg2, 0)) |
9433 return fold_convert (type, arg1); | 8864 return fold_convert_loc (loc, type, arg1); |
9434 | 8865 |
9435 /* If ARG1 and ARG2 are compile-time constants, determine the result. */ | 8866 /* If ARG1 and ARG2 are compile-time constants, determine the result. */ |
9436 if (TREE_CODE (arg1) == REAL_CST | 8867 if (TREE_CODE (arg1) == REAL_CST |
9437 && TREE_CODE (arg2) == REAL_CST | 8868 && TREE_CODE (arg2) == REAL_CST |
9438 && !TREE_OVERFLOW (arg1) | 8869 && !TREE_OVERFLOW (arg1) |
9448 } | 8879 } |
9449 | 8880 |
9450 /* copysign(X, Y) is fabs(X) when Y is always non-negative. | 8881 /* copysign(X, Y) is fabs(X) when Y is always non-negative. |
9451 Remember to evaluate Y for side-effects. */ | 8882 Remember to evaluate Y for side-effects. */ |
9452 if (tree_expr_nonnegative_p (arg2)) | 8883 if (tree_expr_nonnegative_p (arg2)) |
9453 return omit_one_operand (type, | 8884 return omit_one_operand_loc (loc, type, |
9454 fold_build1 (ABS_EXPR, type, arg1), | 8885 fold_build1_loc (loc, ABS_EXPR, type, arg1), |
9455 arg2); | 8886 arg2); |
9456 | 8887 |
9457 /* Strip sign changing operations for the first argument. */ | 8888 /* Strip sign changing operations for the first argument. */ |
9458 tem = fold_strip_sign_ops (arg1); | 8889 tem = fold_strip_sign_ops (arg1); |
9459 if (tem) | 8890 if (tem) |
9460 return build_call_expr (fndecl, 2, tem, arg2); | 8891 return build_call_expr_loc (loc, fndecl, 2, tem, arg2); |
9461 | 8892 |
9462 return NULL_TREE; | 8893 return NULL_TREE; |
9463 } | 8894 } |
9464 | 8895 |
9465 /* Fold a call to builtin isascii with argument ARG. */ | 8896 /* Fold a call to builtin isascii with argument ARG. */ |
9466 | 8897 |
9467 static tree | 8898 static tree |
9468 fold_builtin_isascii (tree arg) | 8899 fold_builtin_isascii (location_t loc, tree arg) |
9469 { | 8900 { |
9470 if (!validate_arg (arg, INTEGER_TYPE)) | 8901 if (!validate_arg (arg, INTEGER_TYPE)) |
9471 return NULL_TREE; | 8902 return NULL_TREE; |
9472 else | 8903 else |
9473 { | 8904 { |
9474 /* Transform isascii(c) -> ((c & ~0x7f) == 0). */ | 8905 /* Transform isascii(c) -> ((c & ~0x7f) == 0). */ |
9475 arg = build2 (BIT_AND_EXPR, integer_type_node, arg, | 8906 arg = fold_build2 (BIT_AND_EXPR, integer_type_node, arg, |
9476 build_int_cst (NULL_TREE, | 8907 build_int_cst (NULL_TREE, |
9477 ~ (unsigned HOST_WIDE_INT) 0x7f)); | 8908 ~ (unsigned HOST_WIDE_INT) 0x7f)); |
9478 return fold_build2 (EQ_EXPR, integer_type_node, | 8909 return fold_build2_loc (loc, EQ_EXPR, integer_type_node, |
9479 arg, integer_zero_node); | 8910 arg, integer_zero_node); |
9480 } | 8911 } |
9481 } | 8912 } |
9482 | 8913 |
9483 /* Fold a call to builtin toascii with argument ARG. */ | 8914 /* Fold a call to builtin toascii with argument ARG. */ |
9484 | 8915 |
9485 static tree | 8916 static tree |
9486 fold_builtin_toascii (tree arg) | 8917 fold_builtin_toascii (location_t loc, tree arg) |
9487 { | 8918 { |
9488 if (!validate_arg (arg, INTEGER_TYPE)) | 8919 if (!validate_arg (arg, INTEGER_TYPE)) |
9489 return NULL_TREE; | 8920 return NULL_TREE; |
9490 | 8921 |
9491 /* Transform toascii(c) -> (c & 0x7f). */ | 8922 /* Transform toascii(c) -> (c & 0x7f). */ |
9492 return fold_build2 (BIT_AND_EXPR, integer_type_node, arg, | 8923 return fold_build2_loc (loc, BIT_AND_EXPR, integer_type_node, arg, |
9493 build_int_cst (NULL_TREE, 0x7f)); | 8924 build_int_cst (NULL_TREE, 0x7f)); |
9494 } | 8925 } |
9495 | 8926 |
9496 /* Fold a call to builtin isdigit with argument ARG. */ | 8927 /* Fold a call to builtin isdigit with argument ARG. */ |
9497 | 8928 |
9498 static tree | 8929 static tree |
9499 fold_builtin_isdigit (tree arg) | 8930 fold_builtin_isdigit (location_t loc, tree arg) |
9500 { | 8931 { |
9501 if (!validate_arg (arg, INTEGER_TYPE)) | 8932 if (!validate_arg (arg, INTEGER_TYPE)) |
9502 return NULL_TREE; | 8933 return NULL_TREE; |
9503 else | 8934 else |
9504 { | 8935 { |
9509 = lang_hooks.to_target_charset ('0'); | 8940 = lang_hooks.to_target_charset ('0'); |
9510 | 8941 |
9511 if (target_digit0 == 0) | 8942 if (target_digit0 == 0) |
9512 return NULL_TREE; | 8943 return NULL_TREE; |
9513 | 8944 |
9514 arg = fold_convert (unsigned_type_node, arg); | 8945 arg = fold_convert_loc (loc, unsigned_type_node, arg); |
9515 arg = build2 (MINUS_EXPR, unsigned_type_node, arg, | 8946 arg = fold_build2 (MINUS_EXPR, unsigned_type_node, arg, |
9516 build_int_cst (unsigned_type_node, target_digit0)); | 8947 build_int_cst (unsigned_type_node, target_digit0)); |
9517 return fold_build2 (LE_EXPR, integer_type_node, arg, | 8948 return fold_build2_loc (loc, LE_EXPR, integer_type_node, arg, |
9518 build_int_cst (unsigned_type_node, 9)); | 8949 build_int_cst (unsigned_type_node, 9)); |
9519 } | 8950 } |
9520 } | 8951 } |
9521 | 8952 |
9522 /* Fold a call to fabs, fabsf or fabsl with argument ARG. */ | 8953 /* Fold a call to fabs, fabsf or fabsl with argument ARG. */ |
9523 | 8954 |
9524 static tree | 8955 static tree |
9525 fold_builtin_fabs (tree arg, tree type) | 8956 fold_builtin_fabs (location_t loc, tree arg, tree type) |
9526 { | 8957 { |
9527 if (!validate_arg (arg, REAL_TYPE)) | 8958 if (!validate_arg (arg, REAL_TYPE)) |
9528 return NULL_TREE; | 8959 return NULL_TREE; |
9529 | 8960 |
9530 arg = fold_convert (type, arg); | 8961 arg = fold_convert_loc (loc, type, arg); |
9531 if (TREE_CODE (arg) == REAL_CST) | 8962 if (TREE_CODE (arg) == REAL_CST) |
9532 return fold_abs_const (arg, type); | 8963 return fold_abs_const (arg, type); |
9533 return fold_build1 (ABS_EXPR, type, arg); | 8964 return fold_build1_loc (loc, ABS_EXPR, type, arg); |
9534 } | 8965 } |
9535 | 8966 |
9536 /* Fold a call to abs, labs, llabs or imaxabs with argument ARG. */ | 8967 /* Fold a call to abs, labs, llabs or imaxabs with argument ARG. */ |
9537 | 8968 |
9538 static tree | 8969 static tree |
9539 fold_builtin_abs (tree arg, tree type) | 8970 fold_builtin_abs (location_t loc, tree arg, tree type) |
9540 { | 8971 { |
9541 if (!validate_arg (arg, INTEGER_TYPE)) | 8972 if (!validate_arg (arg, INTEGER_TYPE)) |
9542 return NULL_TREE; | 8973 return NULL_TREE; |
9543 | 8974 |
9544 arg = fold_convert (type, arg); | 8975 arg = fold_convert_loc (loc, type, arg); |
9545 if (TREE_CODE (arg) == INTEGER_CST) | 8976 if (TREE_CODE (arg) == INTEGER_CST) |
9546 return fold_abs_const (arg, type); | 8977 return fold_abs_const (arg, type); |
9547 return fold_build1 (ABS_EXPR, type, arg); | 8978 return fold_build1_loc (loc, ABS_EXPR, type, arg); |
9548 } | 8979 } |
9549 | 8980 |
9550 /* Fold a call to builtin fmin or fmax. */ | 8981 /* Fold a call to builtin fmin or fmax. */ |
9551 | 8982 |
9552 static tree | 8983 static tree |
9553 fold_builtin_fmin_fmax (tree arg0, tree arg1, tree type, bool max) | 8984 fold_builtin_fmin_fmax (location_t loc, tree arg0, tree arg1, |
8985 tree type, bool max) | |
9554 { | 8986 { |
9555 if (validate_arg (arg0, REAL_TYPE) && validate_arg (arg1, REAL_TYPE)) | 8987 if (validate_arg (arg0, REAL_TYPE) && validate_arg (arg1, REAL_TYPE)) |
9556 { | 8988 { |
9557 /* Calculate the result when the argument is a constant. */ | 8989 /* Calculate the result when the argument is a constant. */ |
9558 tree res = do_mpfr_arg2 (arg0, arg1, type, (max ? mpfr_max : mpfr_min)); | 8990 tree res = do_mpfr_arg2 (arg0, arg1, type, (max ? mpfr_max : mpfr_min)); |
9565 omit_one_operand() ensures we create a non-lvalue. */ | 8997 omit_one_operand() ensures we create a non-lvalue. */ |
9566 if (TREE_CODE (arg0) == REAL_CST | 8998 if (TREE_CODE (arg0) == REAL_CST |
9567 && real_isnan (&TREE_REAL_CST (arg0)) | 8999 && real_isnan (&TREE_REAL_CST (arg0)) |
9568 && (! HONOR_SNANS (TYPE_MODE (TREE_TYPE (arg0))) | 9000 && (! HONOR_SNANS (TYPE_MODE (TREE_TYPE (arg0))) |
9569 || ! TREE_REAL_CST (arg0).signalling)) | 9001 || ! TREE_REAL_CST (arg0).signalling)) |
9570 return omit_one_operand (type, arg1, arg0); | 9002 return omit_one_operand_loc (loc, type, arg1, arg0); |
9571 if (TREE_CODE (arg1) == REAL_CST | 9003 if (TREE_CODE (arg1) == REAL_CST |
9572 && real_isnan (&TREE_REAL_CST (arg1)) | 9004 && real_isnan (&TREE_REAL_CST (arg1)) |
9573 && (! HONOR_SNANS (TYPE_MODE (TREE_TYPE (arg1))) | 9005 && (! HONOR_SNANS (TYPE_MODE (TREE_TYPE (arg1))) |
9574 || ! TREE_REAL_CST (arg1).signalling)) | 9006 || ! TREE_REAL_CST (arg1).signalling)) |
9575 return omit_one_operand (type, arg0, arg1); | 9007 return omit_one_operand_loc (loc, type, arg0, arg1); |
9576 | 9008 |
9577 /* Transform fmin/fmax(x,x) -> x. */ | 9009 /* Transform fmin/fmax(x,x) -> x. */ |
9578 if (operand_equal_p (arg0, arg1, OEP_PURE_SAME)) | 9010 if (operand_equal_p (arg0, arg1, OEP_PURE_SAME)) |
9579 return omit_one_operand (type, arg0, arg1); | 9011 return omit_one_operand_loc (loc, type, arg0, arg1); |
9580 | 9012 |
9581 /* Convert fmin/fmax to MIN_EXPR/MAX_EXPR. C99 requires these | 9013 /* Convert fmin/fmax to MIN_EXPR/MAX_EXPR. C99 requires these |
9582 functions to return the numeric arg if the other one is NaN. | 9014 functions to return the numeric arg if the other one is NaN. |
9583 These tree codes don't honor that, so only transform if | 9015 These tree codes don't honor that, so only transform if |
9584 -ffinite-math-only is set. C99 doesn't require -0.0 to be | 9016 -ffinite-math-only is set. C99 doesn't require -0.0 to be |
9585 handled, so we don't have to worry about it either. */ | 9017 handled, so we don't have to worry about it either. */ |
9586 if (flag_finite_math_only) | 9018 if (flag_finite_math_only) |
9587 return fold_build2 ((max ? MAX_EXPR : MIN_EXPR), type, | 9019 return fold_build2_loc (loc, (max ? MAX_EXPR : MIN_EXPR), type, |
9588 fold_convert (type, arg0), | 9020 fold_convert_loc (loc, type, arg0), |
9589 fold_convert (type, arg1)); | 9021 fold_convert_loc (loc, type, arg1)); |
9590 } | 9022 } |
9591 return NULL_TREE; | 9023 return NULL_TREE; |
9592 } | 9024 } |
9593 | 9025 |
9594 /* Fold a call to builtin carg(a+bi) -> atan2(b,a). */ | 9026 /* Fold a call to builtin carg(a+bi) -> atan2(b,a). */ |
9595 | 9027 |
9596 static tree | 9028 static tree |
9597 fold_builtin_carg (tree arg, tree type) | 9029 fold_builtin_carg (location_t loc, tree arg, tree type) |
9598 { | 9030 { |
9599 if (validate_arg (arg, COMPLEX_TYPE)) | 9031 if (validate_arg (arg, COMPLEX_TYPE) |
9032 && TREE_CODE (TREE_TYPE (TREE_TYPE (arg))) == REAL_TYPE) | |
9600 { | 9033 { |
9601 tree atan2_fn = mathfn_built_in (type, BUILT_IN_ATAN2); | 9034 tree atan2_fn = mathfn_built_in (type, BUILT_IN_ATAN2); |
9602 | 9035 |
9603 if (atan2_fn) | 9036 if (atan2_fn) |
9604 { | 9037 { |
9605 tree new_arg = builtin_save_expr (arg); | 9038 tree new_arg = builtin_save_expr (arg); |
9606 tree r_arg = fold_build1 (REALPART_EXPR, type, new_arg); | 9039 tree r_arg = fold_build1_loc (loc, REALPART_EXPR, type, new_arg); |
9607 tree i_arg = fold_build1 (IMAGPART_EXPR, type, new_arg); | 9040 tree i_arg = fold_build1_loc (loc, IMAGPART_EXPR, type, new_arg); |
9608 return build_call_expr (atan2_fn, 2, i_arg, r_arg); | 9041 return build_call_expr_loc (loc, atan2_fn, 2, i_arg, r_arg); |
9609 } | 9042 } |
9610 } | 9043 } |
9611 | 9044 |
9612 return NULL_TREE; | 9045 return NULL_TREE; |
9613 } | 9046 } |
9614 | 9047 |
9615 /* Fold a call to builtin logb/ilogb. */ | 9048 /* Fold a call to builtin logb/ilogb. */ |
9616 | 9049 |
9617 static tree | 9050 static tree |
9618 fold_builtin_logb (tree arg, tree rettype) | 9051 fold_builtin_logb (location_t loc, tree arg, tree rettype) |
9619 { | 9052 { |
9620 if (! validate_arg (arg, REAL_TYPE)) | 9053 if (! validate_arg (arg, REAL_TYPE)) |
9621 return NULL_TREE; | 9054 return NULL_TREE; |
9622 | 9055 |
9623 STRIP_NOPS (arg); | 9056 STRIP_NOPS (arg); |
9624 | 9057 |
9625 if (TREE_CODE (arg) == REAL_CST && ! TREE_OVERFLOW (arg)) | 9058 if (TREE_CODE (arg) == REAL_CST && ! TREE_OVERFLOW (arg)) |
9626 { | 9059 { |
9627 const REAL_VALUE_TYPE *const value = TREE_REAL_CST_PTR (arg); | 9060 const REAL_VALUE_TYPE *const value = TREE_REAL_CST_PTR (arg); |
9628 | 9061 |
9629 switch (value->cl) | 9062 switch (value->cl) |
9630 { | 9063 { |
9631 case rvc_nan: | 9064 case rvc_nan: |
9632 case rvc_inf: | 9065 case rvc_inf: |
9633 /* If arg is Inf or NaN and we're logb, return it. */ | 9066 /* If arg is Inf or NaN and we're logb, return it. */ |
9634 if (TREE_CODE (rettype) == REAL_TYPE) | 9067 if (TREE_CODE (rettype) == REAL_TYPE) |
9635 return fold_convert (rettype, arg); | 9068 return fold_convert_loc (loc, rettype, arg); |
9636 /* Fall through... */ | 9069 /* Fall through... */ |
9637 case rvc_zero: | 9070 case rvc_zero: |
9638 /* Zero may set errno and/or raise an exception for logb, also | 9071 /* Zero may set errno and/or raise an exception for logb, also |
9639 for ilogb we don't know FP_ILOGB0. */ | 9072 for ilogb we don't know FP_ILOGB0. */ |
9640 return NULL_TREE; | 9073 return NULL_TREE; |
9642 /* For normal numbers, proceed iff radix == 2. In GCC, | 9075 /* For normal numbers, proceed iff radix == 2. In GCC, |
9643 normalized significands are in the range [0.5, 1.0). We | 9076 normalized significands are in the range [0.5, 1.0). We |
9644 want the exponent as if they were [1.0, 2.0) so get the | 9077 want the exponent as if they were [1.0, 2.0) so get the |
9645 exponent and subtract 1. */ | 9078 exponent and subtract 1. */ |
9646 if (REAL_MODE_FORMAT (TYPE_MODE (TREE_TYPE (arg)))->b == 2) | 9079 if (REAL_MODE_FORMAT (TYPE_MODE (TREE_TYPE (arg)))->b == 2) |
9647 return fold_convert (rettype, build_int_cst (NULL_TREE, | 9080 return fold_convert_loc (loc, rettype, |
9648 REAL_EXP (value)-1)); | 9081 build_int_cst (NULL_TREE, |
9082 REAL_EXP (value)-1)); | |
9649 break; | 9083 break; |
9650 } | 9084 } |
9651 } | 9085 } |
9652 | 9086 |
9653 return NULL_TREE; | 9087 return NULL_TREE; |
9654 } | 9088 } |
9655 | 9089 |
9656 /* Fold a call to builtin significand, if radix == 2. */ | 9090 /* Fold a call to builtin significand, if radix == 2. */ |
9657 | 9091 |
9658 static tree | 9092 static tree |
9659 fold_builtin_significand (tree arg, tree rettype) | 9093 fold_builtin_significand (location_t loc, tree arg, tree rettype) |
9660 { | 9094 { |
9661 if (! validate_arg (arg, REAL_TYPE)) | 9095 if (! validate_arg (arg, REAL_TYPE)) |
9662 return NULL_TREE; | 9096 return NULL_TREE; |
9663 | 9097 |
9664 STRIP_NOPS (arg); | 9098 STRIP_NOPS (arg); |
9665 | 9099 |
9666 if (TREE_CODE (arg) == REAL_CST && ! TREE_OVERFLOW (arg)) | 9100 if (TREE_CODE (arg) == REAL_CST && ! TREE_OVERFLOW (arg)) |
9667 { | 9101 { |
9668 const REAL_VALUE_TYPE *const value = TREE_REAL_CST_PTR (arg); | 9102 const REAL_VALUE_TYPE *const value = TREE_REAL_CST_PTR (arg); |
9669 | 9103 |
9670 switch (value->cl) | 9104 switch (value->cl) |
9671 { | 9105 { |
9672 case rvc_zero: | 9106 case rvc_zero: |
9673 case rvc_nan: | 9107 case rvc_nan: |
9674 case rvc_inf: | 9108 case rvc_inf: |
9675 /* If arg is +-0, +-Inf or +-NaN, then return it. */ | 9109 /* If arg is +-0, +-Inf or +-NaN, then return it. */ |
9676 return fold_convert (rettype, arg); | 9110 return fold_convert_loc (loc, rettype, arg); |
9677 case rvc_normal: | 9111 case rvc_normal: |
9678 /* For normal numbers, proceed iff radix == 2. */ | 9112 /* For normal numbers, proceed iff radix == 2. */ |
9679 if (REAL_MODE_FORMAT (TYPE_MODE (TREE_TYPE (arg)))->b == 2) | 9113 if (REAL_MODE_FORMAT (TYPE_MODE (TREE_TYPE (arg)))->b == 2) |
9680 { | 9114 { |
9681 REAL_VALUE_TYPE result = *value; | 9115 REAL_VALUE_TYPE result = *value; |
9686 return build_real (rettype, result); | 9120 return build_real (rettype, result); |
9687 } | 9121 } |
9688 break; | 9122 break; |
9689 } | 9123 } |
9690 } | 9124 } |
9691 | 9125 |
9692 return NULL_TREE; | 9126 return NULL_TREE; |
9693 } | 9127 } |
9694 | 9128 |
9695 /* Fold a call to builtin frexp, we can assume the base is 2. */ | 9129 /* Fold a call to builtin frexp, we can assume the base is 2. */ |
9696 | 9130 |
9697 static tree | 9131 static tree |
9698 fold_builtin_frexp (tree arg0, tree arg1, tree rettype) | 9132 fold_builtin_frexp (location_t loc, tree arg0, tree arg1, tree rettype) |
9699 { | 9133 { |
9700 if (! validate_arg (arg0, REAL_TYPE) || ! validate_arg (arg1, POINTER_TYPE)) | 9134 if (! validate_arg (arg0, REAL_TYPE) || ! validate_arg (arg1, POINTER_TYPE)) |
9701 return NULL_TREE; | 9135 return NULL_TREE; |
9702 | 9136 |
9703 STRIP_NOPS (arg0); | 9137 STRIP_NOPS (arg0); |
9704 | 9138 |
9705 if (!(TREE_CODE (arg0) == REAL_CST && ! TREE_OVERFLOW (arg0))) | 9139 if (!(TREE_CODE (arg0) == REAL_CST && ! TREE_OVERFLOW (arg0))) |
9706 return NULL_TREE; | 9140 return NULL_TREE; |
9707 | 9141 |
9708 arg1 = build_fold_indirect_ref (arg1); | 9142 arg1 = build_fold_indirect_ref_loc (loc, arg1); |
9709 | 9143 |
9710 /* Proceed if a valid pointer type was passed in. */ | 9144 /* Proceed if a valid pointer type was passed in. */ |
9711 if (TYPE_MAIN_VARIANT (TREE_TYPE (arg1)) == integer_type_node) | 9145 if (TYPE_MAIN_VARIANT (TREE_TYPE (arg1)) == integer_type_node) |
9712 { | 9146 { |
9713 const REAL_VALUE_TYPE *const value = TREE_REAL_CST_PTR (arg0); | 9147 const REAL_VALUE_TYPE *const value = TREE_REAL_CST_PTR (arg0); |
9714 tree frac, exp; | 9148 tree frac, exp; |
9715 | 9149 |
9716 switch (value->cl) | 9150 switch (value->cl) |
9717 { | 9151 { |
9718 case rvc_zero: | 9152 case rvc_zero: |
9719 /* For +-0, return (*exp = 0, +-0). */ | 9153 /* For +-0, return (*exp = 0, +-0). */ |
9720 exp = integer_zero_node; | 9154 exp = integer_zero_node; |
9721 frac = arg0; | 9155 frac = arg0; |
9722 break; | 9156 break; |
9723 case rvc_nan: | 9157 case rvc_nan: |
9724 case rvc_inf: | 9158 case rvc_inf: |
9725 /* For +-NaN or +-Inf, *exp is unspecified, return arg0. */ | 9159 /* For +-NaN or +-Inf, *exp is unspecified, return arg0. */ |
9726 return omit_one_operand (rettype, arg0, arg1); | 9160 return omit_one_operand_loc (loc, rettype, arg0, arg1); |
9727 case rvc_normal: | 9161 case rvc_normal: |
9728 { | 9162 { |
9729 /* Since the frexp function always expects base 2, and in | 9163 /* Since the frexp function always expects base 2, and in |
9730 GCC normalized significands are already in the range | 9164 GCC normalized significands are already in the range |
9731 [0.5, 1.0), we have exactly what frexp wants. */ | 9165 [0.5, 1.0), we have exactly what frexp wants. */ |
9736 } | 9170 } |
9737 break; | 9171 break; |
9738 default: | 9172 default: |
9739 gcc_unreachable (); | 9173 gcc_unreachable (); |
9740 } | 9174 } |
9741 | 9175 |
9742 /* Create the COMPOUND_EXPR (*arg1 = trunc, frac). */ | 9176 /* Create the COMPOUND_EXPR (*arg1 = trunc, frac). */ |
9743 arg1 = fold_build2 (MODIFY_EXPR, rettype, arg1, exp); | 9177 arg1 = fold_build2_loc (loc, MODIFY_EXPR, rettype, arg1, exp); |
9744 TREE_SIDE_EFFECTS (arg1) = 1; | 9178 TREE_SIDE_EFFECTS (arg1) = 1; |
9745 return fold_build2 (COMPOUND_EXPR, rettype, arg1, frac); | 9179 return fold_build2_loc (loc, COMPOUND_EXPR, rettype, arg1, frac); |
9746 } | 9180 } |
9747 | 9181 |
9748 return NULL_TREE; | 9182 return NULL_TREE; |
9749 } | 9183 } |
9750 | 9184 |
9751 /* Fold a call to builtin ldexp or scalbn/scalbln. If LDEXP is true | 9185 /* Fold a call to builtin ldexp or scalbn/scalbln. If LDEXP is true |
9752 then we can assume the base is two. If it's false, then we have to | 9186 then we can assume the base is two. If it's false, then we have to |
9753 check the mode of the TYPE parameter in certain cases. */ | 9187 check the mode of the TYPE parameter in certain cases. */ |
9754 | 9188 |
9755 static tree | 9189 static tree |
9756 fold_builtin_load_exponent (tree arg0, tree arg1, tree type, bool ldexp) | 9190 fold_builtin_load_exponent (location_t loc, tree arg0, tree arg1, |
9191 tree type, bool ldexp) | |
9757 { | 9192 { |
9758 if (validate_arg (arg0, REAL_TYPE) && validate_arg (arg1, INTEGER_TYPE)) | 9193 if (validate_arg (arg0, REAL_TYPE) && validate_arg (arg1, INTEGER_TYPE)) |
9759 { | 9194 { |
9760 STRIP_NOPS (arg0); | 9195 STRIP_NOPS (arg0); |
9761 STRIP_NOPS (arg1); | 9196 STRIP_NOPS (arg1); |
9762 | 9197 |
9763 /* If arg0 is 0, Inf or NaN, or if arg1 is 0, then return arg0. */ | 9198 /* If arg0 is 0, Inf or NaN, or if arg1 is 0, then return arg0. */ |
9764 if (real_zerop (arg0) || integer_zerop (arg1) | 9199 if (real_zerop (arg0) || integer_zerop (arg1) |
9765 || (TREE_CODE (arg0) == REAL_CST | 9200 || (TREE_CODE (arg0) == REAL_CST |
9766 && !real_isfinite (&TREE_REAL_CST (arg0)))) | 9201 && !real_isfinite (&TREE_REAL_CST (arg0)))) |
9767 return omit_one_operand (type, arg0, arg1); | 9202 return omit_one_operand_loc (loc, type, arg0, arg1); |
9768 | 9203 |
9769 /* If both arguments are constant, then try to evaluate it. */ | 9204 /* If both arguments are constant, then try to evaluate it. */ |
9770 if ((ldexp || REAL_MODE_FORMAT (TYPE_MODE (type))->b == 2) | 9205 if ((ldexp || REAL_MODE_FORMAT (TYPE_MODE (type))->b == 2) |
9771 && TREE_CODE (arg0) == REAL_CST && !TREE_OVERFLOW (arg0) | 9206 && TREE_CODE (arg0) == REAL_CST && !TREE_OVERFLOW (arg0) |
9772 && host_integerp (arg1, 0)) | 9207 && host_integerp (arg1, 0)) |
9773 { | 9208 { |
9774 /* Bound the maximum adjustment to twice the range of the | 9209 /* Bound the maximum adjustment to twice the range of the |
9775 mode's valid exponents. Use abs to ensure the range is | 9210 mode's valid exponents. Use abs to ensure the range is |
9776 positive as a sanity check. */ | 9211 positive as a sanity check. */ |
9777 const long max_exp_adj = 2 * | 9212 const long max_exp_adj = 2 * |
9778 labs (REAL_MODE_FORMAT (TYPE_MODE (type))->emax | 9213 labs (REAL_MODE_FORMAT (TYPE_MODE (type))->emax |
9779 - REAL_MODE_FORMAT (TYPE_MODE (type))->emin); | 9214 - REAL_MODE_FORMAT (TYPE_MODE (type))->emin); |
9780 | 9215 |
9781 /* Get the user-requested adjustment. */ | 9216 /* Get the user-requested adjustment. */ |
9782 const HOST_WIDE_INT req_exp_adj = tree_low_cst (arg1, 0); | 9217 const HOST_WIDE_INT req_exp_adj = tree_low_cst (arg1, 0); |
9783 | 9218 |
9784 /* The requested adjustment must be inside this range. This | 9219 /* The requested adjustment must be inside this range. This |
9785 is a preliminary cap to avoid things like overflow, we | 9220 is a preliminary cap to avoid things like overflow, we |
9786 may still fail to compute the result for other reasons. */ | 9221 may still fail to compute the result for other reasons. */ |
9787 if (-max_exp_adj < req_exp_adj && req_exp_adj < max_exp_adj) | 9222 if (-max_exp_adj < req_exp_adj && req_exp_adj < max_exp_adj) |
9788 { | 9223 { |
9789 REAL_VALUE_TYPE initial_result; | 9224 REAL_VALUE_TYPE initial_result; |
9790 | 9225 |
9791 real_ldexp (&initial_result, &TREE_REAL_CST (arg0), req_exp_adj); | 9226 real_ldexp (&initial_result, &TREE_REAL_CST (arg0), req_exp_adj); |
9792 | 9227 |
9793 /* Ensure we didn't overflow. */ | 9228 /* Ensure we didn't overflow. */ |
9794 if (! real_isinf (&initial_result)) | 9229 if (! real_isinf (&initial_result)) |
9795 { | 9230 { |
9796 const REAL_VALUE_TYPE trunc_result | 9231 const REAL_VALUE_TYPE trunc_result |
9797 = real_value_truncate (TYPE_MODE (type), initial_result); | 9232 = real_value_truncate (TYPE_MODE (type), initial_result); |
9798 | 9233 |
9799 /* Only proceed if the target mode can hold the | 9234 /* Only proceed if the target mode can hold the |
9800 resulting value. */ | 9235 resulting value. */ |
9801 if (REAL_VALUES_EQUAL (initial_result, trunc_result)) | 9236 if (REAL_VALUES_EQUAL (initial_result, trunc_result)) |
9802 return build_real (type, trunc_result); | 9237 return build_real (type, trunc_result); |
9803 } | 9238 } |
9809 } | 9244 } |
9810 | 9245 |
9811 /* Fold a call to builtin modf. */ | 9246 /* Fold a call to builtin modf. */ |
9812 | 9247 |
9813 static tree | 9248 static tree |
9814 fold_builtin_modf (tree arg0, tree arg1, tree rettype) | 9249 fold_builtin_modf (location_t loc, tree arg0, tree arg1, tree rettype) |
9815 { | 9250 { |
9816 if (! validate_arg (arg0, REAL_TYPE) || ! validate_arg (arg1, POINTER_TYPE)) | 9251 if (! validate_arg (arg0, REAL_TYPE) || ! validate_arg (arg1, POINTER_TYPE)) |
9817 return NULL_TREE; | 9252 return NULL_TREE; |
9818 | 9253 |
9819 STRIP_NOPS (arg0); | 9254 STRIP_NOPS (arg0); |
9820 | 9255 |
9821 if (!(TREE_CODE (arg0) == REAL_CST && ! TREE_OVERFLOW (arg0))) | 9256 if (!(TREE_CODE (arg0) == REAL_CST && ! TREE_OVERFLOW (arg0))) |
9822 return NULL_TREE; | 9257 return NULL_TREE; |
9823 | 9258 |
9824 arg1 = build_fold_indirect_ref (arg1); | 9259 arg1 = build_fold_indirect_ref_loc (loc, arg1); |
9825 | 9260 |
9826 /* Proceed if a valid pointer type was passed in. */ | 9261 /* Proceed if a valid pointer type was passed in. */ |
9827 if (TYPE_MAIN_VARIANT (TREE_TYPE (arg1)) == TYPE_MAIN_VARIANT (rettype)) | 9262 if (TYPE_MAIN_VARIANT (TREE_TYPE (arg1)) == TYPE_MAIN_VARIANT (rettype)) |
9828 { | 9263 { |
9829 const REAL_VALUE_TYPE *const value = TREE_REAL_CST_PTR (arg0); | 9264 const REAL_VALUE_TYPE *const value = TREE_REAL_CST_PTR (arg0); |
9850 integral, then the fractional part is -0.0. */ | 9285 integral, then the fractional part is -0.0. */ |
9851 if (value->sign && frac.cl == rvc_zero) | 9286 if (value->sign && frac.cl == rvc_zero) |
9852 frac.sign = value->sign; | 9287 frac.sign = value->sign; |
9853 break; | 9288 break; |
9854 } | 9289 } |
9855 | 9290 |
9856 /* Create the COMPOUND_EXPR (*arg1 = trunc, frac). */ | 9291 /* Create the COMPOUND_EXPR (*arg1 = trunc, frac). */ |
9857 arg1 = fold_build2 (MODIFY_EXPR, rettype, arg1, | 9292 arg1 = fold_build2_loc (loc, MODIFY_EXPR, rettype, arg1, |
9858 build_real (rettype, trunc)); | 9293 build_real (rettype, trunc)); |
9859 TREE_SIDE_EFFECTS (arg1) = 1; | 9294 TREE_SIDE_EFFECTS (arg1) = 1; |
9860 return fold_build2 (COMPOUND_EXPR, rettype, arg1, | 9295 return fold_build2_loc (loc, COMPOUND_EXPR, rettype, arg1, |
9861 build_real (rettype, frac)); | 9296 build_real (rettype, frac)); |
9862 } | 9297 } |
9863 | 9298 |
9299 return NULL_TREE; | |
9300 } | |
9301 | |
9302 /* Given a location LOC, an interclass builtin function decl FNDECL | |
9303 and its single argument ARG, return an folded expression computing | |
9304 the same, or NULL_TREE if we either couldn't or didn't want to fold | |
9305 (the latter happen if there's an RTL instruction available). */ | |
9306 | |
9307 static tree | |
9308 fold_builtin_interclass_mathfn (location_t loc, tree fndecl, tree arg) | |
9309 { | |
9310 enum machine_mode mode; | |
9311 | |
9312 if (!validate_arg (arg, REAL_TYPE)) | |
9313 return NULL_TREE; | |
9314 | |
9315 if (interclass_mathfn_icode (arg, fndecl) != CODE_FOR_nothing) | |
9316 return NULL_TREE; | |
9317 | |
9318 mode = TYPE_MODE (TREE_TYPE (arg)); | |
9319 | |
9320 /* If there is no optab, try generic code. */ | |
9321 switch (DECL_FUNCTION_CODE (fndecl)) | |
9322 { | |
9323 tree result; | |
9324 | |
9325 CASE_FLT_FN (BUILT_IN_ISINF): | |
9326 { | |
9327 /* isinf(x) -> isgreater(fabs(x),DBL_MAX). */ | |
9328 tree const isgr_fn = built_in_decls[BUILT_IN_ISGREATER]; | |
9329 tree const type = TREE_TYPE (arg); | |
9330 REAL_VALUE_TYPE r; | |
9331 char buf[128]; | |
9332 | |
9333 get_max_float (REAL_MODE_FORMAT (mode), buf, sizeof (buf)); | |
9334 real_from_string (&r, buf); | |
9335 result = build_call_expr (isgr_fn, 2, | |
9336 fold_build1_loc (loc, ABS_EXPR, type, arg), | |
9337 build_real (type, r)); | |
9338 return result; | |
9339 } | |
9340 CASE_FLT_FN (BUILT_IN_FINITE): | |
9341 case BUILT_IN_ISFINITE: | |
9342 { | |
9343 /* isfinite(x) -> islessequal(fabs(x),DBL_MAX). */ | |
9344 tree const isle_fn = built_in_decls[BUILT_IN_ISLESSEQUAL]; | |
9345 tree const type = TREE_TYPE (arg); | |
9346 REAL_VALUE_TYPE r; | |
9347 char buf[128]; | |
9348 | |
9349 get_max_float (REAL_MODE_FORMAT (mode), buf, sizeof (buf)); | |
9350 real_from_string (&r, buf); | |
9351 result = build_call_expr (isle_fn, 2, | |
9352 fold_build1_loc (loc, ABS_EXPR, type, arg), | |
9353 build_real (type, r)); | |
9354 /*result = fold_build2_loc (loc, UNGT_EXPR, | |
9355 TREE_TYPE (TREE_TYPE (fndecl)), | |
9356 fold_build1_loc (loc, ABS_EXPR, type, arg), | |
9357 build_real (type, r)); | |
9358 result = fold_build1_loc (loc, TRUTH_NOT_EXPR, | |
9359 TREE_TYPE (TREE_TYPE (fndecl)), | |
9360 result);*/ | |
9361 return result; | |
9362 } | |
9363 case BUILT_IN_ISNORMAL: | |
9364 { | |
9365 /* isnormal(x) -> isgreaterequal(fabs(x),DBL_MIN) & | |
9366 islessequal(fabs(x),DBL_MAX). */ | |
9367 tree const isle_fn = built_in_decls[BUILT_IN_ISLESSEQUAL]; | |
9368 tree const isge_fn = built_in_decls[BUILT_IN_ISGREATEREQUAL]; | |
9369 tree const type = TREE_TYPE (arg); | |
9370 REAL_VALUE_TYPE rmax, rmin; | |
9371 char buf[128]; | |
9372 | |
9373 get_max_float (REAL_MODE_FORMAT (mode), buf, sizeof (buf)); | |
9374 real_from_string (&rmax, buf); | |
9375 sprintf (buf, "0x1p%d", REAL_MODE_FORMAT (mode)->emin - 1); | |
9376 real_from_string (&rmin, buf); | |
9377 arg = builtin_save_expr (fold_build1_loc (loc, ABS_EXPR, type, arg)); | |
9378 result = build_call_expr (isle_fn, 2, arg, | |
9379 build_real (type, rmax)); | |
9380 result = fold_build2 (BIT_AND_EXPR, integer_type_node, result, | |
9381 build_call_expr (isge_fn, 2, arg, | |
9382 build_real (type, rmin))); | |
9383 return result; | |
9384 } | |
9385 default: | |
9386 break; | |
9387 } | |
9388 | |
9864 return NULL_TREE; | 9389 return NULL_TREE; |
9865 } | 9390 } |
9866 | 9391 |
9867 /* Fold a call to __builtin_isnan(), __builtin_isinf, __builtin_finite. | 9392 /* Fold a call to __builtin_isnan(), __builtin_isinf, __builtin_finite. |
9868 ARG is the argument for the call. */ | 9393 ARG is the argument for the call. */ |
9869 | 9394 |
9870 static tree | 9395 static tree |
9871 fold_builtin_classify (tree fndecl, tree arg, int builtin_index) | 9396 fold_builtin_classify (location_t loc, tree fndecl, tree arg, int builtin_index) |
9872 { | 9397 { |
9873 tree type = TREE_TYPE (TREE_TYPE (fndecl)); | 9398 tree type = TREE_TYPE (TREE_TYPE (fndecl)); |
9874 REAL_VALUE_TYPE r; | 9399 REAL_VALUE_TYPE r; |
9875 | 9400 |
9876 if (!validate_arg (arg, REAL_TYPE)) | 9401 if (!validate_arg (arg, REAL_TYPE)) |
9878 | 9403 |
9879 switch (builtin_index) | 9404 switch (builtin_index) |
9880 { | 9405 { |
9881 case BUILT_IN_ISINF: | 9406 case BUILT_IN_ISINF: |
9882 if (!HONOR_INFINITIES (TYPE_MODE (TREE_TYPE (arg)))) | 9407 if (!HONOR_INFINITIES (TYPE_MODE (TREE_TYPE (arg)))) |
9883 return omit_one_operand (type, integer_zero_node, arg); | 9408 return omit_one_operand_loc (loc, type, integer_zero_node, arg); |
9884 | 9409 |
9885 if (TREE_CODE (arg) == REAL_CST) | 9410 if (TREE_CODE (arg) == REAL_CST) |
9886 { | 9411 { |
9887 r = TREE_REAL_CST (arg); | 9412 r = TREE_REAL_CST (arg); |
9888 if (real_isinf (&r)) | 9413 if (real_isinf (&r)) |
9906 | 9431 |
9907 arg = builtin_save_expr (arg); | 9432 arg = builtin_save_expr (arg); |
9908 | 9433 |
9909 if (signbit_fn && isinf_fn) | 9434 if (signbit_fn && isinf_fn) |
9910 { | 9435 { |
9911 tree signbit_call = build_call_expr (signbit_fn, 1, arg); | 9436 tree signbit_call = build_call_expr_loc (loc, signbit_fn, 1, arg); |
9912 tree isinf_call = build_call_expr (isinf_fn, 1, arg); | 9437 tree isinf_call = build_call_expr_loc (loc, isinf_fn, 1, arg); |
9913 | 9438 |
9914 signbit_call = fold_build2 (NE_EXPR, integer_type_node, | 9439 signbit_call = fold_build2_loc (loc, NE_EXPR, integer_type_node, |
9915 signbit_call, integer_zero_node); | 9440 signbit_call, integer_zero_node); |
9916 isinf_call = fold_build2 (NE_EXPR, integer_type_node, | 9441 isinf_call = fold_build2_loc (loc, NE_EXPR, integer_type_node, |
9917 isinf_call, integer_zero_node); | 9442 isinf_call, integer_zero_node); |
9918 | 9443 |
9919 tmp = fold_build3 (COND_EXPR, integer_type_node, signbit_call, | 9444 tmp = fold_build3_loc (loc, COND_EXPR, integer_type_node, signbit_call, |
9920 integer_minus_one_node, integer_one_node); | 9445 integer_minus_one_node, integer_one_node); |
9921 tmp = fold_build3 (COND_EXPR, integer_type_node, isinf_call, tmp, | 9446 tmp = fold_build3_loc (loc, COND_EXPR, integer_type_node, |
9447 isinf_call, tmp, | |
9922 integer_zero_node); | 9448 integer_zero_node); |
9923 } | 9449 } |
9924 | 9450 |
9925 return tmp; | 9451 return tmp; |
9926 } | 9452 } |
9927 | 9453 |
9928 case BUILT_IN_ISFINITE: | 9454 case BUILT_IN_ISFINITE: |
9929 if (!HONOR_NANS (TYPE_MODE (TREE_TYPE (arg))) | 9455 if (!HONOR_NANS (TYPE_MODE (TREE_TYPE (arg))) |
9930 && !HONOR_INFINITIES (TYPE_MODE (TREE_TYPE (arg)))) | 9456 && !HONOR_INFINITIES (TYPE_MODE (TREE_TYPE (arg)))) |
9931 return omit_one_operand (type, integer_one_node, arg); | 9457 return omit_one_operand_loc (loc, type, integer_one_node, arg); |
9932 | 9458 |
9933 if (TREE_CODE (arg) == REAL_CST) | 9459 if (TREE_CODE (arg) == REAL_CST) |
9934 { | 9460 { |
9935 r = TREE_REAL_CST (arg); | 9461 r = TREE_REAL_CST (arg); |
9936 return real_isfinite (&r) ? integer_one_node : integer_zero_node; | 9462 return real_isfinite (&r) ? integer_one_node : integer_zero_node; |
9938 | 9464 |
9939 return NULL_TREE; | 9465 return NULL_TREE; |
9940 | 9466 |
9941 case BUILT_IN_ISNAN: | 9467 case BUILT_IN_ISNAN: |
9942 if (!HONOR_NANS (TYPE_MODE (TREE_TYPE (arg)))) | 9468 if (!HONOR_NANS (TYPE_MODE (TREE_TYPE (arg)))) |
9943 return omit_one_operand (type, integer_zero_node, arg); | 9469 return omit_one_operand_loc (loc, type, integer_zero_node, arg); |
9944 | 9470 |
9945 if (TREE_CODE (arg) == REAL_CST) | 9471 if (TREE_CODE (arg) == REAL_CST) |
9946 { | 9472 { |
9947 r = TREE_REAL_CST (arg); | 9473 r = TREE_REAL_CST (arg); |
9948 return real_isnan (&r) ? integer_one_node : integer_zero_node; | 9474 return real_isnan (&r) ? integer_one_node : integer_zero_node; |
9949 } | 9475 } |
9950 | 9476 |
9951 arg = builtin_save_expr (arg); | 9477 arg = builtin_save_expr (arg); |
9952 return fold_build2 (UNORDERED_EXPR, type, arg, arg); | 9478 return fold_build2_loc (loc, UNORDERED_EXPR, type, arg, arg); |
9953 | 9479 |
9954 default: | 9480 default: |
9955 gcc_unreachable (); | 9481 gcc_unreachable (); |
9956 } | 9482 } |
9957 } | 9483 } |
9963 int arguments to the call in the following order: FP_NAN, FP_INFINITE, | 9489 int arguments to the call in the following order: FP_NAN, FP_INFINITE, |
9964 FP_NORMAL, FP_SUBNORMAL and FP_ZERO. The ellipses is for exactly | 9490 FP_NORMAL, FP_SUBNORMAL and FP_ZERO. The ellipses is for exactly |
9965 one floating point argument which is "type generic". */ | 9491 one floating point argument which is "type generic". */ |
9966 | 9492 |
9967 static tree | 9493 static tree |
9968 fold_builtin_fpclassify (tree exp) | 9494 fold_builtin_fpclassify (location_t loc, tree exp) |
9969 { | 9495 { |
9970 tree fp_nan, fp_infinite, fp_normal, fp_subnormal, fp_zero, | 9496 tree fp_nan, fp_infinite, fp_normal, fp_subnormal, fp_zero, |
9971 arg, type, res, tmp; | 9497 arg, type, res, tmp; |
9972 enum machine_mode mode; | 9498 enum machine_mode mode; |
9973 REAL_VALUE_TYPE r; | 9499 REAL_VALUE_TYPE r; |
9974 char buf[128]; | 9500 char buf[128]; |
9975 | 9501 |
9976 /* Verify the required arguments in the original call. */ | 9502 /* Verify the required arguments in the original call. */ |
9977 if (!validate_arglist (exp, INTEGER_TYPE, INTEGER_TYPE, | 9503 if (!validate_arglist (exp, INTEGER_TYPE, INTEGER_TYPE, |
9978 INTEGER_TYPE, INTEGER_TYPE, | 9504 INTEGER_TYPE, INTEGER_TYPE, |
9979 INTEGER_TYPE, REAL_TYPE, VOID_TYPE)) | 9505 INTEGER_TYPE, REAL_TYPE, VOID_TYPE)) |
9980 return NULL_TREE; | 9506 return NULL_TREE; |
9981 | 9507 |
9982 fp_nan = CALL_EXPR_ARG (exp, 0); | 9508 fp_nan = CALL_EXPR_ARG (exp, 0); |
9983 fp_infinite = CALL_EXPR_ARG (exp, 1); | 9509 fp_infinite = CALL_EXPR_ARG (exp, 1); |
9984 fp_normal = CALL_EXPR_ARG (exp, 2); | 9510 fp_normal = CALL_EXPR_ARG (exp, 2); |
9985 fp_subnormal = CALL_EXPR_ARG (exp, 3); | 9511 fp_subnormal = CALL_EXPR_ARG (exp, 3); |
9986 fp_zero = CALL_EXPR_ARG (exp, 4); | 9512 fp_zero = CALL_EXPR_ARG (exp, 4); |
9987 arg = CALL_EXPR_ARG (exp, 5); | 9513 arg = CALL_EXPR_ARG (exp, 5); |
9988 type = TREE_TYPE (arg); | 9514 type = TREE_TYPE (arg); |
9989 mode = TYPE_MODE (type); | 9515 mode = TYPE_MODE (type); |
9990 arg = builtin_save_expr (fold_build1 (ABS_EXPR, type, arg)); | 9516 arg = builtin_save_expr (fold_build1_loc (loc, ABS_EXPR, type, arg)); |
9991 | 9517 |
9992 /* fpclassify(x) -> | 9518 /* fpclassify(x) -> |
9993 isnan(x) ? FP_NAN : | 9519 isnan(x) ? FP_NAN : |
9994 (fabs(x) == Inf ? FP_INFINITE : | 9520 (fabs(x) == Inf ? FP_INFINITE : |
9995 (fabs(x) >= DBL_MIN ? FP_NORMAL : | 9521 (fabs(x) >= DBL_MIN ? FP_NORMAL : |
9996 (x == 0 ? FP_ZERO : FP_SUBNORMAL))). */ | 9522 (x == 0 ? FP_ZERO : FP_SUBNORMAL))). */ |
9997 | 9523 |
9998 tmp = fold_build2 (EQ_EXPR, integer_type_node, arg, | 9524 tmp = fold_build2_loc (loc, EQ_EXPR, integer_type_node, arg, |
9999 build_real (type, dconst0)); | 9525 build_real (type, dconst0)); |
10000 res = fold_build3 (COND_EXPR, integer_type_node, tmp, fp_zero, fp_subnormal); | 9526 res = fold_build3_loc (loc, COND_EXPR, integer_type_node, |
9527 tmp, fp_zero, fp_subnormal); | |
10001 | 9528 |
10002 sprintf (buf, "0x1p%d", REAL_MODE_FORMAT (mode)->emin - 1); | 9529 sprintf (buf, "0x1p%d", REAL_MODE_FORMAT (mode)->emin - 1); |
10003 real_from_string (&r, buf); | 9530 real_from_string (&r, buf); |
10004 tmp = fold_build2 (GE_EXPR, integer_type_node, arg, build_real (type, r)); | 9531 tmp = fold_build2_loc (loc, GE_EXPR, integer_type_node, |
10005 res = fold_build3 (COND_EXPR, integer_type_node, tmp, fp_normal, res); | 9532 arg, build_real (type, r)); |
10006 | 9533 res = fold_build3_loc (loc, COND_EXPR, integer_type_node, tmp, fp_normal, res); |
9534 | |
10007 if (HONOR_INFINITIES (mode)) | 9535 if (HONOR_INFINITIES (mode)) |
10008 { | 9536 { |
10009 real_inf (&r); | 9537 real_inf (&r); |
10010 tmp = fold_build2 (EQ_EXPR, integer_type_node, arg, | 9538 tmp = fold_build2_loc (loc, EQ_EXPR, integer_type_node, arg, |
10011 build_real (type, r)); | 9539 build_real (type, r)); |
10012 res = fold_build3 (COND_EXPR, integer_type_node, tmp, fp_infinite, res); | 9540 res = fold_build3_loc (loc, COND_EXPR, integer_type_node, tmp, |
9541 fp_infinite, res); | |
10013 } | 9542 } |
10014 | 9543 |
10015 if (HONOR_NANS (mode)) | 9544 if (HONOR_NANS (mode)) |
10016 { | 9545 { |
10017 tmp = fold_build2 (ORDERED_EXPR, integer_type_node, arg, arg); | 9546 tmp = fold_build2_loc (loc, ORDERED_EXPR, integer_type_node, arg, arg); |
10018 res = fold_build3 (COND_EXPR, integer_type_node, tmp, res, fp_nan); | 9547 res = fold_build3_loc (loc, COND_EXPR, integer_type_node, tmp, res, fp_nan); |
10019 } | 9548 } |
10020 | 9549 |
10021 return res; | 9550 return res; |
10022 } | 9551 } |
10023 | 9552 |
10024 /* Fold a call to an unordered comparison function such as | 9553 /* Fold a call to an unordered comparison function such as |
10025 __builtin_isgreater(). FNDECL is the FUNCTION_DECL for the function | 9554 __builtin_isgreater(). FNDECL is the FUNCTION_DECL for the function |
10028 the opposite of the desired result. UNORDERED_CODE is used | 9557 the opposite of the desired result. UNORDERED_CODE is used |
10029 for modes that can hold NaNs and ORDERED_CODE is used for | 9558 for modes that can hold NaNs and ORDERED_CODE is used for |
10030 the rest. */ | 9559 the rest. */ |
10031 | 9560 |
10032 static tree | 9561 static tree |
10033 fold_builtin_unordered_cmp (tree fndecl, tree arg0, tree arg1, | 9562 fold_builtin_unordered_cmp (location_t loc, tree fndecl, tree arg0, tree arg1, |
10034 enum tree_code unordered_code, | 9563 enum tree_code unordered_code, |
10035 enum tree_code ordered_code) | 9564 enum tree_code ordered_code) |
10036 { | 9565 { |
10037 tree type = TREE_TYPE (TREE_TYPE (fndecl)); | 9566 tree type = TREE_TYPE (TREE_TYPE (fndecl)); |
10038 enum tree_code code; | 9567 enum tree_code code; |
10053 else if (code0 == REAL_TYPE && code1 == INTEGER_TYPE) | 9582 else if (code0 == REAL_TYPE && code1 == INTEGER_TYPE) |
10054 cmp_type = type0; | 9583 cmp_type = type0; |
10055 else if (code0 == INTEGER_TYPE && code1 == REAL_TYPE) | 9584 else if (code0 == INTEGER_TYPE && code1 == REAL_TYPE) |
10056 cmp_type = type1; | 9585 cmp_type = type1; |
10057 | 9586 |
10058 arg0 = fold_convert (cmp_type, arg0); | 9587 arg0 = fold_convert_loc (loc, cmp_type, arg0); |
10059 arg1 = fold_convert (cmp_type, arg1); | 9588 arg1 = fold_convert_loc (loc, cmp_type, arg1); |
10060 | 9589 |
10061 if (unordered_code == UNORDERED_EXPR) | 9590 if (unordered_code == UNORDERED_EXPR) |
10062 { | 9591 { |
10063 if (!HONOR_NANS (TYPE_MODE (TREE_TYPE (arg0)))) | 9592 if (!HONOR_NANS (TYPE_MODE (TREE_TYPE (arg0)))) |
10064 return omit_two_operands (type, integer_zero_node, arg0, arg1); | 9593 return omit_two_operands_loc (loc, type, integer_zero_node, arg0, arg1); |
10065 return fold_build2 (UNORDERED_EXPR, type, arg0, arg1); | 9594 return fold_build2_loc (loc, UNORDERED_EXPR, type, arg0, arg1); |
10066 } | 9595 } |
10067 | 9596 |
10068 code = HONOR_NANS (TYPE_MODE (TREE_TYPE (arg0))) ? unordered_code | 9597 code = HONOR_NANS (TYPE_MODE (TREE_TYPE (arg0))) ? unordered_code |
10069 : ordered_code; | 9598 : ordered_code; |
10070 return fold_build1 (TRUTH_NOT_EXPR, type, | 9599 return fold_build1_loc (loc, TRUTH_NOT_EXPR, type, |
10071 fold_build2 (code, type, arg0, arg1)); | 9600 fold_build2_loc (loc, code, type, arg0, arg1)); |
10072 } | 9601 } |
10073 | 9602 |
10074 /* Fold a call to built-in function FNDECL with 0 arguments. | 9603 /* Fold a call to built-in function FNDECL with 0 arguments. |
10075 IGNORE is true if the result of the function call is ignored. This | 9604 IGNORE is true if the result of the function call is ignored. This |
10076 function returns NULL_TREE if no simplification was possible. */ | 9605 function returns NULL_TREE if no simplification was possible. */ |
10077 | 9606 |
10078 static tree | 9607 static tree |
10079 fold_builtin_0 (tree fndecl, bool ignore ATTRIBUTE_UNUSED) | 9608 fold_builtin_0 (location_t loc, tree fndecl, bool ignore ATTRIBUTE_UNUSED) |
10080 { | 9609 { |
10081 tree type = TREE_TYPE (TREE_TYPE (fndecl)); | 9610 tree type = TREE_TYPE (TREE_TYPE (fndecl)); |
10082 enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl); | 9611 enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl); |
10083 switch (fcode) | 9612 switch (fcode) |
10084 { | 9613 { |
10085 CASE_FLT_FN (BUILT_IN_INF): | 9614 CASE_FLT_FN (BUILT_IN_INF): |
10086 case BUILT_IN_INFD32: | 9615 case BUILT_IN_INFD32: |
10087 case BUILT_IN_INFD64: | 9616 case BUILT_IN_INFD64: |
10088 case BUILT_IN_INFD128: | 9617 case BUILT_IN_INFD128: |
10089 return fold_builtin_inf (type, true); | 9618 return fold_builtin_inf (loc, type, true); |
10090 | 9619 |
10091 CASE_FLT_FN (BUILT_IN_HUGE_VAL): | 9620 CASE_FLT_FN (BUILT_IN_HUGE_VAL): |
10092 return fold_builtin_inf (type, false); | 9621 return fold_builtin_inf (loc, type, false); |
10093 | 9622 |
10094 case BUILT_IN_CLASSIFY_TYPE: | 9623 case BUILT_IN_CLASSIFY_TYPE: |
10095 return fold_builtin_classify_type (NULL_TREE); | 9624 return fold_builtin_classify_type (NULL_TREE); |
10096 | 9625 |
10097 default: | 9626 default: |
10103 /* Fold a call to built-in function FNDECL with 1 argument, ARG0. | 9632 /* Fold a call to built-in function FNDECL with 1 argument, ARG0. |
10104 IGNORE is true if the result of the function call is ignored. This | 9633 IGNORE is true if the result of the function call is ignored. This |
10105 function returns NULL_TREE if no simplification was possible. */ | 9634 function returns NULL_TREE if no simplification was possible. */ |
10106 | 9635 |
10107 static tree | 9636 static tree |
10108 fold_builtin_1 (tree fndecl, tree arg0, bool ignore) | 9637 fold_builtin_1 (location_t loc, tree fndecl, tree arg0, bool ignore) |
10109 { | 9638 { |
10110 tree type = TREE_TYPE (TREE_TYPE (fndecl)); | 9639 tree type = TREE_TYPE (TREE_TYPE (fndecl)); |
10111 enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl); | 9640 enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl); |
10112 switch (fcode) | 9641 switch (fcode) |
10113 { | 9642 { |
10127 | 9656 |
10128 case BUILT_IN_CLASSIFY_TYPE: | 9657 case BUILT_IN_CLASSIFY_TYPE: |
10129 return fold_builtin_classify_type (arg0); | 9658 return fold_builtin_classify_type (arg0); |
10130 | 9659 |
10131 case BUILT_IN_STRLEN: | 9660 case BUILT_IN_STRLEN: |
10132 return fold_builtin_strlen (type, arg0); | 9661 return fold_builtin_strlen (loc, arg0); |
10133 | 9662 |
10134 CASE_FLT_FN (BUILT_IN_FABS): | 9663 CASE_FLT_FN (BUILT_IN_FABS): |
10135 return fold_builtin_fabs (arg0, type); | 9664 return fold_builtin_fabs (loc, arg0, type); |
10136 | 9665 |
10137 case BUILT_IN_ABS: | 9666 case BUILT_IN_ABS: |
10138 case BUILT_IN_LABS: | 9667 case BUILT_IN_LABS: |
10139 case BUILT_IN_LLABS: | 9668 case BUILT_IN_LLABS: |
10140 case BUILT_IN_IMAXABS: | 9669 case BUILT_IN_IMAXABS: |
10141 return fold_builtin_abs (arg0, type); | 9670 return fold_builtin_abs (loc, arg0, type); |
10142 | 9671 |
10143 CASE_FLT_FN (BUILT_IN_CONJ): | 9672 CASE_FLT_FN (BUILT_IN_CONJ): |
10144 if (validate_arg (arg0, COMPLEX_TYPE)) | 9673 if (validate_arg (arg0, COMPLEX_TYPE) |
10145 return fold_build1 (CONJ_EXPR, type, arg0); | 9674 && TREE_CODE (TREE_TYPE (TREE_TYPE (arg0))) == REAL_TYPE) |
9675 return fold_build1_loc (loc, CONJ_EXPR, type, arg0); | |
10146 break; | 9676 break; |
10147 | 9677 |
10148 CASE_FLT_FN (BUILT_IN_CREAL): | 9678 CASE_FLT_FN (BUILT_IN_CREAL): |
10149 if (validate_arg (arg0, COMPLEX_TYPE)) | 9679 if (validate_arg (arg0, COMPLEX_TYPE) |
10150 return non_lvalue (fold_build1 (REALPART_EXPR, type, arg0));; | 9680 && TREE_CODE (TREE_TYPE (TREE_TYPE (arg0))) == REAL_TYPE) |
9681 return non_lvalue_loc (loc, fold_build1_loc (loc, REALPART_EXPR, type, arg0));; | |
10151 break; | 9682 break; |
10152 | 9683 |
10153 CASE_FLT_FN (BUILT_IN_CIMAG): | 9684 CASE_FLT_FN (BUILT_IN_CIMAG): |
10154 if (validate_arg (arg0, COMPLEX_TYPE)) | 9685 if (validate_arg (arg0, COMPLEX_TYPE) |
10155 return non_lvalue (fold_build1 (IMAGPART_EXPR, type, arg0)); | 9686 && TREE_CODE (TREE_TYPE (TREE_TYPE (arg0))) == REAL_TYPE) |
9687 return non_lvalue_loc (loc, fold_build1_loc (loc, IMAGPART_EXPR, type, arg0)); | |
10156 break; | 9688 break; |
10157 | 9689 |
10158 CASE_FLT_FN (BUILT_IN_CCOS): | 9690 CASE_FLT_FN (BUILT_IN_CCOS): |
9691 return fold_builtin_ccos(loc, arg0, type, fndecl, /*hyper=*/ false); | |
9692 | |
10159 CASE_FLT_FN (BUILT_IN_CCOSH): | 9693 CASE_FLT_FN (BUILT_IN_CCOSH): |
10160 /* These functions are "even", i.e. f(x) == f(-x). */ | 9694 return fold_builtin_ccos(loc, arg0, type, fndecl, /*hyper=*/ true); |
10161 if (validate_arg (arg0, COMPLEX_TYPE)) | 9695 |
10162 { | 9696 CASE_FLT_FN (BUILT_IN_CSIN): |
10163 tree narg = fold_strip_sign_ops (arg0); | 9697 if (validate_arg (arg0, COMPLEX_TYPE) |
10164 if (narg) | 9698 && TREE_CODE (TREE_TYPE (TREE_TYPE (arg0))) == REAL_TYPE) |
10165 return build_call_expr (fndecl, 1, narg); | 9699 return do_mpc_arg1 (arg0, type, mpc_sin); |
10166 } | |
10167 break; | 9700 break; |
10168 | 9701 |
9702 CASE_FLT_FN (BUILT_IN_CSINH): | |
9703 if (validate_arg (arg0, COMPLEX_TYPE) | |
9704 && TREE_CODE (TREE_TYPE (TREE_TYPE (arg0))) == REAL_TYPE) | |
9705 return do_mpc_arg1 (arg0, type, mpc_sinh); | |
9706 break; | |
9707 | |
9708 CASE_FLT_FN (BUILT_IN_CTAN): | |
9709 if (validate_arg (arg0, COMPLEX_TYPE) | |
9710 && TREE_CODE (TREE_TYPE (TREE_TYPE (arg0))) == REAL_TYPE) | |
9711 return do_mpc_arg1 (arg0, type, mpc_tan); | |
9712 break; | |
9713 | |
9714 CASE_FLT_FN (BUILT_IN_CTANH): | |
9715 if (validate_arg (arg0, COMPLEX_TYPE) | |
9716 && TREE_CODE (TREE_TYPE (TREE_TYPE (arg0))) == REAL_TYPE) | |
9717 return do_mpc_arg1 (arg0, type, mpc_tanh); | |
9718 break; | |
9719 | |
9720 CASE_FLT_FN (BUILT_IN_CLOG): | |
9721 if (validate_arg (arg0, COMPLEX_TYPE) | |
9722 && TREE_CODE (TREE_TYPE (TREE_TYPE (arg0))) == REAL_TYPE) | |
9723 return do_mpc_arg1 (arg0, type, mpc_log); | |
9724 break; | |
9725 | |
9726 CASE_FLT_FN (BUILT_IN_CSQRT): | |
9727 if (validate_arg (arg0, COMPLEX_TYPE) | |
9728 && TREE_CODE (TREE_TYPE (TREE_TYPE (arg0))) == REAL_TYPE) | |
9729 return do_mpc_arg1 (arg0, type, mpc_sqrt); | |
9730 break; | |
9731 | |
9732 CASE_FLT_FN (BUILT_IN_CASIN): | |
9733 if (validate_arg (arg0, COMPLEX_TYPE) | |
9734 && TREE_CODE (TREE_TYPE (TREE_TYPE (arg0))) == REAL_TYPE) | |
9735 return do_mpc_arg1 (arg0, type, mpc_asin); | |
9736 break; | |
9737 | |
9738 CASE_FLT_FN (BUILT_IN_CACOS): | |
9739 if (validate_arg (arg0, COMPLEX_TYPE) | |
9740 && TREE_CODE (TREE_TYPE (TREE_TYPE (arg0))) == REAL_TYPE) | |
9741 return do_mpc_arg1 (arg0, type, mpc_acos); | |
9742 break; | |
9743 | |
9744 CASE_FLT_FN (BUILT_IN_CATAN): | |
9745 if (validate_arg (arg0, COMPLEX_TYPE) | |
9746 && TREE_CODE (TREE_TYPE (TREE_TYPE (arg0))) == REAL_TYPE) | |
9747 return do_mpc_arg1 (arg0, type, mpc_atan); | |
9748 break; | |
9749 | |
9750 CASE_FLT_FN (BUILT_IN_CASINH): | |
9751 if (validate_arg (arg0, COMPLEX_TYPE) | |
9752 && TREE_CODE (TREE_TYPE (TREE_TYPE (arg0))) == REAL_TYPE) | |
9753 return do_mpc_arg1 (arg0, type, mpc_asinh); | |
9754 break; | |
9755 | |
9756 CASE_FLT_FN (BUILT_IN_CACOSH): | |
9757 if (validate_arg (arg0, COMPLEX_TYPE) | |
9758 && TREE_CODE (TREE_TYPE (TREE_TYPE (arg0))) == REAL_TYPE) | |
9759 return do_mpc_arg1 (arg0, type, mpc_acosh); | |
9760 break; | |
9761 | |
9762 CASE_FLT_FN (BUILT_IN_CATANH): | |
9763 if (validate_arg (arg0, COMPLEX_TYPE) | |
9764 && TREE_CODE (TREE_TYPE (TREE_TYPE (arg0))) == REAL_TYPE) | |
9765 return do_mpc_arg1 (arg0, type, mpc_atanh); | |
9766 break; | |
9767 | |
10169 CASE_FLT_FN (BUILT_IN_CABS): | 9768 CASE_FLT_FN (BUILT_IN_CABS): |
10170 return fold_builtin_cabs (arg0, type, fndecl); | 9769 return fold_builtin_cabs (loc, arg0, type, fndecl); |
10171 | 9770 |
10172 CASE_FLT_FN (BUILT_IN_CARG): | 9771 CASE_FLT_FN (BUILT_IN_CARG): |
10173 return fold_builtin_carg (arg0, type); | 9772 return fold_builtin_carg (loc, arg0, type); |
10174 | 9773 |
10175 CASE_FLT_FN (BUILT_IN_SQRT): | 9774 CASE_FLT_FN (BUILT_IN_SQRT): |
10176 return fold_builtin_sqrt (arg0, type); | 9775 return fold_builtin_sqrt (loc, arg0, type); |
10177 | 9776 |
10178 CASE_FLT_FN (BUILT_IN_CBRT): | 9777 CASE_FLT_FN (BUILT_IN_CBRT): |
10179 return fold_builtin_cbrt (arg0, type); | 9778 return fold_builtin_cbrt (loc, arg0, type); |
10180 | 9779 |
10181 CASE_FLT_FN (BUILT_IN_ASIN): | 9780 CASE_FLT_FN (BUILT_IN_ASIN): |
10182 if (validate_arg (arg0, REAL_TYPE)) | 9781 if (validate_arg (arg0, REAL_TYPE)) |
10183 return do_mpfr_arg1 (arg0, type, mpfr_asin, | 9782 return do_mpfr_arg1 (arg0, type, mpfr_asin, |
10184 &dconstm1, &dconst1, true); | 9783 &dconstm1, &dconst1, true); |
10216 if (validate_arg (arg0, REAL_TYPE)) | 9815 if (validate_arg (arg0, REAL_TYPE)) |
10217 return do_mpfr_arg1 (arg0, type, mpfr_sin, NULL, NULL, 0); | 9816 return do_mpfr_arg1 (arg0, type, mpfr_sin, NULL, NULL, 0); |
10218 break; | 9817 break; |
10219 | 9818 |
10220 CASE_FLT_FN (BUILT_IN_COS): | 9819 CASE_FLT_FN (BUILT_IN_COS): |
10221 return fold_builtin_cos (arg0, type, fndecl); | 9820 return fold_builtin_cos (loc, arg0, type, fndecl); |
10222 break; | |
10223 | 9821 |
10224 CASE_FLT_FN (BUILT_IN_TAN): | 9822 CASE_FLT_FN (BUILT_IN_TAN): |
10225 return fold_builtin_tan (arg0, type); | 9823 return fold_builtin_tan (arg0, type); |
10226 | 9824 |
10227 CASE_FLT_FN (BUILT_IN_CEXP): | 9825 CASE_FLT_FN (BUILT_IN_CEXP): |
10228 return fold_builtin_cexp (arg0, type); | 9826 return fold_builtin_cexp (loc, arg0, type); |
10229 | 9827 |
10230 CASE_FLT_FN (BUILT_IN_CEXPI): | 9828 CASE_FLT_FN (BUILT_IN_CEXPI): |
10231 if (validate_arg (arg0, REAL_TYPE)) | 9829 if (validate_arg (arg0, REAL_TYPE)) |
10232 return do_mpfr_sincos (arg0, NULL_TREE, NULL_TREE); | 9830 return do_mpfr_sincos (arg0, NULL_TREE, NULL_TREE); |
10233 break; | 9831 break; |
10236 if (validate_arg (arg0, REAL_TYPE)) | 9834 if (validate_arg (arg0, REAL_TYPE)) |
10237 return do_mpfr_arg1 (arg0, type, mpfr_sinh, NULL, NULL, 0); | 9835 return do_mpfr_arg1 (arg0, type, mpfr_sinh, NULL, NULL, 0); |
10238 break; | 9836 break; |
10239 | 9837 |
10240 CASE_FLT_FN (BUILT_IN_COSH): | 9838 CASE_FLT_FN (BUILT_IN_COSH): |
10241 return fold_builtin_cosh (arg0, type, fndecl); | 9839 return fold_builtin_cosh (loc, arg0, type, fndecl); |
10242 | 9840 |
10243 CASE_FLT_FN (BUILT_IN_TANH): | 9841 CASE_FLT_FN (BUILT_IN_TANH): |
10244 if (validate_arg (arg0, REAL_TYPE)) | 9842 if (validate_arg (arg0, REAL_TYPE)) |
10245 return do_mpfr_arg1 (arg0, type, mpfr_tanh, NULL, NULL, 0); | 9843 return do_mpfr_arg1 (arg0, type, mpfr_tanh, NULL, NULL, 0); |
10246 break; | 9844 break; |
10257 | 9855 |
10258 CASE_FLT_FN (BUILT_IN_TGAMMA): | 9856 CASE_FLT_FN (BUILT_IN_TGAMMA): |
10259 if (validate_arg (arg0, REAL_TYPE)) | 9857 if (validate_arg (arg0, REAL_TYPE)) |
10260 return do_mpfr_arg1 (arg0, type, mpfr_gamma, NULL, NULL, 0); | 9858 return do_mpfr_arg1 (arg0, type, mpfr_gamma, NULL, NULL, 0); |
10261 break; | 9859 break; |
10262 | 9860 |
10263 CASE_FLT_FN (BUILT_IN_EXP): | 9861 CASE_FLT_FN (BUILT_IN_EXP): |
10264 return fold_builtin_exponent (fndecl, arg0, mpfr_exp); | 9862 return fold_builtin_exponent (loc, fndecl, arg0, mpfr_exp); |
10265 | 9863 |
10266 CASE_FLT_FN (BUILT_IN_EXP2): | 9864 CASE_FLT_FN (BUILT_IN_EXP2): |
10267 return fold_builtin_exponent (fndecl, arg0, mpfr_exp2); | 9865 return fold_builtin_exponent (loc, fndecl, arg0, mpfr_exp2); |
10268 | 9866 |
10269 CASE_FLT_FN (BUILT_IN_EXP10): | 9867 CASE_FLT_FN (BUILT_IN_EXP10): |
10270 CASE_FLT_FN (BUILT_IN_POW10): | 9868 CASE_FLT_FN (BUILT_IN_POW10): |
10271 return fold_builtin_exponent (fndecl, arg0, mpfr_exp10); | 9869 return fold_builtin_exponent (loc, fndecl, arg0, mpfr_exp10); |
10272 | 9870 |
10273 CASE_FLT_FN (BUILT_IN_EXPM1): | 9871 CASE_FLT_FN (BUILT_IN_EXPM1): |
10274 if (validate_arg (arg0, REAL_TYPE)) | 9872 if (validate_arg (arg0, REAL_TYPE)) |
10275 return do_mpfr_arg1 (arg0, type, mpfr_expm1, NULL, NULL, 0); | 9873 return do_mpfr_arg1 (arg0, type, mpfr_expm1, NULL, NULL, 0); |
10276 break; | 9874 break; |
10277 | 9875 |
10278 CASE_FLT_FN (BUILT_IN_LOG): | 9876 CASE_FLT_FN (BUILT_IN_LOG): |
10279 return fold_builtin_logarithm (fndecl, arg0, mpfr_log); | 9877 return fold_builtin_logarithm (loc, fndecl, arg0, mpfr_log); |
10280 | 9878 |
10281 CASE_FLT_FN (BUILT_IN_LOG2): | 9879 CASE_FLT_FN (BUILT_IN_LOG2): |
10282 return fold_builtin_logarithm (fndecl, arg0, mpfr_log2); | 9880 return fold_builtin_logarithm (loc, fndecl, arg0, mpfr_log2); |
10283 | 9881 |
10284 CASE_FLT_FN (BUILT_IN_LOG10): | 9882 CASE_FLT_FN (BUILT_IN_LOG10): |
10285 return fold_builtin_logarithm (fndecl, arg0, mpfr_log10); | 9883 return fold_builtin_logarithm (loc, fndecl, arg0, mpfr_log10); |
10286 | 9884 |
10287 CASE_FLT_FN (BUILT_IN_LOG1P): | 9885 CASE_FLT_FN (BUILT_IN_LOG1P): |
10288 if (validate_arg (arg0, REAL_TYPE)) | 9886 if (validate_arg (arg0, REAL_TYPE)) |
10289 return do_mpfr_arg1 (arg0, type, mpfr_log1p, | 9887 return do_mpfr_arg1 (arg0, type, mpfr_log1p, |
10290 &dconstm1, NULL, false); | 9888 &dconstm1, NULL, false); |
10322 | 9920 |
10323 CASE_FLT_FN (BUILT_IN_NANS): | 9921 CASE_FLT_FN (BUILT_IN_NANS): |
10324 return fold_builtin_nan (arg0, type, false); | 9922 return fold_builtin_nan (arg0, type, false); |
10325 | 9923 |
10326 CASE_FLT_FN (BUILT_IN_FLOOR): | 9924 CASE_FLT_FN (BUILT_IN_FLOOR): |
10327 return fold_builtin_floor (fndecl, arg0); | 9925 return fold_builtin_floor (loc, fndecl, arg0); |
10328 | 9926 |
10329 CASE_FLT_FN (BUILT_IN_CEIL): | 9927 CASE_FLT_FN (BUILT_IN_CEIL): |
10330 return fold_builtin_ceil (fndecl, arg0); | 9928 return fold_builtin_ceil (loc, fndecl, arg0); |
10331 | 9929 |
10332 CASE_FLT_FN (BUILT_IN_TRUNC): | 9930 CASE_FLT_FN (BUILT_IN_TRUNC): |
10333 return fold_builtin_trunc (fndecl, arg0); | 9931 return fold_builtin_trunc (loc, fndecl, arg0); |
10334 | 9932 |
10335 CASE_FLT_FN (BUILT_IN_ROUND): | 9933 CASE_FLT_FN (BUILT_IN_ROUND): |
10336 return fold_builtin_round (fndecl, arg0); | 9934 return fold_builtin_round (loc, fndecl, arg0); |
10337 | 9935 |
10338 CASE_FLT_FN (BUILT_IN_NEARBYINT): | 9936 CASE_FLT_FN (BUILT_IN_NEARBYINT): |
10339 CASE_FLT_FN (BUILT_IN_RINT): | 9937 CASE_FLT_FN (BUILT_IN_RINT): |
10340 return fold_trunc_transparent_mathfn (fndecl, arg0); | 9938 return fold_trunc_transparent_mathfn (loc, fndecl, arg0); |
10341 | 9939 |
10342 CASE_FLT_FN (BUILT_IN_LCEIL): | 9940 CASE_FLT_FN (BUILT_IN_LCEIL): |
10343 CASE_FLT_FN (BUILT_IN_LLCEIL): | 9941 CASE_FLT_FN (BUILT_IN_LLCEIL): |
10344 CASE_FLT_FN (BUILT_IN_LFLOOR): | 9942 CASE_FLT_FN (BUILT_IN_LFLOOR): |
10345 CASE_FLT_FN (BUILT_IN_LLFLOOR): | 9943 CASE_FLT_FN (BUILT_IN_LLFLOOR): |
10346 CASE_FLT_FN (BUILT_IN_LROUND): | 9944 CASE_FLT_FN (BUILT_IN_LROUND): |
10347 CASE_FLT_FN (BUILT_IN_LLROUND): | 9945 CASE_FLT_FN (BUILT_IN_LLROUND): |
10348 return fold_builtin_int_roundingfn (fndecl, arg0); | 9946 return fold_builtin_int_roundingfn (loc, fndecl, arg0); |
10349 | 9947 |
10350 CASE_FLT_FN (BUILT_IN_LRINT): | 9948 CASE_FLT_FN (BUILT_IN_LRINT): |
10351 CASE_FLT_FN (BUILT_IN_LLRINT): | 9949 CASE_FLT_FN (BUILT_IN_LLRINT): |
10352 return fold_fixed_mathfn (fndecl, arg0); | 9950 return fold_fixed_mathfn (loc, fndecl, arg0); |
10353 | 9951 |
10354 case BUILT_IN_BSWAP32: | 9952 case BUILT_IN_BSWAP32: |
10355 case BUILT_IN_BSWAP64: | 9953 case BUILT_IN_BSWAP64: |
10356 return fold_builtin_bswap (fndecl, arg0); | 9954 return fold_builtin_bswap (fndecl, arg0); |
10357 | 9955 |
10361 CASE_INT_FN (BUILT_IN_POPCOUNT): | 9959 CASE_INT_FN (BUILT_IN_POPCOUNT): |
10362 CASE_INT_FN (BUILT_IN_PARITY): | 9960 CASE_INT_FN (BUILT_IN_PARITY): |
10363 return fold_builtin_bitop (fndecl, arg0); | 9961 return fold_builtin_bitop (fndecl, arg0); |
10364 | 9962 |
10365 CASE_FLT_FN (BUILT_IN_SIGNBIT): | 9963 CASE_FLT_FN (BUILT_IN_SIGNBIT): |
10366 return fold_builtin_signbit (arg0, type); | 9964 return fold_builtin_signbit (loc, arg0, type); |
10367 | 9965 |
10368 CASE_FLT_FN (BUILT_IN_SIGNIFICAND): | 9966 CASE_FLT_FN (BUILT_IN_SIGNIFICAND): |
10369 return fold_builtin_significand (arg0, type); | 9967 return fold_builtin_significand (loc, arg0, type); |
10370 | 9968 |
10371 CASE_FLT_FN (BUILT_IN_ILOGB): | 9969 CASE_FLT_FN (BUILT_IN_ILOGB): |
10372 CASE_FLT_FN (BUILT_IN_LOGB): | 9970 CASE_FLT_FN (BUILT_IN_LOGB): |
10373 return fold_builtin_logb (arg0, type); | 9971 return fold_builtin_logb (loc, arg0, type); |
10374 | 9972 |
10375 case BUILT_IN_ISASCII: | 9973 case BUILT_IN_ISASCII: |
10376 return fold_builtin_isascii (arg0); | 9974 return fold_builtin_isascii (loc, arg0); |
10377 | 9975 |
10378 case BUILT_IN_TOASCII: | 9976 case BUILT_IN_TOASCII: |
10379 return fold_builtin_toascii (arg0); | 9977 return fold_builtin_toascii (loc, arg0); |
10380 | 9978 |
10381 case BUILT_IN_ISDIGIT: | 9979 case BUILT_IN_ISDIGIT: |
10382 return fold_builtin_isdigit (arg0); | 9980 return fold_builtin_isdigit (loc, arg0); |
10383 | 9981 |
10384 CASE_FLT_FN (BUILT_IN_FINITE): | 9982 CASE_FLT_FN (BUILT_IN_FINITE): |
10385 case BUILT_IN_FINITED32: | 9983 case BUILT_IN_FINITED32: |
10386 case BUILT_IN_FINITED64: | 9984 case BUILT_IN_FINITED64: |
10387 case BUILT_IN_FINITED128: | 9985 case BUILT_IN_FINITED128: |
10388 case BUILT_IN_ISFINITE: | 9986 case BUILT_IN_ISFINITE: |
10389 return fold_builtin_classify (fndecl, arg0, BUILT_IN_ISFINITE); | 9987 { |
9988 tree ret = fold_builtin_classify (loc, fndecl, arg0, BUILT_IN_ISFINITE); | |
9989 if (ret) | |
9990 return ret; | |
9991 return fold_builtin_interclass_mathfn (loc, fndecl, arg0); | |
9992 } | |
10390 | 9993 |
10391 CASE_FLT_FN (BUILT_IN_ISINF): | 9994 CASE_FLT_FN (BUILT_IN_ISINF): |
10392 case BUILT_IN_ISINFD32: | 9995 case BUILT_IN_ISINFD32: |
10393 case BUILT_IN_ISINFD64: | 9996 case BUILT_IN_ISINFD64: |
10394 case BUILT_IN_ISINFD128: | 9997 case BUILT_IN_ISINFD128: |
10395 return fold_builtin_classify (fndecl, arg0, BUILT_IN_ISINF); | 9998 { |
9999 tree ret = fold_builtin_classify (loc, fndecl, arg0, BUILT_IN_ISINF); | |
10000 if (ret) | |
10001 return ret; | |
10002 return fold_builtin_interclass_mathfn (loc, fndecl, arg0); | |
10003 } | |
10004 | |
10005 case BUILT_IN_ISNORMAL: | |
10006 return fold_builtin_interclass_mathfn (loc, fndecl, arg0); | |
10396 | 10007 |
10397 case BUILT_IN_ISINF_SIGN: | 10008 case BUILT_IN_ISINF_SIGN: |
10398 return fold_builtin_classify (fndecl, arg0, BUILT_IN_ISINF_SIGN); | 10009 return fold_builtin_classify (loc, fndecl, arg0, BUILT_IN_ISINF_SIGN); |
10399 | 10010 |
10400 CASE_FLT_FN (BUILT_IN_ISNAN): | 10011 CASE_FLT_FN (BUILT_IN_ISNAN): |
10401 case BUILT_IN_ISNAND32: | 10012 case BUILT_IN_ISNAND32: |
10402 case BUILT_IN_ISNAND64: | 10013 case BUILT_IN_ISNAND64: |
10403 case BUILT_IN_ISNAND128: | 10014 case BUILT_IN_ISNAND128: |
10404 return fold_builtin_classify (fndecl, arg0, BUILT_IN_ISNAN); | 10015 return fold_builtin_classify (loc, fndecl, arg0, BUILT_IN_ISNAN); |
10405 | 10016 |
10406 case BUILT_IN_PRINTF: | 10017 case BUILT_IN_PRINTF: |
10407 case BUILT_IN_PRINTF_UNLOCKED: | 10018 case BUILT_IN_PRINTF_UNLOCKED: |
10408 case BUILT_IN_VPRINTF: | 10019 case BUILT_IN_VPRINTF: |
10409 return fold_builtin_printf (fndecl, arg0, NULL_TREE, ignore, fcode); | 10020 return fold_builtin_printf (loc, fndecl, arg0, NULL_TREE, ignore, fcode); |
10410 | 10021 |
10411 default: | 10022 default: |
10412 break; | 10023 break; |
10413 } | 10024 } |
10414 | 10025 |
10419 /* Fold a call to built-in function FNDECL with 2 arguments, ARG0 and ARG1. | 10030 /* Fold a call to built-in function FNDECL with 2 arguments, ARG0 and ARG1. |
10420 IGNORE is true if the result of the function call is ignored. This | 10031 IGNORE is true if the result of the function call is ignored. This |
10421 function returns NULL_TREE if no simplification was possible. */ | 10032 function returns NULL_TREE if no simplification was possible. */ |
10422 | 10033 |
10423 static tree | 10034 static tree |
10424 fold_builtin_2 (tree fndecl, tree arg0, tree arg1, bool ignore) | 10035 fold_builtin_2 (location_t loc, tree fndecl, tree arg0, tree arg1, bool ignore) |
10425 { | 10036 { |
10426 tree type = TREE_TYPE (TREE_TYPE (fndecl)); | 10037 tree type = TREE_TYPE (TREE_TYPE (fndecl)); |
10427 enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl); | 10038 enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl); |
10428 | 10039 |
10429 switch (fcode) | 10040 switch (fcode) |
10466 && validate_arg(arg1, REAL_TYPE)) | 10077 && validate_arg(arg1, REAL_TYPE)) |
10467 return do_mpfr_arg2 (arg0, arg1, type, mpfr_dim); | 10078 return do_mpfr_arg2 (arg0, arg1, type, mpfr_dim); |
10468 break; | 10079 break; |
10469 | 10080 |
10470 CASE_FLT_FN (BUILT_IN_HYPOT): | 10081 CASE_FLT_FN (BUILT_IN_HYPOT): |
10471 return fold_builtin_hypot (fndecl, arg0, arg1, type); | 10082 return fold_builtin_hypot (loc, fndecl, arg0, arg1, type); |
10083 | |
10084 CASE_FLT_FN (BUILT_IN_CPOW): | |
10085 if (validate_arg (arg0, COMPLEX_TYPE) | |
10086 && TREE_CODE (TREE_TYPE (TREE_TYPE (arg0))) == REAL_TYPE | |
10087 && validate_arg (arg1, COMPLEX_TYPE) | |
10088 && TREE_CODE (TREE_TYPE (TREE_TYPE (arg1))) == REAL_TYPE) | |
10089 return do_mpc_arg2 (arg0, arg1, type, /*do_nonfinite=*/ 0, mpc_pow); | |
10090 break; | |
10472 | 10091 |
10473 CASE_FLT_FN (BUILT_IN_LDEXP): | 10092 CASE_FLT_FN (BUILT_IN_LDEXP): |
10474 return fold_builtin_load_exponent (arg0, arg1, type, /*ldexp=*/true); | 10093 return fold_builtin_load_exponent (loc, arg0, arg1, type, /*ldexp=*/true); |
10475 CASE_FLT_FN (BUILT_IN_SCALBN): | 10094 CASE_FLT_FN (BUILT_IN_SCALBN): |
10476 CASE_FLT_FN (BUILT_IN_SCALBLN): | 10095 CASE_FLT_FN (BUILT_IN_SCALBLN): |
10477 return fold_builtin_load_exponent (arg0, arg1, type, /*ldexp=*/false); | 10096 return fold_builtin_load_exponent (loc, arg0, arg1, |
10097 type, /*ldexp=*/false); | |
10478 | 10098 |
10479 CASE_FLT_FN (BUILT_IN_FREXP): | 10099 CASE_FLT_FN (BUILT_IN_FREXP): |
10480 return fold_builtin_frexp (arg0, arg1, type); | 10100 return fold_builtin_frexp (loc, arg0, arg1, type); |
10481 | 10101 |
10482 CASE_FLT_FN (BUILT_IN_MODF): | 10102 CASE_FLT_FN (BUILT_IN_MODF): |
10483 return fold_builtin_modf (arg0, arg1, type); | 10103 return fold_builtin_modf (loc, arg0, arg1, type); |
10484 | 10104 |
10485 case BUILT_IN_BZERO: | 10105 case BUILT_IN_BZERO: |
10486 return fold_builtin_bzero (arg0, arg1, ignore); | 10106 return fold_builtin_bzero (loc, arg0, arg1, ignore); |
10487 | 10107 |
10488 case BUILT_IN_FPUTS: | 10108 case BUILT_IN_FPUTS: |
10489 return fold_builtin_fputs (arg0, arg1, ignore, false, NULL_TREE); | 10109 return fold_builtin_fputs (loc, arg0, arg1, ignore, false, NULL_TREE); |
10490 | 10110 |
10491 case BUILT_IN_FPUTS_UNLOCKED: | 10111 case BUILT_IN_FPUTS_UNLOCKED: |
10492 return fold_builtin_fputs (arg0, arg1, ignore, true, NULL_TREE); | 10112 return fold_builtin_fputs (loc, arg0, arg1, ignore, true, NULL_TREE); |
10493 | 10113 |
10494 case BUILT_IN_STRSTR: | 10114 case BUILT_IN_STRSTR: |
10495 return fold_builtin_strstr (arg0, arg1, type); | 10115 return fold_builtin_strstr (loc, arg0, arg1, type); |
10496 | 10116 |
10497 case BUILT_IN_STRCAT: | 10117 case BUILT_IN_STRCAT: |
10498 return fold_builtin_strcat (arg0, arg1); | 10118 return fold_builtin_strcat (loc, arg0, arg1); |
10499 | 10119 |
10500 case BUILT_IN_STRSPN: | 10120 case BUILT_IN_STRSPN: |
10501 return fold_builtin_strspn (arg0, arg1); | 10121 return fold_builtin_strspn (loc, arg0, arg1); |
10502 | 10122 |
10503 case BUILT_IN_STRCSPN: | 10123 case BUILT_IN_STRCSPN: |
10504 return fold_builtin_strcspn (arg0, arg1); | 10124 return fold_builtin_strcspn (loc, arg0, arg1); |
10505 | 10125 |
10506 case BUILT_IN_STRCHR: | 10126 case BUILT_IN_STRCHR: |
10507 case BUILT_IN_INDEX: | 10127 case BUILT_IN_INDEX: |
10508 return fold_builtin_strchr (arg0, arg1, type); | 10128 return fold_builtin_strchr (loc, arg0, arg1, type); |
10509 | 10129 |
10510 case BUILT_IN_STRRCHR: | 10130 case BUILT_IN_STRRCHR: |
10511 case BUILT_IN_RINDEX: | 10131 case BUILT_IN_RINDEX: |
10512 return fold_builtin_strrchr (arg0, arg1, type); | 10132 return fold_builtin_strrchr (loc, arg0, arg1, type); |
10513 | 10133 |
10514 case BUILT_IN_STRCPY: | 10134 case BUILT_IN_STRCPY: |
10515 return fold_builtin_strcpy (fndecl, arg0, arg1, NULL_TREE); | 10135 return fold_builtin_strcpy (loc, fndecl, arg0, arg1, NULL_TREE); |
10516 | 10136 |
10517 case BUILT_IN_STPCPY: | 10137 case BUILT_IN_STPCPY: |
10518 if (ignore) | 10138 if (ignore) |
10519 { | 10139 { |
10520 tree fn = implicit_built_in_decls[BUILT_IN_STRCPY]; | 10140 tree fn = implicit_built_in_decls[BUILT_IN_STRCPY]; |
10521 if (!fn) | 10141 if (!fn) |
10522 break; | 10142 break; |
10523 | 10143 |
10524 return build_call_expr (fn, 2, arg0, arg1); | 10144 return build_call_expr_loc (loc, fn, 2, arg0, arg1); |
10525 } | 10145 } |
10146 else | |
10147 return fold_builtin_stpcpy (loc, fndecl, arg0, arg1); | |
10526 break; | 10148 break; |
10527 | 10149 |
10528 case BUILT_IN_STRCMP: | 10150 case BUILT_IN_STRCMP: |
10529 return fold_builtin_strcmp (arg0, arg1); | 10151 return fold_builtin_strcmp (loc, arg0, arg1); |
10530 | 10152 |
10531 case BUILT_IN_STRPBRK: | 10153 case BUILT_IN_STRPBRK: |
10532 return fold_builtin_strpbrk (arg0, arg1, type); | 10154 return fold_builtin_strpbrk (loc, arg0, arg1, type); |
10533 | 10155 |
10534 case BUILT_IN_EXPECT: | 10156 case BUILT_IN_EXPECT: |
10535 return fold_builtin_expect (arg0, arg1); | 10157 return fold_builtin_expect (loc, arg0, arg1); |
10536 | 10158 |
10537 CASE_FLT_FN (BUILT_IN_POW): | 10159 CASE_FLT_FN (BUILT_IN_POW): |
10538 return fold_builtin_pow (fndecl, arg0, arg1, type); | 10160 return fold_builtin_pow (loc, fndecl, arg0, arg1, type); |
10539 | 10161 |
10540 CASE_FLT_FN (BUILT_IN_POWI): | 10162 CASE_FLT_FN (BUILT_IN_POWI): |
10541 return fold_builtin_powi (fndecl, arg0, arg1, type); | 10163 return fold_builtin_powi (loc, fndecl, arg0, arg1, type); |
10542 | 10164 |
10543 CASE_FLT_FN (BUILT_IN_COPYSIGN): | 10165 CASE_FLT_FN (BUILT_IN_COPYSIGN): |
10544 return fold_builtin_copysign (fndecl, arg0, arg1, type); | 10166 return fold_builtin_copysign (loc, fndecl, arg0, arg1, type); |
10545 | 10167 |
10546 CASE_FLT_FN (BUILT_IN_FMIN): | 10168 CASE_FLT_FN (BUILT_IN_FMIN): |
10547 return fold_builtin_fmin_fmax (arg0, arg1, type, /*max=*/false); | 10169 return fold_builtin_fmin_fmax (loc, arg0, arg1, type, /*max=*/false); |
10548 | 10170 |
10549 CASE_FLT_FN (BUILT_IN_FMAX): | 10171 CASE_FLT_FN (BUILT_IN_FMAX): |
10550 return fold_builtin_fmin_fmax (arg0, arg1, type, /*max=*/true); | 10172 return fold_builtin_fmin_fmax (loc, arg0, arg1, type, /*max=*/true); |
10551 | 10173 |
10552 case BUILT_IN_ISGREATER: | 10174 case BUILT_IN_ISGREATER: |
10553 return fold_builtin_unordered_cmp (fndecl, arg0, arg1, UNLE_EXPR, LE_EXPR); | 10175 return fold_builtin_unordered_cmp (loc, fndecl, |
10176 arg0, arg1, UNLE_EXPR, LE_EXPR); | |
10554 case BUILT_IN_ISGREATEREQUAL: | 10177 case BUILT_IN_ISGREATEREQUAL: |
10555 return fold_builtin_unordered_cmp (fndecl, arg0, arg1, UNLT_EXPR, LT_EXPR); | 10178 return fold_builtin_unordered_cmp (loc, fndecl, |
10179 arg0, arg1, UNLT_EXPR, LT_EXPR); | |
10556 case BUILT_IN_ISLESS: | 10180 case BUILT_IN_ISLESS: |
10557 return fold_builtin_unordered_cmp (fndecl, arg0, arg1, UNGE_EXPR, GE_EXPR); | 10181 return fold_builtin_unordered_cmp (loc, fndecl, |
10182 arg0, arg1, UNGE_EXPR, GE_EXPR); | |
10558 case BUILT_IN_ISLESSEQUAL: | 10183 case BUILT_IN_ISLESSEQUAL: |
10559 return fold_builtin_unordered_cmp (fndecl, arg0, arg1, UNGT_EXPR, GT_EXPR); | 10184 return fold_builtin_unordered_cmp (loc, fndecl, |
10185 arg0, arg1, UNGT_EXPR, GT_EXPR); | |
10560 case BUILT_IN_ISLESSGREATER: | 10186 case BUILT_IN_ISLESSGREATER: |
10561 return fold_builtin_unordered_cmp (fndecl, arg0, arg1, UNEQ_EXPR, EQ_EXPR); | 10187 return fold_builtin_unordered_cmp (loc, fndecl, |
10188 arg0, arg1, UNEQ_EXPR, EQ_EXPR); | |
10562 case BUILT_IN_ISUNORDERED: | 10189 case BUILT_IN_ISUNORDERED: |
10563 return fold_builtin_unordered_cmp (fndecl, arg0, arg1, UNORDERED_EXPR, | 10190 return fold_builtin_unordered_cmp (loc, fndecl, |
10191 arg0, arg1, UNORDERED_EXPR, | |
10564 NOP_EXPR); | 10192 NOP_EXPR); |
10565 | 10193 |
10566 /* We do the folding for va_start in the expander. */ | 10194 /* We do the folding for va_start in the expander. */ |
10567 case BUILT_IN_VA_START: | 10195 case BUILT_IN_VA_START: |
10568 break; | 10196 break; |
10569 | 10197 |
10570 case BUILT_IN_SPRINTF: | 10198 case BUILT_IN_SPRINTF: |
10571 return fold_builtin_sprintf (arg0, arg1, NULL_TREE, ignore); | 10199 return fold_builtin_sprintf (loc, arg0, arg1, NULL_TREE, ignore); |
10572 | 10200 |
10573 case BUILT_IN_OBJECT_SIZE: | 10201 case BUILT_IN_OBJECT_SIZE: |
10574 return fold_builtin_object_size (arg0, arg1); | 10202 return fold_builtin_object_size (arg0, arg1); |
10575 | 10203 |
10576 case BUILT_IN_PRINTF: | 10204 case BUILT_IN_PRINTF: |
10577 case BUILT_IN_PRINTF_UNLOCKED: | 10205 case BUILT_IN_PRINTF_UNLOCKED: |
10578 case BUILT_IN_VPRINTF: | 10206 case BUILT_IN_VPRINTF: |
10579 return fold_builtin_printf (fndecl, arg0, arg1, ignore, fcode); | 10207 return fold_builtin_printf (loc, fndecl, arg0, arg1, ignore, fcode); |
10580 | 10208 |
10581 case BUILT_IN_PRINTF_CHK: | 10209 case BUILT_IN_PRINTF_CHK: |
10582 case BUILT_IN_VPRINTF_CHK: | 10210 case BUILT_IN_VPRINTF_CHK: |
10583 if (!validate_arg (arg0, INTEGER_TYPE) | 10211 if (!validate_arg (arg0, INTEGER_TYPE) |
10584 || TREE_SIDE_EFFECTS (arg0)) | 10212 || TREE_SIDE_EFFECTS (arg0)) |
10585 return NULL_TREE; | 10213 return NULL_TREE; |
10586 else | 10214 else |
10587 return fold_builtin_printf (fndecl, arg1, NULL_TREE, ignore, fcode); | 10215 return fold_builtin_printf (loc, fndecl, |
10216 arg1, NULL_TREE, ignore, fcode); | |
10588 break; | 10217 break; |
10589 | 10218 |
10590 case BUILT_IN_FPRINTF: | 10219 case BUILT_IN_FPRINTF: |
10591 case BUILT_IN_FPRINTF_UNLOCKED: | 10220 case BUILT_IN_FPRINTF_UNLOCKED: |
10592 case BUILT_IN_VFPRINTF: | 10221 case BUILT_IN_VFPRINTF: |
10593 return fold_builtin_fprintf (fndecl, arg0, arg1, NULL_TREE, | 10222 return fold_builtin_fprintf (loc, fndecl, arg0, arg1, NULL_TREE, |
10594 ignore, fcode); | 10223 ignore, fcode); |
10595 | 10224 |
10596 default: | 10225 default: |
10597 break; | 10226 break; |
10598 } | 10227 } |
10602 /* Fold a call to built-in function FNDECL with 3 arguments, ARG0, ARG1, | 10231 /* Fold a call to built-in function FNDECL with 3 arguments, ARG0, ARG1, |
10603 and ARG2. IGNORE is true if the result of the function call is ignored. | 10232 and ARG2. IGNORE is true if the result of the function call is ignored. |
10604 This function returns NULL_TREE if no simplification was possible. */ | 10233 This function returns NULL_TREE if no simplification was possible. */ |
10605 | 10234 |
10606 static tree | 10235 static tree |
10607 fold_builtin_3 (tree fndecl, tree arg0, tree arg1, tree arg2, bool ignore) | 10236 fold_builtin_3 (location_t loc, tree fndecl, |
10237 tree arg0, tree arg1, tree arg2, bool ignore) | |
10608 { | 10238 { |
10609 tree type = TREE_TYPE (TREE_TYPE (fndecl)); | 10239 tree type = TREE_TYPE (TREE_TYPE (fndecl)); |
10610 enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl); | 10240 enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl); |
10611 switch (fcode) | 10241 switch (fcode) |
10612 { | 10242 { |
10613 | 10243 |
10614 CASE_FLT_FN (BUILT_IN_SINCOS): | 10244 CASE_FLT_FN (BUILT_IN_SINCOS): |
10615 return fold_builtin_sincos (arg0, arg1, arg2); | 10245 return fold_builtin_sincos (loc, arg0, arg1, arg2); |
10616 | 10246 |
10617 CASE_FLT_FN (BUILT_IN_FMA): | 10247 CASE_FLT_FN (BUILT_IN_FMA): |
10618 if (validate_arg (arg0, REAL_TYPE) | 10248 if (validate_arg (arg0, REAL_TYPE) |
10619 && validate_arg(arg1, REAL_TYPE) | 10249 && validate_arg(arg1, REAL_TYPE) |
10620 && validate_arg(arg2, REAL_TYPE)) | 10250 && validate_arg(arg2, REAL_TYPE)) |
10627 && validate_arg(arg2, POINTER_TYPE)) | 10257 && validate_arg(arg2, POINTER_TYPE)) |
10628 return do_mpfr_remquo (arg0, arg1, arg2); | 10258 return do_mpfr_remquo (arg0, arg1, arg2); |
10629 break; | 10259 break; |
10630 | 10260 |
10631 case BUILT_IN_MEMSET: | 10261 case BUILT_IN_MEMSET: |
10632 return fold_builtin_memset (arg0, arg1, arg2, type, ignore); | 10262 return fold_builtin_memset (loc, arg0, arg1, arg2, type, ignore); |
10633 | 10263 |
10634 case BUILT_IN_BCOPY: | 10264 case BUILT_IN_BCOPY: |
10635 return fold_builtin_memory_op (arg1, arg0, arg2, void_type_node, true, /*endp=*/3); | 10265 return fold_builtin_memory_op (loc, arg1, arg0, arg2, |
10266 void_type_node, true, /*endp=*/3); | |
10636 | 10267 |
10637 case BUILT_IN_MEMCPY: | 10268 case BUILT_IN_MEMCPY: |
10638 return fold_builtin_memory_op (arg0, arg1, arg2, type, ignore, /*endp=*/0); | 10269 return fold_builtin_memory_op (loc, arg0, arg1, arg2, |
10270 type, ignore, /*endp=*/0); | |
10639 | 10271 |
10640 case BUILT_IN_MEMPCPY: | 10272 case BUILT_IN_MEMPCPY: |
10641 return fold_builtin_memory_op (arg0, arg1, arg2, type, ignore, /*endp=*/1); | 10273 return fold_builtin_memory_op (loc, arg0, arg1, arg2, |
10274 type, ignore, /*endp=*/1); | |
10642 | 10275 |
10643 case BUILT_IN_MEMMOVE: | 10276 case BUILT_IN_MEMMOVE: |
10644 return fold_builtin_memory_op (arg0, arg1, arg2, type, ignore, /*endp=*/3); | 10277 return fold_builtin_memory_op (loc, arg0, arg1, arg2, |
10278 type, ignore, /*endp=*/3); | |
10645 | 10279 |
10646 case BUILT_IN_STRNCAT: | 10280 case BUILT_IN_STRNCAT: |
10647 return fold_builtin_strncat (arg0, arg1, arg2); | 10281 return fold_builtin_strncat (loc, arg0, arg1, arg2); |
10648 | 10282 |
10649 case BUILT_IN_STRNCPY: | 10283 case BUILT_IN_STRNCPY: |
10650 return fold_builtin_strncpy (fndecl, arg0, arg1, arg2, NULL_TREE); | 10284 return fold_builtin_strncpy (loc, fndecl, arg0, arg1, arg2, NULL_TREE); |
10651 | 10285 |
10652 case BUILT_IN_STRNCMP: | 10286 case BUILT_IN_STRNCMP: |
10653 return fold_builtin_strncmp (arg0, arg1, arg2); | 10287 return fold_builtin_strncmp (loc, arg0, arg1, arg2); |
10654 | 10288 |
10655 case BUILT_IN_MEMCHR: | 10289 case BUILT_IN_MEMCHR: |
10656 return fold_builtin_memchr (arg0, arg1, arg2, type); | 10290 return fold_builtin_memchr (loc, arg0, arg1, arg2, type); |
10657 | 10291 |
10658 case BUILT_IN_BCMP: | 10292 case BUILT_IN_BCMP: |
10659 case BUILT_IN_MEMCMP: | 10293 case BUILT_IN_MEMCMP: |
10660 return fold_builtin_memcmp (arg0, arg1, arg2);; | 10294 return fold_builtin_memcmp (loc, arg0, arg1, arg2);; |
10661 | 10295 |
10662 case BUILT_IN_SPRINTF: | 10296 case BUILT_IN_SPRINTF: |
10663 return fold_builtin_sprintf (arg0, arg1, arg2, ignore); | 10297 return fold_builtin_sprintf (loc, arg0, arg1, arg2, ignore); |
10664 | 10298 |
10665 case BUILT_IN_STRCPY_CHK: | 10299 case BUILT_IN_STRCPY_CHK: |
10666 case BUILT_IN_STPCPY_CHK: | 10300 case BUILT_IN_STPCPY_CHK: |
10667 return fold_builtin_stxcpy_chk (fndecl, arg0, arg1, arg2, NULL_TREE, | 10301 return fold_builtin_stxcpy_chk (loc, fndecl, arg0, arg1, arg2, NULL_TREE, |
10668 ignore, fcode); | 10302 ignore, fcode); |
10669 | 10303 |
10670 case BUILT_IN_STRCAT_CHK: | 10304 case BUILT_IN_STRCAT_CHK: |
10671 return fold_builtin_strcat_chk (fndecl, arg0, arg1, arg2); | 10305 return fold_builtin_strcat_chk (loc, fndecl, arg0, arg1, arg2); |
10672 | 10306 |
10673 case BUILT_IN_PRINTF_CHK: | 10307 case BUILT_IN_PRINTF_CHK: |
10674 case BUILT_IN_VPRINTF_CHK: | 10308 case BUILT_IN_VPRINTF_CHK: |
10675 if (!validate_arg (arg0, INTEGER_TYPE) | 10309 if (!validate_arg (arg0, INTEGER_TYPE) |
10676 || TREE_SIDE_EFFECTS (arg0)) | 10310 || TREE_SIDE_EFFECTS (arg0)) |
10677 return NULL_TREE; | 10311 return NULL_TREE; |
10678 else | 10312 else |
10679 return fold_builtin_printf (fndecl, arg1, arg2, ignore, fcode); | 10313 return fold_builtin_printf (loc, fndecl, arg1, arg2, ignore, fcode); |
10680 break; | 10314 break; |
10681 | 10315 |
10682 case BUILT_IN_FPRINTF: | 10316 case BUILT_IN_FPRINTF: |
10683 case BUILT_IN_FPRINTF_UNLOCKED: | 10317 case BUILT_IN_FPRINTF_UNLOCKED: |
10684 case BUILT_IN_VFPRINTF: | 10318 case BUILT_IN_VFPRINTF: |
10685 return fold_builtin_fprintf (fndecl, arg0, arg1, arg2, ignore, fcode); | 10319 return fold_builtin_fprintf (loc, fndecl, arg0, arg1, arg2, |
10320 ignore, fcode); | |
10686 | 10321 |
10687 case BUILT_IN_FPRINTF_CHK: | 10322 case BUILT_IN_FPRINTF_CHK: |
10688 case BUILT_IN_VFPRINTF_CHK: | 10323 case BUILT_IN_VFPRINTF_CHK: |
10689 if (!validate_arg (arg1, INTEGER_TYPE) | 10324 if (!validate_arg (arg1, INTEGER_TYPE) |
10690 || TREE_SIDE_EFFECTS (arg1)) | 10325 || TREE_SIDE_EFFECTS (arg1)) |
10691 return NULL_TREE; | 10326 return NULL_TREE; |
10692 else | 10327 else |
10693 return fold_builtin_fprintf (fndecl, arg0, arg2, NULL_TREE, | 10328 return fold_builtin_fprintf (loc, fndecl, arg0, arg2, NULL_TREE, |
10694 ignore, fcode); | 10329 ignore, fcode); |
10695 | 10330 |
10696 default: | 10331 default: |
10697 break; | 10332 break; |
10698 } | 10333 } |
10701 | 10336 |
10702 /* Fold a call to built-in function FNDECL with 4 arguments, ARG0, ARG1, | 10337 /* Fold a call to built-in function FNDECL with 4 arguments, ARG0, ARG1, |
10703 ARG2, and ARG3. IGNORE is true if the result of the function call is | 10338 ARG2, and ARG3. IGNORE is true if the result of the function call is |
10704 ignored. This function returns NULL_TREE if no simplification was | 10339 ignored. This function returns NULL_TREE if no simplification was |
10705 possible. */ | 10340 possible. */ |
10706 | 10341 |
10707 static tree | 10342 static tree |
10708 fold_builtin_4 (tree fndecl, tree arg0, tree arg1, tree arg2, tree arg3, | 10343 fold_builtin_4 (location_t loc, tree fndecl, |
10709 bool ignore) | 10344 tree arg0, tree arg1, tree arg2, tree arg3, bool ignore) |
10710 { | 10345 { |
10711 enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl); | 10346 enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl); |
10712 | 10347 |
10713 switch (fcode) | 10348 switch (fcode) |
10714 { | 10349 { |
10715 case BUILT_IN_MEMCPY_CHK: | 10350 case BUILT_IN_MEMCPY_CHK: |
10716 case BUILT_IN_MEMPCPY_CHK: | 10351 case BUILT_IN_MEMPCPY_CHK: |
10717 case BUILT_IN_MEMMOVE_CHK: | 10352 case BUILT_IN_MEMMOVE_CHK: |
10718 case BUILT_IN_MEMSET_CHK: | 10353 case BUILT_IN_MEMSET_CHK: |
10719 return fold_builtin_memory_chk (fndecl, arg0, arg1, arg2, arg3, | 10354 return fold_builtin_memory_chk (loc, fndecl, arg0, arg1, arg2, arg3, |
10720 NULL_TREE, ignore, | 10355 NULL_TREE, ignore, |
10721 DECL_FUNCTION_CODE (fndecl)); | 10356 DECL_FUNCTION_CODE (fndecl)); |
10722 | 10357 |
10723 case BUILT_IN_STRNCPY_CHK: | 10358 case BUILT_IN_STRNCPY_CHK: |
10724 return fold_builtin_strncpy_chk (arg0, arg1, arg2, arg3, NULL_TREE); | 10359 return fold_builtin_strncpy_chk (loc, arg0, arg1, arg2, arg3, NULL_TREE); |
10725 | 10360 |
10726 case BUILT_IN_STRNCAT_CHK: | 10361 case BUILT_IN_STRNCAT_CHK: |
10727 return fold_builtin_strncat_chk (fndecl, arg0, arg1, arg2, arg3); | 10362 return fold_builtin_strncat_chk (loc, fndecl, arg0, arg1, arg2, arg3); |
10728 | 10363 |
10729 case BUILT_IN_FPRINTF_CHK: | 10364 case BUILT_IN_FPRINTF_CHK: |
10730 case BUILT_IN_VFPRINTF_CHK: | 10365 case BUILT_IN_VFPRINTF_CHK: |
10731 if (!validate_arg (arg1, INTEGER_TYPE) | 10366 if (!validate_arg (arg1, INTEGER_TYPE) |
10732 || TREE_SIDE_EFFECTS (arg1)) | 10367 || TREE_SIDE_EFFECTS (arg1)) |
10733 return NULL_TREE; | 10368 return NULL_TREE; |
10734 else | 10369 else |
10735 return fold_builtin_fprintf (fndecl, arg0, arg2, arg3, | 10370 return fold_builtin_fprintf (loc, fndecl, arg0, arg2, arg3, |
10736 ignore, fcode); | 10371 ignore, fcode); |
10737 break; | 10372 break; |
10738 | 10373 |
10739 default: | 10374 default: |
10740 break; | 10375 break; |
10747 function call is ignored. This function returns NULL_TREE if no | 10382 function call is ignored. This function returns NULL_TREE if no |
10748 simplification was possible. Note that this only folds builtins with | 10383 simplification was possible. Note that this only folds builtins with |
10749 fixed argument patterns. Foldings that do varargs-to-varargs | 10384 fixed argument patterns. Foldings that do varargs-to-varargs |
10750 transformations, or that match calls with more than 4 arguments, | 10385 transformations, or that match calls with more than 4 arguments, |
10751 need to be handled with fold_builtin_varargs instead. */ | 10386 need to be handled with fold_builtin_varargs instead. */ |
10752 | 10387 |
10753 #define MAX_ARGS_TO_FOLD_BUILTIN 4 | 10388 #define MAX_ARGS_TO_FOLD_BUILTIN 4 |
10754 | 10389 |
10755 static tree | 10390 static tree |
10756 fold_builtin_n (tree fndecl, tree *args, int nargs, bool ignore) | 10391 fold_builtin_n (location_t loc, tree fndecl, tree *args, int nargs, bool ignore) |
10757 { | 10392 { |
10758 tree ret = NULL_TREE; | 10393 tree ret = NULL_TREE; |
10759 | 10394 |
10760 switch (nargs) | 10395 switch (nargs) |
10761 { | 10396 { |
10762 case 0: | 10397 case 0: |
10763 ret = fold_builtin_0 (fndecl, ignore); | 10398 ret = fold_builtin_0 (loc, fndecl, ignore); |
10764 break; | 10399 break; |
10765 case 1: | 10400 case 1: |
10766 ret = fold_builtin_1 (fndecl, args[0], ignore); | 10401 ret = fold_builtin_1 (loc, fndecl, args[0], ignore); |
10767 break; | 10402 break; |
10768 case 2: | 10403 case 2: |
10769 ret = fold_builtin_2 (fndecl, args[0], args[1], ignore); | 10404 ret = fold_builtin_2 (loc, fndecl, args[0], args[1], ignore); |
10770 break; | 10405 break; |
10771 case 3: | 10406 case 3: |
10772 ret = fold_builtin_3 (fndecl, args[0], args[1], args[2], ignore); | 10407 ret = fold_builtin_3 (loc, fndecl, args[0], args[1], args[2], ignore); |
10773 break; | 10408 break; |
10774 case 4: | 10409 case 4: |
10775 ret = fold_builtin_4 (fndecl, args[0], args[1], args[2], args[3], | 10410 ret = fold_builtin_4 (loc, fndecl, args[0], args[1], args[2], args[3], |
10776 ignore); | 10411 ignore); |
10777 break; | 10412 break; |
10778 default: | 10413 default: |
10779 break; | 10414 break; |
10780 } | 10415 } |
10781 if (ret) | 10416 if (ret) |
10782 { | 10417 { |
10783 ret = build1 (NOP_EXPR, TREE_TYPE (ret), ret); | 10418 ret = build1 (NOP_EXPR, TREE_TYPE (ret), ret); |
10419 SET_EXPR_LOCATION (ret, loc); | |
10784 TREE_NO_WARNING (ret) = 1; | 10420 TREE_NO_WARNING (ret) = 1; |
10785 return ret; | 10421 return ret; |
10786 } | 10422 } |
10787 return NULL_TREE; | 10423 return NULL_TREE; |
10788 } | 10424 } |
10793 only a few builtins that fall into this category. FNDECL is the | 10429 only a few builtins that fall into this category. FNDECL is the |
10794 function, EXP is the CALL_EXPR for the call, and IGNORE is true if the | 10430 function, EXP is the CALL_EXPR for the call, and IGNORE is true if the |
10795 result of the function call is ignored. */ | 10431 result of the function call is ignored. */ |
10796 | 10432 |
10797 static tree | 10433 static tree |
10798 fold_builtin_varargs (tree fndecl, tree exp, bool ignore ATTRIBUTE_UNUSED) | 10434 fold_builtin_varargs (location_t loc, tree fndecl, tree exp, |
10435 bool ignore ATTRIBUTE_UNUSED) | |
10799 { | 10436 { |
10800 enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl); | 10437 enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl); |
10801 tree ret = NULL_TREE; | 10438 tree ret = NULL_TREE; |
10802 | 10439 |
10803 switch (fcode) | 10440 switch (fcode) |
10804 { | 10441 { |
10805 case BUILT_IN_SPRINTF_CHK: | 10442 case BUILT_IN_SPRINTF_CHK: |
10806 case BUILT_IN_VSPRINTF_CHK: | 10443 case BUILT_IN_VSPRINTF_CHK: |
10807 ret = fold_builtin_sprintf_chk (exp, fcode); | 10444 ret = fold_builtin_sprintf_chk (loc, exp, fcode); |
10808 break; | 10445 break; |
10809 | 10446 |
10810 case BUILT_IN_SNPRINTF_CHK: | 10447 case BUILT_IN_SNPRINTF_CHK: |
10811 case BUILT_IN_VSNPRINTF_CHK: | 10448 case BUILT_IN_VSNPRINTF_CHK: |
10812 ret = fold_builtin_snprintf_chk (exp, NULL_TREE, fcode); | 10449 ret = fold_builtin_snprintf_chk (loc, exp, NULL_TREE, fcode); |
10813 break; | 10450 break; |
10814 | 10451 |
10815 case BUILT_IN_FPCLASSIFY: | 10452 case BUILT_IN_FPCLASSIFY: |
10816 ret = fold_builtin_fpclassify (exp); | 10453 ret = fold_builtin_fpclassify (loc, exp); |
10817 break; | 10454 break; |
10818 | 10455 |
10819 default: | 10456 default: |
10820 break; | 10457 break; |
10821 } | 10458 } |
10822 if (ret) | 10459 if (ret) |
10823 { | 10460 { |
10824 ret = build1 (NOP_EXPR, TREE_TYPE (ret), ret); | 10461 ret = build1 (NOP_EXPR, TREE_TYPE (ret), ret); |
10462 SET_EXPR_LOCATION (ret, loc); | |
10825 TREE_NO_WARNING (ret) = 1; | 10463 TREE_NO_WARNING (ret) = 1; |
10826 return ret; | 10464 return ret; |
10827 } | 10465 } |
10828 return NULL_TREE; | 10466 return NULL_TREE; |
10829 } | 10467 } |
10847 /* A wrapper function for builtin folding that prevents warnings for | 10485 /* A wrapper function for builtin folding that prevents warnings for |
10848 "statement without effect" and the like, caused by removing the | 10486 "statement without effect" and the like, caused by removing the |
10849 call node earlier than the warning is generated. */ | 10487 call node earlier than the warning is generated. */ |
10850 | 10488 |
10851 tree | 10489 tree |
10852 fold_call_expr (tree exp, bool ignore) | 10490 fold_call_expr (location_t loc, tree exp, bool ignore) |
10853 { | 10491 { |
10854 tree ret = NULL_TREE; | 10492 tree ret = NULL_TREE; |
10855 tree fndecl = get_callee_fndecl (exp); | 10493 tree fndecl = get_callee_fndecl (exp); |
10856 if (fndecl | 10494 if (fndecl |
10857 && TREE_CODE (fndecl) == FUNCTION_DECL | 10495 && TREE_CODE (fndecl) == FUNCTION_DECL |
10885 else | 10523 else |
10886 { | 10524 { |
10887 if (nargs <= MAX_ARGS_TO_FOLD_BUILTIN) | 10525 if (nargs <= MAX_ARGS_TO_FOLD_BUILTIN) |
10888 { | 10526 { |
10889 tree *args = CALL_EXPR_ARGP (exp); | 10527 tree *args = CALL_EXPR_ARGP (exp); |
10890 ret = fold_builtin_n (fndecl, args, nargs, ignore); | 10528 ret = fold_builtin_n (loc, fndecl, args, nargs, ignore); |
10891 } | 10529 } |
10892 if (!ret) | 10530 if (!ret) |
10893 ret = fold_builtin_varargs (fndecl, exp, ignore); | 10531 ret = fold_builtin_varargs (loc, fndecl, exp, ignore); |
10894 if (ret) | 10532 if (ret) |
10895 { | 10533 return ret; |
10896 /* Propagate location information from original call to | |
10897 expansion of builtin. Otherwise things like | |
10898 maybe_emit_chk_warning, that operate on the expansion | |
10899 of a builtin, will use the wrong location information. */ | |
10900 if (CAN_HAVE_LOCATION_P (exp) && EXPR_HAS_LOCATION (exp)) | |
10901 { | |
10902 tree realret = ret; | |
10903 if (TREE_CODE (ret) == NOP_EXPR) | |
10904 realret = TREE_OPERAND (ret, 0); | |
10905 if (CAN_HAVE_LOCATION_P (realret) | |
10906 && !EXPR_HAS_LOCATION (realret)) | |
10907 SET_EXPR_LOCATION (realret, EXPR_LOCATION (exp)); | |
10908 return realret; | |
10909 } | |
10910 return ret; | |
10911 } | |
10912 } | 10534 } |
10913 } | 10535 } |
10914 return NULL_TREE; | 10536 return NULL_TREE; |
10915 } | 10537 } |
10916 | 10538 |
10917 /* Conveniently construct a function call expression. FNDECL names the | 10539 /* Conveniently construct a function call expression. FNDECL names the |
10918 function to be called and ARGLIST is a TREE_LIST of arguments. */ | 10540 function to be called and ARGLIST is a TREE_LIST of arguments. */ |
10919 | 10541 |
10920 tree | 10542 tree |
10921 build_function_call_expr (tree fndecl, tree arglist) | 10543 build_function_call_expr (location_t loc, tree fndecl, tree arglist) |
10922 { | 10544 { |
10923 tree fntype = TREE_TYPE (fndecl); | 10545 tree fntype = TREE_TYPE (fndecl); |
10924 tree fn = build1 (ADDR_EXPR, build_pointer_type (fntype), fndecl); | 10546 tree fn = build1 (ADDR_EXPR, build_pointer_type (fntype), fndecl); |
10925 int n = list_length (arglist); | 10547 int n = list_length (arglist); |
10926 tree *argarray = (tree *) alloca (n * sizeof (tree)); | 10548 tree *argarray = (tree *) alloca (n * sizeof (tree)); |
10927 int i; | 10549 int i; |
10928 | 10550 |
10929 for (i = 0; i < n; i++, arglist = TREE_CHAIN (arglist)) | 10551 for (i = 0; i < n; i++, arglist = TREE_CHAIN (arglist)) |
10930 argarray[i] = TREE_VALUE (arglist); | 10552 argarray[i] = TREE_VALUE (arglist); |
10931 return fold_builtin_call_array (TREE_TYPE (fntype), fn, n, argarray); | 10553 return fold_builtin_call_array (loc, TREE_TYPE (fntype), fn, n, argarray); |
10932 } | 10554 } |
10933 | 10555 |
10934 /* Conveniently construct a function call expression. FNDECL names the | 10556 /* Conveniently construct a function call expression. FNDECL names the |
10935 function to be called, N is the number of arguments, and the "..." | 10557 function to be called, N is the number of arguments, and the "..." |
10936 parameters are the argument expressions. */ | 10558 parameters are the argument expressions. */ |
10937 | 10559 |
10938 tree | 10560 tree |
10939 build_call_expr (tree fndecl, int n, ...) | 10561 build_call_expr_loc (location_t loc, tree fndecl, int n, ...) |
10940 { | 10562 { |
10941 va_list ap; | 10563 va_list ap; |
10942 tree fntype = TREE_TYPE (fndecl); | 10564 tree fntype = TREE_TYPE (fndecl); |
10943 tree fn = build1 (ADDR_EXPR, build_pointer_type (fntype), fndecl); | 10565 tree fn = build1 (ADDR_EXPR, build_pointer_type (fntype), fndecl); |
10944 tree *argarray = (tree *) alloca (n * sizeof (tree)); | 10566 tree *argarray = (tree *) alloca (n * sizeof (tree)); |
10946 | 10568 |
10947 va_start (ap, n); | 10569 va_start (ap, n); |
10948 for (i = 0; i < n; i++) | 10570 for (i = 0; i < n; i++) |
10949 argarray[i] = va_arg (ap, tree); | 10571 argarray[i] = va_arg (ap, tree); |
10950 va_end (ap); | 10572 va_end (ap); |
10951 return fold_builtin_call_array (TREE_TYPE (fntype), fn, n, argarray); | 10573 return fold_builtin_call_array (loc, TREE_TYPE (fntype), fn, n, argarray); |
10952 } | 10574 } |
10953 | 10575 |
10954 /* Construct a CALL_EXPR with type TYPE with FN as the function expression. | 10576 /* Construct a CALL_EXPR with type TYPE with FN as the function expression. |
10955 N arguments are passed in the array ARGARRAY. */ | 10577 N arguments are passed in the array ARGARRAY. */ |
10956 | 10578 |
10957 tree | 10579 tree |
10958 fold_builtin_call_array (tree type, | 10580 fold_builtin_call_array (location_t loc, tree type, |
10959 tree fn, | 10581 tree fn, |
10960 int n, | 10582 int n, |
10961 tree *argarray) | 10583 tree *argarray) |
10962 { | 10584 { |
10963 tree ret = NULL_TREE; | 10585 tree ret = NULL_TREE; |
10977 tree fndecl2 = get_callee_fndecl (argarray[n - 1]); | 10599 tree fndecl2 = get_callee_fndecl (argarray[n - 1]); |
10978 if (fndecl2 | 10600 if (fndecl2 |
10979 && TREE_CODE (fndecl2) == FUNCTION_DECL | 10601 && TREE_CODE (fndecl2) == FUNCTION_DECL |
10980 && DECL_BUILT_IN_CLASS (fndecl2) == BUILT_IN_NORMAL | 10602 && DECL_BUILT_IN_CLASS (fndecl2) == BUILT_IN_NORMAL |
10981 && DECL_FUNCTION_CODE (fndecl2) == BUILT_IN_VA_ARG_PACK) | 10603 && DECL_FUNCTION_CODE (fndecl2) == BUILT_IN_VA_ARG_PACK) |
10982 return build_call_array (type, fn, n, argarray); | 10604 return build_call_array_loc (loc, type, fn, n, argarray); |
10983 } | 10605 } |
10984 if (avoid_folding_inline_builtin (fndecl)) | 10606 if (avoid_folding_inline_builtin (fndecl)) |
10985 return build_call_array (type, fn, n, argarray); | 10607 return build_call_array_loc (loc, type, fn, n, argarray); |
10986 if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_MD) | 10608 if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_MD) |
10987 { | 10609 { |
10988 tree arglist = NULL_TREE; | 10610 tree arglist = NULL_TREE; |
10989 for (i = n - 1; i >= 0; i--) | 10611 for (i = n - 1; i >= 0; i--) |
10990 arglist = tree_cons (NULL_TREE, argarray[i], arglist); | 10612 arglist = tree_cons (NULL_TREE, argarray[i], arglist); |
10991 ret = targetm.fold_builtin (fndecl, arglist, false); | 10613 ret = targetm.fold_builtin (fndecl, arglist, false); |
10992 if (ret) | 10614 if (ret) |
10993 return ret; | 10615 return ret; |
10994 return build_call_array (type, fn, n, argarray); | 10616 return build_call_array_loc (loc, type, fn, n, argarray); |
10995 } | 10617 } |
10996 else if (n <= MAX_ARGS_TO_FOLD_BUILTIN) | 10618 else if (n <= MAX_ARGS_TO_FOLD_BUILTIN) |
10997 { | 10619 { |
10998 /* First try the transformations that don't require consing up | 10620 /* First try the transformations that don't require consing up |
10999 an exp. */ | 10621 an exp. */ |
11000 ret = fold_builtin_n (fndecl, argarray, n, false); | 10622 ret = fold_builtin_n (loc, fndecl, argarray, n, false); |
11001 if (ret) | 10623 if (ret) |
11002 return ret; | 10624 return ret; |
11003 } | 10625 } |
11004 | 10626 |
11005 /* If we got this far, we need to build an exp. */ | 10627 /* If we got this far, we need to build an exp. */ |
11006 exp = build_call_array (type, fn, n, argarray); | 10628 exp = build_call_array_loc (loc, type, fn, n, argarray); |
11007 ret = fold_builtin_varargs (fndecl, exp, false); | 10629 ret = fold_builtin_varargs (loc, fndecl, exp, false); |
11008 return ret ? ret : exp; | 10630 return ret ? ret : exp; |
11009 } | 10631 } |
11010 } | 10632 } |
11011 | 10633 |
11012 return build_call_array (type, fn, n, argarray); | 10634 return build_call_array_loc (loc, type, fn, n, argarray); |
11013 } | 10635 } |
11014 | 10636 |
11015 /* Construct a new CALL_EXPR using the tail of the argument list of EXP | 10637 /* Construct a new CALL_EXPR using the tail of the argument list of EXP |
11016 along with N new arguments specified as the "..." parameters. SKIP | 10638 along with N new arguments specified as the "..." parameters. SKIP |
11017 is the number of arguments in EXP to be omitted. This function is used | 10639 is the number of arguments in EXP to be omitted. This function is used |
11018 to do varargs-to-varargs transformations. */ | 10640 to do varargs-to-varargs transformations. */ |
11019 | 10641 |
11020 static tree | 10642 static tree |
11021 rewrite_call_expr (tree exp, int skip, tree fndecl, int n, ...) | 10643 rewrite_call_expr (location_t loc, tree exp, int skip, tree fndecl, int n, ...) |
11022 { | 10644 { |
11023 int oldnargs = call_expr_nargs (exp); | 10645 int oldnargs = call_expr_nargs (exp); |
11024 int nargs = oldnargs - skip + n; | 10646 int nargs = oldnargs - skip + n; |
11025 tree fntype = TREE_TYPE (fndecl); | 10647 tree fntype = TREE_TYPE (fndecl); |
11026 tree fn = build1 (ADDR_EXPR, build_pointer_type (fntype), fndecl); | 10648 tree fn = build1 (ADDR_EXPR, build_pointer_type (fntype), fndecl); |
11037 buffer[i] = va_arg (ap, tree); | 10659 buffer[i] = va_arg (ap, tree); |
11038 va_end (ap); | 10660 va_end (ap); |
11039 for (j = skip; j < oldnargs; j++, i++) | 10661 for (j = skip; j < oldnargs; j++, i++) |
11040 buffer[i] = CALL_EXPR_ARG (exp, j); | 10662 buffer[i] = CALL_EXPR_ARG (exp, j); |
11041 } | 10663 } |
11042 else | 10664 else |
11043 buffer = CALL_EXPR_ARGP (exp) + skip; | 10665 buffer = CALL_EXPR_ARGP (exp) + skip; |
11044 | 10666 |
11045 return fold (build_call_array (TREE_TYPE (exp), fn, nargs, buffer)); | 10667 return fold (build_call_array_loc (loc, TREE_TYPE (exp), fn, nargs, buffer)); |
11046 } | 10668 } |
11047 | 10669 |
11048 /* Validate a single argument ARG against a tree code CODE representing | 10670 /* Validate a single argument ARG against a tree code CODE representing |
11049 a type. */ | 10671 a type. */ |
11050 | 10672 |
11051 static bool | 10673 static bool |
11052 validate_arg (const_tree arg, enum tree_code code) | 10674 validate_arg (const_tree arg, enum tree_code code) |
11053 { | 10675 { |
11054 if (!arg) | 10676 if (!arg) |
11055 return false; | 10677 return false; |
11081 va_start (ap, call); | 10703 va_start (ap, call); |
11082 i = 0; | 10704 i = 0; |
11083 | 10705 |
11084 do | 10706 do |
11085 { | 10707 { |
11086 code = va_arg (ap, enum tree_code); | 10708 code = (enum tree_code) va_arg (ap, int); |
11087 switch (code) | 10709 switch (code) |
11088 { | 10710 { |
11089 case 0: | 10711 case 0: |
11090 /* This signifies an ellipses, any further arguments are all ok. */ | 10712 /* This signifies an ellipses, any further arguments are all ok. */ |
11091 res = true; | 10713 res = true; |
11132 va_start (ap, callexpr); | 10754 va_start (ap, callexpr); |
11133 init_const_call_expr_arg_iterator (callexpr, &iter); | 10755 init_const_call_expr_arg_iterator (callexpr, &iter); |
11134 | 10756 |
11135 do | 10757 do |
11136 { | 10758 { |
11137 code = va_arg (ap, enum tree_code); | 10759 code = (enum tree_code) va_arg (ap, int); |
11138 switch (code) | 10760 switch (code) |
11139 { | 10761 { |
11140 case 0: | 10762 case 0: |
11141 /* This signifies an ellipses, any further arguments are all ok. */ | 10763 /* This signifies an ellipses, any further arguments are all ok. */ |
11142 res = true; | 10764 res = true; |
11221 COMPOUND_EXPRs are chained through their RHS. The RHS of the last | 10843 COMPOUND_EXPRs are chained through their RHS. The RHS of the last |
11222 COMPOUND_EXPR in the chain will contain the tree for the simplified | 10844 COMPOUND_EXPR in the chain will contain the tree for the simplified |
11223 form of the builtin function call. */ | 10845 form of the builtin function call. */ |
11224 | 10846 |
11225 static tree | 10847 static tree |
11226 fold_builtin_strstr (tree s1, tree s2, tree type) | 10848 fold_builtin_strstr (location_t loc, tree s1, tree s2, tree type) |
11227 { | 10849 { |
11228 if (!validate_arg (s1, POINTER_TYPE) | 10850 if (!validate_arg (s1, POINTER_TYPE) |
11229 || !validate_arg (s2, POINTER_TYPE)) | 10851 || !validate_arg (s2, POINTER_TYPE)) |
11230 return NULL_TREE; | 10852 return NULL_TREE; |
11231 else | 10853 else |
11245 | 10867 |
11246 if (r == NULL) | 10868 if (r == NULL) |
11247 return build_int_cst (TREE_TYPE (s1), 0); | 10869 return build_int_cst (TREE_TYPE (s1), 0); |
11248 | 10870 |
11249 /* Return an offset into the constant string argument. */ | 10871 /* Return an offset into the constant string argument. */ |
11250 tem = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (s1), | 10872 tem = fold_build2_loc (loc, POINTER_PLUS_EXPR, TREE_TYPE (s1), |
11251 s1, size_int (r - p1)); | 10873 s1, size_int (r - p1)); |
11252 return fold_convert (type, tem); | 10874 return fold_convert_loc (loc, type, tem); |
11253 } | 10875 } |
11254 | 10876 |
11255 /* The argument is const char *, and the result is char *, so we need | 10877 /* The argument is const char *, and the result is char *, so we need |
11256 a type conversion here to avoid a warning. */ | 10878 a type conversion here to avoid a warning. */ |
11257 if (p2[0] == '\0') | 10879 if (p2[0] == '\0') |
11258 return fold_convert (type, s1); | 10880 return fold_convert_loc (loc, type, s1); |
11259 | 10881 |
11260 if (p2[1] != '\0') | 10882 if (p2[1] != '\0') |
11261 return NULL_TREE; | 10883 return NULL_TREE; |
11262 | 10884 |
11263 fn = implicit_built_in_decls[BUILT_IN_STRCHR]; | 10885 fn = implicit_built_in_decls[BUILT_IN_STRCHR]; |
11264 if (!fn) | 10886 if (!fn) |
11265 return NULL_TREE; | 10887 return NULL_TREE; |
11266 | 10888 |
11267 /* New argument list transforming strstr(s1, s2) to | 10889 /* New argument list transforming strstr(s1, s2) to |
11268 strchr(s1, s2[0]). */ | 10890 strchr(s1, s2[0]). */ |
11269 return build_call_expr (fn, 2, s1, build_int_cst (NULL_TREE, p2[0])); | 10891 return build_call_expr_loc (loc, fn, 2, s1, build_int_cst (NULL_TREE, p2[0])); |
11270 } | 10892 } |
11271 } | 10893 } |
11272 | 10894 |
11273 /* Simplify a call to the strchr builtin. S1 and S2 are the arguments to | 10895 /* Simplify a call to the strchr builtin. S1 and S2 are the arguments to |
11274 the call, and TYPE is its return type. | 10896 the call, and TYPE is its return type. |
11287 COMPOUND_EXPRs are chained through their RHS. The RHS of the last | 10909 COMPOUND_EXPRs are chained through their RHS. The RHS of the last |
11288 COMPOUND_EXPR in the chain will contain the tree for the simplified | 10910 COMPOUND_EXPR in the chain will contain the tree for the simplified |
11289 form of the builtin function call. */ | 10911 form of the builtin function call. */ |
11290 | 10912 |
11291 static tree | 10913 static tree |
11292 fold_builtin_strchr (tree s1, tree s2, tree type) | 10914 fold_builtin_strchr (location_t loc, tree s1, tree s2, tree type) |
11293 { | 10915 { |
11294 if (!validate_arg (s1, POINTER_TYPE) | 10916 if (!validate_arg (s1, POINTER_TYPE) |
11295 || !validate_arg (s2, INTEGER_TYPE)) | 10917 || !validate_arg (s2, INTEGER_TYPE)) |
11296 return NULL_TREE; | 10918 return NULL_TREE; |
11297 else | 10919 else |
11315 | 10937 |
11316 if (r == NULL) | 10938 if (r == NULL) |
11317 return build_int_cst (TREE_TYPE (s1), 0); | 10939 return build_int_cst (TREE_TYPE (s1), 0); |
11318 | 10940 |
11319 /* Return an offset into the constant string argument. */ | 10941 /* Return an offset into the constant string argument. */ |
11320 tem = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (s1), | 10942 tem = fold_build2_loc (loc, POINTER_PLUS_EXPR, TREE_TYPE (s1), |
11321 s1, size_int (r - p1)); | 10943 s1, size_int (r - p1)); |
11322 return fold_convert (type, tem); | 10944 return fold_convert_loc (loc, type, tem); |
11323 } | 10945 } |
11324 return NULL_TREE; | 10946 return NULL_TREE; |
11325 } | 10947 } |
11326 } | 10948 } |
11327 | 10949 |
11342 COMPOUND_EXPRs are chained through their RHS. The RHS of the last | 10964 COMPOUND_EXPRs are chained through their RHS. The RHS of the last |
11343 COMPOUND_EXPR in the chain will contain the tree for the simplified | 10965 COMPOUND_EXPR in the chain will contain the tree for the simplified |
11344 form of the builtin function call. */ | 10966 form of the builtin function call. */ |
11345 | 10967 |
11346 static tree | 10968 static tree |
11347 fold_builtin_strrchr (tree s1, tree s2, tree type) | 10969 fold_builtin_strrchr (location_t loc, tree s1, tree s2, tree type) |
11348 { | 10970 { |
11349 if (!validate_arg (s1, POINTER_TYPE) | 10971 if (!validate_arg (s1, POINTER_TYPE) |
11350 || !validate_arg (s2, INTEGER_TYPE)) | 10972 || !validate_arg (s2, INTEGER_TYPE)) |
11351 return NULL_TREE; | 10973 return NULL_TREE; |
11352 else | 10974 else |
11371 | 10993 |
11372 if (r == NULL) | 10994 if (r == NULL) |
11373 return build_int_cst (TREE_TYPE (s1), 0); | 10995 return build_int_cst (TREE_TYPE (s1), 0); |
11374 | 10996 |
11375 /* Return an offset into the constant string argument. */ | 10997 /* Return an offset into the constant string argument. */ |
11376 tem = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (s1), | 10998 tem = fold_build2_loc (loc, POINTER_PLUS_EXPR, TREE_TYPE (s1), |
11377 s1, size_int (r - p1)); | 10999 s1, size_int (r - p1)); |
11378 return fold_convert (type, tem); | 11000 return fold_convert_loc (loc, type, tem); |
11379 } | 11001 } |
11380 | 11002 |
11381 if (! integer_zerop (s2)) | 11003 if (! integer_zerop (s2)) |
11382 return NULL_TREE; | 11004 return NULL_TREE; |
11383 | 11005 |
11384 fn = implicit_built_in_decls[BUILT_IN_STRCHR]; | 11006 fn = implicit_built_in_decls[BUILT_IN_STRCHR]; |
11385 if (!fn) | 11007 if (!fn) |
11386 return NULL_TREE; | 11008 return NULL_TREE; |
11387 | 11009 |
11388 /* Transform strrchr(s1, '\0') to strchr(s1, '\0'). */ | 11010 /* Transform strrchr(s1, '\0') to strchr(s1, '\0'). */ |
11389 return build_call_expr (fn, 2, s1, s2); | 11011 return build_call_expr_loc (loc, fn, 2, s1, s2); |
11390 } | 11012 } |
11391 } | 11013 } |
11392 | 11014 |
11393 /* Simplify a call to the strpbrk builtin. S1 and S2 are the arguments | 11015 /* Simplify a call to the strpbrk builtin. S1 and S2 are the arguments |
11394 to the call, and TYPE is its return type. | 11016 to the call, and TYPE is its return type. |
11407 COMPOUND_EXPRs are chained through their RHS. The RHS of the last | 11029 COMPOUND_EXPRs are chained through their RHS. The RHS of the last |
11408 COMPOUND_EXPR in the chain will contain the tree for the simplified | 11030 COMPOUND_EXPR in the chain will contain the tree for the simplified |
11409 form of the builtin function call. */ | 11031 form of the builtin function call. */ |
11410 | 11032 |
11411 static tree | 11033 static tree |
11412 fold_builtin_strpbrk (tree s1, tree s2, tree type) | 11034 fold_builtin_strpbrk (location_t loc, tree s1, tree s2, tree type) |
11413 { | 11035 { |
11414 if (!validate_arg (s1, POINTER_TYPE) | 11036 if (!validate_arg (s1, POINTER_TYPE) |
11415 || !validate_arg (s2, POINTER_TYPE)) | 11037 || !validate_arg (s2, POINTER_TYPE)) |
11416 return NULL_TREE; | 11038 return NULL_TREE; |
11417 else | 11039 else |
11431 | 11053 |
11432 if (r == NULL) | 11054 if (r == NULL) |
11433 return build_int_cst (TREE_TYPE (s1), 0); | 11055 return build_int_cst (TREE_TYPE (s1), 0); |
11434 | 11056 |
11435 /* Return an offset into the constant string argument. */ | 11057 /* Return an offset into the constant string argument. */ |
11436 tem = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (s1), | 11058 tem = fold_build2_loc (loc, POINTER_PLUS_EXPR, TREE_TYPE (s1), |
11437 s1, size_int (r - p1)); | 11059 s1, size_int (r - p1)); |
11438 return fold_convert (type, tem); | 11060 return fold_convert_loc (loc, type, tem); |
11439 } | 11061 } |
11440 | 11062 |
11441 if (p2[0] == '\0') | 11063 if (p2[0] == '\0') |
11442 /* strpbrk(x, "") == NULL. | 11064 /* strpbrk(x, "") == NULL. |
11443 Evaluate and ignore s1 in case it had side-effects. */ | 11065 Evaluate and ignore s1 in case it had side-effects. */ |
11444 return omit_one_operand (TREE_TYPE (s1), integer_zero_node, s1); | 11066 return omit_one_operand_loc (loc, TREE_TYPE (s1), integer_zero_node, s1); |
11445 | 11067 |
11446 if (p2[1] != '\0') | 11068 if (p2[1] != '\0') |
11447 return NULL_TREE; /* Really call strpbrk. */ | 11069 return NULL_TREE; /* Really call strpbrk. */ |
11448 | 11070 |
11449 fn = implicit_built_in_decls[BUILT_IN_STRCHR]; | 11071 fn = implicit_built_in_decls[BUILT_IN_STRCHR]; |
11450 if (!fn) | 11072 if (!fn) |
11451 return NULL_TREE; | 11073 return NULL_TREE; |
11452 | 11074 |
11453 /* New argument list transforming strpbrk(s1, s2) to | 11075 /* New argument list transforming strpbrk(s1, s2) to |
11454 strchr(s1, s2[0]). */ | 11076 strchr(s1, s2[0]). */ |
11455 return build_call_expr (fn, 2, s1, build_int_cst (NULL_TREE, p2[0])); | 11077 return build_call_expr_loc (loc, fn, 2, s1, build_int_cst (NULL_TREE, p2[0])); |
11456 } | 11078 } |
11457 } | 11079 } |
11458 | 11080 |
11459 /* Simplify a call to the strcat builtin. DST and SRC are the arguments | 11081 /* Simplify a call to the strcat builtin. DST and SRC are the arguments |
11460 to the call. | 11082 to the call. |
11473 COMPOUND_EXPRs are chained through their RHS. The RHS of the last | 11095 COMPOUND_EXPRs are chained through their RHS. The RHS of the last |
11474 COMPOUND_EXPR in the chain will contain the tree for the simplified | 11096 COMPOUND_EXPR in the chain will contain the tree for the simplified |
11475 form of the builtin function call. */ | 11097 form of the builtin function call. */ |
11476 | 11098 |
11477 static tree | 11099 static tree |
11478 fold_builtin_strcat (tree dst, tree src) | 11100 fold_builtin_strcat (location_t loc ATTRIBUTE_UNUSED, tree dst, tree src) |
11479 { | 11101 { |
11480 if (!validate_arg (dst, POINTER_TYPE) | 11102 if (!validate_arg (dst, POINTER_TYPE) |
11481 || !validate_arg (src, POINTER_TYPE)) | 11103 || !validate_arg (src, POINTER_TYPE)) |
11482 return NULL_TREE; | 11104 return NULL_TREE; |
11483 else | 11105 else |
11486 | 11108 |
11487 /* If the string length is zero, return the dst parameter. */ | 11109 /* If the string length is zero, return the dst parameter. */ |
11488 if (p && *p == '\0') | 11110 if (p && *p == '\0') |
11489 return dst; | 11111 return dst; |
11490 | 11112 |
11113 if (optimize_insn_for_speed_p ()) | |
11114 { | |
11115 /* See if we can store by pieces into (dst + strlen(dst)). */ | |
11116 tree newdst, call; | |
11117 tree strlen_fn = implicit_built_in_decls[BUILT_IN_STRLEN]; | |
11118 tree strcpy_fn = implicit_built_in_decls[BUILT_IN_STRCPY]; | |
11119 | |
11120 if (!strlen_fn || !strcpy_fn) | |
11121 return NULL_TREE; | |
11122 | |
11123 /* If we don't have a movstr we don't want to emit an strcpy | |
11124 call. We have to do that if the length of the source string | |
11125 isn't computable (in that case we can use memcpy probably | |
11126 later expanding to a sequence of mov instructions). If we | |
11127 have movstr instructions we can emit strcpy calls. */ | |
11128 if (!HAVE_movstr) | |
11129 { | |
11130 tree len = c_strlen (src, 1); | |
11131 if (! len || TREE_SIDE_EFFECTS (len)) | |
11132 return NULL_TREE; | |
11133 } | |
11134 | |
11135 /* Stabilize the argument list. */ | |
11136 dst = builtin_save_expr (dst); | |
11137 | |
11138 /* Create strlen (dst). */ | |
11139 newdst = build_call_expr_loc (loc, strlen_fn, 1, dst); | |
11140 /* Create (dst p+ strlen (dst)). */ | |
11141 | |
11142 newdst = fold_build2_loc (loc, POINTER_PLUS_EXPR, | |
11143 TREE_TYPE (dst), dst, newdst); | |
11144 newdst = builtin_save_expr (newdst); | |
11145 | |
11146 call = build_call_expr_loc (loc, strcpy_fn, 2, newdst, src); | |
11147 return build2 (COMPOUND_EXPR, TREE_TYPE (dst), call, dst); | |
11148 } | |
11491 return NULL_TREE; | 11149 return NULL_TREE; |
11492 } | 11150 } |
11493 } | 11151 } |
11494 | 11152 |
11495 /* Simplify a call to the strncat builtin. DST, SRC, and LEN are the | 11153 /* Simplify a call to the strncat builtin. DST, SRC, and LEN are the |
11509 COMPOUND_EXPRs are chained through their RHS. The RHS of the last | 11167 COMPOUND_EXPRs are chained through their RHS. The RHS of the last |
11510 COMPOUND_EXPR in the chain will contain the tree for the simplified | 11168 COMPOUND_EXPR in the chain will contain the tree for the simplified |
11511 form of the builtin function call. */ | 11169 form of the builtin function call. */ |
11512 | 11170 |
11513 static tree | 11171 static tree |
11514 fold_builtin_strncat (tree dst, tree src, tree len) | 11172 fold_builtin_strncat (location_t loc, tree dst, tree src, tree len) |
11515 { | 11173 { |
11516 if (!validate_arg (dst, POINTER_TYPE) | 11174 if (!validate_arg (dst, POINTER_TYPE) |
11517 || !validate_arg (src, POINTER_TYPE) | 11175 || !validate_arg (src, POINTER_TYPE) |
11518 || !validate_arg (len, INTEGER_TYPE)) | 11176 || !validate_arg (len, INTEGER_TYPE)) |
11519 return NULL_TREE; | 11177 return NULL_TREE; |
11522 const char *p = c_getstr (src); | 11180 const char *p = c_getstr (src); |
11523 | 11181 |
11524 /* If the requested length is zero, or the src parameter string | 11182 /* If the requested length is zero, or the src parameter string |
11525 length is zero, return the dst parameter. */ | 11183 length is zero, return the dst parameter. */ |
11526 if (integer_zerop (len) || (p && *p == '\0')) | 11184 if (integer_zerop (len) || (p && *p == '\0')) |
11527 return omit_two_operands (TREE_TYPE (dst), dst, src, len); | 11185 return omit_two_operands_loc (loc, TREE_TYPE (dst), dst, src, len); |
11528 | 11186 |
11529 /* If the requested len is greater than or equal to the string | 11187 /* If the requested len is greater than or equal to the string |
11530 length, call strcat. */ | 11188 length, call strcat. */ |
11531 if (TREE_CODE (len) == INTEGER_CST && p | 11189 if (TREE_CODE (len) == INTEGER_CST && p |
11532 && compare_tree_int (len, strlen (p)) >= 0) | 11190 && compare_tree_int (len, strlen (p)) >= 0) |
11536 /* If the replacement _DECL isn't initialized, don't do the | 11194 /* If the replacement _DECL isn't initialized, don't do the |
11537 transformation. */ | 11195 transformation. */ |
11538 if (!fn) | 11196 if (!fn) |
11539 return NULL_TREE; | 11197 return NULL_TREE; |
11540 | 11198 |
11541 return build_call_expr (fn, 2, dst, src); | 11199 return build_call_expr_loc (loc, fn, 2, dst, src); |
11542 } | 11200 } |
11543 return NULL_TREE; | 11201 return NULL_TREE; |
11544 } | 11202 } |
11545 } | 11203 } |
11546 | 11204 |
11561 COMPOUND_EXPRs are chained through their RHS. The RHS of the last | 11219 COMPOUND_EXPRs are chained through their RHS. The RHS of the last |
11562 COMPOUND_EXPR in the chain will contain the tree for the simplified | 11220 COMPOUND_EXPR in the chain will contain the tree for the simplified |
11563 form of the builtin function call. */ | 11221 form of the builtin function call. */ |
11564 | 11222 |
11565 static tree | 11223 static tree |
11566 fold_builtin_strspn (tree s1, tree s2) | 11224 fold_builtin_strspn (location_t loc, tree s1, tree s2) |
11567 { | 11225 { |
11568 if (!validate_arg (s1, POINTER_TYPE) | 11226 if (!validate_arg (s1, POINTER_TYPE) |
11569 || !validate_arg (s2, POINTER_TYPE)) | 11227 || !validate_arg (s2, POINTER_TYPE)) |
11570 return NULL_TREE; | 11228 return NULL_TREE; |
11571 else | 11229 else |
11581 | 11239 |
11582 /* If either argument is "", return NULL_TREE. */ | 11240 /* If either argument is "", return NULL_TREE. */ |
11583 if ((p1 && *p1 == '\0') || (p2 && *p2 == '\0')) | 11241 if ((p1 && *p1 == '\0') || (p2 && *p2 == '\0')) |
11584 /* Evaluate and ignore both arguments in case either one has | 11242 /* Evaluate and ignore both arguments in case either one has |
11585 side-effects. */ | 11243 side-effects. */ |
11586 return omit_two_operands (size_type_node, size_zero_node, | 11244 return omit_two_operands_loc (loc, size_type_node, size_zero_node, |
11587 s1, s2); | 11245 s1, s2); |
11588 return NULL_TREE; | 11246 return NULL_TREE; |
11589 } | 11247 } |
11590 } | 11248 } |
11591 | 11249 |
11606 COMPOUND_EXPRs are chained through their RHS. The RHS of the last | 11264 COMPOUND_EXPRs are chained through their RHS. The RHS of the last |
11607 COMPOUND_EXPR in the chain will contain the tree for the simplified | 11265 COMPOUND_EXPR in the chain will contain the tree for the simplified |
11608 form of the builtin function call. */ | 11266 form of the builtin function call. */ |
11609 | 11267 |
11610 static tree | 11268 static tree |
11611 fold_builtin_strcspn (tree s1, tree s2) | 11269 fold_builtin_strcspn (location_t loc, tree s1, tree s2) |
11612 { | 11270 { |
11613 if (!validate_arg (s1, POINTER_TYPE) | 11271 if (!validate_arg (s1, POINTER_TYPE) |
11614 || !validate_arg (s2, POINTER_TYPE)) | 11272 || !validate_arg (s2, POINTER_TYPE)) |
11615 return NULL_TREE; | 11273 return NULL_TREE; |
11616 else | 11274 else |
11627 /* If the first argument is "", return NULL_TREE. */ | 11285 /* If the first argument is "", return NULL_TREE. */ |
11628 if (p1 && *p1 == '\0') | 11286 if (p1 && *p1 == '\0') |
11629 { | 11287 { |
11630 /* Evaluate and ignore argument s2 in case it has | 11288 /* Evaluate and ignore argument s2 in case it has |
11631 side-effects. */ | 11289 side-effects. */ |
11632 return omit_one_operand (size_type_node, | 11290 return omit_one_operand_loc (loc, size_type_node, |
11633 size_zero_node, s2); | 11291 size_zero_node, s2); |
11634 } | 11292 } |
11635 | 11293 |
11636 /* If the second argument is "", return __builtin_strlen(s1). */ | 11294 /* If the second argument is "", return __builtin_strlen(s1). */ |
11637 if (p2 && *p2 == '\0') | 11295 if (p2 && *p2 == '\0') |
11641 /* If the replacement _DECL isn't initialized, don't do the | 11299 /* If the replacement _DECL isn't initialized, don't do the |
11642 transformation. */ | 11300 transformation. */ |
11643 if (!fn) | 11301 if (!fn) |
11644 return NULL_TREE; | 11302 return NULL_TREE; |
11645 | 11303 |
11646 return build_call_expr (fn, 1, s1); | 11304 return build_call_expr_loc (loc, fn, 1, s1); |
11647 } | 11305 } |
11648 return NULL_TREE; | 11306 return NULL_TREE; |
11649 } | 11307 } |
11650 } | 11308 } |
11651 | 11309 |
11655 actually a call to fputs_unlocked. If LEN in non-NULL, it represents | 11313 actually a call to fputs_unlocked. If LEN in non-NULL, it represents |
11656 the known length of the string. Return NULL_TREE if no simplification | 11314 the known length of the string. Return NULL_TREE if no simplification |
11657 was possible. */ | 11315 was possible. */ |
11658 | 11316 |
11659 tree | 11317 tree |
11660 fold_builtin_fputs (tree arg0, tree arg1, bool ignore, bool unlocked, tree len) | 11318 fold_builtin_fputs (location_t loc, tree arg0, tree arg1, |
11319 bool ignore, bool unlocked, tree len) | |
11661 { | 11320 { |
11662 /* If we're using an unlocked function, assume the other unlocked | 11321 /* If we're using an unlocked function, assume the other unlocked |
11663 functions exist explicitly. */ | 11322 functions exist explicitly. */ |
11664 tree const fn_fputc = unlocked ? built_in_decls[BUILT_IN_FPUTC_UNLOCKED] | 11323 tree const fn_fputc = unlocked ? built_in_decls[BUILT_IN_FPUTC_UNLOCKED] |
11665 : implicit_built_in_decls[BUILT_IN_FPUTC]; | 11324 : implicit_built_in_decls[BUILT_IN_FPUTC]; |
11685 return NULL_TREE; | 11344 return NULL_TREE; |
11686 | 11345 |
11687 switch (compare_tree_int (len, 1)) | 11346 switch (compare_tree_int (len, 1)) |
11688 { | 11347 { |
11689 case -1: /* length is 0, delete the call entirely . */ | 11348 case -1: /* length is 0, delete the call entirely . */ |
11690 return omit_one_operand (integer_type_node, integer_zero_node, arg1);; | 11349 return omit_one_operand_loc (loc, integer_type_node, |
11350 integer_zero_node, arg1);; | |
11691 | 11351 |
11692 case 0: /* length is 1, call fputc. */ | 11352 case 0: /* length is 1, call fputc. */ |
11693 { | 11353 { |
11694 const char *p = c_getstr (arg0); | 11354 const char *p = c_getstr (arg0); |
11695 | 11355 |
11696 if (p != NULL) | 11356 if (p != NULL) |
11697 { | 11357 { |
11698 if (fn_fputc) | 11358 if (fn_fputc) |
11699 return build_call_expr (fn_fputc, 2, | 11359 return build_call_expr_loc (loc, fn_fputc, 2, |
11700 build_int_cst (NULL_TREE, p[0]), arg1); | 11360 build_int_cst (NULL_TREE, p[0]), arg1); |
11701 else | 11361 else |
11702 return NULL_TREE; | 11362 return NULL_TREE; |
11703 } | 11363 } |
11704 } | 11364 } |
11709 if (optimize_function_for_size_p (cfun)) | 11369 if (optimize_function_for_size_p (cfun)) |
11710 return NULL_TREE; | 11370 return NULL_TREE; |
11711 /* New argument list transforming fputs(string, stream) to | 11371 /* New argument list transforming fputs(string, stream) to |
11712 fwrite(string, 1, len, stream). */ | 11372 fwrite(string, 1, len, stream). */ |
11713 if (fn_fwrite) | 11373 if (fn_fwrite) |
11714 return build_call_expr (fn_fwrite, 4, arg0, size_one_node, len, arg1); | 11374 return build_call_expr_loc (loc, fn_fwrite, 4, arg0, |
11375 size_one_node, len, arg1); | |
11715 else | 11376 else |
11716 return NULL_TREE; | 11377 return NULL_TREE; |
11717 } | 11378 } |
11718 default: | 11379 default: |
11719 gcc_unreachable (); | 11380 gcc_unreachable (); |
11766 return true; | 11427 return true; |
11767 } | 11428 } |
11768 arg = CALL_EXPR_ARG (exp, 0); | 11429 arg = CALL_EXPR_ARG (exp, 0); |
11769 } | 11430 } |
11770 | 11431 |
11432 if (TREE_CODE (arg) == SSA_NAME) | |
11433 arg = SSA_NAME_VAR (arg); | |
11434 | |
11771 /* We destructively modify the call to be __builtin_va_start (ap, 0) | 11435 /* We destructively modify the call to be __builtin_va_start (ap, 0) |
11772 or __builtin_next_arg (0) the first time we see it, after checking | 11436 or __builtin_next_arg (0) the first time we see it, after checking |
11773 the arguments and if needed issuing a warning. */ | 11437 the arguments and if needed issuing a warning. */ |
11774 if (!integer_zerop (arg)) | 11438 if (!integer_zerop (arg)) |
11775 { | 11439 { |
11776 tree last_parm = tree_last (DECL_ARGUMENTS (current_function_decl)); | 11440 tree last_parm = tree_last (DECL_ARGUMENTS (current_function_decl)); |
11777 | 11441 |
11823 Return NULL_TREE if no simplification was possible, otherwise return the | 11487 Return NULL_TREE if no simplification was possible, otherwise return the |
11824 simplified form of the call as a tree. If IGNORED is true, it means that | 11488 simplified form of the call as a tree. If IGNORED is true, it means that |
11825 the caller does not use the returned value of the function. */ | 11489 the caller does not use the returned value of the function. */ |
11826 | 11490 |
11827 static tree | 11491 static tree |
11828 fold_builtin_sprintf (tree dest, tree fmt, tree orig, int ignored) | 11492 fold_builtin_sprintf (location_t loc, tree dest, tree fmt, |
11493 tree orig, int ignored) | |
11829 { | 11494 { |
11830 tree call, retval; | 11495 tree call, retval; |
11831 const char *fmt_str = NULL; | 11496 const char *fmt_str = NULL; |
11832 | 11497 |
11833 /* Verify the required arguments in the original call. We deal with two | 11498 /* Verify the required arguments in the original call. We deal with two |
11862 if (orig) | 11527 if (orig) |
11863 return NULL_TREE; | 11528 return NULL_TREE; |
11864 | 11529 |
11865 /* Convert sprintf (str, fmt) into strcpy (str, fmt) when | 11530 /* Convert sprintf (str, fmt) into strcpy (str, fmt) when |
11866 'format' is known to contain no % formats. */ | 11531 'format' is known to contain no % formats. */ |
11867 call = build_call_expr (fn, 2, dest, fmt); | 11532 call = build_call_expr_loc (loc, fn, 2, dest, fmt); |
11868 if (!ignored) | 11533 if (!ignored) |
11869 retval = build_int_cst (NULL_TREE, strlen (fmt_str)); | 11534 retval = build_int_cst (NULL_TREE, strlen (fmt_str)); |
11870 } | 11535 } |
11871 | 11536 |
11872 /* If the format is "%s", use strcpy if the result isn't used. */ | 11537 /* If the format is "%s", use strcpy if the result isn't used. */ |
11887 { | 11552 { |
11888 retval = c_strlen (orig, 1); | 11553 retval = c_strlen (orig, 1); |
11889 if (!retval || TREE_CODE (retval) != INTEGER_CST) | 11554 if (!retval || TREE_CODE (retval) != INTEGER_CST) |
11890 return NULL_TREE; | 11555 return NULL_TREE; |
11891 } | 11556 } |
11892 call = build_call_expr (fn, 2, dest, orig); | 11557 call = build_call_expr_loc (loc, fn, 2, dest, orig); |
11893 } | 11558 } |
11894 | 11559 |
11895 if (call && retval) | 11560 if (call && retval) |
11896 { | 11561 { |
11897 retval = fold_convert | 11562 retval = fold_convert_loc |
11898 (TREE_TYPE (TREE_TYPE (implicit_built_in_decls[BUILT_IN_SPRINTF])), | 11563 (loc, TREE_TYPE (TREE_TYPE (implicit_built_in_decls[BUILT_IN_SPRINTF])), |
11899 retval); | 11564 retval); |
11900 return build2 (COMPOUND_EXPR, TREE_TYPE (retval), call, retval); | 11565 return build2 (COMPOUND_EXPR, TREE_TYPE (retval), call, retval); |
11901 } | 11566 } |
11902 else | 11567 else |
11903 return call; | 11568 return call; |
11999 } | 11664 } |
12000 | 11665 |
12001 if (! fn) | 11666 if (! fn) |
12002 return NULL_RTX; | 11667 return NULL_RTX; |
12003 | 11668 |
12004 fn = build_call_expr (fn, 3, dest, src, len); | 11669 fn = build_call_nofold (fn, 3, dest, src, len); |
12005 STRIP_TYPE_NOPS (fn); | 11670 gcc_assert (TREE_CODE (fn) == CALL_EXPR); |
12006 while (TREE_CODE (fn) == COMPOUND_EXPR) | 11671 CALL_EXPR_TAILCALL (fn) = CALL_EXPR_TAILCALL (exp); |
12007 { | |
12008 expand_expr (TREE_OPERAND (fn, 0), const0_rtx, VOIDmode, | |
12009 EXPAND_NORMAL); | |
12010 fn = TREE_OPERAND (fn, 1); | |
12011 } | |
12012 if (TREE_CODE (fn) == CALL_EXPR) | |
12013 CALL_EXPR_TAILCALL (fn) = CALL_EXPR_TAILCALL (exp); | |
12014 return expand_expr (fn, target, mode, EXPAND_NORMAL); | 11672 return expand_expr (fn, target, mode, EXPAND_NORMAL); |
12015 } | 11673 } |
12016 else if (fcode == BUILT_IN_MEMSET_CHK) | 11674 else if (fcode == BUILT_IN_MEMSET_CHK) |
12017 return NULL_RTX; | 11675 return NULL_RTX; |
12018 else | 11676 else |
12054 if (readonly_data_expr (src)) | 11712 if (readonly_data_expr (src)) |
12055 { | 11713 { |
12056 tree fn = built_in_decls[BUILT_IN_MEMCPY_CHK]; | 11714 tree fn = built_in_decls[BUILT_IN_MEMCPY_CHK]; |
12057 if (!fn) | 11715 if (!fn) |
12058 return NULL_RTX; | 11716 return NULL_RTX; |
12059 fn = build_call_expr (fn, 4, dest, src, len, size); | 11717 fn = build_call_nofold (fn, 4, dest, src, len, size); |
12060 STRIP_TYPE_NOPS (fn); | 11718 gcc_assert (TREE_CODE (fn) == CALL_EXPR); |
12061 while (TREE_CODE (fn) == COMPOUND_EXPR) | 11719 CALL_EXPR_TAILCALL (fn) = CALL_EXPR_TAILCALL (exp); |
12062 { | |
12063 expand_expr (TREE_OPERAND (fn, 0), const0_rtx, VOIDmode, | |
12064 EXPAND_NORMAL); | |
12065 fn = TREE_OPERAND (fn, 1); | |
12066 } | |
12067 if (TREE_CODE (fn) == CALL_EXPR) | |
12068 CALL_EXPR_TAILCALL (fn) = CALL_EXPR_TAILCALL (exp); | |
12069 return expand_expr (fn, target, mode, EXPAND_NORMAL); | 11720 return expand_expr (fn, target, mode, EXPAND_NORMAL); |
12070 } | 11721 } |
12071 } | 11722 } |
12072 return NULL_RTX; | 11723 return NULL_RTX; |
12073 } | 11724 } |
12145 in __sprintf_chk/__vsprintf_chk calls. */ | 11796 in __sprintf_chk/__vsprintf_chk calls. */ |
12146 | 11797 |
12147 static void | 11798 static void |
12148 maybe_emit_sprintf_chk_warning (tree exp, enum built_in_function fcode) | 11799 maybe_emit_sprintf_chk_warning (tree exp, enum built_in_function fcode) |
12149 { | 11800 { |
12150 tree dest, size, len, fmt, flag; | 11801 tree size, len, fmt; |
12151 const char *fmt_str; | 11802 const char *fmt_str; |
12152 int nargs = call_expr_nargs (exp); | 11803 int nargs = call_expr_nargs (exp); |
12153 | 11804 |
12154 /* Verify the required arguments in the original call. */ | 11805 /* Verify the required arguments in the original call. */ |
12155 | 11806 |
12156 if (nargs < 4) | 11807 if (nargs < 4) |
12157 return; | 11808 return; |
12158 dest = CALL_EXPR_ARG (exp, 0); | |
12159 flag = CALL_EXPR_ARG (exp, 1); | |
12160 size = CALL_EXPR_ARG (exp, 2); | 11809 size = CALL_EXPR_ARG (exp, 2); |
12161 fmt = CALL_EXPR_ARG (exp, 3); | 11810 fmt = CALL_EXPR_ARG (exp, 3); |
12162 | 11811 |
12163 if (! host_integerp (size, 1) || integer_all_onesp (size)) | 11812 if (! host_integerp (size, 1) || integer_all_onesp (size)) |
12164 return; | 11813 return; |
12284 IGNORE is true, if return value can be ignored. FCODE is the BUILT_IN_* | 11933 IGNORE is true, if return value can be ignored. FCODE is the BUILT_IN_* |
12285 code of the builtin. If MAXLEN is not NULL, it is maximum length | 11934 code of the builtin. If MAXLEN is not NULL, it is maximum length |
12286 passed as third argument. */ | 11935 passed as third argument. */ |
12287 | 11936 |
12288 tree | 11937 tree |
12289 fold_builtin_memory_chk (tree fndecl, | 11938 fold_builtin_memory_chk (location_t loc, tree fndecl, |
12290 tree dest, tree src, tree len, tree size, | 11939 tree dest, tree src, tree len, tree size, |
12291 tree maxlen, bool ignore, | 11940 tree maxlen, bool ignore, |
12292 enum built_in_function fcode) | 11941 enum built_in_function fcode) |
12293 { | 11942 { |
12294 tree fn; | 11943 tree fn; |
12304 /* If SRC and DEST are the same (and not volatile), return DEST | 11953 /* If SRC and DEST are the same (and not volatile), return DEST |
12305 (resp. DEST+LEN for __mempcpy_chk). */ | 11954 (resp. DEST+LEN for __mempcpy_chk). */ |
12306 if (fcode != BUILT_IN_MEMSET_CHK && operand_equal_p (src, dest, 0)) | 11955 if (fcode != BUILT_IN_MEMSET_CHK && operand_equal_p (src, dest, 0)) |
12307 { | 11956 { |
12308 if (fcode != BUILT_IN_MEMPCPY_CHK) | 11957 if (fcode != BUILT_IN_MEMPCPY_CHK) |
12309 return omit_one_operand (TREE_TYPE (TREE_TYPE (fndecl)), dest, len); | 11958 return omit_one_operand_loc (loc, TREE_TYPE (TREE_TYPE (fndecl)), |
11959 dest, len); | |
12310 else | 11960 else |
12311 { | 11961 { |
12312 tree temp = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (dest), dest, len); | 11962 tree temp = fold_build2_loc (loc, POINTER_PLUS_EXPR, TREE_TYPE (dest), |
12313 return fold_convert (TREE_TYPE (TREE_TYPE (fndecl)), temp); | 11963 dest, len); |
11964 return fold_convert_loc (loc, TREE_TYPE (TREE_TYPE (fndecl)), temp); | |
12314 } | 11965 } |
12315 } | 11966 } |
12316 | 11967 |
12317 if (! host_integerp (size, 1)) | 11968 if (! host_integerp (size, 1)) |
12318 return NULL_TREE; | 11969 return NULL_TREE; |
12332 (void) __memcpy_chk (). */ | 11983 (void) __memcpy_chk (). */ |
12333 fn = built_in_decls[BUILT_IN_MEMCPY_CHK]; | 11984 fn = built_in_decls[BUILT_IN_MEMCPY_CHK]; |
12334 if (!fn) | 11985 if (!fn) |
12335 return NULL_TREE; | 11986 return NULL_TREE; |
12336 | 11987 |
12337 return build_call_expr (fn, 4, dest, src, len, size); | 11988 return build_call_expr_loc (loc, fn, 4, dest, src, len, size); |
12338 } | 11989 } |
12339 return NULL_TREE; | 11990 return NULL_TREE; |
12340 } | 11991 } |
12341 } | 11992 } |
12342 else | 11993 else |
12368 } | 12019 } |
12369 | 12020 |
12370 if (!fn) | 12021 if (!fn) |
12371 return NULL_TREE; | 12022 return NULL_TREE; |
12372 | 12023 |
12373 return build_call_expr (fn, 3, dest, src, len); | 12024 return build_call_expr_loc (loc, fn, 3, dest, src, len); |
12374 } | 12025 } |
12375 | 12026 |
12376 /* Fold a call to the __st[rp]cpy_chk builtin. | 12027 /* Fold a call to the __st[rp]cpy_chk builtin. |
12377 DEST, SRC, and SIZE are the arguments to the call. | 12028 DEST, SRC, and SIZE are the arguments to the call. |
12378 IGNORE is true if return value can be ignored. FCODE is the BUILT_IN_* | 12029 IGNORE is true if return value can be ignored. FCODE is the BUILT_IN_* |
12379 code of the builtin. If MAXLEN is not NULL, it is maximum length of | 12030 code of the builtin. If MAXLEN is not NULL, it is maximum length of |
12380 strings passed as second argument. */ | 12031 strings passed as second argument. */ |
12381 | 12032 |
12382 tree | 12033 tree |
12383 fold_builtin_stxcpy_chk (tree fndecl, tree dest, tree src, tree size, | 12034 fold_builtin_stxcpy_chk (location_t loc, tree fndecl, tree dest, |
12035 tree src, tree size, | |
12384 tree maxlen, bool ignore, | 12036 tree maxlen, bool ignore, |
12385 enum built_in_function fcode) | 12037 enum built_in_function fcode) |
12386 { | 12038 { |
12387 tree len, fn; | 12039 tree len, fn; |
12388 | 12040 |
12391 || !validate_arg (size, INTEGER_TYPE)) | 12043 || !validate_arg (size, INTEGER_TYPE)) |
12392 return NULL_TREE; | 12044 return NULL_TREE; |
12393 | 12045 |
12394 /* If SRC and DEST are the same (and not volatile), return DEST. */ | 12046 /* If SRC and DEST are the same (and not volatile), return DEST. */ |
12395 if (fcode == BUILT_IN_STRCPY_CHK && operand_equal_p (src, dest, 0)) | 12047 if (fcode == BUILT_IN_STRCPY_CHK && operand_equal_p (src, dest, 0)) |
12396 return fold_convert (TREE_TYPE (TREE_TYPE (fndecl)), dest); | 12048 return fold_convert_loc (loc, TREE_TYPE (TREE_TYPE (fndecl)), dest); |
12397 | 12049 |
12398 if (! host_integerp (size, 1)) | 12050 if (! host_integerp (size, 1)) |
12399 return NULL_TREE; | 12051 return NULL_TREE; |
12400 | 12052 |
12401 if (! integer_all_onesp (size)) | 12053 if (! integer_all_onesp (size)) |
12417 optimize into __strcpy_chk. */ | 12069 optimize into __strcpy_chk. */ |
12418 fn = built_in_decls[BUILT_IN_STRCPY_CHK]; | 12070 fn = built_in_decls[BUILT_IN_STRCPY_CHK]; |
12419 if (!fn) | 12071 if (!fn) |
12420 return NULL_TREE; | 12072 return NULL_TREE; |
12421 | 12073 |
12422 return build_call_expr (fn, 3, dest, src, size); | 12074 return build_call_expr_loc (loc, fn, 3, dest, src, size); |
12423 } | 12075 } |
12424 | 12076 |
12425 if (! len || TREE_SIDE_EFFECTS (len)) | 12077 if (! len || TREE_SIDE_EFFECTS (len)) |
12426 return NULL_TREE; | 12078 return NULL_TREE; |
12427 | 12079 |
12429 transform __strcpy_chk into __memcpy_chk. */ | 12081 transform __strcpy_chk into __memcpy_chk. */ |
12430 fn = built_in_decls[BUILT_IN_MEMCPY_CHK]; | 12082 fn = built_in_decls[BUILT_IN_MEMCPY_CHK]; |
12431 if (!fn) | 12083 if (!fn) |
12432 return NULL_TREE; | 12084 return NULL_TREE; |
12433 | 12085 |
12434 len = size_binop (PLUS_EXPR, len, ssize_int (1)); | 12086 len = size_binop_loc (loc, PLUS_EXPR, len, ssize_int (1)); |
12435 return fold_convert (TREE_TYPE (TREE_TYPE (fndecl)), | 12087 return fold_convert_loc (loc, TREE_TYPE (TREE_TYPE (fndecl)), |
12436 build_call_expr (fn, 4, | 12088 build_call_expr_loc (loc, fn, 4, |
12437 dest, src, len, size)); | 12089 dest, src, len, size)); |
12438 } | 12090 } |
12439 } | 12091 } |
12440 else | 12092 else |
12441 maxlen = len; | 12093 maxlen = len; |
12442 | 12094 |
12448 fn = built_in_decls[fcode == BUILT_IN_STPCPY_CHK | 12100 fn = built_in_decls[fcode == BUILT_IN_STPCPY_CHK |
12449 ? BUILT_IN_STPCPY : BUILT_IN_STRCPY]; | 12101 ? BUILT_IN_STPCPY : BUILT_IN_STRCPY]; |
12450 if (!fn) | 12102 if (!fn) |
12451 return NULL_TREE; | 12103 return NULL_TREE; |
12452 | 12104 |
12453 return build_call_expr (fn, 2, dest, src); | 12105 return build_call_expr_loc (loc, fn, 2, dest, src); |
12454 } | 12106 } |
12455 | 12107 |
12456 /* Fold a call to the __strncpy_chk builtin. DEST, SRC, LEN, and SIZE | 12108 /* Fold a call to the __strncpy_chk builtin. DEST, SRC, LEN, and SIZE |
12457 are the arguments to the call. If MAXLEN is not NULL, it is maximum | 12109 are the arguments to the call. If MAXLEN is not NULL, it is maximum |
12458 length passed as third argument. */ | 12110 length passed as third argument. */ |
12459 | 12111 |
12460 tree | 12112 tree |
12461 fold_builtin_strncpy_chk (tree dest, tree src, tree len, tree size, | 12113 fold_builtin_strncpy_chk (location_t loc, tree dest, tree src, |
12462 tree maxlen) | 12114 tree len, tree size, tree maxlen) |
12463 { | 12115 { |
12464 tree fn; | 12116 tree fn; |
12465 | 12117 |
12466 if (!validate_arg (dest, POINTER_TYPE) | 12118 if (!validate_arg (dest, POINTER_TYPE) |
12467 || !validate_arg (src, POINTER_TYPE) | 12119 || !validate_arg (src, POINTER_TYPE) |
12492 /* If __builtin_strncpy_chk is used, assume strncpy is available. */ | 12144 /* If __builtin_strncpy_chk is used, assume strncpy is available. */ |
12493 fn = built_in_decls[BUILT_IN_STRNCPY]; | 12145 fn = built_in_decls[BUILT_IN_STRNCPY]; |
12494 if (!fn) | 12146 if (!fn) |
12495 return NULL_TREE; | 12147 return NULL_TREE; |
12496 | 12148 |
12497 return build_call_expr (fn, 3, dest, src, len); | 12149 return build_call_expr_loc (loc, fn, 3, dest, src, len); |
12498 } | 12150 } |
12499 | 12151 |
12500 /* Fold a call to the __strcat_chk builtin FNDECL. DEST, SRC, and SIZE | 12152 /* Fold a call to the __strcat_chk builtin FNDECL. DEST, SRC, and SIZE |
12501 are the arguments to the call. */ | 12153 are the arguments to the call. */ |
12502 | 12154 |
12503 static tree | 12155 static tree |
12504 fold_builtin_strcat_chk (tree fndecl, tree dest, tree src, tree size) | 12156 fold_builtin_strcat_chk (location_t loc, tree fndecl, tree dest, |
12157 tree src, tree size) | |
12505 { | 12158 { |
12506 tree fn; | 12159 tree fn; |
12507 const char *p; | 12160 const char *p; |
12508 | 12161 |
12509 if (!validate_arg (dest, POINTER_TYPE) | 12162 if (!validate_arg (dest, POINTER_TYPE) |
12512 return NULL_TREE; | 12165 return NULL_TREE; |
12513 | 12166 |
12514 p = c_getstr (src); | 12167 p = c_getstr (src); |
12515 /* If the SRC parameter is "", return DEST. */ | 12168 /* If the SRC parameter is "", return DEST. */ |
12516 if (p && *p == '\0') | 12169 if (p && *p == '\0') |
12517 return omit_one_operand (TREE_TYPE (TREE_TYPE (fndecl)), dest, src); | 12170 return omit_one_operand_loc (loc, TREE_TYPE (TREE_TYPE (fndecl)), dest, src); |
12518 | 12171 |
12519 if (! host_integerp (size, 1) || ! integer_all_onesp (size)) | 12172 if (! host_integerp (size, 1) || ! integer_all_onesp (size)) |
12520 return NULL_TREE; | 12173 return NULL_TREE; |
12521 | 12174 |
12522 /* If __builtin_strcat_chk is used, assume strcat is available. */ | 12175 /* If __builtin_strcat_chk is used, assume strcat is available. */ |
12523 fn = built_in_decls[BUILT_IN_STRCAT]; | 12176 fn = built_in_decls[BUILT_IN_STRCAT]; |
12524 if (!fn) | 12177 if (!fn) |
12525 return NULL_TREE; | 12178 return NULL_TREE; |
12526 | 12179 |
12527 return build_call_expr (fn, 2, dest, src); | 12180 return build_call_expr_loc (loc, fn, 2, dest, src); |
12528 } | 12181 } |
12529 | 12182 |
12530 /* Fold a call to the __strncat_chk builtin with arguments DEST, SRC, | 12183 /* Fold a call to the __strncat_chk builtin with arguments DEST, SRC, |
12531 LEN, and SIZE. */ | 12184 LEN, and SIZE. */ |
12532 | 12185 |
12533 static tree | 12186 static tree |
12534 fold_builtin_strncat_chk (tree fndecl, | 12187 fold_builtin_strncat_chk (location_t loc, tree fndecl, |
12535 tree dest, tree src, tree len, tree size) | 12188 tree dest, tree src, tree len, tree size) |
12536 { | 12189 { |
12537 tree fn; | 12190 tree fn; |
12538 const char *p; | 12191 const char *p; |
12539 | 12192 |
12544 return NULL_TREE; | 12197 return NULL_TREE; |
12545 | 12198 |
12546 p = c_getstr (src); | 12199 p = c_getstr (src); |
12547 /* If the SRC parameter is "" or if LEN is 0, return DEST. */ | 12200 /* If the SRC parameter is "" or if LEN is 0, return DEST. */ |
12548 if (p && *p == '\0') | 12201 if (p && *p == '\0') |
12549 return omit_one_operand (TREE_TYPE (TREE_TYPE (fndecl)), dest, len); | 12202 return omit_one_operand_loc (loc, TREE_TYPE (TREE_TYPE (fndecl)), dest, len); |
12550 else if (integer_zerop (len)) | 12203 else if (integer_zerop (len)) |
12551 return omit_one_operand (TREE_TYPE (TREE_TYPE (fndecl)), dest, src); | 12204 return omit_one_operand_loc (loc, TREE_TYPE (TREE_TYPE (fndecl)), dest, src); |
12552 | 12205 |
12553 if (! host_integerp (size, 1)) | 12206 if (! host_integerp (size, 1)) |
12554 return NULL_TREE; | 12207 return NULL_TREE; |
12555 | 12208 |
12556 if (! integer_all_onesp (size)) | 12209 if (! integer_all_onesp (size)) |
12564 /* If LEN >= strlen (SRC), optimize into __strcat_chk. */ | 12217 /* If LEN >= strlen (SRC), optimize into __strcat_chk. */ |
12565 fn = built_in_decls[BUILT_IN_STRCAT_CHK]; | 12218 fn = built_in_decls[BUILT_IN_STRCAT_CHK]; |
12566 if (!fn) | 12219 if (!fn) |
12567 return NULL_TREE; | 12220 return NULL_TREE; |
12568 | 12221 |
12569 return build_call_expr (fn, 3, dest, src, size); | 12222 return build_call_expr_loc (loc, fn, 3, dest, src, size); |
12570 } | 12223 } |
12571 return NULL_TREE; | 12224 return NULL_TREE; |
12572 } | 12225 } |
12573 | 12226 |
12574 /* If __builtin_strncat_chk is used, assume strncat is available. */ | 12227 /* If __builtin_strncat_chk is used, assume strncat is available. */ |
12575 fn = built_in_decls[BUILT_IN_STRNCAT]; | 12228 fn = built_in_decls[BUILT_IN_STRNCAT]; |
12576 if (!fn) | 12229 if (!fn) |
12577 return NULL_TREE; | 12230 return NULL_TREE; |
12578 | 12231 |
12579 return build_call_expr (fn, 3, dest, src, len); | 12232 return build_call_expr_loc (loc, fn, 3, dest, src, len); |
12580 } | 12233 } |
12581 | 12234 |
12582 /* Fold a call EXP to __{,v}sprintf_chk. Return NULL_TREE if | 12235 /* Fold a call EXP to __{,v}sprintf_chk. Return NULL_TREE if |
12583 a normal call should be emitted rather than expanding the function | 12236 a normal call should be emitted rather than expanding the function |
12584 inline. FCODE is either BUILT_IN_SPRINTF_CHK or BUILT_IN_VSPRINTF_CHK. */ | 12237 inline. FCODE is either BUILT_IN_SPRINTF_CHK or BUILT_IN_VSPRINTF_CHK. */ |
12585 | 12238 |
12586 static tree | 12239 static tree |
12587 fold_builtin_sprintf_chk (tree exp, enum built_in_function fcode) | 12240 fold_builtin_sprintf_chk (location_t loc, tree exp, |
12241 enum built_in_function fcode) | |
12588 { | 12242 { |
12589 tree dest, size, len, fn, fmt, flag; | 12243 tree dest, size, len, fn, fmt, flag; |
12590 const char *fmt_str; | 12244 const char *fmt_str; |
12591 int nargs = call_expr_nargs (exp); | 12245 int nargs = call_expr_nargs (exp); |
12592 | 12246 |
12665 fn = built_in_decls[fcode == BUILT_IN_VSPRINTF_CHK | 12319 fn = built_in_decls[fcode == BUILT_IN_VSPRINTF_CHK |
12666 ? BUILT_IN_VSPRINTF : BUILT_IN_SPRINTF]; | 12320 ? BUILT_IN_VSPRINTF : BUILT_IN_SPRINTF]; |
12667 if (!fn) | 12321 if (!fn) |
12668 return NULL_TREE; | 12322 return NULL_TREE; |
12669 | 12323 |
12670 return rewrite_call_expr (exp, 4, fn, 2, dest, fmt); | 12324 return rewrite_call_expr (loc, exp, 4, fn, 2, dest, fmt); |
12671 } | 12325 } |
12672 | 12326 |
12673 /* Fold a call EXP to {,v}snprintf. Return NULL_TREE if | 12327 /* Fold a call EXP to {,v}snprintf. Return NULL_TREE if |
12674 a normal call should be emitted rather than expanding the function | 12328 a normal call should be emitted rather than expanding the function |
12675 inline. FCODE is either BUILT_IN_SNPRINTF_CHK or | 12329 inline. FCODE is either BUILT_IN_SNPRINTF_CHK or |
12676 BUILT_IN_VSNPRINTF_CHK. If MAXLEN is not NULL, it is maximum length | 12330 BUILT_IN_VSNPRINTF_CHK. If MAXLEN is not NULL, it is maximum length |
12677 passed as second argument. */ | 12331 passed as second argument. */ |
12678 | 12332 |
12679 tree | 12333 tree |
12680 fold_builtin_snprintf_chk (tree exp, tree maxlen, | 12334 fold_builtin_snprintf_chk (location_t loc, tree exp, tree maxlen, |
12681 enum built_in_function fcode) | 12335 enum built_in_function fcode) |
12682 { | 12336 { |
12683 tree dest, size, len, fn, fmt, flag; | 12337 tree dest, size, len, fn, fmt, flag; |
12684 const char *fmt_str; | 12338 const char *fmt_str; |
12685 | 12339 |
12742 fn = built_in_decls[fcode == BUILT_IN_VSNPRINTF_CHK | 12396 fn = built_in_decls[fcode == BUILT_IN_VSNPRINTF_CHK |
12743 ? BUILT_IN_VSNPRINTF : BUILT_IN_SNPRINTF]; | 12397 ? BUILT_IN_VSNPRINTF : BUILT_IN_SNPRINTF]; |
12744 if (!fn) | 12398 if (!fn) |
12745 return NULL_TREE; | 12399 return NULL_TREE; |
12746 | 12400 |
12747 return rewrite_call_expr (exp, 5, fn, 3, dest, len, fmt); | 12401 return rewrite_call_expr (loc, exp, 5, fn, 3, dest, len, fmt); |
12748 } | 12402 } |
12749 | 12403 |
12750 /* Fold a call to the {,v}printf{,_unlocked} and __{,v}printf_chk builtins. | 12404 /* Fold a call to the {,v}printf{,_unlocked} and __{,v}printf_chk builtins. |
12751 FMT and ARG are the arguments to the call; we don't fold cases with | 12405 FMT and ARG are the arguments to the call; we don't fold cases with |
12752 more than 2 arguments, and ARG may be null if this is a 1-argument case. | 12406 more than 2 arguments, and ARG may be null if this is a 1-argument case. |
12754 Return NULL_TREE if no simplification was possible, otherwise return the | 12408 Return NULL_TREE if no simplification was possible, otherwise return the |
12755 simplified form of the call as a tree. FCODE is the BUILT_IN_* | 12409 simplified form of the call as a tree. FCODE is the BUILT_IN_* |
12756 code of the function to be simplified. */ | 12410 code of the function to be simplified. */ |
12757 | 12411 |
12758 static tree | 12412 static tree |
12759 fold_builtin_printf (tree fndecl, tree fmt, tree arg, bool ignore, | 12413 fold_builtin_printf (location_t loc, tree fndecl, tree fmt, |
12414 tree arg, bool ignore, | |
12760 enum built_in_function fcode) | 12415 enum built_in_function fcode) |
12761 { | 12416 { |
12762 tree fn_putchar, fn_puts, newarg, call = NULL_TREE; | 12417 tree fn_putchar, fn_puts, newarg, call = NULL_TREE; |
12763 const char *fmt_str = NULL; | 12418 const char *fmt_str = NULL; |
12764 | 12419 |
12827 /* Given printf("c"), (where c is any one character,) | 12482 /* Given printf("c"), (where c is any one character,) |
12828 convert "c"[0] to an int and pass that to the replacement | 12483 convert "c"[0] to an int and pass that to the replacement |
12829 function. */ | 12484 function. */ |
12830 newarg = build_int_cst (NULL_TREE, str[0]); | 12485 newarg = build_int_cst (NULL_TREE, str[0]); |
12831 if (fn_putchar) | 12486 if (fn_putchar) |
12832 call = build_call_expr (fn_putchar, 1, newarg); | 12487 call = build_call_expr_loc (loc, fn_putchar, 1, newarg); |
12833 } | 12488 } |
12834 else | 12489 else |
12835 { | 12490 { |
12836 /* If the string was "string\n", call puts("string"). */ | 12491 /* If the string was "string\n", call puts("string"). */ |
12837 size_t len = strlen (str); | 12492 size_t len = strlen (str); |
12843 memcpy (newstr, str, len - 1); | 12498 memcpy (newstr, str, len - 1); |
12844 newstr[len - 1] = 0; | 12499 newstr[len - 1] = 0; |
12845 | 12500 |
12846 newarg = build_string_literal (len, newstr); | 12501 newarg = build_string_literal (len, newstr); |
12847 if (fn_puts) | 12502 if (fn_puts) |
12848 call = build_call_expr (fn_puts, 1, newarg); | 12503 call = build_call_expr_loc (loc, fn_puts, 1, newarg); |
12849 } | 12504 } |
12850 else | 12505 else |
12851 /* We'd like to arrange to call fputs(string,stdout) here, | 12506 /* We'd like to arrange to call fputs(string,stdout) here, |
12852 but we need stdout and don't have a way to get it yet. */ | 12507 but we need stdout and don't have a way to get it yet. */ |
12853 return NULL_TREE; | 12508 return NULL_TREE; |
12862 else if (strcmp (fmt_str, target_percent_s_newline) == 0) | 12517 else if (strcmp (fmt_str, target_percent_s_newline) == 0) |
12863 { | 12518 { |
12864 if (!arg || !validate_arg (arg, POINTER_TYPE)) | 12519 if (!arg || !validate_arg (arg, POINTER_TYPE)) |
12865 return NULL_TREE; | 12520 return NULL_TREE; |
12866 if (fn_puts) | 12521 if (fn_puts) |
12867 call = build_call_expr (fn_puts, 1, arg); | 12522 call = build_call_expr_loc (loc, fn_puts, 1, arg); |
12868 } | 12523 } |
12869 | 12524 |
12870 /* If the format specifier was "%c", call __builtin_putchar(arg). */ | 12525 /* If the format specifier was "%c", call __builtin_putchar(arg). */ |
12871 else if (strcmp (fmt_str, target_percent_c) == 0) | 12526 else if (strcmp (fmt_str, target_percent_c) == 0) |
12872 { | 12527 { |
12873 if (!arg || !validate_arg (arg, INTEGER_TYPE)) | 12528 if (!arg || !validate_arg (arg, INTEGER_TYPE)) |
12874 return NULL_TREE; | 12529 return NULL_TREE; |
12875 if (fn_putchar) | 12530 if (fn_putchar) |
12876 call = build_call_expr (fn_putchar, 1, arg); | 12531 call = build_call_expr_loc (loc, fn_putchar, 1, arg); |
12877 } | 12532 } |
12878 | 12533 |
12879 if (!call) | 12534 if (!call) |
12880 return NULL_TREE; | 12535 return NULL_TREE; |
12881 | 12536 |
12882 return fold_convert (TREE_TYPE (TREE_TYPE (fndecl)), call); | 12537 return fold_convert_loc (loc, TREE_TYPE (TREE_TYPE (fndecl)), call); |
12883 } | 12538 } |
12884 | 12539 |
12885 /* Fold a call to the {,v}fprintf{,_unlocked} and __{,v}printf_chk builtins. | 12540 /* Fold a call to the {,v}fprintf{,_unlocked} and __{,v}printf_chk builtins. |
12886 FP, FMT, and ARG are the arguments to the call. We don't fold calls with | 12541 FP, FMT, and ARG are the arguments to the call. We don't fold calls with |
12887 more than 3 arguments, and ARG may be null in the 2-argument case. | 12542 more than 3 arguments, and ARG may be null in the 2-argument case. |
12889 Return NULL_TREE if no simplification was possible, otherwise return the | 12544 Return NULL_TREE if no simplification was possible, otherwise return the |
12890 simplified form of the call as a tree. FCODE is the BUILT_IN_* | 12545 simplified form of the call as a tree. FCODE is the BUILT_IN_* |
12891 code of the function to be simplified. */ | 12546 code of the function to be simplified. */ |
12892 | 12547 |
12893 static tree | 12548 static tree |
12894 fold_builtin_fprintf (tree fndecl, tree fp, tree fmt, tree arg, bool ignore, | 12549 fold_builtin_fprintf (location_t loc, tree fndecl, tree fp, |
12550 tree fmt, tree arg, bool ignore, | |
12895 enum built_in_function fcode) | 12551 enum built_in_function fcode) |
12896 { | 12552 { |
12897 tree fn_fputc, fn_fputs, call = NULL_TREE; | 12553 tree fn_fputc, fn_fputs, call = NULL_TREE; |
12898 const char *fmt_str = NULL; | 12554 const char *fmt_str = NULL; |
12899 | 12555 |
12948 | 12604 |
12949 /* When "string" doesn't contain %, replace all cases of | 12605 /* When "string" doesn't contain %, replace all cases of |
12950 fprintf (fp, string) with fputs (string, fp). The fputs | 12606 fprintf (fp, string) with fputs (string, fp). The fputs |
12951 builtin will take care of special cases like length == 1. */ | 12607 builtin will take care of special cases like length == 1. */ |
12952 if (fn_fputs) | 12608 if (fn_fputs) |
12953 call = build_call_expr (fn_fputs, 2, fmt, fp); | 12609 call = build_call_expr_loc (loc, fn_fputs, 2, fmt, fp); |
12954 } | 12610 } |
12955 | 12611 |
12956 /* The other optimizations can be done only on the non-va_list variants. */ | 12612 /* The other optimizations can be done only on the non-va_list variants. */ |
12957 else if (fcode == BUILT_IN_VFPRINTF || fcode == BUILT_IN_VFPRINTF_CHK) | 12613 else if (fcode == BUILT_IN_VFPRINTF || fcode == BUILT_IN_VFPRINTF_CHK) |
12958 return NULL_TREE; | 12614 return NULL_TREE; |
12961 else if (strcmp (fmt_str, target_percent_s) == 0) | 12617 else if (strcmp (fmt_str, target_percent_s) == 0) |
12962 { | 12618 { |
12963 if (!arg || !validate_arg (arg, POINTER_TYPE)) | 12619 if (!arg || !validate_arg (arg, POINTER_TYPE)) |
12964 return NULL_TREE; | 12620 return NULL_TREE; |
12965 if (fn_fputs) | 12621 if (fn_fputs) |
12966 call = build_call_expr (fn_fputs, 2, arg, fp); | 12622 call = build_call_expr_loc (loc, fn_fputs, 2, arg, fp); |
12967 } | 12623 } |
12968 | 12624 |
12969 /* If the format specifier was "%c", call __builtin_fputc (arg, fp). */ | 12625 /* If the format specifier was "%c", call __builtin_fputc (arg, fp). */ |
12970 else if (strcmp (fmt_str, target_percent_c) == 0) | 12626 else if (strcmp (fmt_str, target_percent_c) == 0) |
12971 { | 12627 { |
12972 if (!arg || !validate_arg (arg, INTEGER_TYPE)) | 12628 if (!arg || !validate_arg (arg, INTEGER_TYPE)) |
12973 return NULL_TREE; | 12629 return NULL_TREE; |
12974 if (fn_fputc) | 12630 if (fn_fputc) |
12975 call = build_call_expr (fn_fputc, 2, arg, fp); | 12631 call = build_call_expr_loc (loc, fn_fputc, 2, arg, fp); |
12976 } | 12632 } |
12977 | 12633 |
12978 if (!call) | 12634 if (!call) |
12979 return NULL_TREE; | 12635 return NULL_TREE; |
12980 return fold_convert (TREE_TYPE (TREE_TYPE (fndecl)), call); | 12636 return fold_convert_loc (loc, TREE_TYPE (TREE_TYPE (fndecl)), call); |
12981 } | 12637 } |
12982 | 12638 |
12983 /* Initialize format string characters in the target charset. */ | 12639 /* Initialize format string characters in the target charset. */ |
12984 | 12640 |
12985 static bool | 12641 static bool |
13049 } | 12705 } |
13050 } | 12706 } |
13051 return NULL_TREE; | 12707 return NULL_TREE; |
13052 } | 12708 } |
13053 | 12709 |
12710 /* Helper function for do_mpc_arg*(). Ensure M is a normal complex | |
12711 number and no overflow/underflow occurred. INEXACT is true if M | |
12712 was not exactly calculated. TYPE is the tree type for the result. | |
12713 This function assumes that you cleared the MPFR flags and then | |
12714 calculated M to see if anything subsequently set a flag prior to | |
12715 entering this function. Return NULL_TREE if any checks fail, if | |
12716 FORCE_CONVERT is true, then bypass the checks. */ | |
12717 | |
12718 static tree | |
12719 do_mpc_ckconv (mpc_srcptr m, tree type, int inexact, int force_convert) | |
12720 { | |
12721 /* Proceed iff we get a normal number, i.e. not NaN or Inf and no | |
12722 overflow/underflow occurred. If -frounding-math, proceed iff the | |
12723 result of calling FUNC was exact. */ | |
12724 if (force_convert | |
12725 || (mpfr_number_p (mpc_realref (m)) && mpfr_number_p (mpc_imagref (m)) | |
12726 && !mpfr_overflow_p () && !mpfr_underflow_p () | |
12727 && (!flag_rounding_math || !inexact))) | |
12728 { | |
12729 REAL_VALUE_TYPE re, im; | |
12730 | |
12731 real_from_mpfr (&re, mpc_realref (m), TREE_TYPE (type), GMP_RNDN); | |
12732 real_from_mpfr (&im, mpc_imagref (m), TREE_TYPE (type), GMP_RNDN); | |
12733 /* Proceed iff GCC's REAL_VALUE_TYPE can hold the MPFR values, | |
12734 check for overflow/underflow. If the REAL_VALUE_TYPE is zero | |
12735 but the mpft_t is not, then we underflowed in the | |
12736 conversion. */ | |
12737 if (force_convert | |
12738 || (real_isfinite (&re) && real_isfinite (&im) | |
12739 && (re.cl == rvc_zero) == (mpfr_zero_p (mpc_realref (m)) != 0) | |
12740 && (im.cl == rvc_zero) == (mpfr_zero_p (mpc_imagref (m)) != 0))) | |
12741 { | |
12742 REAL_VALUE_TYPE re_mode, im_mode; | |
12743 | |
12744 real_convert (&re_mode, TYPE_MODE (TREE_TYPE (type)), &re); | |
12745 real_convert (&im_mode, TYPE_MODE (TREE_TYPE (type)), &im); | |
12746 /* Proceed iff the specified mode can hold the value. */ | |
12747 if (force_convert | |
12748 || (real_identical (&re_mode, &re) | |
12749 && real_identical (&im_mode, &im))) | |
12750 return build_complex (type, build_real (TREE_TYPE (type), re_mode), | |
12751 build_real (TREE_TYPE (type), im_mode)); | |
12752 } | |
12753 } | |
12754 return NULL_TREE; | |
12755 } | |
12756 | |
13054 /* If argument ARG is a REAL_CST, call the one-argument mpfr function | 12757 /* If argument ARG is a REAL_CST, call the one-argument mpfr function |
13055 FUNC on it and return the resulting value as a tree with type TYPE. | 12758 FUNC on it and return the resulting value as a tree with type TYPE. |
13056 If MIN and/or MAX are not NULL, then the supplied ARG must be | 12759 If MIN and/or MAX are not NULL, then the supplied ARG must be |
13057 within those bounds. If INCLUSIVE is true, then MIN/MAX are | 12760 within those bounds. If INCLUSIVE is true, then MIN/MAX are |
13058 acceptable values, otherwise they are not. The mpfr precision is | 12761 acceptable values, otherwise they are not. The mpfr precision is |
13064 do_mpfr_arg1 (tree arg, tree type, int (*func)(mpfr_ptr, mpfr_srcptr, mp_rnd_t), | 12767 do_mpfr_arg1 (tree arg, tree type, int (*func)(mpfr_ptr, mpfr_srcptr, mp_rnd_t), |
13065 const REAL_VALUE_TYPE *min, const REAL_VALUE_TYPE *max, | 12768 const REAL_VALUE_TYPE *min, const REAL_VALUE_TYPE *max, |
13066 bool inclusive) | 12769 bool inclusive) |
13067 { | 12770 { |
13068 tree result = NULL_TREE; | 12771 tree result = NULL_TREE; |
13069 | 12772 |
13070 STRIP_NOPS (arg); | 12773 STRIP_NOPS (arg); |
13071 | 12774 |
13072 /* To proceed, MPFR must exactly represent the target floating point | 12775 /* To proceed, MPFR must exactly represent the target floating point |
13073 format, which only happens when the target base equals two. */ | 12776 format, which only happens when the target base equals two. */ |
13074 if (REAL_MODE_FORMAT (TYPE_MODE (type))->b == 2 | 12777 if (REAL_MODE_FORMAT (TYPE_MODE (type))->b == 2 |
13092 inexact = func (m, m, rnd); | 12795 inexact = func (m, m, rnd); |
13093 result = do_mpfr_ckconv (m, type, inexact); | 12796 result = do_mpfr_ckconv (m, type, inexact); |
13094 mpfr_clear (m); | 12797 mpfr_clear (m); |
13095 } | 12798 } |
13096 } | 12799 } |
13097 | 12800 |
13098 return result; | 12801 return result; |
13099 } | 12802 } |
13100 | 12803 |
13101 /* If argument ARG is a REAL_CST, call the two-argument mpfr function | 12804 /* If argument ARG is a REAL_CST, call the two-argument mpfr function |
13102 FUNC on it and return the resulting value as a tree with type TYPE. | 12805 FUNC on it and return the resulting value as a tree with type TYPE. |
13107 static tree | 12810 static tree |
13108 do_mpfr_arg2 (tree arg1, tree arg2, tree type, | 12811 do_mpfr_arg2 (tree arg1, tree arg2, tree type, |
13109 int (*func)(mpfr_ptr, mpfr_srcptr, mpfr_srcptr, mp_rnd_t)) | 12812 int (*func)(mpfr_ptr, mpfr_srcptr, mpfr_srcptr, mp_rnd_t)) |
13110 { | 12813 { |
13111 tree result = NULL_TREE; | 12814 tree result = NULL_TREE; |
13112 | 12815 |
13113 STRIP_NOPS (arg1); | 12816 STRIP_NOPS (arg1); |
13114 STRIP_NOPS (arg2); | 12817 STRIP_NOPS (arg2); |
13115 | 12818 |
13116 /* To proceed, MPFR must exactly represent the target floating point | 12819 /* To proceed, MPFR must exactly represent the target floating point |
13117 format, which only happens when the target base equals two. */ | 12820 format, which only happens when the target base equals two. */ |
13137 inexact = func (m1, m1, m2, rnd); | 12840 inexact = func (m1, m1, m2, rnd); |
13138 result = do_mpfr_ckconv (m1, type, inexact); | 12841 result = do_mpfr_ckconv (m1, type, inexact); |
13139 mpfr_clears (m1, m2, NULL); | 12842 mpfr_clears (m1, m2, NULL); |
13140 } | 12843 } |
13141 } | 12844 } |
13142 | 12845 |
13143 return result; | 12846 return result; |
13144 } | 12847 } |
13145 | 12848 |
13146 /* If argument ARG is a REAL_CST, call the three-argument mpfr function | 12849 /* If argument ARG is a REAL_CST, call the three-argument mpfr function |
13147 FUNC on it and return the resulting value as a tree with type TYPE. | 12850 FUNC on it and return the resulting value as a tree with type TYPE. |
13152 static tree | 12855 static tree |
13153 do_mpfr_arg3 (tree arg1, tree arg2, tree arg3, tree type, | 12856 do_mpfr_arg3 (tree arg1, tree arg2, tree arg3, tree type, |
13154 int (*func)(mpfr_ptr, mpfr_srcptr, mpfr_srcptr, mpfr_srcptr, mp_rnd_t)) | 12857 int (*func)(mpfr_ptr, mpfr_srcptr, mpfr_srcptr, mpfr_srcptr, mp_rnd_t)) |
13155 { | 12858 { |
13156 tree result = NULL_TREE; | 12859 tree result = NULL_TREE; |
13157 | 12860 |
13158 STRIP_NOPS (arg1); | 12861 STRIP_NOPS (arg1); |
13159 STRIP_NOPS (arg2); | 12862 STRIP_NOPS (arg2); |
13160 STRIP_NOPS (arg3); | 12863 STRIP_NOPS (arg3); |
13161 | 12864 |
13162 /* To proceed, MPFR must exactly represent the target floating point | 12865 /* To proceed, MPFR must exactly represent the target floating point |
13186 inexact = func (m1, m1, m2, m3, rnd); | 12889 inexact = func (m1, m1, m2, m3, rnd); |
13187 result = do_mpfr_ckconv (m1, type, inexact); | 12890 result = do_mpfr_ckconv (m1, type, inexact); |
13188 mpfr_clears (m1, m2, m3, NULL); | 12891 mpfr_clears (m1, m2, m3, NULL); |
13189 } | 12892 } |
13190 } | 12893 } |
13191 | 12894 |
13192 return result; | 12895 return result; |
13193 } | 12896 } |
13194 | 12897 |
13195 /* If argument ARG is a REAL_CST, call mpfr_sin_cos() on it and set | 12898 /* If argument ARG is a REAL_CST, call mpfr_sin_cos() on it and set |
13196 the pointers *(ARG_SINP) and *(ARG_COSP) to the resulting values. | 12899 the pointers *(ARG_SINP) and *(ARG_COSP) to the resulting values. |
13202 static tree | 12905 static tree |
13203 do_mpfr_sincos (tree arg, tree arg_sinp, tree arg_cosp) | 12906 do_mpfr_sincos (tree arg, tree arg_sinp, tree arg_cosp) |
13204 { | 12907 { |
13205 tree const type = TREE_TYPE (arg); | 12908 tree const type = TREE_TYPE (arg); |
13206 tree result = NULL_TREE; | 12909 tree result = NULL_TREE; |
13207 | 12910 |
13208 STRIP_NOPS (arg); | 12911 STRIP_NOPS (arg); |
13209 | 12912 |
13210 /* To proceed, MPFR must exactly represent the target floating point | 12913 /* To proceed, MPFR must exactly represent the target floating point |
13211 format, which only happens when the target base equals two. */ | 12914 format, which only happens when the target base equals two. */ |
13212 if (REAL_MODE_FORMAT (TYPE_MODE (type))->b == 2 | 12915 if (REAL_MODE_FORMAT (TYPE_MODE (type))->b == 2 |
13213 && TREE_CODE (arg) == REAL_CST | 12916 && TREE_CODE (arg) == REAL_CST |
13214 && !TREE_OVERFLOW (arg)) | 12917 && !TREE_OVERFLOW (arg)) |
13303 inexact = func (m, n, m, rnd); | 13006 inexact = func (m, n, m, rnd); |
13304 result = do_mpfr_ckconv (m, type, inexact); | 13007 result = do_mpfr_ckconv (m, type, inexact); |
13305 mpfr_clear (m); | 13008 mpfr_clear (m); |
13306 } | 13009 } |
13307 } | 13010 } |
13308 | 13011 |
13309 return result; | 13012 return result; |
13310 } | 13013 } |
13311 | 13014 |
13312 /* If arguments ARG0 and ARG1 are REAL_CSTs, call mpfr_remquo() to set | 13015 /* If arguments ARG0 and ARG1 are REAL_CSTs, call mpfr_remquo() to set |
13313 the pointer *(ARG_QUO) and return the result. The type is taken | 13016 the pointer *(ARG_QUO) and return the result. The type is taken |
13317 static tree | 13020 static tree |
13318 do_mpfr_remquo (tree arg0, tree arg1, tree arg_quo) | 13021 do_mpfr_remquo (tree arg0, tree arg1, tree arg_quo) |
13319 { | 13022 { |
13320 tree const type = TREE_TYPE (arg0); | 13023 tree const type = TREE_TYPE (arg0); |
13321 tree result = NULL_TREE; | 13024 tree result = NULL_TREE; |
13322 | 13025 |
13323 STRIP_NOPS (arg0); | 13026 STRIP_NOPS (arg0); |
13324 STRIP_NOPS (arg1); | 13027 STRIP_NOPS (arg1); |
13325 | 13028 |
13326 /* To proceed, MPFR must exactly represent the target floating point | 13029 /* To proceed, MPFR must exactly represent the target floating point |
13327 format, which only happens when the target base equals two. */ | 13030 format, which only happens when the target base equals two. */ |
13328 if (REAL_MODE_FORMAT (TYPE_MODE (type))->b == 2 | 13031 if (REAL_MODE_FORMAT (TYPE_MODE (type))->b == 2 |
13329 && TREE_CODE (arg0) == REAL_CST && !TREE_OVERFLOW (arg0) | 13032 && TREE_CODE (arg0) == REAL_CST && !TREE_OVERFLOW (arg0) |
13330 && TREE_CODE (arg1) == REAL_CST && !TREE_OVERFLOW (arg1)) | 13033 && TREE_CODE (arg1) == REAL_CST && !TREE_OVERFLOW (arg1)) |
13394 do_mpfr_lgamma_r (tree arg, tree arg_sg, tree type) | 13097 do_mpfr_lgamma_r (tree arg, tree arg_sg, tree type) |
13395 { | 13098 { |
13396 tree result = NULL_TREE; | 13099 tree result = NULL_TREE; |
13397 | 13100 |
13398 STRIP_NOPS (arg); | 13101 STRIP_NOPS (arg); |
13399 | 13102 |
13400 /* To proceed, MPFR must exactly represent the target floating point | 13103 /* To proceed, MPFR must exactly represent the target floating point |
13401 format, which only happens when the target base equals two. Also | 13104 format, which only happens when the target base equals two. Also |
13402 verify ARG is a constant and that ARG_SG is an int pointer. */ | 13105 verify ARG is a constant and that ARG_SG is an int pointer. */ |
13403 if (REAL_MODE_FORMAT (TYPE_MODE (type))->b == 2 | 13106 if (REAL_MODE_FORMAT (TYPE_MODE (type))->b == 2 |
13404 && TREE_CODE (arg) == REAL_CST && !TREE_OVERFLOW (arg) | 13107 && TREE_CODE (arg) == REAL_CST && !TREE_OVERFLOW (arg) |
13445 } | 13148 } |
13446 | 13149 |
13447 return result; | 13150 return result; |
13448 } | 13151 } |
13449 | 13152 |
13153 /* If argument ARG is a COMPLEX_CST, call the one-argument mpc | |
13154 function FUNC on it and return the resulting value as a tree with | |
13155 type TYPE. The mpfr precision is set to the precision of TYPE. We | |
13156 assume that function FUNC returns zero if the result could be | |
13157 calculated exactly within the requested precision. */ | |
13158 | |
13159 static tree | |
13160 do_mpc_arg1 (tree arg, tree type, int (*func)(mpc_ptr, mpc_srcptr, mpc_rnd_t)) | |
13161 { | |
13162 tree result = NULL_TREE; | |
13163 | |
13164 STRIP_NOPS (arg); | |
13165 | |
13166 /* To proceed, MPFR must exactly represent the target floating point | |
13167 format, which only happens when the target base equals two. */ | |
13168 if (TREE_CODE (arg) == COMPLEX_CST && !TREE_OVERFLOW (arg) | |
13169 && TREE_CODE (TREE_TYPE (TREE_TYPE (arg))) == REAL_TYPE | |
13170 && REAL_MODE_FORMAT (TYPE_MODE (TREE_TYPE (TREE_TYPE (arg))))->b == 2) | |
13171 { | |
13172 const REAL_VALUE_TYPE *const re = TREE_REAL_CST_PTR (TREE_REALPART (arg)); | |
13173 const REAL_VALUE_TYPE *const im = TREE_REAL_CST_PTR (TREE_IMAGPART (arg)); | |
13174 | |
13175 if (real_isfinite (re) && real_isfinite (im)) | |
13176 { | |
13177 const struct real_format *const fmt = | |
13178 REAL_MODE_FORMAT (TYPE_MODE (TREE_TYPE (type))); | |
13179 const int prec = fmt->p; | |
13180 const mp_rnd_t rnd = fmt->round_towards_zero ? GMP_RNDZ : GMP_RNDN; | |
13181 const mpc_rnd_t crnd = fmt->round_towards_zero ? MPC_RNDZZ : MPC_RNDNN; | |
13182 int inexact; | |
13183 mpc_t m; | |
13184 | |
13185 mpc_init2 (m, prec); | |
13186 mpfr_from_real (mpc_realref(m), re, rnd); | |
13187 mpfr_from_real (mpc_imagref(m), im, rnd); | |
13188 mpfr_clear_flags (); | |
13189 inexact = func (m, m, crnd); | |
13190 result = do_mpc_ckconv (m, type, inexact, /*force_convert=*/ 0); | |
13191 mpc_clear (m); | |
13192 } | |
13193 } | |
13194 | |
13195 return result; | |
13196 } | |
13197 | |
13198 /* If arguments ARG0 and ARG1 are a COMPLEX_CST, call the two-argument | |
13199 mpc function FUNC on it and return the resulting value as a tree | |
13200 with type TYPE. The mpfr precision is set to the precision of | |
13201 TYPE. We assume that function FUNC returns zero if the result | |
13202 could be calculated exactly within the requested precision. If | |
13203 DO_NONFINITE is true, then fold expressions containing Inf or NaN | |
13204 in the arguments and/or results. */ | |
13205 | |
13206 tree | |
13207 do_mpc_arg2 (tree arg0, tree arg1, tree type, int do_nonfinite, | |
13208 int (*func)(mpc_ptr, mpc_srcptr, mpc_srcptr, mpc_rnd_t)) | |
13209 { | |
13210 tree result = NULL_TREE; | |
13211 | |
13212 STRIP_NOPS (arg0); | |
13213 STRIP_NOPS (arg1); | |
13214 | |
13215 /* To proceed, MPFR must exactly represent the target floating point | |
13216 format, which only happens when the target base equals two. */ | |
13217 if (TREE_CODE (arg0) == COMPLEX_CST && !TREE_OVERFLOW (arg0) | |
13218 && TREE_CODE (TREE_TYPE (TREE_TYPE (arg0))) == REAL_TYPE | |
13219 && TREE_CODE (arg1) == COMPLEX_CST && !TREE_OVERFLOW (arg1) | |
13220 && TREE_CODE (TREE_TYPE (TREE_TYPE (arg1))) == REAL_TYPE | |
13221 && REAL_MODE_FORMAT (TYPE_MODE (TREE_TYPE (TREE_TYPE (arg0))))->b == 2) | |
13222 { | |
13223 const REAL_VALUE_TYPE *const re0 = TREE_REAL_CST_PTR (TREE_REALPART (arg0)); | |
13224 const REAL_VALUE_TYPE *const im0 = TREE_REAL_CST_PTR (TREE_IMAGPART (arg0)); | |
13225 const REAL_VALUE_TYPE *const re1 = TREE_REAL_CST_PTR (TREE_REALPART (arg1)); | |
13226 const REAL_VALUE_TYPE *const im1 = TREE_REAL_CST_PTR (TREE_IMAGPART (arg1)); | |
13227 | |
13228 if (do_nonfinite | |
13229 || (real_isfinite (re0) && real_isfinite (im0) | |
13230 && real_isfinite (re1) && real_isfinite (im1))) | |
13231 { | |
13232 const struct real_format *const fmt = | |
13233 REAL_MODE_FORMAT (TYPE_MODE (TREE_TYPE (type))); | |
13234 const int prec = fmt->p; | |
13235 const mp_rnd_t rnd = fmt->round_towards_zero ? GMP_RNDZ : GMP_RNDN; | |
13236 const mpc_rnd_t crnd = fmt->round_towards_zero ? MPC_RNDZZ : MPC_RNDNN; | |
13237 int inexact; | |
13238 mpc_t m0, m1; | |
13239 | |
13240 mpc_init2 (m0, prec); | |
13241 mpc_init2 (m1, prec); | |
13242 mpfr_from_real (mpc_realref(m0), re0, rnd); | |
13243 mpfr_from_real (mpc_imagref(m0), im0, rnd); | |
13244 mpfr_from_real (mpc_realref(m1), re1, rnd); | |
13245 mpfr_from_real (mpc_imagref(m1), im1, rnd); | |
13246 mpfr_clear_flags (); | |
13247 inexact = func (m0, m0, m1, crnd); | |
13248 result = do_mpc_ckconv (m0, type, inexact, do_nonfinite); | |
13249 mpc_clear (m0); | |
13250 mpc_clear (m1); | |
13251 } | |
13252 } | |
13253 | |
13254 return result; | |
13255 } | |
13256 | |
13450 /* FIXME tuples. | 13257 /* FIXME tuples. |
13451 The functions below provide an alternate interface for folding | 13258 The functions below provide an alternate interface for folding |
13452 builtin function calls presented as GIMPLE_CALL statements rather | 13259 builtin function calls presented as GIMPLE_CALL statements rather |
13453 than as CALL_EXPRs. The folded result is still expressed as a | 13260 than as CALL_EXPRs. The folded result is still expressed as a |
13454 tree. There is too much code duplication in the handling of | 13261 tree. There is too much code duplication in the handling of |
13469 tree fntype = TREE_TYPE (fndecl); | 13276 tree fntype = TREE_TYPE (fndecl); |
13470 tree fn = build1 (ADDR_EXPR, build_pointer_type (fntype), fndecl); | 13277 tree fn = build1 (ADDR_EXPR, build_pointer_type (fntype), fndecl); |
13471 tree *buffer; | 13278 tree *buffer; |
13472 int i, j; | 13279 int i, j; |
13473 va_list ap; | 13280 va_list ap; |
13281 location_t loc = gimple_location (stmt); | |
13474 | 13282 |
13475 buffer = XALLOCAVEC (tree, nargs); | 13283 buffer = XALLOCAVEC (tree, nargs); |
13476 va_start (ap, n); | 13284 va_start (ap, n); |
13477 for (i = 0; i < n; i++) | 13285 for (i = 0; i < n; i++) |
13478 buffer[i] = va_arg (ap, tree); | 13286 buffer[i] = va_arg (ap, tree); |
13479 va_end (ap); | 13287 va_end (ap); |
13480 for (j = skip; j < oldnargs; j++, i++) | 13288 for (j = skip; j < oldnargs; j++, i++) |
13481 buffer[i] = gimple_call_arg (stmt, j); | 13289 buffer[i] = gimple_call_arg (stmt, j); |
13482 | 13290 |
13483 return fold (build_call_array (TREE_TYPE (fntype), fn, nargs, buffer)); | 13291 return fold (build_call_array_loc (loc, TREE_TYPE (fntype), fn, nargs, buffer)); |
13484 } | 13292 } |
13485 | 13293 |
13486 /* Fold a call STMT to __{,v}sprintf_chk. Return NULL_TREE if | 13294 /* Fold a call STMT to __{,v}sprintf_chk. Return NULL_TREE if |
13487 a normal call should be emitted rather than expanding the function | 13295 a normal call should be emitted rather than expanding the function |
13488 inline. FCODE is either BUILT_IN_SPRINTF_CHK or BUILT_IN_VSPRINTF_CHK. */ | 13296 inline. FCODE is either BUILT_IN_SPRINTF_CHK or BUILT_IN_VSPRINTF_CHK. */ |
13657 only a few builtins that fall into this category. FNDECL is the | 13465 only a few builtins that fall into this category. FNDECL is the |
13658 function, EXP is the CALL_EXPR for the call, and IGNORE is true if the | 13466 function, EXP is the CALL_EXPR for the call, and IGNORE is true if the |
13659 result of the function call is ignored. */ | 13467 result of the function call is ignored. */ |
13660 | 13468 |
13661 static tree | 13469 static tree |
13662 gimple_fold_builtin_varargs (tree fndecl, gimple stmt, bool ignore ATTRIBUTE_UNUSED) | 13470 gimple_fold_builtin_varargs (tree fndecl, gimple stmt, |
13471 bool ignore ATTRIBUTE_UNUSED) | |
13663 { | 13472 { |
13664 enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl); | 13473 enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl); |
13665 tree ret = NULL_TREE; | 13474 tree ret = NULL_TREE; |
13666 | 13475 |
13667 switch (fcode) | 13476 switch (fcode) |
13694 tree | 13503 tree |
13695 fold_call_stmt (gimple stmt, bool ignore) | 13504 fold_call_stmt (gimple stmt, bool ignore) |
13696 { | 13505 { |
13697 tree ret = NULL_TREE; | 13506 tree ret = NULL_TREE; |
13698 tree fndecl = gimple_call_fndecl (stmt); | 13507 tree fndecl = gimple_call_fndecl (stmt); |
13508 location_t loc = gimple_location (stmt); | |
13699 if (fndecl | 13509 if (fndecl |
13700 && TREE_CODE (fndecl) == FUNCTION_DECL | 13510 && TREE_CODE (fndecl) == FUNCTION_DECL |
13701 && DECL_BUILT_IN (fndecl) | 13511 && DECL_BUILT_IN (fndecl) |
13702 && !gimple_call_va_arg_pack_p (stmt)) | 13512 && !gimple_call_va_arg_pack_p (stmt)) |
13703 { | 13513 { |
13720 { | 13530 { |
13721 tree args[MAX_ARGS_TO_FOLD_BUILTIN]; | 13531 tree args[MAX_ARGS_TO_FOLD_BUILTIN]; |
13722 int i; | 13532 int i; |
13723 for (i = 0; i < nargs; i++) | 13533 for (i = 0; i < nargs; i++) |
13724 args[i] = gimple_call_arg (stmt, i); | 13534 args[i] = gimple_call_arg (stmt, i); |
13725 ret = fold_builtin_n (fndecl, args, nargs, ignore); | 13535 ret = fold_builtin_n (loc, fndecl, args, nargs, ignore); |
13726 } | 13536 } |
13727 if (!ret) | 13537 if (!ret) |
13728 ret = gimple_fold_builtin_varargs (fndecl, stmt, ignore); | 13538 ret = gimple_fold_builtin_varargs (fndecl, stmt, ignore); |
13729 if (ret) | 13539 if (ret) |
13730 { | 13540 { |
13737 tree realret = ret; | 13547 tree realret = ret; |
13738 if (TREE_CODE (ret) == NOP_EXPR) | 13548 if (TREE_CODE (ret) == NOP_EXPR) |
13739 realret = TREE_OPERAND (ret, 0); | 13549 realret = TREE_OPERAND (ret, 0); |
13740 if (CAN_HAVE_LOCATION_P (realret) | 13550 if (CAN_HAVE_LOCATION_P (realret) |
13741 && !EXPR_HAS_LOCATION (realret)) | 13551 && !EXPR_HAS_LOCATION (realret)) |
13742 SET_EXPR_LOCATION (realret, gimple_location (stmt)); | 13552 SET_EXPR_LOCATION (realret, loc); |
13743 return realret; | 13553 return realret; |
13744 } | 13554 } |
13745 return ret; | 13555 return ret; |
13746 } | 13556 } |
13747 } | 13557 } |
13748 } | 13558 } |
13749 return NULL_TREE; | 13559 return NULL_TREE; |
13750 } | 13560 } |
13561 | |
13562 /* Look up the function in built_in_decls that corresponds to DECL | |
13563 and set ASMSPEC as its user assembler name. DECL must be a | |
13564 function decl that declares a builtin. */ | |
13565 | |
13566 void | |
13567 set_builtin_user_assembler_name (tree decl, const char *asmspec) | |
13568 { | |
13569 tree builtin; | |
13570 gcc_assert (TREE_CODE (decl) == FUNCTION_DECL | |
13571 && DECL_BUILT_IN_CLASS (decl) == BUILT_IN_NORMAL | |
13572 && asmspec != 0); | |
13573 | |
13574 builtin = built_in_decls [DECL_FUNCTION_CODE (decl)]; | |
13575 set_user_assembler_name (builtin, asmspec); | |
13576 switch (DECL_FUNCTION_CODE (decl)) | |
13577 { | |
13578 case BUILT_IN_MEMCPY: | |
13579 init_block_move_fn (asmspec); | |
13580 memcpy_libfunc = set_user_assembler_libfunc ("memcpy", asmspec); | |
13581 break; | |
13582 case BUILT_IN_MEMSET: | |
13583 init_block_clear_fn (asmspec); | |
13584 memset_libfunc = set_user_assembler_libfunc ("memset", asmspec); | |
13585 break; | |
13586 case BUILT_IN_MEMMOVE: | |
13587 memmove_libfunc = set_user_assembler_libfunc ("memmove", asmspec); | |
13588 break; | |
13589 case BUILT_IN_MEMCMP: | |
13590 memcmp_libfunc = set_user_assembler_libfunc ("memcmp", asmspec); | |
13591 break; | |
13592 case BUILT_IN_ABORT: | |
13593 abort_libfunc = set_user_assembler_libfunc ("abort", asmspec); | |
13594 break; | |
13595 default: | |
13596 break; | |
13597 } | |
13598 } |