1 /* Expand builtin functions.
2    Copyright (C) 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
3    2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
4 
5 This file is part of GCC.
6 
7 GCC is free software; you can redistribute it and/or modify it under
8 the terms of the GNU General Public License as published by the Free
9 Software Foundation; either version 2, or (at your option) any later
10 version.
11 
12 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
13 WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
15 for more details.
16 
17 You should have received a copy of the GNU General Public License
18 along with GCC; see the file COPYING.  If not, write to the Free
19 Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
20 02110-1301, USA.  */
21 
22 #include "config.h"
23 #include "system.h"
24 #include "coretypes.h"
25 #include "tm.h"
26 #include "machmode.h"
27 #include "real.h"
28 #include "rtl.h"
29 #include "tree.h"
30 #include "tree-gimple.h"
31 #include "flags.h"
32 #include "regs.h"
33 #include "hard-reg-set.h"
34 #include "except.h"
35 #include "function.h"
36 #include "insn-config.h"
37 #include "expr.h"
38 #include "optabs.h"
39 #include "libfuncs.h"
40 #include "recog.h"
41 #include "output.h"
42 #include "typeclass.h"
43 #include "toplev.h"
44 #include "predict.h"
45 #include "tm_p.h"
46 #include "target.h"
47 #include "langhooks.h"
48 #include "basic-block.h"
49 #include "tree-mudflap.h"
50 #include "ggc.h"
51 
52 #ifndef PAD_VARARGS_DOWN
53 #define PAD_VARARGS_DOWN BYTES_BIG_ENDIAN
54 #endif
55 
56 /* Define the names of the builtin function types and codes.  */
57 const char *const built_in_class_names[4]
58   = {"NOT_BUILT_IN", "BUILT_IN_FRONTEND", "BUILT_IN_MD", "BUILT_IN_NORMAL"};
59 
60 #define DEF_BUILTIN(X, N, C, T, LT, B, F, NA, AT, IM, COND) #X,
61 const char * built_in_names[(int) END_BUILTINS] =
62 {
63 #include "builtins.def"
64 };
65 #undef DEF_BUILTIN
66 
67 /* Setup an array of _DECL trees, make sure each element is
68    initialized to NULL_TREE.  */
69 tree built_in_decls[(int) END_BUILTINS];
70 /* Declarations used when constructing the builtin implicitly in the compiler.
71    It may be NULL_TREE when this is invalid (for instance runtime is not
72    required to implement the function call in all cases).  */
73 tree implicit_built_in_decls[(int) END_BUILTINS];
74 
75 static int get_pointer_alignment (tree, unsigned int);
76 static const char *c_getstr (tree);
77 static rtx c_readstr (const char *, enum machine_mode);
78 static int target_char_cast (tree, char *);
79 static rtx get_memory_rtx (tree, tree);
80 #if 0
81 static tree build_string_literal (int, const char *);
82 #endif /* 0 */
83 static int apply_args_size (void);
84 static int apply_result_size (void);
85 #if defined (HAVE_untyped_call) || defined (HAVE_untyped_return)
86 static rtx result_vector (int, rtx);
87 #endif
88 static rtx expand_builtin_setjmp (tree, rtx);
89 static void expand_builtin_update_setjmp_buf (rtx);
90 static void expand_builtin_prefetch (tree);
91 static rtx expand_builtin_apply_args (void);
92 static rtx expand_builtin_apply_args_1 (void);
93 static rtx expand_builtin_apply (rtx, rtx, rtx);
94 static void expand_builtin_return (rtx);
95 static enum type_class type_to_class (tree);
96 static rtx expand_builtin_classify_type (tree);
97 #if 0
98 static void expand_errno_check (tree, rtx);
99 static rtx expand_builtin_mathfn (tree, rtx, rtx);
100 static rtx expand_builtin_mathfn_2 (tree, rtx, rtx);
101 static rtx expand_builtin_mathfn_3 (tree, rtx, rtx);
102 static rtx expand_builtin_int_roundingfn (tree, rtx, rtx);
103 #endif /* 0 */
104 static rtx expand_builtin_args_info (tree);
105 static rtx expand_builtin_next_arg (void);
106 static rtx expand_builtin_va_start (tree);
107 static rtx expand_builtin_va_end (tree);
108 static rtx expand_builtin_va_copy (tree);
109 #if 0
110 static rtx expand_builtin_memcmp (tree, tree, rtx, enum machine_mode);
111 static rtx expand_builtin_strcmp (tree, rtx, enum machine_mode);
112 static rtx expand_builtin_strncmp (tree, rtx, enum machine_mode);
113 #endif /* 0 */
114 static rtx builtin_memcpy_read_str (void *, HOST_WIDE_INT, enum machine_mode);
115 #if 0
116 static rtx expand_builtin_strcat (tree, tree, rtx, enum machine_mode);
117 static rtx expand_builtin_strncat (tree, rtx, enum machine_mode);
118 static rtx expand_builtin_strspn (tree, rtx, enum machine_mode);
119 static rtx expand_builtin_strcspn (tree, rtx, enum machine_mode);
120 #endif /* 0 */
121 static rtx expand_builtin_memcpy (tree, rtx, enum machine_mode);
122 #if 0
123 static rtx expand_builtin_mempcpy (tree, tree, rtx, enum machine_mode, int);
124 static rtx expand_builtin_memmove (tree, tree, rtx, enum machine_mode, tree);
125 static rtx expand_builtin_bcopy (tree);
126 static rtx expand_builtin_strcpy (tree, tree, rtx, enum machine_mode);
127 static rtx expand_builtin_stpcpy (tree, rtx, enum machine_mode);
128 static rtx builtin_strncpy_read_str (void *, HOST_WIDE_INT, enum machine_mode);
129 static rtx expand_builtin_strncpy (tree, rtx, enum machine_mode);
130 #endif /* 0 */
131 static rtx builtin_memset_read_str (void *, HOST_WIDE_INT, enum machine_mode);
132 static rtx builtin_memset_gen_str (void *, HOST_WIDE_INT, enum machine_mode);
133 static rtx expand_builtin_memset (tree, rtx, enum machine_mode, tree);
134 #if 0
135 static rtx expand_builtin_bzero (tree);
136 static rtx expand_builtin_strlen (tree, rtx, enum machine_mode);
137 static rtx expand_builtin_strstr (tree, tree, rtx, enum machine_mode);
138 static rtx expand_builtin_strpbrk (tree, tree, rtx, enum machine_mode);
139 static rtx expand_builtin_strchr (tree, tree, rtx, enum machine_mode);
140 static rtx expand_builtin_strrchr (tree, tree, rtx, enum machine_mode);
141 #endif /* 0 */
142 static rtx expand_builtin_alloca (tree, rtx);
143 static rtx expand_builtin_unop (enum machine_mode, tree, rtx, rtx, optab);
144 static rtx expand_builtin_frame_address (tree, tree);
145 #if 0
146 static rtx expand_builtin_fputs (tree, rtx, bool);
147 static rtx expand_builtin_printf (tree, rtx, enum machine_mode, bool);
148 static rtx expand_builtin_fprintf (tree, rtx, enum machine_mode, bool);
149 static rtx expand_builtin_sprintf (tree, rtx, enum machine_mode);
150 #endif /* 0 */
151 static tree stabilize_va_list (tree, int);
152 static rtx expand_builtin_expect (tree, rtx);
153 static tree fold_builtin_constant_p (tree);
154 static tree fold_builtin_classify_type (tree);
155 #if 0
156 static tree fold_builtin_strlen (tree);
157 static tree fold_builtin_inf (tree, int);
158 static tree fold_builtin_nan (tree, tree, int);
159 #endif /* 0 */
160 static int validate_arglist (tree, ...);
161 #if 0
162 static bool integer_valued_real_p (tree);
163 static tree fold_trunc_transparent_mathfn (tree, tree);
164 #endif /* 0 */
165 static bool readonly_data_expr (tree);
166 #if 0
167 static rtx expand_builtin_fabs (tree, rtx, rtx);
168 static rtx expand_builtin_signbit (tree, rtx);
169 static tree fold_builtin_cabs (tree, tree);
170 static tree fold_builtin_sqrt (tree, tree);
171 static tree fold_builtin_cbrt (tree, tree);
172 static tree fold_builtin_pow (tree, tree, tree);
173 static tree fold_builtin_powi (tree, tree, tree);
174 static tree fold_builtin_sin (tree);
175 static tree fold_builtin_cos (tree, tree, tree);
176 static tree fold_builtin_tan (tree);
177 static tree fold_builtin_atan (tree, tree);
178 static tree fold_builtin_trunc (tree, tree);
179 static tree fold_builtin_floor (tree, tree);
180 static tree fold_builtin_ceil (tree, tree);
181 static tree fold_builtin_round (tree, tree);
182 static tree fold_builtin_int_roundingfn (tree, tree);
183 static tree fold_builtin_bitop (tree, tree);
184 #endif /* 0 */
185 static tree fold_builtin_memcpy (tree, tree);
186 #if 0
187 static tree fold_builtin_mempcpy (tree, tree, int);
188 static tree fold_builtin_memmove (tree, tree);
189 static tree fold_builtin_strchr (tree, tree);
190 static tree fold_builtin_memcmp (tree);
191 static tree fold_builtin_strcmp (tree);
192 static tree fold_builtin_strncmp (tree);
193 static tree fold_builtin_signbit (tree, tree);
194 static tree fold_builtin_copysign (tree, tree, tree);
195 static tree fold_builtin_isascii (tree);
196 static tree fold_builtin_toascii (tree);
197 static tree fold_builtin_isdigit (tree);
198 static tree fold_builtin_fabs (tree, tree);
199 static tree fold_builtin_abs (tree, tree);
200 static tree fold_builtin_unordered_cmp (tree, tree, enum tree_code,
201 					enum tree_code);
202 #endif /* 0 */
203 static tree fold_builtin_1 (tree, tree, bool);
204 
205 #if 0
206 static tree fold_builtin_strpbrk (tree, tree);
207 static tree fold_builtin_strstr (tree, tree);
208 static tree fold_builtin_strrchr (tree, tree);
209 static tree fold_builtin_strcat (tree);
210 static tree fold_builtin_strncat (tree);
211 static tree fold_builtin_strspn (tree);
212 static tree fold_builtin_strcspn (tree);
213 static tree fold_builtin_sprintf (tree, int);
214 
215 static rtx expand_builtin_object_size (tree);
216 static rtx expand_builtin_memory_chk (tree, rtx, enum machine_mode,
217 				      enum built_in_function);
218 static void maybe_emit_chk_warning (tree, enum built_in_function);
219 static void maybe_emit_sprintf_chk_warning (tree, enum built_in_function);
220 static tree fold_builtin_object_size (tree);
221 static tree fold_builtin_strcat_chk (tree, tree);
222 static tree fold_builtin_strncat_chk (tree, tree);
223 static tree fold_builtin_sprintf_chk (tree, enum built_in_function);
224 static tree fold_builtin_printf (tree, tree, bool, enum built_in_function);
225 static tree fold_builtin_fprintf (tree, tree, bool, enum built_in_function);
226 static bool init_target_chars (void);
227 
228 static unsigned HOST_WIDE_INT target_newline;
229 static unsigned HOST_WIDE_INT target_percent;
230 static unsigned HOST_WIDE_INT target_c;
231 static unsigned HOST_WIDE_INT target_s;
232 static char target_percent_c[3];
233 static char target_percent_s[3];
234 static char target_percent_s_newline[4];
235 #endif /* 0 */
236 
237 /* (TIGCC 20050206) Implement ER_throw. */
238 static void expand_builtin_ER_throw (tree);
239 
240 /* Return true if NODE should be considered for inline expansion regardless
241    of the optimization level.  This means whenever a function is invoked with
242    its "internal" name, which normally contains the prefix "__builtin".  */
243 
called_as_built_in(tree node)244 static bool called_as_built_in (tree node)
245 {
246   const char *name = IDENTIFIER_POINTER (DECL_NAME (node));
247   if (strncmp (name, "__builtin_", 10) == 0)
248     return true;
249   if (strncmp (name, "__sync_", 7) == 0)
250     return true;
251   return false;
252 }
253 
254 /* Return the alignment in bits of EXP, a pointer valued expression.
255    But don't return more than MAX_ALIGN no matter what.
256    The alignment returned is, by default, the alignment of the thing that
257    EXP points to.  If it is not a POINTER_TYPE, 0 is returned.
258 
259    Otherwise, look at the expression to see if we can do better, i.e., if the
260    expression is actually pointing at an object whose alignment is tighter.  */
261 
262 static int
get_pointer_alignment(tree exp,unsigned int max_align)263 get_pointer_alignment (tree exp, unsigned int max_align)
264 {
265   unsigned int align, inner;
266 
267   if (! POINTER_TYPE_P (TREE_TYPE (exp)))
268     return 0;
269 
270   align = TYPE_ALIGN (TREE_TYPE (TREE_TYPE (exp)));
271   align = MIN (align, max_align);
272 
273   while (1)
274     {
275       switch (TREE_CODE (exp))
276 	{
277 	case NOP_EXPR:
278 	case CONVERT_EXPR:
279 	case NON_LVALUE_EXPR:
280 	  exp = TREE_OPERAND (exp, 0);
281 	  if (! POINTER_TYPE_P (TREE_TYPE (exp)))
282 	    return align;
283 
284 	  inner = TYPE_ALIGN (TREE_TYPE (TREE_TYPE (exp)));
285 	  align = MIN (inner, max_align);
286 	  break;
287 
288 	case PLUS_EXPR:
289 	  /* If sum of pointer + int, restrict our maximum alignment to that
290 	     imposed by the integer.  If not, we can't do any better than
291 	     ALIGN.  */
292 	  if (! host_integerp (TREE_OPERAND (exp, 1), 1))
293 	    return align;
294 
295 	  while (((tree_low_cst (TREE_OPERAND (exp, 1), 1))
296 		  & (max_align / BITS_PER_UNIT - 1))
297 		 != 0)
298 	    max_align >>= 1;
299 
300 	  exp = TREE_OPERAND (exp, 0);
301 	  break;
302 
303 	case ADDR_EXPR:
304 	  /* See what we are pointing at and look at its alignment.  */
305 	  exp = TREE_OPERAND (exp, 0);
306 	  inner = max_align;
307 	  while (handled_component_p (exp))
308 	    {
309 	      /* Fields in a structure can be packed, honour DECL_ALIGN
310 		 of the FIELD_DECL.  For all other references the conservative
311 		 alignment is the element type alignment.  */
312 	      if (TREE_CODE (exp) == COMPONENT_REF)
313 		inner = MIN (inner, DECL_ALIGN (TREE_OPERAND (exp, 1)));
314 	      else
315 		inner = MIN (inner, TYPE_ALIGN (TREE_TYPE (exp)));
316 	      exp = TREE_OPERAND (exp, 0);
317 	    }
318 	  if (TREE_CODE (exp) == FUNCTION_DECL)
319 	    align = FUNCTION_BOUNDARY;
320 	  else if (DECL_P (exp))
321 	    align = MIN (inner, DECL_ALIGN (exp));
322 #ifdef CONSTANT_ALIGNMENT
323 	  else if (CONSTANT_CLASS_P (exp))
324 	    align = MIN (inner, (unsigned)CONSTANT_ALIGNMENT (exp, align));
325 #endif
326 	  else
327 	    align = MIN (align, inner);
328 	  return MIN (align, max_align);
329 
330 	default:
331 	  return align;
332 	}
333     }
334 }
335 
336 /* Compute the length of a C string.  TREE_STRING_LENGTH is not the right
337    way, because it could contain a zero byte in the middle.
338    TREE_STRING_LENGTH is the size of the character array, not the string.
339 
340    ONLY_VALUE should be nonzero if the result is not going to be emitted
341    into the instruction stream and zero if it is going to be expanded.
342    E.g. with i++ ? "foo" : "bar", if ONLY_VALUE is nonzero, constant 3
343    is returned, otherwise NULL, since
344    len = c_strlen (src, 1); if (len) expand_expr (len, ...); would not
345    evaluate the side-effects.
346 
347    The value returned is of type `ssizetype'.
348 
349    Unfortunately, string_constant can't access the values of const char
350    arrays with initializers, so neither can we do so here.  */
351 
352 tree
c_strlen(tree src,int only_value)353 c_strlen (tree src, int only_value)
354 {
355   tree offset_node;
356   HOST_WIDE_INT offset;
357   int max;
358   const char *ptr;
359 
360   STRIP_NOPS (src);
361   if (TREE_CODE (src) == COND_EXPR
362       && (only_value || !TREE_SIDE_EFFECTS (TREE_OPERAND (src, 0))))
363     {
364       tree len1, len2;
365 
366       len1 = c_strlen (TREE_OPERAND (src, 1), only_value);
367       len2 = c_strlen (TREE_OPERAND (src, 2), only_value);
368       if (tree_int_cst_equal (len1, len2))
369 	return len1;
370     }
371 
372   if (TREE_CODE (src) == COMPOUND_EXPR
373       && (only_value || !TREE_SIDE_EFFECTS (TREE_OPERAND (src, 0))))
374     return c_strlen (TREE_OPERAND (src, 1), only_value);
375 
376   src = string_constant (src, &offset_node);
377   if (src == 0)
378     return 0;
379 
380   max = TREE_STRING_LENGTH (src) - 1;
381   ptr = TREE_STRING_POINTER (src);
382 
383   if (offset_node && TREE_CODE (offset_node) != INTEGER_CST)
384     {
385       /* If the string has an internal zero byte (e.g., "foo\0bar"), we can't
386 	 compute the offset to the following null if we don't know where to
387 	 start searching for it.  */
388       int i;
389 
390       for (i = 0; i < max; i++)
391 	if (ptr[i] == 0)
392 	  return 0;
393 
394       /* We don't know the starting offset, but we do know that the string
395 	 has no internal zero bytes.  We can assume that the offset falls
396 	 within the bounds of the string; otherwise, the programmer deserves
397 	 what he gets.  Subtract the offset from the length of the string,
398 	 and return that.  This would perhaps not be valid if we were dealing
399 	 with named arrays in addition to literal string constants.  */
400 
401       return size_diffop (size_int (max), offset_node);
402     }
403 
404   /* We have a known offset into the string.  Start searching there for
405      a null character if we can represent it as a single HOST_WIDE_INT.  */
406   if (offset_node == 0)
407     offset = 0;
408   else if (! host_integerp (offset_node, 0))
409     offset = -1;
410   else
411     offset = tree_low_cst (offset_node, 0);
412 
413   /* If the offset is known to be out of bounds, warn, and call strlen at
414      runtime.  */
415   if (offset < 0 || offset > max)
416     {
417       warning (0, "offset outside bounds of constant string");
418       return 0;
419     }
420 
421   /* Use strlen to search for the first zero byte.  Since any strings
422      constructed with build_string will have nulls appended, we win even
423      if we get handed something like (char[4])"abcd".
424 
425      Since OFFSET is our starting index into the string, no further
426      calculation is needed.  */
427   return ssize_int (strlen (ptr + offset));
428 }
429 
430 /* Return a char pointer for a C string if it is a string constant
431    or sum of string constant and integer constant.  */
432 
433 static const char *
c_getstr(tree src)434 c_getstr (tree src)
435 {
436   tree offset_node;
437 
438   src = string_constant (src, &offset_node);
439   if (src == 0)
440     return 0;
441 
442   if (offset_node == 0)
443     return TREE_STRING_POINTER (src);
444   else if (!host_integerp (offset_node, 1)
445 	   || compare_tree_int (offset_node, TREE_STRING_LENGTH (src) - 1) > 0)
446     return 0;
447 
448   return TREE_STRING_POINTER (src) + tree_low_cst (offset_node, 1);
449 }
450 
451 /* Return a CONST_INT or CONST_DOUBLE corresponding to target reading
452    GET_MODE_BITSIZE (MODE) bits from string constant STR.  */
453 
454 static rtx
c_readstr(const char * str,enum machine_mode mode)455 c_readstr (const char *str, enum machine_mode mode)
456 {
457   HOST_WIDE_INT c[2];
458   HOST_WIDE_INT ch;
459   unsigned int i, j;
460 
461   gcc_assert (GET_MODE_CLASS (mode) == MODE_INT);
462 
463   c[0] = 0;
464   c[1] = 0;
465   ch = 1;
466   for (i = 0; i < GET_MODE_SIZE (mode); i++)
467     {
468       j = i;
469       if (WORDS_BIG_ENDIAN)
470 	j = GET_MODE_SIZE (mode) - i - 1;
471       if (BYTES_BIG_ENDIAN != WORDS_BIG_ENDIAN
472 	  && GET_MODE_SIZE (mode) > UNITS_PER_WORD)
473 	j = j + UNITS_PER_WORD - 2 * (j % UNITS_PER_WORD) - 1;
474       j *= BITS_PER_UNIT;
475       gcc_assert (j <= 2 * HOST_BITS_PER_WIDE_INT);
476 
477       if (ch)
478 	ch = (unsigned char) str[i];
479       c[j / HOST_BITS_PER_WIDE_INT] |= ch << (j % HOST_BITS_PER_WIDE_INT);
480     }
481   return immed_double_const (c[0], c[1], mode);
482 }
483 
484 /* Cast a target constant CST to target CHAR and if that value fits into
485    host char type, return zero and put that value into variable pointed to by
486    P.  */
487 
488 static int
target_char_cast(tree cst,char * p)489 target_char_cast (tree cst, char *p)
490 {
491   unsigned HOST_WIDE_INT val, hostval;
492 
493   if (!host_integerp (cst, 1)
494       || CHAR_TYPE_SIZE > HOST_BITS_PER_WIDE_INT)
495     return 1;
496 
497   val = tree_low_cst (cst, 1);
498   if (CHAR_TYPE_SIZE < HOST_BITS_PER_WIDE_INT)
499     val &= (((unsigned HOST_WIDE_INT) 1) << CHAR_TYPE_SIZE) - 1;
500 
501   hostval = val;
502   if (HOST_BITS_PER_CHAR < HOST_BITS_PER_WIDE_INT)
503     hostval &= (((unsigned HOST_WIDE_INT) 1) << HOST_BITS_PER_CHAR) - 1;
504 
505   if (val != hostval)
506     return 1;
507 
508   *p = hostval;
509   return 0;
510 }
511 
512 /* Similar to save_expr, but assumes that arbitrary code is not executed
513    in between the multiple evaluations.  In particular, we assume that a
514    non-addressable local variable will not be modified.  */
515 
516 static tree
builtin_save_expr(tree exp)517 builtin_save_expr (tree exp)
518 {
519   if (TREE_ADDRESSABLE (exp) == 0
520       && (TREE_CODE (exp) == PARM_DECL
521 	  || (TREE_CODE (exp) == VAR_DECL && !TREE_STATIC (exp))))
522     return exp;
523 
524   return save_expr (exp);
525 }
526 
527 /* Given TEM, a pointer to a stack frame, follow the dynamic chain COUNT
528    times to get the address of either a higher stack frame, or a return
529    address located within it (depending on FNDECL_CODE).  */
530 
531 static rtx
expand_builtin_return_addr(enum built_in_function fndecl_code,int count)532 expand_builtin_return_addr (enum built_in_function fndecl_code, int count)
533 {
534   int i;
535 
536 #ifdef INITIAL_FRAME_ADDRESS_RTX
537   rtx tem = INITIAL_FRAME_ADDRESS_RTX;
538 #else
539   rtx tem;
540 
541   /* For a zero count, we don't care what frame address we return, so frame
542      pointer elimination is OK, and using the soft frame pointer is OK.
543      For a non-zero count, we require a stable offset from the current frame
544      pointer to the previous one, so we must use the hard frame pointer, and
545      we must disable frame pointer elimination.  */
546   if (count == 0)
547     tem = frame_pointer_rtx;
548   else
549     {
550       tem = hard_frame_pointer_rtx;
551 
552       /* Tell reload not to eliminate the frame pointer.  */
553       current_function_accesses_prior_frames = 1;
554     }
555 #endif
556 
557   /* Some machines need special handling before we can access
558      arbitrary frames.  For example, on the sparc, we must first flush
559      all register windows to the stack.  */
560 #ifdef SETUP_FRAME_ADDRESSES
561   if (count > 0)
562     SETUP_FRAME_ADDRESSES ();
563 #endif
564 
565   /* On the sparc, the return address is not in the frame, it is in a
566      register.  There is no way to access it off of the current frame
567      pointer, but it can be accessed off the previous frame pointer by
568      reading the value from the register window save area.  */
569 #ifdef RETURN_ADDR_IN_PREVIOUS_FRAME
570   if (fndecl_code == BUILT_IN_RETURN_ADDRESS)
571     count--;
572 #endif
573 
574   /* Scan back COUNT frames to the specified frame.  */
575   for (i = 0; i < count; i++)
576     {
577       /* Assume the dynamic chain pointer is in the word that the
578 	 frame address points to, unless otherwise specified.  */
579 #ifdef DYNAMIC_CHAIN_ADDRESS
580       tem = DYNAMIC_CHAIN_ADDRESS (tem);
581 #endif
582       tem = memory_address (Pmode, tem);
583       tem = gen_frame_mem (Pmode, tem);
584       tem = copy_to_reg (tem);
585     }
586 
587   /* For __builtin_frame_address, return what we've got.  */
588   if (fndecl_code == BUILT_IN_FRAME_ADDRESS)
589     return tem;
590 
591   /* For __builtin_return_address, Get the return address from that
592      frame.  */
593 #ifdef RETURN_ADDR_RTX
594   tem = RETURN_ADDR_RTX (count, tem);
595 #else
596   tem = memory_address (Pmode,
597 			plus_constant (tem, GET_MODE_SIZE (Pmode)));
598   tem = gen_frame_mem (Pmode, tem);
599 #endif
600   return tem;
601 }
602 
603 /* Alias set used for setjmp buffer.  */
604 static HOST_WIDE_INT setjmp_alias_set = -1;
605 
606 /* Construct the leading half of a __builtin_setjmp call.  Control will
607    return to RECEIVER_LABEL.  This is used directly by sjlj exception
608    handling code.  */
609 
610 void
expand_builtin_setjmp_setup(rtx buf_addr,rtx receiver_label)611 expand_builtin_setjmp_setup (rtx buf_addr, rtx receiver_label)
612 {
613   enum machine_mode sa_mode = STACK_SAVEAREA_MODE (SAVE_NONLOCAL);
614   rtx stack_save;
615   rtx mem;
616 
617   if (setjmp_alias_set == -1)
618     setjmp_alias_set = new_alias_set ();
619 
620   buf_addr = convert_memory_address (Pmode, buf_addr);
621 
622   buf_addr = force_reg (Pmode, force_operand (buf_addr, NULL_RTX));
623 
624   /* We store the frame pointer and the address of receiver_label in
625      the buffer and use the rest of it for the stack save area, which
626      is machine-dependent.  */
627 
628   mem = gen_rtx_MEM (Pmode, buf_addr);
629   set_mem_alias_set (mem, setjmp_alias_set);
630   emit_move_insn (mem, targetm.builtin_setjmp_frame_value ());
631 
632   mem = gen_rtx_MEM (Pmode, plus_constant (buf_addr, GET_MODE_SIZE (Pmode))),
633   set_mem_alias_set (mem, setjmp_alias_set);
634 
635   emit_move_insn (validize_mem (mem),
636 		  force_reg (Pmode, gen_rtx_LABEL_REF (Pmode, receiver_label)));
637 
638   stack_save = gen_rtx_MEM (sa_mode,
639 			    plus_constant (buf_addr,
640 					   2 * GET_MODE_SIZE (Pmode)));
641   set_mem_alias_set (stack_save, setjmp_alias_set);
642   emit_stack_save (SAVE_NONLOCAL, &stack_save, NULL_RTX);
643 
644   /* If there is further processing to do, do it.  */
645 #ifdef HAVE_builtin_setjmp_setup
646   if (HAVE_builtin_setjmp_setup)
647     emit_insn (gen_builtin_setjmp_setup (buf_addr));
648 #endif
649 
650   /* Tell optimize_save_area_alloca that extra work is going to
651      need to go on during alloca.  */
652   current_function_calls_setjmp = 1;
653 
654   /* Set this so all the registers get saved in our frame; we need to be
655      able to copy the saved values for any registers from frames we unwind.  */
656   current_function_has_nonlocal_label = 1;
657 }
658 
659 /* Construct the trailing part of a __builtin_setjmp call.
660    This is used directly by sjlj exception handling code.  */
661 
662 void
expand_builtin_setjmp_receiver(rtx receiver_label ATTRIBUTE_UNUSED)663 expand_builtin_setjmp_receiver (rtx receiver_label ATTRIBUTE_UNUSED)
664 {
665   /* Clobber the FP when we get here, so we have to make sure it's
666      marked as used by this function.  */
667   emit_insn (gen_rtx_USE (VOIDmode, hard_frame_pointer_rtx));
668 
669   /* Mark the static chain as clobbered here so life information
670      doesn't get messed up for it.  */
671   emit_insn (gen_rtx_CLOBBER (VOIDmode, static_chain_rtx));
672 
673   /* Now put in the code to restore the frame pointer, and argument
674      pointer, if needed.  */
675 #ifdef HAVE_nonlocal_goto
676   if (! HAVE_nonlocal_goto)
677 #endif
678     emit_move_insn (virtual_stack_vars_rtx, hard_frame_pointer_rtx);
679 
680 #if ARG_POINTER_REGNUM != HARD_FRAME_POINTER_REGNUM
681   if (fixed_regs[ARG_POINTER_REGNUM])
682     {
683 #ifdef ELIMINABLE_REGS
684       size_t i;
685       static const struct elims {const int from, to;} elim_regs[] = ELIMINABLE_REGS;
686 
687       for (i = 0; i < ARRAY_SIZE (elim_regs); i++)
688 	if (elim_regs[i].from == ARG_POINTER_REGNUM
689 	    && elim_regs[i].to == HARD_FRAME_POINTER_REGNUM)
690 	  break;
691 
692       if (i == ARRAY_SIZE (elim_regs))
693 #endif
694 	{
695 	  /* Now restore our arg pointer from the address at which it
696 	     was saved in our stack frame.  */
697 	  emit_move_insn (virtual_incoming_args_rtx,
698 			  copy_to_reg (get_arg_pointer_save_area (cfun)));
699 	}
700     }
701 #endif
702 
703 #ifdef HAVE_builtin_setjmp_receiver
704   if (HAVE_builtin_setjmp_receiver)
705     emit_insn (gen_builtin_setjmp_receiver (receiver_label));
706   else
707 #endif
708 #ifdef HAVE_nonlocal_goto_receiver
709     if (HAVE_nonlocal_goto_receiver)
710       emit_insn (gen_nonlocal_goto_receiver ());
711     else
712 #endif
713       { /* Nothing */ }
714 
715   /* @@@ This is a kludge.  Not all machine descriptions define a blockage
716      insn, but we must not allow the code we just generated to be reordered
717      by scheduling.  Specifically, the update of the frame pointer must
718      happen immediately, not later.  So emit an ASM_INPUT to act as blockage
719      insn.  */
720   emit_insn (gen_rtx_ASM_INPUT (VOIDmode, ""));
721 }
722 
723 /* __builtin_setjmp is passed a pointer to an array of five words (not
724    all will be used on all machines).  It operates similarly to the C
725    library function of the same name, but is more efficient.  Much of
726    the code below (and for longjmp) is copied from the handling of
727    non-local gotos.
728 
729    NOTE: This is intended for use by GNAT and the exception handling
730    scheme in the compiler and will only work in the method used by
731    them.  */
732 
733 static rtx
expand_builtin_setjmp(tree arglist,rtx target)734 expand_builtin_setjmp (tree arglist, rtx target)
735 {
736   rtx buf_addr, next_lab, cont_lab;
737 
738   if (!validate_arglist (arglist, POINTER_TYPE, VOID_TYPE))
739     return NULL_RTX;
740 
741   if (target == 0 || !REG_P (target)
742       || REGNO (target) < FIRST_PSEUDO_REGISTER)
743     target = gen_reg_rtx (TYPE_MODE (integer_type_node));
744 
745   buf_addr = expand_expr (TREE_VALUE (arglist), NULL_RTX, VOIDmode, 0);
746 
747   next_lab = gen_label_rtx ();
748   cont_lab = gen_label_rtx ();
749 
750   expand_builtin_setjmp_setup (buf_addr, next_lab);
751 
752   /* Set TARGET to zero and branch to the continue label.  Use emit_jump to
753      ensure that pending stack adjustments are flushed.  */
754   emit_move_insn (target, const0_rtx);
755   emit_jump (cont_lab);
756 
757   emit_label (next_lab);
758 
759   expand_builtin_setjmp_receiver (next_lab);
760 
761   /* Set TARGET to one.  */
762   emit_move_insn (target, const1_rtx);
763   emit_label (cont_lab);
764 
765   /* Tell flow about the strange goings on.  Putting `next_lab' on
766      `nonlocal_goto_handler_labels' to indicates that function
767      calls may traverse the arc back to this label.  */
768 
769   current_function_has_nonlocal_label = 1;
770   nonlocal_goto_handler_labels
771     = gen_rtx_EXPR_LIST (VOIDmode, next_lab, nonlocal_goto_handler_labels);
772 
773   return target;
774 }
775 
776 /* __builtin_longjmp is passed a pointer to an array of five words (not
777    all will be used on all machines).  It operates similarly to the C
778    library function of the same name, but is more efficient.  Much of
779    the code below is copied from the handling of non-local gotos.
780 
781    NOTE: This is intended for use by GNAT and the exception handling
782    scheme in the compiler and will only work in the method used by
783    them.  */
784 
785 static void
expand_builtin_longjmp(rtx buf_addr,rtx value)786 expand_builtin_longjmp (rtx buf_addr, rtx value)
787 {
788   rtx fp, lab, stack, insn, last;
789   enum machine_mode sa_mode = STACK_SAVEAREA_MODE (SAVE_NONLOCAL);
790 
791   if (setjmp_alias_set == -1)
792     setjmp_alias_set = new_alias_set ();
793 
794   buf_addr = convert_memory_address (Pmode, buf_addr);
795 
796   buf_addr = force_reg (Pmode, buf_addr);
797 
798   /* We used to store value in static_chain_rtx, but that fails if pointers
799      are smaller than integers.  We instead require that the user must pass
800      a second argument of 1, because that is what builtin_setjmp will
801      return.  This also makes EH slightly more efficient, since we are no
802      longer copying around a value that we don't care about.  */
803   gcc_assert (value == const1_rtx);
804 
805   last = get_last_insn ();
806 #ifdef HAVE_builtin_longjmp
807   if (HAVE_builtin_longjmp)
808     emit_insn (gen_builtin_longjmp (buf_addr));
809   else
810 #endif
811     {
812       fp = gen_rtx_MEM (Pmode, buf_addr);
813       lab = gen_rtx_MEM (Pmode, plus_constant (buf_addr,
814 					       GET_MODE_SIZE (Pmode)));
815 
816       stack = gen_rtx_MEM (sa_mode, plus_constant (buf_addr,
817 						   2 * GET_MODE_SIZE (Pmode)));
818       set_mem_alias_set (fp, setjmp_alias_set);
819       set_mem_alias_set (lab, setjmp_alias_set);
820       set_mem_alias_set (stack, setjmp_alias_set);
821 
822       /* Pick up FP, label, and SP from the block and jump.  This code is
823 	 from expand_goto in stmt.c; see there for detailed comments.  */
824 #if HAVE_nonlocal_goto
825       if (HAVE_nonlocal_goto)
826 	/* We have to pass a value to the nonlocal_goto pattern that will
827 	   get copied into the static_chain pointer, but it does not matter
828 	   what that value is, because builtin_setjmp does not use it.  */
829 	emit_insn (gen_nonlocal_goto (value, lab, stack, fp));
830       else
831 #endif
832 	{
833 	  lab = copy_to_reg (lab);
834 
835 	  emit_insn (gen_rtx_CLOBBER (VOIDmode,
836 				      gen_rtx_MEM (BLKmode,
837 						   gen_rtx_SCRATCH (VOIDmode))));
838 	  emit_insn (gen_rtx_CLOBBER (VOIDmode,
839 				      gen_rtx_MEM (BLKmode,
840 						   hard_frame_pointer_rtx)));
841 
842 	  emit_move_insn (hard_frame_pointer_rtx, fp);
843 	  emit_stack_restore (SAVE_NONLOCAL, stack, NULL_RTX);
844 
845 	  emit_insn (gen_rtx_USE (VOIDmode, hard_frame_pointer_rtx));
846 	  emit_insn (gen_rtx_USE (VOIDmode, stack_pointer_rtx));
847 	  emit_indirect_jump (lab);
848 	}
849     }
850 
851   /* Search backwards and mark the jump insn as a non-local goto.
852      Note that this precludes the use of __builtin_longjmp to a
853      __builtin_setjmp target in the same function.  However, we've
854      already cautioned the user that these functions are for
855      internal exception handling use only.  */
856   for (insn = get_last_insn (); insn; insn = PREV_INSN (insn))
857     {
858       gcc_assert (insn != last);
859 
860       if (JUMP_P (insn))
861 	{
862 	  REG_NOTES (insn) = alloc_EXPR_LIST (REG_NON_LOCAL_GOTO, const0_rtx,
863 					      REG_NOTES (insn));
864 	  break;
865 	}
866       else if (CALL_P (insn))
867 	break;
868     }
869 }
870 
871 /* Expand a call to __builtin_nonlocal_goto.  We're passed the target label
872    and the address of the save area.  */
873 
874 static rtx
expand_builtin_nonlocal_goto(tree arglist)875 expand_builtin_nonlocal_goto (tree arglist)
876 {
877   tree t_label, t_save_area;
878   rtx r_label, r_save_area, r_fp, r_sp, insn;
879 
880   if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
881     return NULL_RTX;
882 
883   t_label = TREE_VALUE (arglist);
884   arglist = TREE_CHAIN (arglist);
885   t_save_area = TREE_VALUE (arglist);
886 
887   r_label = expand_expr (t_label, NULL_RTX, VOIDmode, 0);
888   r_label = convert_memory_address (Pmode, r_label);
889   r_save_area = expand_expr (t_save_area, NULL_RTX, VOIDmode, 0);
890   r_save_area = convert_memory_address (Pmode, r_save_area);
891   r_fp = gen_rtx_MEM (Pmode, r_save_area);
892   r_sp = gen_rtx_MEM (STACK_SAVEAREA_MODE (SAVE_NONLOCAL),
893 		      plus_constant (r_save_area, GET_MODE_SIZE (Pmode)));
894 
895   current_function_has_nonlocal_goto = 1;
896 
897 #if HAVE_nonlocal_goto
898   /* ??? We no longer need to pass the static chain value, afaik.  */
899   if (HAVE_nonlocal_goto)
900     emit_insn (gen_nonlocal_goto (const0_rtx, r_label, r_sp, r_fp));
901   else
902 #endif
903     {
904       r_label = copy_to_reg (r_label);
905 
906       emit_insn (gen_rtx_CLOBBER (VOIDmode,
907 				  gen_rtx_MEM (BLKmode,
908 					       gen_rtx_SCRATCH (VOIDmode))));
909 
910       emit_insn (gen_rtx_CLOBBER (VOIDmode,
911 				  gen_rtx_MEM (BLKmode,
912 					       hard_frame_pointer_rtx)));
913 
914       /* Restore frame pointer for containing function.
915 	 This sets the actual hard register used for the frame pointer
916 	 to the location of the function's incoming static chain info.
917 	 The non-local goto handler will then adjust it to contain the
918 	 proper value and reload the argument pointer, if needed.  */
919       emit_move_insn (hard_frame_pointer_rtx, r_fp);
920       emit_stack_restore (SAVE_NONLOCAL, r_sp, NULL_RTX);
921 
922       /* USE of hard_frame_pointer_rtx added for consistency;
923 	 not clear if really needed.  */
924       emit_insn (gen_rtx_USE (VOIDmode, hard_frame_pointer_rtx));
925       emit_insn (gen_rtx_USE (VOIDmode, stack_pointer_rtx));
926       emit_indirect_jump (r_label);
927     }
928 
929   /* Search backwards to the jump insn and mark it as a
930      non-local goto.  */
931   for (insn = get_last_insn (); insn; insn = PREV_INSN (insn))
932     {
933       if (JUMP_P (insn))
934 	{
935 	  REG_NOTES (insn) = alloc_EXPR_LIST (REG_NON_LOCAL_GOTO,
936 					      const0_rtx, REG_NOTES (insn));
937 	  break;
938 	}
939       else if (CALL_P (insn))
940 	break;
941     }
942 
943   return const0_rtx;
944 }
945 
946 /* __builtin_update_setjmp_buf is passed a pointer to an array of five words
947    (not all will be used on all machines) that was passed to __builtin_setjmp.
948    It updates the stack pointer in that block to correspond to the current
949    stack pointer.  */
950 
951 static void
expand_builtin_update_setjmp_buf(rtx buf_addr)952 expand_builtin_update_setjmp_buf (rtx buf_addr)
953 {
954   enum machine_mode sa_mode = Pmode;
955   rtx stack_save;
956 
957 
958 #ifdef HAVE_save_stack_nonlocal
959   if (HAVE_save_stack_nonlocal)
960     sa_mode = insn_data[(int) CODE_FOR_save_stack_nonlocal].operand[0].mode;
961 #endif
962 #ifdef STACK_SAVEAREA_MODE
963   sa_mode = STACK_SAVEAREA_MODE (SAVE_NONLOCAL);
964 #endif
965 
966   stack_save
967     = gen_rtx_MEM (sa_mode,
968 		   memory_address
969 		   (sa_mode,
970 		    plus_constant (buf_addr, 2 * GET_MODE_SIZE (Pmode))));
971 
972 #ifdef HAVE_setjmp
973   if (HAVE_setjmp)
974     emit_insn (gen_setjmp ());
975 #endif
976 
977   emit_stack_save (SAVE_NONLOCAL, &stack_save, NULL_RTX);
978 }
979 
980 /* Expand a call to __builtin_prefetch.  For a target that does not support
981    data prefetch, evaluate the memory address argument in case it has side
982    effects.  */
983 
984 static void
expand_builtin_prefetch(tree arglist)985 expand_builtin_prefetch (tree arglist)
986 {
987   tree arg0, arg1, arg2;
988   rtx op0, op1, op2;
989 
990   if (!validate_arglist (arglist, POINTER_TYPE, 0))
991     return;
992 
993   arg0 = TREE_VALUE (arglist);
994   /* Arguments 1 and 2 are optional; argument 1 (read/write) defaults to
995      zero (read) and argument 2 (locality) defaults to 3 (high degree of
996      locality).  */
997   if (TREE_CHAIN (arglist))
998     {
999       arg1 = TREE_VALUE (TREE_CHAIN (arglist));
1000       if (TREE_CHAIN (TREE_CHAIN (arglist)))
1001 	arg2 = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
1002       else
1003 	arg2 = build_int_cst (NULL_TREE, 3);
1004     }
1005   else
1006     {
1007       arg1 = integer_zero_node;
1008       arg2 = build_int_cst (NULL_TREE, 3);
1009     }
1010 
1011   /* Argument 0 is an address.  */
1012   op0 = expand_expr (arg0, NULL_RTX, Pmode, EXPAND_NORMAL);
1013 
1014   /* Argument 1 (read/write flag) must be a compile-time constant int.  */
1015   if (TREE_CODE (arg1) != INTEGER_CST)
1016     {
1017       error ("second argument to %<__builtin_prefetch%> must be a constant");
1018       arg1 = integer_zero_node;
1019     }
1020   op1 = expand_expr (arg1, NULL_RTX, VOIDmode, 0);
1021   /* Argument 1 must be either zero or one.  */
1022   if (INTVAL (op1) != 0 && INTVAL (op1) != 1)
1023     {
1024       warning (0, "invalid second argument to %<__builtin_prefetch%>;"
1025 	       " using zero");
1026       op1 = const0_rtx;
1027     }
1028 
1029   /* Argument 2 (locality) must be a compile-time constant int.  */
1030   if (TREE_CODE (arg2) != INTEGER_CST)
1031     {
1032       error ("third argument to %<__builtin_prefetch%> must be a constant");
1033       arg2 = integer_zero_node;
1034     }
1035   op2 = expand_expr (arg2, NULL_RTX, VOIDmode, 0);
1036   /* Argument 2 must be 0, 1, 2, or 3.  */
1037   if (INTVAL (op2) < 0 || INTVAL (op2) > 3)
1038     {
1039       warning (0, "invalid third argument to %<__builtin_prefetch%>; using zero");
1040       op2 = const0_rtx;
1041     }
1042 
1043 #ifdef HAVE_prefetch
1044   if (HAVE_prefetch)
1045     {
1046       if ((! (*insn_data[(int) CODE_FOR_prefetch].operand[0].predicate)
1047 	     (op0,
1048 	      insn_data[(int) CODE_FOR_prefetch].operand[0].mode))
1049 	  || (GET_MODE (op0) != Pmode))
1050 	{
1051 	  op0 = convert_memory_address (Pmode, op0);
1052 	  op0 = force_reg (Pmode, op0);
1053 	}
1054       emit_insn (gen_prefetch (op0, op1, op2));
1055     }
1056 #endif
1057 
1058   /* Don't do anything with direct references to volatile memory, but
1059      generate code to handle other side effects.  */
1060   if (!MEM_P (op0) && side_effects_p (op0))
1061     emit_insn (op0);
1062 }
1063 
1064 /* Get a MEM rtx for expression EXP which is the address of an operand
1065    to be used in a string instruction (cmpstrsi, movmemsi, ..).  LEN is
1066    the maximum length of the block of memory that might be accessed or
1067    NULL if unknown.  */
1068 
1069 static rtx
get_memory_rtx(tree exp,tree len)1070 get_memory_rtx (tree exp, tree len)
1071 {
1072   rtx addr = expand_expr (exp, NULL_RTX, ptr_mode, EXPAND_NORMAL);
1073   rtx mem = gen_rtx_MEM (BLKmode, memory_address (BLKmode, addr));
1074 
1075   /* Get an expression we can use to find the attributes to assign to MEM.
1076      If it is an ADDR_EXPR, use the operand.  Otherwise, dereference it if
1077      we can.  First remove any nops.  */
1078   while ((TREE_CODE (exp) == NOP_EXPR || TREE_CODE (exp) == CONVERT_EXPR
1079 	  || TREE_CODE (exp) == NON_LVALUE_EXPR)
1080 	 && POINTER_TYPE_P (TREE_TYPE (TREE_OPERAND (exp, 0))))
1081     exp = TREE_OPERAND (exp, 0);
1082 
1083   if (TREE_CODE (exp) == ADDR_EXPR)
1084     exp = TREE_OPERAND (exp, 0);
1085   else if (POINTER_TYPE_P (TREE_TYPE (exp)))
1086     exp = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (exp)), exp);
1087   else
1088     exp = NULL;
1089 
1090   /* Honor attributes derived from exp, except for the alias set
1091      (as builtin stringops may alias with anything) and the size
1092      (as stringops may access multiple array elements).  */
1093   if (exp)
1094     {
1095       set_mem_attributes (mem, exp, 0);
1096 
1097       /* Allow the string and memory builtins to overflow from one
1098 	 field into another, see http://gcc.gnu.org/PR23561.
1099 	 Thus avoid COMPONENT_REFs in MEM_EXPR unless we know the whole
1100 	 memory accessed by the string or memory builtin will fit
1101 	 within the field.  */
1102       if (MEM_EXPR (mem) && TREE_CODE (MEM_EXPR (mem)) == COMPONENT_REF)
1103 	{
1104 	  tree mem_expr = MEM_EXPR (mem);
1105 	  HOST_WIDE_INT offset = -1, length = -1;
1106 	  tree inner = exp;
1107 
1108 	  while (TREE_CODE (inner) == ARRAY_REF
1109 		 || TREE_CODE (inner) == NOP_EXPR
1110 		 || TREE_CODE (inner) == CONVERT_EXPR
1111 		 || TREE_CODE (inner) == NON_LVALUE_EXPR
1112 		 || TREE_CODE (inner) == VIEW_CONVERT_EXPR
1113 		 || TREE_CODE (inner) == SAVE_EXPR)
1114 	    inner = TREE_OPERAND (inner, 0);
1115 
1116 	  gcc_assert (TREE_CODE (inner) == COMPONENT_REF);
1117 
1118 	  if (MEM_OFFSET (mem)
1119 	      && GET_CODE (MEM_OFFSET (mem)) == CONST_INT)
1120 	    offset = INTVAL (MEM_OFFSET (mem));
1121 
1122 	  if (offset >= 0 && len && host_integerp (len, 0))
1123 	    length = tree_low_cst (len, 0);
1124 
1125 	  while (TREE_CODE (inner) == COMPONENT_REF)
1126 	    {
1127 	      tree field = TREE_OPERAND (inner, 1);
1128 	      gcc_assert (! DECL_BIT_FIELD (field));
1129 	      gcc_assert (TREE_CODE (mem_expr) == COMPONENT_REF);
1130 	      gcc_assert (field == TREE_OPERAND (mem_expr, 1));
1131 
1132 	      if (length >= 0
1133 		  && TYPE_SIZE_UNIT (TREE_TYPE (inner))
1134 		  && host_integerp (TYPE_SIZE_UNIT (TREE_TYPE (inner)), 0))
1135 		{
1136 		  HOST_WIDE_INT size
1137 		    = tree_low_cst (TYPE_SIZE_UNIT (TREE_TYPE (inner)), 0);
1138 		  /* If we can prove the memory starting at XEXP (mem, 0)
1139 		     and ending at XEXP (mem, 0) + LENGTH will fit into
1140 		     this field, we can keep that COMPONENT_REF in MEM_EXPR.  */
1141 		  if (offset <= size
1142 		      && length <= size
1143 		      && offset + length <= size)
1144 		    break;
1145 		}
1146 
1147 	      if (offset >= 0
1148 		  && host_integerp (DECL_FIELD_OFFSET (field), 0))
1149 		offset += tree_low_cst (DECL_FIELD_OFFSET (field), 0)
1150 			  + tree_low_cst (DECL_FIELD_BIT_OFFSET (field), 1)
1151 			    / BITS_PER_UNIT;
1152 	      else
1153 		{
1154 		  offset = -1;
1155 		  length = -1;
1156 		}
1157 
1158 	      mem_expr = TREE_OPERAND (mem_expr, 0);
1159 	      inner = TREE_OPERAND (inner, 0);
1160 	    }
1161 
1162 	  if (mem_expr == NULL)
1163 	    offset = -1;
1164 	  if (mem_expr != MEM_EXPR (mem))
1165 	    {
1166 	      set_mem_expr (mem, mem_expr);
1167 	      set_mem_offset (mem, offset >= 0 ? GEN_INT (offset) : NULL_RTX);
1168 	    }
1169 	}
1170       set_mem_alias_set (mem, 0);
1171       set_mem_size (mem, NULL_RTX);
1172     }
1173 
1174   return mem;
1175 }
1176 
1177 /* Built-in functions to perform an untyped call and return.  */
1178 
1179 /* For each register that may be used for calling a function, this
1180    gives a mode used to copy the register's value.  VOIDmode indicates
1181    the register is not used for calling a function.  If the machine
1182    has register windows, this gives only the outbound registers.
1183    INCOMING_REGNO gives the corresponding inbound register.  */
1184 static enum machine_mode apply_args_mode[FIRST_PSEUDO_REGISTER];
1185 
1186 /* For each register that may be used for returning values, this gives
1187    a mode used to copy the register's value.  VOIDmode indicates the
1188    register is not used for returning values.  If the machine has
1189    register windows, this gives only the outbound registers.
1190    INCOMING_REGNO gives the corresponding inbound register.  */
1191 static enum machine_mode apply_result_mode[FIRST_PSEUDO_REGISTER];
1192 
1193 /* For each register that may be used for calling a function, this
1194    gives the offset of that register into the block returned by
1195    __builtin_apply_args.  0 indicates that the register is not
1196    used for calling a function.  */
1197 static int apply_args_reg_offset[FIRST_PSEUDO_REGISTER];
1198 
1199 /* Return the size required for the block returned by __builtin_apply_args,
1200    and initialize apply_args_mode.  */
1201 
1202 static int
apply_args_size(void)1203 apply_args_size (void)
1204 {
1205   static int size = -1;
1206   int align;
1207   unsigned int regno;
1208   enum machine_mode mode;
1209 
1210   /* The values computed by this function never change.  */
1211   if (size < 0)
1212     {
1213       /* The first value is the incoming arg-pointer.  */
1214       size = GET_MODE_SIZE (Pmode);
1215 
1216       /* The second value is the structure value address unless this is
1217 	 passed as an "invisible" first argument.  */
1218       if (targetm.calls.struct_value_rtx (cfun ? TREE_TYPE (cfun->decl) : 0, 0))
1219 	size += GET_MODE_SIZE (Pmode);
1220 
1221       for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
1222 	if (0 /*FUNCTION_ARG_REGNO_P (regno)*/)
1223 	/* (TIGCC) Do NOT use register passing for __builtin_apply since:
1224 	           1. It doesn't work: ALL registers are POSSIBLE registers for
1225 	                               function parameters, so this code uses up all
1226 	                               registers.
1227 	           2. It significantly increases code size.
1228 	           3. The default calling convention is stkparm anyway. */
1229 	  {
1230 	    mode = reg_raw_mode[regno];
1231 
1232 	    gcc_assert (mode != VOIDmode);
1233 
1234 	    align = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT;
1235 	    if (size % align != 0)
1236 	      size = CEIL (size, align) * align;
1237 	    apply_args_reg_offset[regno] = size;
1238 	    size += GET_MODE_SIZE (mode);
1239 	    apply_args_mode[regno] = mode;
1240 	  }
1241 	else
1242 	  {
1243 	    apply_args_mode[regno] = VOIDmode;
1244 	    apply_args_reg_offset[regno] = 0;
1245 	  }
1246     }
1247   return size;
1248 }
1249 
1250 /* Return the size required for the block returned by __builtin_apply,
1251    and initialize apply_result_mode.  */
1252 
1253 static int
apply_result_size(void)1254 apply_result_size (void)
1255 {
1256   static int size = -1;
1257   int align, regno;
1258   enum machine_mode mode;
1259 
1260   /* The values computed by this function never change.  */
1261   if (size < 0)
1262     {
1263       size = 0;
1264 
1265       for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
1266 	if (FUNCTION_VALUE_REGNO_P (regno))
1267 	  {
1268 	    mode = reg_raw_mode[regno];
1269 
1270 	    gcc_assert (mode != VOIDmode);
1271 
1272 	    align = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT;
1273 	    if (size % align != 0)
1274 	      size = CEIL (size, align) * align;
1275 	    size += GET_MODE_SIZE (mode);
1276 	    apply_result_mode[regno] = mode;
1277 	  }
1278 	else
1279 	  apply_result_mode[regno] = VOIDmode;
1280 
1281       /* Allow targets that use untyped_call and untyped_return to override
1282 	 the size so that machine-specific information can be stored here.  */
1283 #ifdef APPLY_RESULT_SIZE
1284       size = APPLY_RESULT_SIZE;
1285 #endif
1286     }
1287   return size;
1288 }
1289 
1290 #if defined (HAVE_untyped_call) || defined (HAVE_untyped_return)
1291 /* Create a vector describing the result block RESULT.  If SAVEP is true,
1292    the result block is used to save the values; otherwise it is used to
1293    restore the values.  */
1294 
1295 static rtx
result_vector(int savep,rtx result)1296 result_vector (int savep, rtx result)
1297 {
1298   int regno, size, align, nelts;
1299   enum machine_mode mode;
1300   rtx reg, mem;
1301   rtx *savevec = alloca (FIRST_PSEUDO_REGISTER * sizeof (rtx));
1302 
1303   size = nelts = 0;
1304   for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
1305     if ((mode = apply_result_mode[regno]) != VOIDmode)
1306       {
1307 	align = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT;
1308 	if (size % align != 0)
1309 	  size = CEIL (size, align) * align;
1310 	reg = gen_rtx_REG (mode, savep ? regno : INCOMING_REGNO (regno));
1311 	mem = adjust_address (result, mode, size);
1312 	savevec[nelts++] = (savep
1313 			    ? gen_rtx_SET (VOIDmode, mem, reg)
1314 			    : gen_rtx_SET (VOIDmode, reg, mem));
1315 	size += GET_MODE_SIZE (mode);
1316       }
1317   return gen_rtx_PARALLEL (VOIDmode, gen_rtvec_v (nelts, savevec));
1318 }
1319 #endif /* HAVE_untyped_call or HAVE_untyped_return */
1320 
1321 /* Save the state required to perform an untyped call with the same
1322    arguments as were passed to the current function.  */
1323 
1324 static rtx
expand_builtin_apply_args_1(void)1325 expand_builtin_apply_args_1 (void)
1326 {
1327   rtx registers, tem;
1328   int size, align, regno;
1329   enum machine_mode mode;
1330   rtx struct_incoming_value = targetm.calls.struct_value_rtx (cfun ? TREE_TYPE (cfun->decl) : 0, 1);
1331 
1332   /* Create a block where the arg-pointer, structure value address,
1333      and argument registers can be saved.  */
1334   registers = assign_stack_local (BLKmode, apply_args_size (), -1);
1335 
1336   /* Walk past the arg-pointer and structure value address.  */
1337   size = GET_MODE_SIZE (Pmode);
1338   if (targetm.calls.struct_value_rtx (cfun ? TREE_TYPE (cfun->decl) : 0, 0))
1339     size += GET_MODE_SIZE (Pmode);
1340 
1341   /* Save each register used in calling a function to the block.  */
1342   for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
1343     if ((mode = apply_args_mode[regno]) != VOIDmode)
1344       {
1345 	align = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT;
1346 	if (size % align != 0)
1347 	  size = CEIL (size, align) * align;
1348 
1349 	tem = gen_rtx_REG (mode, INCOMING_REGNO (regno));
1350 
1351 	emit_move_insn (adjust_address (registers, mode, size), tem);
1352 	size += GET_MODE_SIZE (mode);
1353       }
1354 
1355   /* Save the arg pointer to the block.  */
1356   tem = copy_to_reg (virtual_incoming_args_rtx);
1357 #ifdef STACK_GROWS_DOWNWARD
1358   /* We need the pointer as the caller actually passed them to us, not
1359      as we might have pretended they were passed.  Make sure it's a valid
1360      operand, as emit_move_insn isn't expected to handle a PLUS.  */
1361   tem
1362     = force_operand (plus_constant (tem, current_function_pretend_args_size),
1363 		     NULL_RTX);
1364 #endif
1365   emit_move_insn (adjust_address (registers, Pmode, 0), tem);
1366 
1367   size = GET_MODE_SIZE (Pmode);
1368 
1369   /* Save the structure value address unless this is passed as an
1370      "invisible" first argument.  */
1371   if (struct_incoming_value)
1372     {
1373       emit_move_insn (adjust_address (registers, Pmode, size),
1374 		      copy_to_reg (struct_incoming_value));
1375       size += GET_MODE_SIZE (Pmode);
1376     }
1377 
1378   /* Return the address of the block.  */
1379   return copy_addr_to_reg (XEXP (registers, 0));
1380 }
1381 
1382 /* __builtin_apply_args returns block of memory allocated on
1383    the stack into which is stored the arg pointer, structure
1384    value address, static chain, and all the registers that might
1385    possibly be used in performing a function call.  The code is
1386    moved to the start of the function so the incoming values are
1387    saved.  */
1388 
1389 static rtx
expand_builtin_apply_args(void)1390 expand_builtin_apply_args (void)
1391 {
1392   /* Don't do __builtin_apply_args more than once in a function.
1393      Save the result of the first call and reuse it.  */
1394   if (apply_args_value != 0)
1395     return apply_args_value;
1396   {
1397     /* When this function is called, it means that registers must be
1398        saved on entry to this function.  So we migrate the
1399        call to the first insn of this function.  */
1400     rtx temp;
1401     rtx seq;
1402 
1403     start_sequence ();
1404     temp = expand_builtin_apply_args_1 ();
1405     seq = get_insns ();
1406     end_sequence ();
1407 
1408     apply_args_value = temp;
1409 
1410     /* Put the insns after the NOTE that starts the function.
1411        If this is inside a start_sequence, make the outer-level insn
1412        chain current, so the code is placed at the start of the
1413        function.  */
1414     push_topmost_sequence ();
1415     emit_insn_before (seq, NEXT_INSN (entry_of_function ()));
1416     pop_topmost_sequence ();
1417     return temp;
1418   }
1419 }
1420 
1421 /* Perform an untyped call and save the state required to perform an
1422    untyped return of whatever value was returned by the given function.  */
1423 
1424 static rtx
expand_builtin_apply(rtx function,rtx arguments,rtx argsize)1425 expand_builtin_apply (rtx function, rtx arguments, rtx argsize)
1426 {
1427   int size, align, regno;
1428   enum machine_mode mode;
1429   rtx incoming_args, result, reg, dest, src, call_insn;
1430   rtx old_stack_level = 0;
1431   rtx call_fusage = 0;
1432   rtx struct_value = targetm.calls.struct_value_rtx (cfun ? TREE_TYPE (cfun->decl) : 0, 0);
1433 
1434   arguments = convert_memory_address (Pmode, arguments);
1435 
1436   /* Create a block where the return registers can be saved.  */
1437   result = assign_stack_local (BLKmode, apply_result_size (), -1);
1438 
1439   /* Fetch the arg pointer from the ARGUMENTS block.  */
1440   incoming_args = gen_reg_rtx (Pmode);
1441   emit_move_insn (incoming_args, gen_rtx_MEM (Pmode, arguments));
1442 #ifndef STACK_GROWS_DOWNWARD
1443   incoming_args = expand_simple_binop (Pmode, MINUS, incoming_args, argsize,
1444 				       incoming_args, 0, OPTAB_LIB_WIDEN);
1445 #endif
1446 
1447   /* Push a new argument block and copy the arguments.  Do not allow
1448      the (potential) memcpy call below to interfere with our stack
1449      manipulations.  */
1450   do_pending_stack_adjust ();
1451   NO_DEFER_POP;
1452 
1453   /* Save the stack with nonlocal if available.  */
1454 #ifdef HAVE_save_stack_nonlocal
1455   if (HAVE_save_stack_nonlocal)
1456     emit_stack_save (SAVE_NONLOCAL, &old_stack_level, NULL_RTX);
1457   else
1458 #endif
1459     emit_stack_save (SAVE_BLOCK, &old_stack_level, NULL_RTX);
1460 
1461   /* Allocate a block of memory onto the stack and copy the memory
1462      arguments to the outgoing arguments address.  */
1463   allocate_dynamic_stack_space (argsize, 0, BITS_PER_UNIT);
1464   dest = virtual_outgoing_args_rtx;
1465 #ifndef STACK_GROWS_DOWNWARD
1466   if (GET_CODE (argsize) == CONST_INT)
1467     dest = plus_constant (dest, -INTVAL (argsize));
1468   else
1469     dest = gen_rtx_PLUS (Pmode, dest, negate_rtx (Pmode, argsize));
1470 #endif
1471   dest = gen_rtx_MEM (BLKmode, dest);
1472   set_mem_align (dest, PARM_BOUNDARY);
1473   src = gen_rtx_MEM (BLKmode, incoming_args);
1474   set_mem_align (src, PARM_BOUNDARY);
1475   emit_block_move (dest, src, argsize, BLOCK_OP_NORMAL);
1476 
1477   /* Refer to the argument block.  */
1478   apply_args_size ();
1479   arguments = gen_rtx_MEM (BLKmode, arguments);
1480   set_mem_align (arguments, PARM_BOUNDARY);
1481 
1482   /* Walk past the arg-pointer and structure value address.  */
1483   size = GET_MODE_SIZE (Pmode);
1484   if (struct_value)
1485     size += GET_MODE_SIZE (Pmode);
1486 
1487   /* Restore each of the registers previously saved.  Make USE insns
1488      for each of these registers for use in making the call.  */
1489   for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
1490     if ((mode = apply_args_mode[regno]) != VOIDmode)
1491       {
1492 	align = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT;
1493 	if (size % align != 0)
1494 	  size = CEIL (size, align) * align;
1495 	reg = gen_rtx_REG (mode, regno);
1496 	emit_move_insn (reg, adjust_address (arguments, mode, size));
1497 	use_reg (&call_fusage, reg);
1498 	size += GET_MODE_SIZE (mode);
1499       }
1500 
1501   /* Restore the structure value address unless this is passed as an
1502      "invisible" first argument.  */
1503   size = GET_MODE_SIZE (Pmode);
1504   if (struct_value)
1505     {
1506       rtx value = gen_reg_rtx (Pmode);
1507       emit_move_insn (value, adjust_address (arguments, Pmode, size));
1508       emit_move_insn (struct_value, value);
1509       if (REG_P (struct_value))
1510 	use_reg (&call_fusage, struct_value);
1511       size += GET_MODE_SIZE (Pmode);
1512     }
1513 
1514   /* All arguments and registers used for the call are set up by now!  */
1515   function = prepare_call_address (function, NULL, &call_fusage, 0, 0);
1516 
1517   /* Ensure address is valid.  SYMBOL_REF is already valid, so no need,
1518      and we don't want to load it into a register as an optimization,
1519      because prepare_call_address already did it if it should be done.  */
1520   if (GET_CODE (function) != SYMBOL_REF)
1521     function = memory_address (FUNCTION_MODE, function);
1522 
1523   /* Generate the actual call instruction and save the return value.  */
1524 #ifdef HAVE_untyped_call
1525   if (HAVE_untyped_call)
1526     emit_call_insn (gen_untyped_call (gen_rtx_MEM (FUNCTION_MODE, function),
1527 				      result, result_vector (1, result)));
1528   else
1529 #endif
1530 #ifdef HAVE_call_value
1531   if (HAVE_call_value)
1532     {
1533       rtx valreg = 0;
1534 
1535       /* Locate the unique return register.  It is not possible to
1536 	 express a call that sets more than one return register using
1537 	 call_value; use untyped_call for that.  In fact, untyped_call
1538 	 only needs to save the return registers in the given block.  */
1539       for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
1540 	if ((mode = apply_result_mode[regno]) != VOIDmode)
1541 	  {
1542 	    gcc_assert (!valreg); /* HAVE_untyped_call required.  */
1543 
1544 	    valreg = gen_rtx_REG (mode, regno);
1545 	  }
1546 
1547       emit_call_insn (GEN_CALL_VALUE (valreg,
1548 				      gen_rtx_MEM (FUNCTION_MODE, function),
1549 				      const0_rtx, NULL_RTX, const0_rtx));
1550 
1551       emit_move_insn (adjust_address (result, GET_MODE (valreg), 0), valreg);
1552     }
1553   else
1554 #endif
1555     gcc_unreachable ();
1556 
1557   /* Find the CALL insn we just emitted, and attach the register usage
1558      information.  */
1559   call_insn = last_call_insn ();
1560   add_function_usage_to (call_insn, call_fusage);
1561 
1562   /* Restore the stack.  */
1563 #ifdef HAVE_save_stack_nonlocal
1564   if (HAVE_save_stack_nonlocal)
1565     emit_stack_restore (SAVE_NONLOCAL, old_stack_level, NULL_RTX);
1566   else
1567 #endif
1568     emit_stack_restore (SAVE_BLOCK, old_stack_level, NULL_RTX);
1569 
1570   OK_DEFER_POP;
1571 
1572   /* Return the address of the result block.  */
1573   result = copy_addr_to_reg (XEXP (result, 0));
1574   return convert_memory_address (ptr_mode, result);
1575 }
1576 
1577 /* Perform an untyped return.  */
1578 
1579 static void
expand_builtin_return(rtx result)1580 expand_builtin_return (rtx result)
1581 {
1582   int size, align, regno;
1583   enum machine_mode mode;
1584   rtx reg;
1585   rtx call_fusage = 0;
1586 
1587   result = convert_memory_address (Pmode, result);
1588 
1589   apply_result_size ();
1590   result = gen_rtx_MEM (BLKmode, result);
1591 
1592 #ifdef HAVE_untyped_return
1593   if (HAVE_untyped_return)
1594     {
1595       emit_jump_insn (gen_untyped_return (result, result_vector (0, result)));
1596       emit_barrier ();
1597       return;
1598     }
1599 #endif
1600 
1601   /* Restore the return value and note that each value is used.  */
1602   size = 0;
1603   for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
1604     if ((mode = apply_result_mode[regno]) != VOIDmode)
1605       {
1606 	align = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT;
1607 	if (size % align != 0)
1608 	  size = CEIL (size, align) * align;
1609 	reg = gen_rtx_REG (mode, INCOMING_REGNO (regno));
1610 	emit_move_insn (reg, adjust_address (result, mode, size));
1611 
1612 	push_to_sequence (call_fusage);
1613 	emit_insn (gen_rtx_USE (VOIDmode, reg));
1614 	call_fusage = get_insns ();
1615 	end_sequence ();
1616 	size += GET_MODE_SIZE (mode);
1617       }
1618 
1619   /* Put the USE insns before the return.  */
1620   emit_insn (call_fusage);
1621 
1622   /* Return whatever values was restored by jumping directly to the end
1623      of the function.  */
1624   expand_naked_return ();
1625 }
1626 
1627 /* Used by expand_builtin_classify_type and fold_builtin_classify_type.  */
1628 
1629 static enum type_class
type_to_class(tree type)1630 type_to_class (tree type)
1631 {
1632   switch (TREE_CODE (type))
1633     {
1634     case VOID_TYPE:	   return void_type_class;
1635     case INTEGER_TYPE:	   return integer_type_class;
1636     case CHAR_TYPE:	   return char_type_class;
1637     case ENUMERAL_TYPE:	   return enumeral_type_class;
1638     case BOOLEAN_TYPE:	   return boolean_type_class;
1639     case POINTER_TYPE:	   return pointer_type_class;
1640     case REFERENCE_TYPE:   return reference_type_class;
1641     case OFFSET_TYPE:	   return offset_type_class;
1642     case REAL_TYPE:	   return real_type_class;
1643     case COMPLEX_TYPE:	   return complex_type_class;
1644     case FUNCTION_TYPE:	   return function_type_class;
1645     case METHOD_TYPE:	   return method_type_class;
1646     case RECORD_TYPE:	   return record_type_class;
1647     case UNION_TYPE:
1648     case QUAL_UNION_TYPE:  return union_type_class;
1649     case ARRAY_TYPE:	   return (TYPE_STRING_FLAG (type)
1650 				   ? string_type_class : array_type_class);
1651     case LANG_TYPE:	   return lang_type_class;
1652     default:		   return no_type_class;
1653     }
1654 }
1655 
1656 /* Expand a call to __builtin_classify_type with arguments found in
1657    ARGLIST.  */
1658 
1659 static rtx
expand_builtin_classify_type(tree arglist)1660 expand_builtin_classify_type (tree arglist)
1661 {
1662   if (arglist != 0)
1663     return GEN_INT (type_to_class (TREE_TYPE (TREE_VALUE (arglist))));
1664   return GEN_INT (no_type_class);
1665 }
1666 
1667 /* This helper macro, meant to be used in mathfn_built_in below,
1668    determines which among a set of three builtin math functions is
1669    appropriate for a given type mode.  The `F' and `L' cases are
1670    automatically generated from the `double' case.  */
1671 #define CASE_MATHFN(BUILT_IN_MATHFN) \
1672   case BUILT_IN_MATHFN: case BUILT_IN_MATHFN##F: case BUILT_IN_MATHFN##L: \
1673   fcode = BUILT_IN_MATHFN; fcodef = BUILT_IN_MATHFN##F ; \
1674   fcodel = BUILT_IN_MATHFN##L ; break;
1675 
1676 /* Return mathematic function equivalent to FN but operating directly
1677    on TYPE, if available.  If we can't do the conversion, return zero.  */
1678 tree
mathfn_built_in(tree type,enum built_in_function fn)1679 mathfn_built_in (tree type, enum built_in_function fn)
1680 {
1681 #if 0
1682   enum built_in_function fcode, fcodef, fcodel;
1683 
1684   switch (fn)
1685     {
1686       CASE_MATHFN (BUILT_IN_ACOS)
1687       CASE_MATHFN (BUILT_IN_ACOSH)
1688       CASE_MATHFN (BUILT_IN_ASIN)
1689       CASE_MATHFN (BUILT_IN_ASINH)
1690       CASE_MATHFN (BUILT_IN_ATAN)
1691       CASE_MATHFN (BUILT_IN_ATAN2)
1692       CASE_MATHFN (BUILT_IN_ATANH)
1693       CASE_MATHFN (BUILT_IN_CBRT)
1694       CASE_MATHFN (BUILT_IN_CEIL)
1695       CASE_MATHFN (BUILT_IN_COPYSIGN)
1696       CASE_MATHFN (BUILT_IN_COS)
1697       CASE_MATHFN (BUILT_IN_COSH)
1698       CASE_MATHFN (BUILT_IN_DREM)
1699       CASE_MATHFN (BUILT_IN_ERF)
1700       CASE_MATHFN (BUILT_IN_ERFC)
1701       CASE_MATHFN (BUILT_IN_EXP)
1702       CASE_MATHFN (BUILT_IN_EXP10)
1703       CASE_MATHFN (BUILT_IN_EXP2)
1704       CASE_MATHFN (BUILT_IN_EXPM1)
1705       CASE_MATHFN (BUILT_IN_FABS)
1706       CASE_MATHFN (BUILT_IN_FDIM)
1707       CASE_MATHFN (BUILT_IN_FLOOR)
1708       CASE_MATHFN (BUILT_IN_FMA)
1709       CASE_MATHFN (BUILT_IN_FMAX)
1710       CASE_MATHFN (BUILT_IN_FMIN)
1711       CASE_MATHFN (BUILT_IN_FMOD)
1712       CASE_MATHFN (BUILT_IN_FREXP)
1713       CASE_MATHFN (BUILT_IN_GAMMA)
1714       CASE_MATHFN (BUILT_IN_HUGE_VAL)
1715       CASE_MATHFN (BUILT_IN_HYPOT)
1716       CASE_MATHFN (BUILT_IN_ILOGB)
1717       CASE_MATHFN (BUILT_IN_INF)
1718       CASE_MATHFN (BUILT_IN_J0)
1719       CASE_MATHFN (BUILT_IN_J1)
1720       CASE_MATHFN (BUILT_IN_JN)
1721       CASE_MATHFN (BUILT_IN_LCEIL)
1722       CASE_MATHFN (BUILT_IN_LDEXP)
1723       CASE_MATHFN (BUILT_IN_LFLOOR)
1724       CASE_MATHFN (BUILT_IN_LGAMMA)
1725       CASE_MATHFN (BUILT_IN_LLCEIL)
1726       CASE_MATHFN (BUILT_IN_LLFLOOR)
1727       CASE_MATHFN (BUILT_IN_LLRINT)
1728       CASE_MATHFN (BUILT_IN_LLROUND)
1729       CASE_MATHFN (BUILT_IN_LOG)
1730       CASE_MATHFN (BUILT_IN_LOG10)
1731       CASE_MATHFN (BUILT_IN_LOG1P)
1732       CASE_MATHFN (BUILT_IN_LOG2)
1733       CASE_MATHFN (BUILT_IN_LOGB)
1734       CASE_MATHFN (BUILT_IN_LRINT)
1735       CASE_MATHFN (BUILT_IN_LROUND)
1736       CASE_MATHFN (BUILT_IN_MODF)
1737       CASE_MATHFN (BUILT_IN_NAN)
1738       CASE_MATHFN (BUILT_IN_NANS)
1739       CASE_MATHFN (BUILT_IN_NEARBYINT)
1740       CASE_MATHFN (BUILT_IN_NEXTAFTER)
1741       CASE_MATHFN (BUILT_IN_NEXTTOWARD)
1742       CASE_MATHFN (BUILT_IN_POW)
1743       CASE_MATHFN (BUILT_IN_POWI)
1744       CASE_MATHFN (BUILT_IN_POW10)
1745       CASE_MATHFN (BUILT_IN_REMAINDER)
1746       CASE_MATHFN (BUILT_IN_REMQUO)
1747       CASE_MATHFN (BUILT_IN_RINT)
1748       CASE_MATHFN (BUILT_IN_ROUND)
1749       CASE_MATHFN (BUILT_IN_SCALB)
1750       CASE_MATHFN (BUILT_IN_SCALBLN)
1751       CASE_MATHFN (BUILT_IN_SCALBN)
1752       CASE_MATHFN (BUILT_IN_SIGNIFICAND)
1753       CASE_MATHFN (BUILT_IN_SIN)
1754       CASE_MATHFN (BUILT_IN_SINCOS)
1755       CASE_MATHFN (BUILT_IN_SINH)
1756       CASE_MATHFN (BUILT_IN_SQRT)
1757       CASE_MATHFN (BUILT_IN_TAN)
1758       CASE_MATHFN (BUILT_IN_TANH)
1759       CASE_MATHFN (BUILT_IN_TGAMMA)
1760       CASE_MATHFN (BUILT_IN_TRUNC)
1761       CASE_MATHFN (BUILT_IN_Y0)
1762       CASE_MATHFN (BUILT_IN_Y1)
1763       CASE_MATHFN (BUILT_IN_YN)
1764 
1765       default:
1766 	return 0;
1767       }
1768 
1769   if (TYPE_MAIN_VARIANT (type) == double_type_node)
1770     return implicit_built_in_decls[fcode];
1771   else if (TYPE_MAIN_VARIANT (type) == float_type_node)
1772     return implicit_built_in_decls[fcodef];
1773   else if (TYPE_MAIN_VARIANT (type) == long_double_type_node)
1774     return implicit_built_in_decls[fcodel];
1775   else
1776 #endif /* 0 */
1777     return 0;
1778 }
1779 
1780 #if 0
1781 /* If errno must be maintained, expand the RTL to check if the result,
1782    TARGET, of a built-in function call, EXP, is NaN, and if so set
1783    errno to EDOM.  */
1784 
1785 static void
1786 expand_errno_check (tree exp, rtx target)
1787 {
1788   rtx lab = gen_label_rtx ();
1789 
1790   /* Test the result; if it is NaN, set errno=EDOM because
1791      the argument was not in the domain.  */
1792   emit_cmp_and_jump_insns (target, target, EQ, 0, GET_MODE (target),
1793 			   0, lab);
1794 
1795 #ifdef TARGET_EDOM
1796   /* If this built-in doesn't throw an exception, set errno directly.  */
1797   if (TREE_NOTHROW (TREE_OPERAND (TREE_OPERAND (exp, 0), 0)))
1798     {
1799 #ifdef GEN_ERRNO_RTX
1800       rtx errno_rtx = GEN_ERRNO_RTX;
1801 #else
1802       rtx errno_rtx
1803 	  = gen_rtx_MEM (word_mode, gen_rtx_SYMBOL_REF (Pmode, "errno"));
1804 #endif
1805       emit_move_insn (errno_rtx, GEN_INT (TARGET_EDOM));
1806       emit_label (lab);
1807       return;
1808     }
1809 #endif
1810 
1811   /* We can't set errno=EDOM directly; let the library call do it.
1812      Pop the arguments right away in case the call gets deleted.  */
1813   NO_DEFER_POP;
1814   expand_call (exp, target, 0);
1815   OK_DEFER_POP;
1816   emit_label (lab);
1817 }
1818 
1819 
1820 /* Expand a call to one of the builtin math functions (sqrt, exp, or log).
1821    Return 0 if a normal call should be emitted rather than expanding the
1822    function in-line.  EXP is the expression that is a call to the builtin
1823    function; if convenient, the result should be placed in TARGET.
1824    SUBTARGET may be used as the target for computing one of EXP's operands.  */
1825 
1826 static rtx
1827 expand_builtin_mathfn (tree exp, rtx target, rtx subtarget)
1828 {
1829   optab builtin_optab;
1830   rtx op0, insns, before_call;
1831   tree fndecl = get_callee_fndecl (exp);
1832   tree arglist = TREE_OPERAND (exp, 1);
1833   enum machine_mode mode;
1834   bool errno_set = false;
1835   tree arg, narg;
1836 
1837   if (!validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
1838     return 0;
1839 
1840   arg = TREE_VALUE (arglist);
1841 
1842   switch (DECL_FUNCTION_CODE (fndecl))
1843     {
1844     case BUILT_IN_SQRT:
1845     case BUILT_IN_SQRTF:
1846     case BUILT_IN_SQRTL:
1847       errno_set = ! tree_expr_nonnegative_p (arg);
1848       builtin_optab = sqrt_optab;
1849       break;
1850     case BUILT_IN_EXP:
1851     case BUILT_IN_EXPF:
1852     case BUILT_IN_EXPL:
1853       errno_set = true; builtin_optab = exp_optab; break;
1854     case BUILT_IN_EXP10:
1855     case BUILT_IN_EXP10F:
1856     case BUILT_IN_EXP10L:
1857     case BUILT_IN_POW10:
1858     case BUILT_IN_POW10F:
1859     case BUILT_IN_POW10L:
1860       errno_set = true; builtin_optab = exp10_optab; break;
1861     case BUILT_IN_EXP2:
1862     case BUILT_IN_EXP2F:
1863     case BUILT_IN_EXP2L:
1864       errno_set = true; builtin_optab = exp2_optab; break;
1865     case BUILT_IN_EXPM1:
1866     case BUILT_IN_EXPM1F:
1867     case BUILT_IN_EXPM1L:
1868       errno_set = true; builtin_optab = expm1_optab; break;
1869     case BUILT_IN_LOGB:
1870     case BUILT_IN_LOGBF:
1871     case BUILT_IN_LOGBL:
1872       errno_set = true; builtin_optab = logb_optab; break;
1873     case BUILT_IN_ILOGB:
1874     case BUILT_IN_ILOGBF:
1875     case BUILT_IN_ILOGBL:
1876       errno_set = true; builtin_optab = ilogb_optab; break;
1877     case BUILT_IN_LOG:
1878     case BUILT_IN_LOGF:
1879     case BUILT_IN_LOGL:
1880       errno_set = true; builtin_optab = log_optab; break;
1881     case BUILT_IN_LOG10:
1882     case BUILT_IN_LOG10F:
1883     case BUILT_IN_LOG10L:
1884       errno_set = true; builtin_optab = log10_optab; break;
1885     case BUILT_IN_LOG2:
1886     case BUILT_IN_LOG2F:
1887     case BUILT_IN_LOG2L:
1888       errno_set = true; builtin_optab = log2_optab; break;
1889     case BUILT_IN_LOG1P:
1890     case BUILT_IN_LOG1PF:
1891     case BUILT_IN_LOG1PL:
1892       errno_set = true; builtin_optab = log1p_optab; break;
1893     case BUILT_IN_ASIN:
1894     case BUILT_IN_ASINF:
1895     case BUILT_IN_ASINL:
1896       builtin_optab = asin_optab; break;
1897     case BUILT_IN_ACOS:
1898     case BUILT_IN_ACOSF:
1899     case BUILT_IN_ACOSL:
1900       builtin_optab = acos_optab; break;
1901     case BUILT_IN_TAN:
1902     case BUILT_IN_TANF:
1903     case BUILT_IN_TANL:
1904       builtin_optab = tan_optab; break;
1905     case BUILT_IN_ATAN:
1906     case BUILT_IN_ATANF:
1907     case BUILT_IN_ATANL:
1908       builtin_optab = atan_optab; break;
1909     case BUILT_IN_FLOOR:
1910     case BUILT_IN_FLOORF:
1911     case BUILT_IN_FLOORL:
1912       builtin_optab = floor_optab; break;
1913     case BUILT_IN_CEIL:
1914     case BUILT_IN_CEILF:
1915     case BUILT_IN_CEILL:
1916       builtin_optab = ceil_optab; break;
1917     case BUILT_IN_TRUNC:
1918     case BUILT_IN_TRUNCF:
1919     case BUILT_IN_TRUNCL:
1920       builtin_optab = btrunc_optab; break;
1921     case BUILT_IN_ROUND:
1922     case BUILT_IN_ROUNDF:
1923     case BUILT_IN_ROUNDL:
1924       builtin_optab = round_optab; break;
1925     case BUILT_IN_NEARBYINT:
1926     case BUILT_IN_NEARBYINTF:
1927     case BUILT_IN_NEARBYINTL:
1928       builtin_optab = nearbyint_optab; break;
1929     case BUILT_IN_RINT:
1930     case BUILT_IN_RINTF:
1931     case BUILT_IN_RINTL:
1932       builtin_optab = rint_optab; break;
1933     case BUILT_IN_LRINT:
1934     case BUILT_IN_LRINTF:
1935     case BUILT_IN_LRINTL:
1936     case BUILT_IN_LLRINT:
1937     case BUILT_IN_LLRINTF:
1938     case BUILT_IN_LLRINTL:
1939       builtin_optab = lrint_optab; break;
1940     default:
1941       gcc_unreachable ();
1942     }
1943 
1944   /* Make a suitable register to place result in.  */
1945   mode = TYPE_MODE (TREE_TYPE (exp));
1946 
1947   if (! flag_errno_math || ! HONOR_NANS (mode))
1948     errno_set = false;
1949 
1950   /* Before working hard, check whether the instruction is available.  */
1951   if (builtin_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing)
1952     {
1953       target = gen_reg_rtx (mode);
1954 
1955       /* Wrap the computation of the argument in a SAVE_EXPR, as we may
1956 	 need to expand the argument again.  This way, we will not perform
1957 	 side-effects more the once.  */
1958       narg = builtin_save_expr (arg);
1959       if (narg != arg)
1960 	{
1961 	  arg = narg;
1962 	  arglist = build_tree_list (NULL_TREE, arg);
1963 	  exp = build_function_call_expr (fndecl, arglist);
1964 	}
1965 
1966       op0 = expand_expr (arg, subtarget, VOIDmode, 0);
1967 
1968       start_sequence ();
1969 
1970       /* Compute into TARGET.
1971 	 Set TARGET to wherever the result comes back.  */
1972       target = expand_unop (mode, builtin_optab, op0, target, 0);
1973 
1974       if (target != 0)
1975 	{
1976 	  if (errno_set)
1977 	    expand_errno_check (exp, target);
1978 
1979 	  /* Output the entire sequence.  */
1980 	  insns = get_insns ();
1981 	  end_sequence ();
1982 	  emit_insn (insns);
1983 	  return target;
1984 	}
1985 
1986       /* If we were unable to expand via the builtin, stop the sequence
1987 	 (without outputting the insns) and call to the library function
1988 	 with the stabilized argument list.  */
1989       end_sequence ();
1990     }
1991 
1992   before_call = get_last_insn ();
1993 
1994   target = expand_call (exp, target, target == const0_rtx);
1995 
1996   /* If this is a sqrt operation and we don't care about errno, try to
1997      attach a REG_EQUAL note with a SQRT rtx to the emitted libcall.
1998      This allows the semantics of the libcall to be visible to the RTL
1999      optimizers.  */
2000   if (builtin_optab == sqrt_optab && !errno_set)
2001     {
2002       /* Search backwards through the insns emitted by expand_call looking
2003 	 for the instruction with the REG_RETVAL note.  */
2004       rtx last = get_last_insn ();
2005       while (last != before_call)
2006 	{
2007 	  if (find_reg_note (last, REG_RETVAL, NULL))
2008 	    {
2009 	      rtx note = find_reg_note (last, REG_EQUAL, NULL);
2010 	      /* Check that the REQ_EQUAL note is an EXPR_LIST with
2011 		 two elements, i.e. symbol_ref(sqrt) and the operand.  */
2012 	      if (note
2013 		  && GET_CODE (note) == EXPR_LIST
2014 		  && GET_CODE (XEXP (note, 0)) == EXPR_LIST
2015 		  && XEXP (XEXP (note, 0), 1) != NULL_RTX
2016 		  && XEXP (XEXP (XEXP (note, 0), 1), 1) == NULL_RTX)
2017 		{
2018 		  rtx operand = XEXP (XEXP (XEXP (note, 0), 1), 0);
2019 		  /* Check operand is a register with expected mode.  */
2020 		  if (operand
2021 		      && REG_P (operand)
2022 		      && GET_MODE (operand) == mode)
2023 		    {
2024 		      /* Replace the REG_EQUAL note with a SQRT rtx.  */
2025 		      rtx equiv = gen_rtx_SQRT (mode, operand);
2026 		      set_unique_reg_note (last, REG_EQUAL, equiv);
2027 		    }
2028 		}
2029 	      break;
2030 	    }
2031 	  last = PREV_INSN (last);
2032 	}
2033     }
2034 
2035   return target;
2036 }
2037 
2038 /* Expand a call to the builtin binary math functions (pow and atan2).
2039    Return 0 if a normal call should be emitted rather than expanding the
2040    function in-line.  EXP is the expression that is a call to the builtin
2041    function; if convenient, the result should be placed in TARGET.
2042    SUBTARGET may be used as the target for computing one of EXP's
2043    operands.  */
2044 
2045 static rtx
2046 expand_builtin_mathfn_2 (tree exp, rtx target, rtx subtarget)
2047 {
2048   optab builtin_optab;
2049   rtx op0, op1, insns;
2050   int op1_type = REAL_TYPE;
2051   tree fndecl = get_callee_fndecl (exp);
2052   tree arglist = TREE_OPERAND (exp, 1);
2053   tree arg0, arg1, temp, narg;
2054   enum machine_mode mode;
2055   bool errno_set = true;
2056   bool stable = true;
2057 
2058   if ((DECL_FUNCTION_CODE (fndecl) == BUILT_IN_LDEXP)
2059       || (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_LDEXPF)
2060       || (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_LDEXPL))
2061     op1_type = INTEGER_TYPE;
2062 
2063   if (!validate_arglist (arglist, REAL_TYPE, op1_type, VOID_TYPE))
2064     return 0;
2065 
2066   arg0 = TREE_VALUE (arglist);
2067   arg1 = TREE_VALUE (TREE_CHAIN (arglist));
2068 
2069   switch (DECL_FUNCTION_CODE (fndecl))
2070     {
2071     case BUILT_IN_POW:
2072     case BUILT_IN_POWF:
2073     case BUILT_IN_POWL:
2074       builtin_optab = pow_optab; break;
2075     case BUILT_IN_ATAN2:
2076     case BUILT_IN_ATAN2F:
2077     case BUILT_IN_ATAN2L:
2078       builtin_optab = atan2_optab; break;
2079     case BUILT_IN_LDEXP:
2080     case BUILT_IN_LDEXPF:
2081     case BUILT_IN_LDEXPL:
2082       builtin_optab = ldexp_optab; break;
2083     case BUILT_IN_FMOD:
2084     case BUILT_IN_FMODF:
2085     case BUILT_IN_FMODL:
2086       builtin_optab = fmod_optab; break;
2087     case BUILT_IN_DREM:
2088     case BUILT_IN_DREMF:
2089     case BUILT_IN_DREML:
2090       builtin_optab = drem_optab; break;
2091     default:
2092       gcc_unreachable ();
2093     }
2094 
2095   /* Make a suitable register to place result in.  */
2096   mode = TYPE_MODE (TREE_TYPE (exp));
2097 
2098   /* Before working hard, check whether the instruction is available.  */
2099   if (builtin_optab->handlers[(int) mode].insn_code == CODE_FOR_nothing)
2100     return 0;
2101 
2102   target = gen_reg_rtx (mode);
2103 
2104   if (! flag_errno_math || ! HONOR_NANS (mode))
2105     errno_set = false;
2106 
2107   /* Always stabilize the argument list.  */
2108   narg = builtin_save_expr (arg1);
2109   if (narg != arg1)
2110     {
2111       arg1 = narg;
2112       temp = build_tree_list (NULL_TREE, narg);
2113       stable = false;
2114     }
2115   else
2116     temp = TREE_CHAIN (arglist);
2117 
2118   narg = builtin_save_expr (arg0);
2119   if (narg != arg0)
2120     {
2121       arg0 = narg;
2122       arglist = tree_cons (NULL_TREE, narg, temp);
2123       stable = false;
2124     }
2125   else if (! stable)
2126     arglist = tree_cons (NULL_TREE, arg0, temp);
2127 
2128   if (! stable)
2129     exp = build_function_call_expr (fndecl, arglist);
2130 
2131   op0 = expand_expr (arg0, subtarget, VOIDmode, 0);
2132   op1 = expand_expr (arg1, 0, VOIDmode, 0);
2133 
2134   start_sequence ();
2135 
2136   /* Compute into TARGET.
2137      Set TARGET to wherever the result comes back.  */
2138   target = expand_binop (mode, builtin_optab, op0, op1,
2139 			 target, 0, OPTAB_DIRECT);
2140 
2141   /* If we were unable to expand via the builtin, stop the sequence
2142      (without outputting the insns) and call to the library function
2143      with the stabilized argument list.  */
2144   if (target == 0)
2145     {
2146       end_sequence ();
2147       return expand_call (exp, target, target == const0_rtx);
2148     }
2149 
2150   if (errno_set)
2151     expand_errno_check (exp, target);
2152 
2153   /* Output the entire sequence.  */
2154   insns = get_insns ();
2155   end_sequence ();
2156   emit_insn (insns);
2157 
2158   return target;
2159 }
2160 
2161 /* Expand a call to the builtin sin and cos math functions.
2162    Return 0 if a normal call should be emitted rather than expanding the
2163    function in-line.  EXP is the expression that is a call to the builtin
2164    function; if convenient, the result should be placed in TARGET.
2165    SUBTARGET may be used as the target for computing one of EXP's
2166    operands.  */
2167 
2168 static rtx
2169 expand_builtin_mathfn_3 (tree exp, rtx target, rtx subtarget)
2170 {
2171   optab builtin_optab;
2172   rtx op0, insns;
2173   tree fndecl = get_callee_fndecl (exp);
2174   tree arglist = TREE_OPERAND (exp, 1);
2175   enum machine_mode mode;
2176   bool errno_set = false;
2177   tree arg, narg;
2178 
2179   if (!validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
2180     return 0;
2181 
2182   arg = TREE_VALUE (arglist);
2183 
2184   switch (DECL_FUNCTION_CODE (fndecl))
2185     {
2186     case BUILT_IN_SIN:
2187     case BUILT_IN_SINF:
2188     case BUILT_IN_SINL:
2189     case BUILT_IN_COS:
2190     case BUILT_IN_COSF:
2191     case BUILT_IN_COSL:
2192       builtin_optab = sincos_optab; break;
2193     default:
2194       gcc_unreachable ();
2195     }
2196 
2197   /* Make a suitable register to place result in.  */
2198   mode = TYPE_MODE (TREE_TYPE (exp));
2199 
2200   if (! flag_errno_math || ! HONOR_NANS (mode))
2201     errno_set = false;
2202 
2203   /* Check if sincos insn is available, otherwise fallback
2204      to sin or cos insn.  */
2205   if (builtin_optab->handlers[(int) mode].insn_code == CODE_FOR_nothing) {
2206     switch (DECL_FUNCTION_CODE (fndecl))
2207       {
2208       case BUILT_IN_SIN:
2209       case BUILT_IN_SINF:
2210       case BUILT_IN_SINL:
2211 	builtin_optab = sin_optab; break;
2212       case BUILT_IN_COS:
2213       case BUILT_IN_COSF:
2214       case BUILT_IN_COSL:
2215 	builtin_optab = cos_optab; break;
2216       default:
2217 	gcc_unreachable ();
2218       }
2219   }
2220 
2221   /* Before working hard, check whether the instruction is available.  */
2222   if (builtin_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing)
2223     {
2224       target = gen_reg_rtx (mode);
2225 
2226       /* Wrap the computation of the argument in a SAVE_EXPR, as we may
2227 	 need to expand the argument again.  This way, we will not perform
2228 	 side-effects more the once.  */
2229       narg = save_expr (arg);
2230       if (narg != arg)
2231 	{
2232 	  arg = narg;
2233 	  arglist = build_tree_list (NULL_TREE, arg);
2234 	  exp = build_function_call_expr (fndecl, arglist);
2235 	}
2236 
2237       op0 = expand_expr (arg, subtarget, VOIDmode, 0);
2238 
2239       start_sequence ();
2240 
2241       /* Compute into TARGET.
2242 	 Set TARGET to wherever the result comes back.  */
2243       if (builtin_optab == sincos_optab)
2244 	{
2245 	  int result;
2246 
2247 	  switch (DECL_FUNCTION_CODE (fndecl))
2248 	    {
2249 	    case BUILT_IN_SIN:
2250 	    case BUILT_IN_SINF:
2251 	    case BUILT_IN_SINL:
2252 	      result = expand_twoval_unop (builtin_optab, op0, 0, target, 0);
2253 	      break;
2254 	    case BUILT_IN_COS:
2255 	    case BUILT_IN_COSF:
2256 	    case BUILT_IN_COSL:
2257 	      result = expand_twoval_unop (builtin_optab, op0, target, 0, 0);
2258 	      break;
2259 	    default:
2260 	      gcc_unreachable ();
2261 	    }
2262 	  gcc_assert (result);
2263 	}
2264       else
2265 	{
2266 	  target = expand_unop (mode, builtin_optab, op0, target, 0);
2267 	}
2268 
2269       if (target != 0)
2270 	{
2271 	  if (errno_set)
2272 	    expand_errno_check (exp, target);
2273 
2274 	  /* Output the entire sequence.  */
2275 	  insns = get_insns ();
2276 	  end_sequence ();
2277 	  emit_insn (insns);
2278 	  return target;
2279 	}
2280 
2281       /* If we were unable to expand via the builtin, stop the sequence
2282 	 (without outputting the insns) and call to the library function
2283 	 with the stabilized argument list.  */
2284       end_sequence ();
2285     }
2286 
2287   target = expand_call (exp, target, target == const0_rtx);
2288 
2289   return target;
2290 }
2291 
2292 /* Expand a call to one of the builtin rounding functions (lfloor).
2293    If expanding via optab fails, lower expression to (int)(floor(x)).
2294    EXP is the expression that is a call to the builtin function;
2295    if convenient, the result should be placed in TARGET.  SUBTARGET may
2296    be used as the target for computing one of EXP's operands.  */
2297 
2298 static rtx
2299 expand_builtin_int_roundingfn (tree exp, rtx target, rtx subtarget)
2300 {
2301   optab builtin_optab;
2302   rtx op0, insns, tmp;
2303   tree fndecl = get_callee_fndecl (exp);
2304   tree arglist = TREE_OPERAND (exp, 1);
2305   enum built_in_function fallback_fn;
2306   tree fallback_fndecl;
2307   enum machine_mode mode;
2308   tree arg, narg;
2309 
2310   if (!validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
2311     gcc_unreachable ();
2312 
2313   arg = TREE_VALUE (arglist);
2314 
2315   switch (DECL_FUNCTION_CODE (fndecl))
2316     {
2317     case BUILT_IN_LCEIL:
2318     case BUILT_IN_LCEILF:
2319     case BUILT_IN_LCEILL:
2320     case BUILT_IN_LLCEIL:
2321     case BUILT_IN_LLCEILF:
2322     case BUILT_IN_LLCEILL:
2323       builtin_optab = lceil_optab;
2324       fallback_fn = BUILT_IN_CEIL;
2325       break;
2326 
2327     case BUILT_IN_LFLOOR:
2328     case BUILT_IN_LFLOORF:
2329     case BUILT_IN_LFLOORL:
2330     case BUILT_IN_LLFLOOR:
2331     case BUILT_IN_LLFLOORF:
2332     case BUILT_IN_LLFLOORL:
2333       builtin_optab = lfloor_optab;
2334       fallback_fn = BUILT_IN_FLOOR;
2335       break;
2336 
2337     default:
2338       gcc_unreachable ();
2339     }
2340 
2341   /* Make a suitable register to place result in.  */
2342   mode = TYPE_MODE (TREE_TYPE (exp));
2343 
2344   /* Before working hard, check whether the instruction is available.  */
2345   if (builtin_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing)
2346     {
2347       target = gen_reg_rtx (mode);
2348 
2349       /* Wrap the computation of the argument in a SAVE_EXPR, as we may
2350 	 need to expand the argument again.  This way, we will not perform
2351 	 side-effects more the once.  */
2352       narg = builtin_save_expr (arg);
2353       if (narg != arg)
2354 	{
2355 	  arg = narg;
2356 	  arglist = build_tree_list (NULL_TREE, arg);
2357 	  exp = build_function_call_expr (fndecl, arglist);
2358 	}
2359 
2360       op0 = expand_expr (arg, subtarget, VOIDmode, 0);
2361 
2362       start_sequence ();
2363 
2364       /* Compute into TARGET.
2365 	 Set TARGET to wherever the result comes back.  */
2366       target = expand_unop (mode, builtin_optab, op0, target, 0);
2367 
2368       if (target != 0)
2369 	{
2370 	  /* Output the entire sequence.  */
2371 	  insns = get_insns ();
2372 	  end_sequence ();
2373 	  emit_insn (insns);
2374 	  return target;
2375 	}
2376 
2377       /* If we were unable to expand via the builtin, stop the sequence
2378 	 (without outputting the insns).  */
2379       end_sequence ();
2380     }
2381 
2382   /* Fall back to floating point rounding optab.  */
2383   fallback_fndecl = mathfn_built_in (TREE_TYPE (arg), fallback_fn);
2384   /* We shouldn't get here on targets without TARGET_C99_FUNCTIONS.
2385      ??? Perhaps convert (int)floorf(x) into (int)floor((double)x).  */
2386   gcc_assert (fallback_fndecl != NULL_TREE);
2387   exp = build_function_call_expr (fallback_fndecl, arglist);
2388 
2389   tmp = expand_expr (exp, NULL_RTX, VOIDmode, EXPAND_NORMAL);
2390 
2391   /* Truncate the result of floating point optab to integer
2392      via expand_fix ().  */
2393   target = gen_reg_rtx (mode);
2394   expand_fix (target, tmp, 0);
2395 
2396   return target;
2397 }
2398 
2399 /* To evaluate powi(x,n), the floating point value x raised to the
2400    constant integer exponent n, we use a hybrid algorithm that
2401    combines the "window method" with look-up tables.  For an
2402    introduction to exponentiation algorithms and "addition chains",
2403    see section 4.6.3, "Evaluation of Powers" of Donald E. Knuth,
2404    "Seminumerical Algorithms", Vol. 2, "The Art of Computer Programming",
2405    3rd Edition, 1998, and Daniel M. Gordon, "A Survey of Fast Exponentiation
2406    Methods", Journal of Algorithms, Vol. 27, pp. 129-146, 1998.  */
2407 
2408 /* Provide a default value for POWI_MAX_MULTS, the maximum number of
2409    multiplications to inline before calling the system library's pow
2410    function.  powi(x,n) requires at worst 2*bits(n)-2 multiplications,
2411    so this default never requires calling pow, powf or powl.  */
2412 
2413 #ifndef POWI_MAX_MULTS
2414 #define POWI_MAX_MULTS  (2*HOST_BITS_PER_WIDE_INT-2)
2415 #endif
2416 
2417 /* The size of the "optimal power tree" lookup table.  All
2418    exponents less than this value are simply looked up in the
2419    powi_table below.  This threshold is also used to size the
2420    cache of pseudo registers that hold intermediate results.  */
2421 #define POWI_TABLE_SIZE 256
2422 
2423 /* The size, in bits of the window, used in the "window method"
2424    exponentiation algorithm.  This is equivalent to a radix of
2425    (1<<POWI_WINDOW_SIZE) in the corresponding "m-ary method".  */
2426 #define POWI_WINDOW_SIZE 3
2427 
2428 /* The following table is an efficient representation of an
2429    "optimal power tree".  For each value, i, the corresponding
2430    value, j, in the table states than an optimal evaluation
2431    sequence for calculating pow(x,i) can be found by evaluating
2432    pow(x,j)*pow(x,i-j).  An optimal power tree for the first
2433    100 integers is given in Knuth's "Seminumerical algorithms".  */
2434 
2435 static const unsigned char powi_table[POWI_TABLE_SIZE] =
2436   {
2437       0,   1,   1,   2,   2,   3,   3,   4,  /*   0 -   7 */
2438       4,   6,   5,   6,   6,  10,   7,   9,  /*   8 -  15 */
2439       8,  16,   9,  16,  10,  12,  11,  13,  /*  16 -  23 */
2440      12,  17,  13,  18,  14,  24,  15,  26,  /*  24 -  31 */
2441      16,  17,  17,  19,  18,  33,  19,  26,  /*  32 -  39 */
2442      20,  25,  21,  40,  22,  27,  23,  44,  /*  40 -  47 */
2443      24,  32,  25,  34,  26,  29,  27,  44,  /*  48 -  55 */
2444      28,  31,  29,  34,  30,  60,  31,  36,  /*  56 -  63 */
2445      32,  64,  33,  34,  34,  46,  35,  37,  /*  64 -  71 */
2446      36,  65,  37,  50,  38,  48,  39,  69,  /*  72 -  79 */
2447      40,  49,  41,  43,  42,  51,  43,  58,  /*  80 -  87 */
2448      44,  64,  45,  47,  46,  59,  47,  76,  /*  88 -  95 */
2449      48,  65,  49,  66,  50,  67,  51,  66,  /*  96 - 103 */
2450      52,  70,  53,  74,  54, 104,  55,  74,  /* 104 - 111 */
2451      56,  64,  57,  69,  58,  78,  59,  68,  /* 112 - 119 */
2452      60,  61,  61,  80,  62,  75,  63,  68,  /* 120 - 127 */
2453      64,  65,  65, 128,  66, 129,  67,  90,  /* 128 - 135 */
2454      68,  73,  69, 131,  70,  94,  71,  88,  /* 136 - 143 */
2455      72, 128,  73,  98,  74, 132,  75, 121,  /* 144 - 151 */
2456      76, 102,  77, 124,  78, 132,  79, 106,  /* 152 - 159 */
2457      80,  97,  81, 160,  82,  99,  83, 134,  /* 160 - 167 */
2458      84,  86,  85,  95,  86, 160,  87, 100,  /* 168 - 175 */
2459      88, 113,  89,  98,  90, 107,  91, 122,  /* 176 - 183 */
2460      92, 111,  93, 102,  94, 126,  95, 150,  /* 184 - 191 */
2461      96, 128,  97, 130,  98, 133,  99, 195,  /* 192 - 199 */
2462     100, 128, 101, 123, 102, 164, 103, 138,  /* 200 - 207 */
2463     104, 145, 105, 146, 106, 109, 107, 149,  /* 208 - 215 */
2464     108, 200, 109, 146, 110, 170, 111, 157,  /* 216 - 223 */
2465     112, 128, 113, 130, 114, 182, 115, 132,  /* 224 - 231 */
2466     116, 200, 117, 132, 118, 158, 119, 206,  /* 232 - 239 */
2467     120, 240, 121, 162, 122, 147, 123, 152,  /* 240 - 247 */
2468     124, 166, 125, 214, 126, 138, 127, 153,  /* 248 - 255 */
2469   };
2470 
2471 
2472 /* Return the number of multiplications required to calculate
2473    powi(x,n) where n is less than POWI_TABLE_SIZE.  This is a
2474    subroutine of powi_cost.  CACHE is an array indicating
2475    which exponents have already been calculated.  */
2476 
2477 static int
2478 powi_lookup_cost (unsigned HOST_WIDE_INT n, bool *cache)
2479 {
2480   /* If we've already calculated this exponent, then this evaluation
2481      doesn't require any additional multiplications.  */
2482   if (cache[n])
2483     return 0;
2484 
2485   cache[n] = true;
2486   return powi_lookup_cost (n - powi_table[n], cache)
2487 	 + powi_lookup_cost (powi_table[n], cache) + 1;
2488 }
2489 
2490 /* Return the number of multiplications required to calculate
2491    powi(x,n) for an arbitrary x, given the exponent N.  This
2492    function needs to be kept in sync with expand_powi below.  */
2493 
2494 static int
2495 powi_cost (HOST_WIDE_INT n)
2496 {
2497   bool cache[POWI_TABLE_SIZE];
2498   unsigned HOST_WIDE_INT digit;
2499   unsigned HOST_WIDE_INT val;
2500   int result;
2501 
2502   if (n == 0)
2503     return 0;
2504 
2505   /* Ignore the reciprocal when calculating the cost.  */
2506   val = (n < 0) ? -n : n;
2507 
2508   /* Initialize the exponent cache.  */
2509   memset (cache, 0, POWI_TABLE_SIZE * sizeof (bool));
2510   cache[1] = true;
2511 
2512   result = 0;
2513 
2514   while (val >= POWI_TABLE_SIZE)
2515     {
2516       if (val & 1)
2517 	{
2518 	  digit = val & ((1 << POWI_WINDOW_SIZE) - 1);
2519 	  result += powi_lookup_cost (digit, cache)
2520 		    + POWI_WINDOW_SIZE + 1;
2521 	  val >>= POWI_WINDOW_SIZE;
2522 	}
2523       else
2524 	{
2525 	  val >>= 1;
2526 	  result++;
2527 	}
2528     }
2529 
2530   return result + powi_lookup_cost (val, cache);
2531 }
2532 
2533 /* Recursive subroutine of expand_powi.  This function takes the array,
2534    CACHE, of already calculated exponents and an exponent N and returns
2535    an RTX that corresponds to CACHE[1]**N, as calculated in mode MODE.  */
2536 
2537 static rtx
2538 expand_powi_1 (enum machine_mode mode, unsigned HOST_WIDE_INT n, rtx *cache)
2539 {
2540   unsigned HOST_WIDE_INT digit;
2541   rtx target, result;
2542   rtx op0, op1;
2543 
2544   if (n < POWI_TABLE_SIZE)
2545     {
2546       if (cache[n])
2547         return cache[n];
2548 
2549       target = gen_reg_rtx (mode);
2550       cache[n] = target;
2551 
2552       op0 = expand_powi_1 (mode, n - powi_table[n], cache);
2553       op1 = expand_powi_1 (mode, powi_table[n], cache);
2554     }
2555   else if (n & 1)
2556     {
2557       target = gen_reg_rtx (mode);
2558       digit = n & ((1 << POWI_WINDOW_SIZE) - 1);
2559       op0 = expand_powi_1 (mode, n - digit, cache);
2560       op1 = expand_powi_1 (mode, digit, cache);
2561     }
2562   else
2563     {
2564       target = gen_reg_rtx (mode);
2565       op0 = expand_powi_1 (mode, n >> 1, cache);
2566       op1 = op0;
2567     }
2568 
2569   result = expand_mult (mode, op0, op1, target, 0);
2570   if (result != target)
2571     emit_move_insn (target, result);
2572   return target;
2573 }
2574 
2575 /* Expand the RTL to evaluate powi(x,n) in mode MODE.  X is the
2576    floating point operand in mode MODE, and N is the exponent.  This
2577    function needs to be kept in sync with powi_cost above.  */
2578 
2579 static rtx
2580 expand_powi (rtx x, enum machine_mode mode, HOST_WIDE_INT n)
2581 {
2582   unsigned HOST_WIDE_INT val;
2583   rtx cache[POWI_TABLE_SIZE];
2584   rtx result;
2585 
2586   if (n == 0)
2587     return CONST1_RTX (mode);
2588 
2589   val = (n < 0) ? -n : n;
2590 
2591   memset (cache, 0, sizeof (cache));
2592   cache[1] = x;
2593 
2594   result = expand_powi_1 (mode, (n < 0) ? -n : n, cache);
2595 
2596   /* If the original exponent was negative, reciprocate the result.  */
2597   if (n < 0)
2598     result = expand_binop (mode, sdiv_optab, CONST1_RTX (mode),
2599 			   result, NULL_RTX, 0, OPTAB_LIB_WIDEN);
2600 
2601   return result;
2602 }
2603 
2604 /* Expand a call to the pow built-in mathematical function.  Return 0 if
2605    a normal call should be emitted rather than expanding the function
2606    in-line.  EXP is the expression that is a call to the builtin
2607    function; if convenient, the result should be placed in TARGET.  */
2608 
2609 static rtx
2610 expand_builtin_pow (tree exp, rtx target, rtx subtarget)
2611 {
2612   tree arglist = TREE_OPERAND (exp, 1);
2613   tree arg0, arg1;
2614 
2615   if (! validate_arglist (arglist, REAL_TYPE, REAL_TYPE, VOID_TYPE))
2616     return 0;
2617 
2618   arg0 = TREE_VALUE (arglist);
2619   arg1 = TREE_VALUE (TREE_CHAIN (arglist));
2620 
2621   if (TREE_CODE (arg1) == REAL_CST
2622       && ! TREE_CONSTANT_OVERFLOW (arg1))
2623     {
2624       REAL_VALUE_TYPE cint;
2625       REAL_VALUE_TYPE c;
2626       HOST_WIDE_INT n;
2627 
2628       c = TREE_REAL_CST (arg1);
2629       n = real_to_integer (&c);
2630       real_from_integer (&cint, VOIDmode, n, n < 0 ? -1 : 0, 0);
2631       if (real_identical (&c, &cint))
2632 	{
2633 	  /* If the exponent is -1, 0, 1 or 2, then expand_powi is exact.
2634 	     Otherwise, check the number of multiplications required.
2635 	     Note that pow never sets errno for an integer exponent.  */
2636 	  if ((n >= -1 && n <= 2)
2637 	      || (flag_unsafe_math_optimizations
2638 		  && ! optimize_size
2639 		  && powi_cost (n) <= POWI_MAX_MULTS))
2640 	    {
2641 	      enum machine_mode mode = TYPE_MODE (TREE_TYPE (exp));
2642 	      rtx op = expand_expr (arg0, subtarget, VOIDmode, 0);
2643 	      op = force_reg (mode, op);
2644 	      return expand_powi (op, mode, n);
2645 	    }
2646 	}
2647     }
2648 
2649   if (! flag_unsafe_math_optimizations)
2650     return NULL_RTX;
2651   return expand_builtin_mathfn_2 (exp, target, subtarget);
2652 }
2653 
2654 /* Expand a call to the powi built-in mathematical function.  Return 0 if
2655    a normal call should be emitted rather than expanding the function
2656    in-line.  EXP is the expression that is a call to the builtin
2657    function; if convenient, the result should be placed in TARGET.  */
2658 
2659 static rtx
2660 expand_builtin_powi (tree exp, rtx target, rtx subtarget)
2661 {
2662   tree arglist = TREE_OPERAND (exp, 1);
2663   tree arg0, arg1;
2664   rtx op0, op1;
2665   enum machine_mode mode;
2666   enum machine_mode mode2;
2667 
2668   if (! validate_arglist (arglist, REAL_TYPE, INTEGER_TYPE, VOID_TYPE))
2669     return 0;
2670 
2671   arg0 = TREE_VALUE (arglist);
2672   arg1 = TREE_VALUE (TREE_CHAIN (arglist));
2673   mode = TYPE_MODE (TREE_TYPE (exp));
2674 
2675   /* Handle constant power.  */
2676 
2677   if (TREE_CODE (arg1) == INTEGER_CST
2678       && ! TREE_CONSTANT_OVERFLOW (arg1))
2679     {
2680       HOST_WIDE_INT n = TREE_INT_CST_LOW (arg1);
2681 
2682       /* If the exponent is -1, 0, 1 or 2, then expand_powi is exact.
2683 	 Otherwise, check the number of multiplications required.  */
2684       if ((TREE_INT_CST_HIGH (arg1) == 0
2685 	   || TREE_INT_CST_HIGH (arg1) == -1)
2686 	  && ((n >= -1 && n <= 2)
2687 	      || (! optimize_size
2688 		  && powi_cost (n) <= POWI_MAX_MULTS)))
2689 	{
2690 	  op0 = expand_expr (arg0, subtarget, VOIDmode, 0);
2691 	  op0 = force_reg (mode, op0);
2692 	  return expand_powi (op0, mode, n);
2693 	}
2694     }
2695 
2696   /* Emit a libcall to libgcc.  */
2697 
2698   /* Mode of the 2nd argument must match that of an int. */
2699   mode2 = mode_for_size (INT_TYPE_SIZE, MODE_INT, 0);
2700 
2701   if (target == NULL_RTX)
2702     target = gen_reg_rtx (mode);
2703 
2704   op0 = expand_expr (arg0, subtarget, mode, 0);
2705   if (GET_MODE (op0) != mode)
2706     op0 = convert_to_mode (mode, op0, 0);
2707   op1 = expand_expr (arg1, 0, mode2, 0);
2708   if (GET_MODE (op1) != mode2)
2709     op1 = convert_to_mode (mode2, op1, 0);
2710 
2711   target = emit_library_call_value (powi_optab->handlers[(int) mode].libfunc,
2712 				    target, LCT_CONST_MAKE_BLOCK, mode, 2,
2713 				    op0, mode, op1, mode2);
2714 
2715   return target;
2716 }
2717 
2718 /* Expand expression EXP which is a call to the strlen builtin.  Return 0
2719    if we failed the caller should emit a normal call, otherwise
2720    try to get the result in TARGET, if convenient.  */
2721 
2722 static rtx
2723 expand_builtin_strlen (tree arglist, rtx target,
2724 		       enum machine_mode target_mode)
2725 {
2726   if (!validate_arglist (arglist, POINTER_TYPE, VOID_TYPE))
2727     return 0;
2728   else
2729     {
2730       rtx pat;
2731       tree len, src = TREE_VALUE (arglist);
2732       rtx result, src_reg, char_rtx, before_strlen;
2733       enum machine_mode insn_mode = target_mode, char_mode;
2734       enum insn_code icode = CODE_FOR_nothing;
2735       int align;
2736 
2737       /* If the length can be computed at compile-time, return it.  */
2738       len = c_strlen (src, 0);
2739       if (len)
2740 	return expand_expr (len, target, target_mode, EXPAND_NORMAL);
2741 
2742       /* If the length can be computed at compile-time and is constant
2743 	 integer, but there are side-effects in src, evaluate
2744 	 src for side-effects, then return len.
2745 	 E.g. x = strlen (i++ ? "xfoo" + 1 : "bar");
2746 	 can be optimized into: i++; x = 3;  */
2747       len = c_strlen (src, 1);
2748       if (len && TREE_CODE (len) == INTEGER_CST)
2749 	{
2750 	  expand_expr (src, const0_rtx, VOIDmode, EXPAND_NORMAL);
2751 	  return expand_expr (len, target, target_mode, EXPAND_NORMAL);
2752 	}
2753 
2754       align = get_pointer_alignment (src, BIGGEST_ALIGNMENT) / BITS_PER_UNIT;
2755 
2756       /* If SRC is not a pointer type, don't do this operation inline.  */
2757       if (align == 0)
2758 	return 0;
2759 
2760       /* Bail out if we can't compute strlen in the right mode.  */
2761       while (insn_mode != VOIDmode)
2762 	{
2763 	  icode = strlen_optab->handlers[(int) insn_mode].insn_code;
2764 	  if (icode != CODE_FOR_nothing)
2765 	    break;
2766 
2767 	  insn_mode = GET_MODE_WIDER_MODE (insn_mode);
2768 	}
2769       if (insn_mode == VOIDmode)
2770 	return 0;
2771 
2772       /* Make a place to write the result of the instruction.  */
2773       result = target;
2774       if (! (result != 0
2775 	     && REG_P (result)
2776 	     && GET_MODE (result) == insn_mode
2777 	     && REGNO (result) >= FIRST_PSEUDO_REGISTER))
2778 	result = gen_reg_rtx (insn_mode);
2779 
2780       /* Make a place to hold the source address.  We will not expand
2781 	 the actual source until we are sure that the expansion will
2782 	 not fail -- there are trees that cannot be expanded twice.  */
2783       src_reg = gen_reg_rtx (Pmode);
2784 
2785       /* Mark the beginning of the strlen sequence so we can emit the
2786 	 source operand later.  */
2787       before_strlen = get_last_insn ();
2788 
2789       char_rtx = const0_rtx;
2790       char_mode = insn_data[(int) icode].operand[2].mode;
2791       if (! (*insn_data[(int) icode].operand[2].predicate) (char_rtx,
2792 							    char_mode))
2793 	char_rtx = copy_to_mode_reg (char_mode, char_rtx);
2794 
2795       pat = GEN_FCN (icode) (result, gen_rtx_MEM (BLKmode, src_reg),
2796 			     char_rtx, GEN_INT (align));
2797       if (! pat)
2798 	return 0;
2799       emit_insn (pat);
2800 
2801       /* Now that we are assured of success, expand the source.  */
2802       start_sequence ();
2803       pat = expand_expr (src, src_reg, ptr_mode, EXPAND_NORMAL);
2804       if (pat != src_reg)
2805 	emit_move_insn (src_reg, pat);
2806       pat = get_insns ();
2807       end_sequence ();
2808 
2809       if (before_strlen)
2810 	emit_insn_after (pat, before_strlen);
2811       else
2812 	emit_insn_before (pat, get_insns ());
2813 
2814       /* Return the value in the proper mode for this function.  */
2815       if (GET_MODE (result) == target_mode)
2816 	target = result;
2817       else if (target != 0)
2818 	convert_move (target, result, 0);
2819       else
2820 	target = convert_to_mode (target_mode, result, 0);
2821 
2822       return target;
2823     }
2824 }
2825 
2826 /* Expand a call to the strstr builtin.  Return 0 if we failed the
2827    caller should emit a normal call, otherwise try to get the result
2828    in TARGET, if convenient (and in mode MODE if that's convenient).  */
2829 
2830 static rtx
2831 expand_builtin_strstr (tree arglist, tree type, rtx target, enum machine_mode mode)
2832 {
2833   if (validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
2834     {
2835       tree result = fold_builtin_strstr (arglist, type);
2836       if (result)
2837 	return expand_expr (result, target, mode, EXPAND_NORMAL);
2838     }
2839   return 0;
2840 }
2841 
2842 /* Expand a call to the strchr builtin.  Return 0 if we failed the
2843    caller should emit a normal call, otherwise try to get the result
2844    in TARGET, if convenient (and in mode MODE if that's convenient).  */
2845 
2846 static rtx
2847 expand_builtin_strchr (tree arglist, tree type, rtx target, enum machine_mode mode)
2848 {
2849   if (validate_arglist (arglist, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
2850     {
2851       tree result = fold_builtin_strchr (arglist, type);
2852       if (result)
2853 	return expand_expr (result, target, mode, EXPAND_NORMAL);
2854 
2855       /* FIXME: Should use strchrM optab so that ports can optimize this.  */
2856     }
2857   return 0;
2858 }
2859 
2860 /* Expand a call to the strrchr builtin.  Return 0 if we failed the
2861    caller should emit a normal call, otherwise try to get the result
2862    in TARGET, if convenient (and in mode MODE if that's convenient).  */
2863 
2864 static rtx
2865 expand_builtin_strrchr (tree arglist, tree type, rtx target, enum machine_mode mode)
2866 {
2867   if (validate_arglist (arglist, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
2868     {
2869       tree result = fold_builtin_strrchr (arglist, type);
2870       if (result)
2871 	return expand_expr (result, target, mode, EXPAND_NORMAL);
2872     }
2873   return 0;
2874 }
2875 
2876 /* Expand a call to the strpbrk builtin.  Return 0 if we failed the
2877    caller should emit a normal call, otherwise try to get the result
2878    in TARGET, if convenient (and in mode MODE if that's convenient).  */
2879 
2880 static rtx
2881 expand_builtin_strpbrk (tree arglist, tree type, rtx target, enum machine_mode mode)
2882 {
2883   if (validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
2884     {
2885       tree result = fold_builtin_strpbrk (arglist, type);
2886       if (result)
2887 	return expand_expr (result, target, mode, EXPAND_NORMAL);
2888     }
2889   return 0;
2890 }
2891 #endif /* 0 */
2892 
2893 /* Callback routine for store_by_pieces.  Read GET_MODE_BITSIZE (MODE)
2894    bytes from constant string DATA + OFFSET and return it as target
2895    constant.  */
2896 
2897 static rtx
builtin_memcpy_read_str(void * data,HOST_WIDE_INT offset,enum machine_mode mode)2898 builtin_memcpy_read_str (void *data, HOST_WIDE_INT offset,
2899 			 enum machine_mode mode)
2900 {
2901   const char *str = (const char *) data;
2902 
2903   gcc_assert (offset >= 0
2904 	      && ((unsigned HOST_WIDE_INT) offset + GET_MODE_SIZE (mode)
2905 		  <= strlen (str) + 1));
2906 
2907   return c_readstr (str + offset, mode);
2908 }
2909 
2910 /* Expand a call to the memcpy builtin, with arguments in ARGLIST.
2911    Return 0 if we failed, the caller should emit a normal call,
2912    otherwise try to get the result in TARGET, if convenient (and in
2913    mode MODE if that's convenient).  */
2914 static rtx
expand_builtin_memcpy(tree exp,rtx target,enum machine_mode mode)2915 expand_builtin_memcpy (tree exp, rtx target, enum machine_mode mode)
2916 {
2917   tree fndecl = get_callee_fndecl (exp);
2918   tree arglist = TREE_OPERAND (exp, 1);
2919   if (!validate_arglist (arglist,
2920 			 POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
2921     return 0;
2922   else
2923     {
2924       tree dest = TREE_VALUE (arglist);
2925       tree src = TREE_VALUE (TREE_CHAIN (arglist));
2926       tree len = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
2927       const char *src_str;
2928       unsigned int src_align = get_pointer_alignment (src, BIGGEST_ALIGNMENT);
2929       unsigned int dest_align
2930 	= get_pointer_alignment (dest, BIGGEST_ALIGNMENT);
2931       rtx dest_mem, src_mem, dest_addr, len_rtx;
2932       tree result = fold_builtin_memcpy (fndecl, arglist);
2933 
2934       if (result)
2935 	return expand_expr (result, target, mode, EXPAND_NORMAL);
2936 
2937       /* If DEST is not a pointer type, call the normal function.  */
2938       if (dest_align == 0)
2939 	return 0;
2940 
2941       /* If either SRC is not a pointer type, don't do this
2942          operation in-line.  */
2943       if (src_align == 0)
2944 	return 0;
2945 
2946       dest_mem = get_memory_rtx (dest, len);
2947       set_mem_align (dest_mem, dest_align);
2948       len_rtx = expand_expr (len, NULL_RTX, VOIDmode, 0);
2949       src_str = c_getstr (src);
2950 
2951       /* If SRC is a string constant and block move would be done
2952 	 by pieces, we can avoid loading the string from memory
2953 	 and only stored the computed constants.  */
2954       if (src_str
2955 	  && GET_CODE (len_rtx) == CONST_INT
2956 	  && (unsigned HOST_WIDE_INT) INTVAL (len_rtx) <= strlen (src_str) + 1
2957 	  && can_store_by_pieces (INTVAL (len_rtx), builtin_memcpy_read_str,
2958 				  (void *) src_str, dest_align))
2959 	{
2960 	  dest_mem = store_by_pieces (dest_mem, INTVAL (len_rtx),
2961 				      builtin_memcpy_read_str,
2962 				      (void *) src_str, dest_align, 0);
2963 	  dest_mem = force_operand (XEXP (dest_mem, 0), NULL_RTX);
2964 	  dest_mem = convert_memory_address (ptr_mode, dest_mem);
2965 	  return dest_mem;
2966 	}
2967 
2968       src_mem = get_memory_rtx (src, len);
2969       set_mem_align (src_mem, src_align);
2970 
2971       /* Copy word part most expediently.  */
2972       dest_addr = emit_block_move (dest_mem, src_mem, len_rtx,
2973 				   CALL_EXPR_TAILCALL (exp)
2974 				   ? BLOCK_OP_TAILCALL : BLOCK_OP_NORMAL);
2975 
2976       if (dest_addr == 0)
2977 	{
2978 	  dest_addr = force_operand (XEXP (dest_mem, 0), NULL_RTX);
2979 	  dest_addr = convert_memory_address (ptr_mode, dest_addr);
2980 	}
2981       return dest_addr;
2982     }
2983 }
2984 
2985 #if 0
2986 /* Expand a call to the mempcpy builtin, with arguments in ARGLIST.
2987    Return 0 if we failed; the caller should emit a normal call,
2988    otherwise try to get the result in TARGET, if convenient (and in
2989    mode MODE if that's convenient).  If ENDP is 0 return the
2990    destination pointer, if ENDP is 1 return the end pointer ala
2991    mempcpy, and if ENDP is 2 return the end pointer minus one ala
2992    stpcpy.  */
2993 
2994 static rtx
2995 expand_builtin_mempcpy (tree arglist, tree type, rtx target, enum machine_mode mode,
2996 			int endp)
2997 {
2998   if (!validate_arglist (arglist,
2999 			 POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
3000     return 0;
3001   /* If return value is ignored, transform mempcpy into memcpy.  */
3002   else if (target == const0_rtx)
3003     {
3004       tree fn = implicit_built_in_decls[BUILT_IN_MEMCPY];
3005 
3006       if (!fn)
3007 	return 0;
3008 
3009       return expand_expr (build_function_call_expr (fn, arglist),
3010 			  target, mode, EXPAND_NORMAL);
3011     }
3012   else
3013     {
3014       tree dest = TREE_VALUE (arglist);
3015       tree src = TREE_VALUE (TREE_CHAIN (arglist));
3016       tree len = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
3017       const char *src_str;
3018       unsigned int src_align = get_pointer_alignment (src, BIGGEST_ALIGNMENT);
3019       unsigned int dest_align
3020 	= get_pointer_alignment (dest, BIGGEST_ALIGNMENT);
3021       rtx dest_mem, src_mem, len_rtx;
3022       tree result = fold_builtin_mempcpy (arglist, type, endp);
3023 
3024       if (result)
3025 	return expand_expr (result, target, mode, EXPAND_NORMAL);
3026 
3027       /* If either SRC or DEST is not a pointer type, don't do this
3028          operation in-line.  */
3029       if (dest_align == 0 || src_align == 0)
3030 	return 0;
3031 
3032       /* If LEN is not constant, call the normal function.  */
3033       if (! host_integerp (len, 1))
3034 	return 0;
3035 
3036       len_rtx = expand_expr (len, NULL_RTX, VOIDmode, 0);
3037       src_str = c_getstr (src);
3038 
3039       /* If SRC is a string constant and block move would be done
3040 	 by pieces, we can avoid loading the string from memory
3041 	 and only stored the computed constants.  */
3042       if (src_str
3043 	  && GET_CODE (len_rtx) == CONST_INT
3044 	  && (unsigned HOST_WIDE_INT) INTVAL (len_rtx) <= strlen (src_str) + 1
3045 	  && can_store_by_pieces (INTVAL (len_rtx), builtin_memcpy_read_str,
3046 				  (void *) src_str, dest_align))
3047 	{
3048 	  dest_mem = get_memory_rtx (dest, len);
3049 	  set_mem_align (dest_mem, dest_align);
3050 	  dest_mem = store_by_pieces (dest_mem, INTVAL (len_rtx),
3051 				      builtin_memcpy_read_str,
3052 				      (void *) src_str, dest_align, endp);
3053 	  dest_mem = force_operand (XEXP (dest_mem, 0), NULL_RTX);
3054 	  dest_mem = convert_memory_address (ptr_mode, dest_mem);
3055 	  return dest_mem;
3056 	}
3057 
3058       if (GET_CODE (len_rtx) == CONST_INT
3059 	  && can_move_by_pieces (INTVAL (len_rtx),
3060 				 MIN (dest_align, src_align)))
3061 	{
3062 	  dest_mem = get_memory_rtx (dest, len);
3063 	  set_mem_align (dest_mem, dest_align);
3064 	  src_mem = get_memory_rtx (src, len);
3065 	  set_mem_align (src_mem, src_align);
3066 	  dest_mem = move_by_pieces (dest_mem, src_mem, INTVAL (len_rtx),
3067 				     MIN (dest_align, src_align), endp);
3068 	  dest_mem = force_operand (XEXP (dest_mem, 0), NULL_RTX);
3069 	  dest_mem = convert_memory_address (ptr_mode, dest_mem);
3070 	  return dest_mem;
3071 	}
3072 
3073       return 0;
3074     }
3075 }
3076 
3077 /* Expand expression EXP, which is a call to the memmove builtin.  Return 0
3078    if we failed; the caller should emit a normal call.  */
3079 
3080 static rtx
3081 expand_builtin_memmove (tree arglist, tree type, rtx target,
3082 			enum machine_mode mode, tree orig_exp)
3083 {
3084   if (!validate_arglist (arglist,
3085 			 POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
3086     return 0;
3087   else
3088     {
3089       tree dest = TREE_VALUE (arglist);
3090       tree src = TREE_VALUE (TREE_CHAIN (arglist));
3091       tree len = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
3092 
3093       unsigned int src_align = get_pointer_alignment (src, BIGGEST_ALIGNMENT);
3094       unsigned int dest_align
3095 	= get_pointer_alignment (dest, BIGGEST_ALIGNMENT);
3096       tree result = fold_builtin_memmove (arglist, type);
3097 
3098       if (result)
3099 	return expand_expr (result, target, mode, EXPAND_NORMAL);
3100 
3101       /* If DEST is not a pointer type, call the normal function.  */
3102       if (dest_align == 0)
3103 	return 0;
3104 
3105       /* If either SRC is not a pointer type, don't do this
3106          operation in-line.  */
3107       if (src_align == 0)
3108 	return 0;
3109 
3110       /* If src is categorized for a readonly section we can use
3111 	 normal memcpy.  */
3112       if (readonly_data_expr (src))
3113         {
3114 	  tree fn = implicit_built_in_decls[BUILT_IN_MEMCPY];
3115 	  if (!fn)
3116 	    return 0;
3117 	  fn = build_function_call_expr (fn, arglist);
3118 	  if (TREE_CODE (fn) == CALL_EXPR)
3119 	    CALL_EXPR_TAILCALL (fn) = CALL_EXPR_TAILCALL (orig_exp);
3120 	  return expand_expr (fn, target, mode, EXPAND_NORMAL);
3121 	}
3122 
3123       /* If length is 1 and we can expand memcpy call inline,
3124 	 it is ok to use memcpy as well.  */
3125       if (integer_onep (len))
3126         {
3127 	  rtx ret = expand_builtin_mempcpy (arglist, type, target, mode,
3128 					    /*endp=*/0);
3129 	  if (ret)
3130 	    return ret;
3131         }
3132 
3133       /* Otherwise, call the normal function.  */
3134       return 0;
3135    }
3136 }
3137 
3138 /* Expand expression EXP, which is a call to the bcopy builtin.  Return 0
3139    if we failed the caller should emit a normal call.  */
3140 
3141 static rtx
3142 expand_builtin_bcopy (tree exp)
3143 {
3144   tree arglist = TREE_OPERAND (exp, 1);
3145   tree type = TREE_TYPE (exp);
3146   tree src, dest, size, newarglist;
3147 
3148   if (!validate_arglist (arglist,
3149 			 POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
3150     return NULL_RTX;
3151 
3152   src = TREE_VALUE (arglist);
3153   dest = TREE_VALUE (TREE_CHAIN (arglist));
3154   size = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
3155 
3156   /* New argument list transforming bcopy(ptr x, ptr y, int z) to
3157      memmove(ptr y, ptr x, size_t z).   This is done this way
3158      so that if it isn't expanded inline, we fallback to
3159      calling bcopy instead of memmove.  */
3160 
3161   newarglist = build_tree_list (NULL_TREE, fold_convert (sizetype, size));
3162   newarglist = tree_cons (NULL_TREE, src, newarglist);
3163   newarglist = tree_cons (NULL_TREE, dest, newarglist);
3164 
3165   return expand_builtin_memmove (newarglist, type, const0_rtx, VOIDmode, exp);
3166 }
3167 
3168 #ifndef HAVE_movstr
3169 # define HAVE_movstr 0
3170 # define CODE_FOR_movstr CODE_FOR_nothing
3171 #endif
3172 
3173 /* Expand into a movstr instruction, if one is available.  Return 0 if
3174    we failed, the caller should emit a normal call, otherwise try to
3175    get the result in TARGET, if convenient.  If ENDP is 0 return the
3176    destination pointer, if ENDP is 1 return the end pointer ala
3177    mempcpy, and if ENDP is 2 return the end pointer minus one ala
3178    stpcpy.  */
3179 
3180 static rtx
3181 expand_movstr (tree dest, tree src, rtx target, int endp)
3182 {
3183   rtx end;
3184   rtx dest_mem;
3185   rtx src_mem;
3186   rtx insn;
3187   const struct insn_data * data;
3188 
3189   if (!HAVE_movstr)
3190     return 0;
3191 
3192   dest_mem = get_memory_rtx (dest, NULL);
3193   src_mem = get_memory_rtx (src, NULL);
3194   if (!endp)
3195     {
3196       target = force_reg (Pmode, XEXP (dest_mem, 0));
3197       dest_mem = replace_equiv_address (dest_mem, target);
3198       end = gen_reg_rtx (Pmode);
3199     }
3200   else
3201     {
3202       if (target == 0 || target == const0_rtx)
3203 	{
3204 	  end = gen_reg_rtx (Pmode);
3205 	  if (target == 0)
3206 	    target = end;
3207 	}
3208       else
3209 	end = target;
3210     }
3211 
3212   data = insn_data + CODE_FOR_movstr;
3213 
3214   if (data->operand[0].mode != VOIDmode)
3215     end = gen_lowpart (data->operand[0].mode, end);
3216 
3217   insn = data->genfun (end, dest_mem, src_mem);
3218 
3219   gcc_assert (insn);
3220 
3221   emit_insn (insn);
3222 
3223   /* movstr is supposed to set end to the address of the NUL
3224      terminator.  If the caller requested a mempcpy-like return value,
3225      adjust it.  */
3226   if (endp == 1 && target != const0_rtx)
3227     {
3228       rtx tem = plus_constant (gen_lowpart (GET_MODE (target), end), 1);
3229       emit_move_insn (target, force_operand (tem, NULL_RTX));
3230     }
3231 
3232   return target;
3233 }
3234 
3235 /* Expand expression EXP, which is a call to the strcpy builtin.  Return 0
3236    if we failed the caller should emit a normal call, otherwise try to get
3237    the result in TARGET, if convenient (and in mode MODE if that's
3238    convenient).  */
3239 
3240 static rtx
3241 expand_builtin_strcpy (tree fndecl, tree arglist, rtx target, enum machine_mode mode)
3242 {
3243   if (validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
3244     {
3245       tree result = fold_builtin_strcpy (fndecl, arglist, 0);
3246       if (result)
3247 	return expand_expr (result, target, mode, EXPAND_NORMAL);
3248 
3249       return expand_movstr (TREE_VALUE (arglist),
3250 			    TREE_VALUE (TREE_CHAIN (arglist)),
3251 			    target, /*endp=*/0);
3252     }
3253   return 0;
3254 }
3255 
3256 /* Expand a call to the stpcpy builtin, with arguments in ARGLIST.
3257    Return 0 if we failed the caller should emit a normal call,
3258    otherwise try to get the result in TARGET, if convenient (and in
3259    mode MODE if that's convenient).  */
3260 
3261 static rtx
3262 expand_builtin_stpcpy (tree exp, rtx target, enum machine_mode mode)
3263 {
3264   tree arglist = TREE_OPERAND (exp, 1);
3265   /* If return value is ignored, transform stpcpy into strcpy.  */
3266   if (target == const0_rtx)
3267     {
3268       tree fn = implicit_built_in_decls[BUILT_IN_STRCPY];
3269       if (!fn)
3270 	return 0;
3271 
3272       return expand_expr (build_function_call_expr (fn, arglist),
3273 			  target, mode, EXPAND_NORMAL);
3274     }
3275 
3276   if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
3277     return 0;
3278   else
3279     {
3280       tree dst, src, len, lenp1;
3281       tree narglist;
3282       rtx ret;
3283 
3284       /* Ensure we get an actual string whose length can be evaluated at
3285          compile-time, not an expression containing a string.  This is
3286          because the latter will potentially produce pessimized code
3287          when used to produce the return value.  */
3288       src = TREE_VALUE (TREE_CHAIN (arglist));
3289       if (! c_getstr (src) || ! (len = c_strlen (src, 0)))
3290 	return expand_movstr (TREE_VALUE (arglist),
3291 			      TREE_VALUE (TREE_CHAIN (arglist)),
3292 			      target, /*endp=*/2);
3293 
3294       dst = TREE_VALUE (arglist);
3295       lenp1 = size_binop (PLUS_EXPR, len, ssize_int (1));
3296       narglist = build_tree_list (NULL_TREE, lenp1);
3297       narglist = tree_cons (NULL_TREE, src, narglist);
3298       narglist = tree_cons (NULL_TREE, dst, narglist);
3299       ret = expand_builtin_mempcpy (narglist, TREE_TYPE (exp),
3300 				    target, mode, /*endp=*/2);
3301 
3302       if (ret)
3303 	return ret;
3304 
3305       if (TREE_CODE (len) == INTEGER_CST)
3306 	{
3307 	  rtx len_rtx = expand_expr (len, NULL_RTX, VOIDmode, 0);
3308 
3309 	  if (GET_CODE (len_rtx) == CONST_INT)
3310 	    {
3311 	      ret = expand_builtin_strcpy (get_callee_fndecl (exp),
3312 					   arglist, target, mode);
3313 
3314 	      if (ret)
3315 		{
3316 		  if (! target)
3317 		    {
3318 		      if (mode != VOIDmode)
3319 			target = gen_reg_rtx (mode);
3320 		      else
3321 			target = gen_reg_rtx (GET_MODE (ret));
3322 		    }
3323 		  if (GET_MODE (target) != GET_MODE (ret))
3324 		    ret = gen_lowpart (GET_MODE (target), ret);
3325 
3326 		  ret = plus_constant (ret, INTVAL (len_rtx));
3327 		  ret = emit_move_insn (target, force_operand (ret, NULL_RTX));
3328 		  gcc_assert (ret);
3329 
3330 		  return target;
3331 		}
3332 	    }
3333 	}
3334 
3335       return expand_movstr (TREE_VALUE (arglist),
3336 			    TREE_VALUE (TREE_CHAIN (arglist)),
3337 			    target, /*endp=*/2);
3338     }
3339 }
3340 
3341 /* Callback routine for store_by_pieces.  Read GET_MODE_BITSIZE (MODE)
3342    bytes from constant string DATA + OFFSET and return it as target
3343    constant.  */
3344 
3345 static rtx
3346 builtin_strncpy_read_str (void *data, HOST_WIDE_INT offset,
3347 			  enum machine_mode mode)
3348 {
3349   const char *str = (const char *) data;
3350 
3351   if ((unsigned HOST_WIDE_INT) offset > strlen (str))
3352     return const0_rtx;
3353 
3354   return c_readstr (str + offset, mode);
3355 }
3356 
3357 /* Expand expression EXP, which is a call to the strncpy builtin.  Return 0
3358    if we failed the caller should emit a normal call.  */
3359 
3360 static rtx
3361 expand_builtin_strncpy (tree exp, rtx target, enum machine_mode mode)
3362 {
3363   tree fndecl = get_callee_fndecl (exp);
3364   tree arglist = TREE_OPERAND (exp, 1);
3365   if (validate_arglist (arglist,
3366 			POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
3367     {
3368       tree slen = c_strlen (TREE_VALUE (TREE_CHAIN (arglist)), 1);
3369       tree len = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
3370       tree result = fold_builtin_strncpy (fndecl, arglist, slen);
3371 
3372       if (result)
3373 	return expand_expr (result, target, mode, EXPAND_NORMAL);
3374 
3375       /* We must be passed a constant len and src parameter.  */
3376       if (!host_integerp (len, 1) || !slen || !host_integerp (slen, 1))
3377 	return 0;
3378 
3379       slen = size_binop (PLUS_EXPR, slen, ssize_int (1));
3380 
3381       /* We're required to pad with trailing zeros if the requested
3382          len is greater than strlen(s2)+1.  In that case try to
3383 	 use store_by_pieces, if it fails, punt.  */
3384       if (tree_int_cst_lt (slen, len))
3385 	{
3386 	  tree dest = TREE_VALUE (arglist);
3387 	  unsigned int dest_align
3388 	    = get_pointer_alignment (dest, BIGGEST_ALIGNMENT);
3389 	  const char *p = c_getstr (TREE_VALUE (TREE_CHAIN (arglist)));
3390 	  rtx dest_mem;
3391 
3392 	  if (!p || dest_align == 0 || !host_integerp (len, 1)
3393 	      || !can_store_by_pieces (tree_low_cst (len, 1),
3394 				       builtin_strncpy_read_str,
3395 				       (void *) p, dest_align))
3396 	    return 0;
3397 
3398 	  dest_mem = get_memory_rtx (dest, len);
3399 	  store_by_pieces (dest_mem, tree_low_cst (len, 1),
3400 			   builtin_strncpy_read_str,
3401 			   (void *) p, dest_align, 0);
3402 	  dest_mem = force_operand (XEXP (dest_mem, 0), NULL_RTX);
3403 	  dest_mem = convert_memory_address (ptr_mode, dest_mem);
3404 	  return dest_mem;
3405 	}
3406     }
3407   return 0;
3408 }
3409 #endif /* 0 */
3410 
3411 /* Callback routine for store_by_pieces.  Read GET_MODE_BITSIZE (MODE)
3412    bytes from constant string DATA + OFFSET and return it as target
3413    constant.  */
3414 
3415 static rtx
builtin_memset_read_str(void * data,HOST_WIDE_INT offset ATTRIBUTE_UNUSED,enum machine_mode mode)3416 builtin_memset_read_str (void *data, HOST_WIDE_INT offset ATTRIBUTE_UNUSED,
3417 			 enum machine_mode mode)
3418 {
3419   const char *c = (const char *) data;
3420   char *p = alloca (GET_MODE_SIZE (mode));
3421 
3422   memset (p, *c, GET_MODE_SIZE (mode));
3423 
3424   return c_readstr (p, mode);
3425 }
3426 
3427 /* Callback routine for store_by_pieces.  Return the RTL of a register
3428    containing GET_MODE_SIZE (MODE) consecutive copies of the unsigned
3429    char value given in the RTL register data.  For example, if mode is
3430    4 bytes wide, return the RTL for 0x01010101*data.  */
3431 
3432 static rtx
builtin_memset_gen_str(void * data,HOST_WIDE_INT offset ATTRIBUTE_UNUSED,enum machine_mode mode)3433 builtin_memset_gen_str (void *data, HOST_WIDE_INT offset ATTRIBUTE_UNUSED,
3434 			enum machine_mode mode)
3435 {
3436   rtx target, coeff;
3437   size_t size;
3438   char *p;
3439 
3440   size = GET_MODE_SIZE (mode);
3441   if (size == 1)
3442     return (rtx) data;
3443 
3444   p = alloca (size);
3445   memset (p, 1, size);
3446   coeff = c_readstr (p, mode);
3447 
3448   target = convert_to_mode (mode, (rtx) data, 1);
3449   target = expand_mult (mode, target, coeff, NULL_RTX, 1);
3450   return force_reg (mode, target);
3451 }
3452 
3453 /* Expand expression EXP, which is a call to the memset builtin.  Return 0
3454    if we failed the caller should emit a normal call, otherwise try to get
3455    the result in TARGET, if convenient (and in mode MODE if that's
3456    convenient).  */
3457 
3458 static rtx
expand_builtin_memset(tree arglist,rtx target,enum machine_mode mode,tree orig_exp)3459 expand_builtin_memset (tree arglist, rtx target, enum machine_mode mode,
3460 		       tree orig_exp)
3461 {
3462   if (!validate_arglist (arglist,
3463 			 POINTER_TYPE, INTEGER_TYPE, INTEGER_TYPE, VOID_TYPE))
3464     return 0;
3465   else
3466     {
3467       tree dest = TREE_VALUE (arglist);
3468       tree val = TREE_VALUE (TREE_CHAIN (arglist));
3469       tree len = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
3470       tree fndecl, fn;
3471       enum built_in_function fcode;
3472       char c;
3473       unsigned int dest_align;
3474       rtx dest_mem, dest_addr, len_rtx;
3475 
3476       dest_align = get_pointer_alignment (dest, BIGGEST_ALIGNMENT);
3477 
3478       /* If DEST is not a pointer type, don't do this
3479 	 operation in-line.  */
3480       if (dest_align == 0)
3481 	return 0;
3482 
3483       /* If the LEN parameter is zero, return DEST.  */
3484       if (integer_zerop (len))
3485 	{
3486 	  /* Evaluate and ignore VAL in case it has side-effects.  */
3487 	  expand_expr (val, const0_rtx, VOIDmode, EXPAND_NORMAL);
3488 	  return expand_expr (dest, target, mode, EXPAND_NORMAL);
3489 	}
3490 
3491       /* Stabilize the arguments in case we fail.  */
3492       dest = builtin_save_expr (dest);
3493       val = builtin_save_expr (val);
3494       len = builtin_save_expr (len);
3495 
3496       len_rtx = expand_expr (len, NULL_RTX, VOIDmode, 0);
3497       dest_mem = get_memory_rtx (dest, len);
3498 
3499       if (TREE_CODE (val) != INTEGER_CST)
3500 	{
3501 	  rtx val_rtx;
3502 
3503 	  val_rtx = expand_expr (val, NULL_RTX, VOIDmode, 0);
3504 	  val_rtx = convert_to_mode (TYPE_MODE (unsigned_char_type_node),
3505 				     val_rtx, 0);
3506 
3507 	  /* Assume that we can memset by pieces if we can store the
3508 	   * the coefficients by pieces (in the required modes).
3509 	   * We can't pass builtin_memset_gen_str as that emits RTL.  */
3510 	  c = 1;
3511 	  if (host_integerp (len, 1)
3512 	      && !(optimize_size && tree_low_cst (len, 1) > 1)
3513 	      && can_store_by_pieces (tree_low_cst (len, 1),
3514 				      builtin_memset_read_str, &c, dest_align))
3515 	    {
3516 	      val_rtx = force_reg (TYPE_MODE (unsigned_char_type_node),
3517 				   val_rtx);
3518 	      store_by_pieces (dest_mem, tree_low_cst (len, 1),
3519 			       builtin_memset_gen_str, val_rtx, dest_align, 0);
3520 	    }
3521 	  else if (!set_storage_via_setmem (dest_mem, len_rtx, val_rtx,
3522 					    dest_align))
3523 	    goto do_libcall;
3524 
3525 	  dest_mem = force_operand (XEXP (dest_mem, 0), NULL_RTX);
3526 	  dest_mem = convert_memory_address (ptr_mode, dest_mem);
3527 	  return dest_mem;
3528 	}
3529 
3530       if (target_char_cast (val, &c))
3531 	goto do_libcall;
3532 
3533       if (c)
3534 	{
3535 	  if (host_integerp (len, 1)
3536 	      && !(optimize_size && tree_low_cst (len, 1) > 1)
3537 	      && can_store_by_pieces (tree_low_cst (len, 1),
3538 				      builtin_memset_read_str, &c, dest_align))
3539 	    store_by_pieces (dest_mem, tree_low_cst (len, 1),
3540 			     builtin_memset_read_str, &c, dest_align, 0);
3541 	  else if (!set_storage_via_setmem (dest_mem, len_rtx, GEN_INT (c),
3542 					    dest_align))
3543 	    goto do_libcall;
3544 
3545 	  dest_mem = force_operand (XEXP (dest_mem, 0), NULL_RTX);
3546 	  dest_mem = convert_memory_address (ptr_mode, dest_mem);
3547 	  return dest_mem;
3548 	}
3549 
3550       set_mem_align (dest_mem, dest_align);
3551       dest_addr = clear_storage (dest_mem, len_rtx,
3552 				 CALL_EXPR_TAILCALL (orig_exp)
3553 				 ? BLOCK_OP_TAILCALL : BLOCK_OP_NORMAL);
3554 
3555       if (dest_addr == 0)
3556 	{
3557 	  dest_addr = force_operand (XEXP (dest_mem, 0), NULL_RTX);
3558 	  dest_addr = convert_memory_address (ptr_mode, dest_addr);
3559 	}
3560 
3561       return dest_addr;
3562 
3563     do_libcall:
3564       fndecl = get_callee_fndecl (orig_exp);
3565       fcode = DECL_FUNCTION_CODE (fndecl);
3566       gcc_assert (fcode == BUILT_IN_MEMSET || fcode == BUILT_IN_BZERO);
3567       arglist = build_tree_list (NULL_TREE, len);
3568       if (fcode == BUILT_IN_MEMSET)
3569 	arglist = tree_cons (NULL_TREE, val, arglist);
3570       arglist = tree_cons (NULL_TREE, dest, arglist);
3571       fn = build_function_call_expr (fndecl, arglist);
3572       if (TREE_CODE (fn) == CALL_EXPR)
3573 	CALL_EXPR_TAILCALL (fn) = CALL_EXPR_TAILCALL (orig_exp);
3574       return expand_call (fn, target, target == const0_rtx);
3575     }
3576 }
3577 
3578 #if 0
3579 /* Expand expression EXP, which is a call to the bzero builtin.  Return 0
3580    if we failed the caller should emit a normal call.  */
3581 
3582 static rtx
3583 expand_builtin_bzero (tree exp)
3584 {
3585   tree arglist = TREE_OPERAND (exp, 1);
3586   tree dest, size, newarglist;
3587 
3588   if (!validate_arglist (arglist, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
3589     return NULL_RTX;
3590 
3591   dest = TREE_VALUE (arglist);
3592   size = TREE_VALUE (TREE_CHAIN (arglist));
3593 
3594   /* New argument list transforming bzero(ptr x, int y) to
3595      memset(ptr x, int 0, size_t y).   This is done this way
3596      so that if it isn't expanded inline, we fallback to
3597      calling bzero instead of memset.  */
3598 
3599   newarglist = build_tree_list (NULL_TREE, fold_convert (sizetype, size));
3600   newarglist = tree_cons (NULL_TREE, integer_zero_node, newarglist);
3601   newarglist = tree_cons (NULL_TREE, dest, newarglist);
3602 
3603   return expand_builtin_memset (newarglist, const0_rtx, VOIDmode, exp);
3604 }
3605 
3606 /* Expand expression EXP, which is a call to the memcmp built-in function.
3607    ARGLIST is the argument list for this call.  Return 0 if we failed and the
3608    caller should emit a normal call, otherwise try to get the result in
3609    TARGET, if convenient (and in mode MODE, if that's convenient).  */
3610 
3611 static rtx
3612 expand_builtin_memcmp (tree exp ATTRIBUTE_UNUSED, tree arglist, rtx target,
3613 		       enum machine_mode mode)
3614 {
3615   if (!validate_arglist (arglist,
3616 			 POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
3617     return 0;
3618   else
3619     {
3620       tree result = fold_builtin_memcmp (arglist);
3621       if (result)
3622 	return expand_expr (result, target, mode, EXPAND_NORMAL);
3623     }
3624 
3625 #if defined HAVE_cmpmemsi || defined HAVE_cmpstrnsi
3626   {
3627     tree arg1 = TREE_VALUE (arglist);
3628     tree arg2 = TREE_VALUE (TREE_CHAIN (arglist));
3629     tree len = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
3630     rtx arg1_rtx, arg2_rtx, arg3_rtx;
3631     rtx result;
3632     rtx insn;
3633 
3634     int arg1_align
3635       = get_pointer_alignment (arg1, BIGGEST_ALIGNMENT) / BITS_PER_UNIT;
3636     int arg2_align
3637       = get_pointer_alignment (arg2, BIGGEST_ALIGNMENT) / BITS_PER_UNIT;
3638     enum machine_mode insn_mode;
3639 
3640 #ifdef HAVE_cmpmemsi
3641     if (HAVE_cmpmemsi)
3642       insn_mode = insn_data[(int) CODE_FOR_cmpmemsi].operand[0].mode;
3643     else
3644 #endif
3645 #ifdef HAVE_cmpstrnsi
3646     if (HAVE_cmpstrnsi)
3647       insn_mode = insn_data[(int) CODE_FOR_cmpstrnsi].operand[0].mode;
3648     else
3649 #endif
3650       return 0;
3651 
3652     /* If we don't have POINTER_TYPE, call the function.  */
3653     if (arg1_align == 0 || arg2_align == 0)
3654       return 0;
3655 
3656     /* Make a place to write the result of the instruction.  */
3657     result = target;
3658     if (! (result != 0
3659 	   && REG_P (result) && GET_MODE (result) == insn_mode
3660 	   && REGNO (result) >= FIRST_PSEUDO_REGISTER))
3661       result = gen_reg_rtx (insn_mode);
3662 
3663     arg1_rtx = get_memory_rtx (arg1, len);
3664     arg2_rtx = get_memory_rtx (arg2, len);
3665     arg3_rtx = expand_expr (len, NULL_RTX, VOIDmode, 0);
3666 
3667     /* Set MEM_SIZE as appropriate.  */
3668     if (GET_CODE (arg3_rtx) == CONST_INT)
3669       {
3670 	set_mem_size (arg1_rtx, arg3_rtx);
3671 	set_mem_size (arg2_rtx, arg3_rtx);
3672       }
3673 
3674 #ifdef HAVE_cmpmemsi
3675     if (HAVE_cmpmemsi)
3676       insn = gen_cmpmemsi (result, arg1_rtx, arg2_rtx, arg3_rtx,
3677 			   GEN_INT (MIN (arg1_align, arg2_align)));
3678     else
3679 #endif
3680 #ifdef HAVE_cmpstrnsi
3681     if (HAVE_cmpstrnsi)
3682       insn = gen_cmpstrnsi (result, arg1_rtx, arg2_rtx, arg3_rtx,
3683 			    GEN_INT (MIN (arg1_align, arg2_align)));
3684     else
3685 #endif
3686       gcc_unreachable ();
3687 
3688     if (insn)
3689       emit_insn (insn);
3690     else
3691       emit_library_call_value (memcmp_libfunc, result, LCT_PURE_MAKE_BLOCK,
3692 			       TYPE_MODE (integer_type_node), 3,
3693 			       XEXP (arg1_rtx, 0), Pmode,
3694 			       XEXP (arg2_rtx, 0), Pmode,
3695 			       convert_to_mode (TYPE_MODE (sizetype), arg3_rtx,
3696 						TYPE_UNSIGNED (sizetype)),
3697 			       TYPE_MODE (sizetype));
3698 
3699     /* Return the value in the proper mode for this function.  */
3700     mode = TYPE_MODE (TREE_TYPE (exp));
3701     if (GET_MODE (result) == mode)
3702       return result;
3703     else if (target != 0)
3704       {
3705 	convert_move (target, result, 0);
3706 	return target;
3707       }
3708     else
3709       return convert_to_mode (mode, result, 0);
3710   }
3711 #endif
3712 
3713   return 0;
3714 }
3715 
3716 /* Expand expression EXP, which is a call to the strcmp builtin.  Return 0
3717    if we failed the caller should emit a normal call, otherwise try to get
3718    the result in TARGET, if convenient.  */
3719 
3720 static rtx
3721 expand_builtin_strcmp (tree exp, rtx target, enum machine_mode mode)
3722 {
3723   tree arglist = TREE_OPERAND (exp, 1);
3724 
3725   if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
3726     return 0;
3727   else
3728     {
3729       tree result = fold_builtin_strcmp (arglist);
3730       if (result)
3731 	return expand_expr (result, target, mode, EXPAND_NORMAL);
3732     }
3733 
3734 #if defined HAVE_cmpstrsi || defined HAVE_cmpstrnsi
3735   if (cmpstr_optab[SImode] != CODE_FOR_nothing
3736       || cmpstrn_optab[SImode] != CODE_FOR_nothing)
3737     {
3738       rtx arg1_rtx, arg2_rtx;
3739       rtx result, insn = NULL_RTX;
3740       tree fndecl, fn;
3741 
3742       tree arg1 = TREE_VALUE (arglist);
3743       tree arg2 = TREE_VALUE (TREE_CHAIN (arglist));
3744       int arg1_align
3745 	= get_pointer_alignment (arg1, BIGGEST_ALIGNMENT) / BITS_PER_UNIT;
3746       int arg2_align
3747 	= get_pointer_alignment (arg2, BIGGEST_ALIGNMENT) / BITS_PER_UNIT;
3748 
3749       /* If we don't have POINTER_TYPE, call the function.  */
3750       if (arg1_align == 0 || arg2_align == 0)
3751 	return 0;
3752 
3753       /* Stabilize the arguments in case gen_cmpstr(n)si fail.  */
3754       arg1 = builtin_save_expr (arg1);
3755       arg2 = builtin_save_expr (arg2);
3756 
3757       arg1_rtx = get_memory_rtx (arg1, NULL);
3758       arg2_rtx = get_memory_rtx (arg2, NULL);
3759 
3760 #ifdef HAVE_cmpstrsi
3761       /* Try to call cmpstrsi.  */
3762       if (HAVE_cmpstrsi)
3763 	{
3764 	  enum machine_mode insn_mode
3765 	    = insn_data[(int) CODE_FOR_cmpstrsi].operand[0].mode;
3766 
3767 	  /* Make a place to write the result of the instruction.  */
3768 	  result = target;
3769 	  if (! (result != 0
3770 		 && REG_P (result) && GET_MODE (result) == insn_mode
3771 		 && REGNO (result) >= FIRST_PSEUDO_REGISTER))
3772 	    result = gen_reg_rtx (insn_mode);
3773 
3774 	  insn = gen_cmpstrsi (result, arg1_rtx, arg2_rtx,
3775 			       GEN_INT (MIN (arg1_align, arg2_align)));
3776 	}
3777 #endif
3778 #if HAVE_cmpstrnsi
3779       /* Try to determine at least one length and call cmpstrnsi.  */
3780       if (!insn && HAVE_cmpstrnsi)
3781 	{
3782 	  tree len;
3783 	  rtx arg3_rtx;
3784 
3785 	  enum machine_mode insn_mode
3786 	    = insn_data[(int) CODE_FOR_cmpstrnsi].operand[0].mode;
3787 	  tree len1 = c_strlen (arg1, 1);
3788 	  tree len2 = c_strlen (arg2, 1);
3789 
3790 	  if (len1)
3791 	    len1 = size_binop (PLUS_EXPR, ssize_int (1), len1);
3792 	  if (len2)
3793 	    len2 = size_binop (PLUS_EXPR, ssize_int (1), len2);
3794 
3795 	  /* If we don't have a constant length for the first, use the length
3796 	     of the second, if we know it.  We don't require a constant for
3797 	     this case; some cost analysis could be done if both are available
3798 	     but neither is constant.  For now, assume they're equally cheap,
3799 	     unless one has side effects.  If both strings have constant lengths,
3800 	     use the smaller.  */
3801 
3802 	  if (!len1)
3803 	    len = len2;
3804 	  else if (!len2)
3805 	    len = len1;
3806 	  else if (TREE_SIDE_EFFECTS (len1))
3807 	    len = len2;
3808 	  else if (TREE_SIDE_EFFECTS (len2))
3809 	    len = len1;
3810 	  else if (TREE_CODE (len1) != INTEGER_CST)
3811 	    len = len2;
3812 	  else if (TREE_CODE (len2) != INTEGER_CST)
3813 	    len = len1;
3814 	  else if (tree_int_cst_lt (len1, len2))
3815 	    len = len1;
3816 	  else
3817 	    len = len2;
3818 
3819 	  /* If both arguments have side effects, we cannot optimize.  */
3820 	  if (!len || TREE_SIDE_EFFECTS (len))
3821 	    goto do_libcall;
3822 
3823 	  arg3_rtx = expand_expr (len, NULL_RTX, VOIDmode, 0);
3824 
3825 	  /* Make a place to write the result of the instruction.  */
3826 	  result = target;
3827 	  if (! (result != 0
3828 		 && REG_P (result) && GET_MODE (result) == insn_mode
3829 		 && REGNO (result) >= FIRST_PSEUDO_REGISTER))
3830 	    result = gen_reg_rtx (insn_mode);
3831 
3832 	  insn = gen_cmpstrnsi (result, arg1_rtx, arg2_rtx, arg3_rtx,
3833 				GEN_INT (MIN (arg1_align, arg2_align)));
3834 	}
3835 #endif
3836 
3837       if (insn)
3838 	{
3839 	  emit_insn (insn);
3840 
3841 	  /* Return the value in the proper mode for this function.  */
3842 	  mode = TYPE_MODE (TREE_TYPE (exp));
3843 	  if (GET_MODE (result) == mode)
3844 	    return result;
3845 	  if (target == 0)
3846 	    return convert_to_mode (mode, result, 0);
3847 	  convert_move (target, result, 0);
3848 	  return target;
3849 	}
3850 
3851       /* Expand the library call ourselves using a stabilized argument
3852 	 list to avoid re-evaluating the function's arguments twice.  */
3853 #if HAVE_cmpstrnsi
3854     do_libcall:
3855 #endif
3856       arglist = build_tree_list (NULL_TREE, arg2);
3857       arglist = tree_cons (NULL_TREE, arg1, arglist);
3858       fndecl = get_callee_fndecl (exp);
3859       fn = build_function_call_expr (fndecl, arglist);
3860       if (TREE_CODE (fn) == CALL_EXPR)
3861 	CALL_EXPR_TAILCALL (fn) = CALL_EXPR_TAILCALL (exp);
3862       return expand_call (fn, target, target == const0_rtx);
3863     }
3864 #endif
3865   return 0;
3866 }
3867 
3868 /* Expand expression EXP, which is a call to the strncmp builtin.  Return 0
3869    if we failed the caller should emit a normal call, otherwise try to get
3870    the result in TARGET, if convenient.  */
3871 
3872 static rtx
3873 expand_builtin_strncmp (tree exp, rtx target, enum machine_mode mode)
3874 {
3875   tree arglist = TREE_OPERAND (exp, 1);
3876 
3877   if (!validate_arglist (arglist,
3878 			 POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
3879     return 0;
3880   else
3881     {
3882       tree result = fold_builtin_strncmp (arglist);
3883       if (result)
3884 	return expand_expr (result, target, mode, EXPAND_NORMAL);
3885     }
3886 
3887   /* If c_strlen can determine an expression for one of the string
3888      lengths, and it doesn't have side effects, then emit cmpstrnsi
3889      using length MIN(strlen(string)+1, arg3).  */
3890 #ifdef HAVE_cmpstrnsi
3891   if (HAVE_cmpstrnsi)
3892   {
3893     tree arg1 = TREE_VALUE (arglist);
3894     tree arg2 = TREE_VALUE (TREE_CHAIN (arglist));
3895     tree arg3 = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
3896     tree len, len1, len2;
3897     rtx arg1_rtx, arg2_rtx, arg3_rtx;
3898     rtx result, insn;
3899     tree fndecl, fn;
3900 
3901     int arg1_align
3902       = get_pointer_alignment (arg1, BIGGEST_ALIGNMENT) / BITS_PER_UNIT;
3903     int arg2_align
3904       = get_pointer_alignment (arg2, BIGGEST_ALIGNMENT) / BITS_PER_UNIT;
3905     enum machine_mode insn_mode
3906       = insn_data[(int) CODE_FOR_cmpstrnsi].operand[0].mode;
3907 
3908     len1 = c_strlen (arg1, 1);
3909     len2 = c_strlen (arg2, 1);
3910 
3911     if (len1)
3912       len1 = size_binop (PLUS_EXPR, ssize_int (1), len1);
3913     if (len2)
3914       len2 = size_binop (PLUS_EXPR, ssize_int (1), len2);
3915 
3916     /* If we don't have a constant length for the first, use the length
3917        of the second, if we know it.  We don't require a constant for
3918        this case; some cost analysis could be done if both are available
3919        but neither is constant.  For now, assume they're equally cheap,
3920        unless one has side effects.  If both strings have constant lengths,
3921        use the smaller.  */
3922 
3923     if (!len1)
3924       len = len2;
3925     else if (!len2)
3926       len = len1;
3927     else if (TREE_SIDE_EFFECTS (len1))
3928       len = len2;
3929     else if (TREE_SIDE_EFFECTS (len2))
3930       len = len1;
3931     else if (TREE_CODE (len1) != INTEGER_CST)
3932       len = len2;
3933     else if (TREE_CODE (len2) != INTEGER_CST)
3934       len = len1;
3935     else if (tree_int_cst_lt (len1, len2))
3936       len = len1;
3937     else
3938       len = len2;
3939 
3940     /* If both arguments have side effects, we cannot optimize.  */
3941     if (!len || TREE_SIDE_EFFECTS (len))
3942       return 0;
3943 
3944     /* The actual new length parameter is MIN(len,arg3).  */
3945     len = fold_build2 (MIN_EXPR, TREE_TYPE (len), len,
3946 		       fold_convert (TREE_TYPE (len), arg3));
3947 
3948     /* If we don't have POINTER_TYPE, call the function.  */
3949     if (arg1_align == 0 || arg2_align == 0)
3950       return 0;
3951 
3952     /* Make a place to write the result of the instruction.  */
3953     result = target;
3954     if (! (result != 0
3955 	   && REG_P (result) && GET_MODE (result) == insn_mode
3956 	   && REGNO (result) >= FIRST_PSEUDO_REGISTER))
3957       result = gen_reg_rtx (insn_mode);
3958 
3959     /* Stabilize the arguments in case gen_cmpstrnsi fails.  */
3960     arg1 = builtin_save_expr (arg1);
3961     arg2 = builtin_save_expr (arg2);
3962     len = builtin_save_expr (len);
3963 
3964     arg1_rtx = get_memory_rtx (arg1, len);
3965     arg2_rtx = get_memory_rtx (arg2, len);
3966     arg3_rtx = expand_expr (len, NULL_RTX, VOIDmode, 0);
3967     insn = gen_cmpstrnsi (result, arg1_rtx, arg2_rtx, arg3_rtx,
3968 			  GEN_INT (MIN (arg1_align, arg2_align)));
3969     if (insn)
3970       {
3971 	emit_insn (insn);
3972 
3973 	/* Return the value in the proper mode for this function.  */
3974 	mode = TYPE_MODE (TREE_TYPE (exp));
3975 	if (GET_MODE (result) == mode)
3976 	  return result;
3977 	if (target == 0)
3978 	  return convert_to_mode (mode, result, 0);
3979 	convert_move (target, result, 0);
3980 	return target;
3981       }
3982 
3983     /* Expand the library call ourselves using a stabilized argument
3984        list to avoid re-evaluating the function's arguments twice.  */
3985     arglist = build_tree_list (NULL_TREE, len);
3986     arglist = tree_cons (NULL_TREE, arg2, arglist);
3987     arglist = tree_cons (NULL_TREE, arg1, arglist);
3988     fndecl = get_callee_fndecl (exp);
3989     fn = build_function_call_expr (fndecl, arglist);
3990     if (TREE_CODE (fn) == CALL_EXPR)
3991       CALL_EXPR_TAILCALL (fn) = CALL_EXPR_TAILCALL (exp);
3992     return expand_call (fn, target, target == const0_rtx);
3993   }
3994 #endif
3995   return 0;
3996 }
3997 
3998 /* Expand expression EXP, which is a call to the strcat builtin.
3999    Return 0 if we failed the caller should emit a normal call,
4000    otherwise try to get the result in TARGET, if convenient.  */
4001 
4002 static rtx
4003 expand_builtin_strcat (tree fndecl, tree arglist, rtx target, enum machine_mode mode)
4004 {
4005   if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
4006     return 0;
4007   else
4008     {
4009       tree dst = TREE_VALUE (arglist),
4010       src = TREE_VALUE (TREE_CHAIN (arglist));
4011       const char *p = c_getstr (src);
4012 
4013       /* If the string length is zero, return the dst parameter.  */
4014       if (p && *p == '\0')
4015 	return expand_expr (dst, target, mode, EXPAND_NORMAL);
4016 
4017       if (!optimize_size)
4018 	{
4019 	  /* See if we can store by pieces into (dst + strlen(dst)).  */
4020 	  tree newsrc, newdst,
4021 	    strlen_fn = implicit_built_in_decls[BUILT_IN_STRLEN];
4022 	  rtx insns;
4023 
4024 	  /* Stabilize the argument list.  */
4025 	  newsrc = builtin_save_expr (src);
4026 	  if (newsrc != src)
4027 	    arglist = build_tree_list (NULL_TREE, newsrc);
4028 	  else
4029 	    arglist = TREE_CHAIN (arglist); /* Reusing arglist if safe.  */
4030 
4031 	  dst = builtin_save_expr (dst);
4032 
4033 	  start_sequence ();
4034 
4035 	  /* Create strlen (dst).  */
4036 	  newdst =
4037 	    build_function_call_expr (strlen_fn,
4038 				      build_tree_list (NULL_TREE, dst));
4039 	  /* Create (dst + (cast) strlen (dst)).  */
4040 	  newdst = fold_convert (TREE_TYPE (dst), newdst);
4041 	  newdst = fold_build2 (PLUS_EXPR, TREE_TYPE (dst), dst, newdst);
4042 
4043 	  newdst = builtin_save_expr (newdst);
4044 	  arglist = tree_cons (NULL_TREE, newdst, arglist);
4045 
4046 	  if (!expand_builtin_strcpy (fndecl, arglist, target, mode))
4047 	    {
4048 	      end_sequence (); /* Stop sequence.  */
4049 	      return 0;
4050 	    }
4051 
4052 	  /* Output the entire sequence.  */
4053 	  insns = get_insns ();
4054 	  end_sequence ();
4055 	  emit_insn (insns);
4056 
4057 	  return expand_expr (dst, target, mode, EXPAND_NORMAL);
4058 	}
4059 
4060       return 0;
4061     }
4062 }
4063 
4064 /* Expand expression EXP, which is a call to the strncat builtin.
4065    Return 0 if we failed the caller should emit a normal call,
4066    otherwise try to get the result in TARGET, if convenient.  */
4067 
4068 static rtx
4069 expand_builtin_strncat (tree arglist, rtx target, enum machine_mode mode)
4070 {
4071   if (validate_arglist (arglist,
4072 			POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
4073     {
4074       tree result = fold_builtin_strncat (arglist);
4075       if (result)
4076 	return expand_expr (result, target, mode, EXPAND_NORMAL);
4077     }
4078   return 0;
4079 }
4080 
4081 /* Expand expression EXP, which is a call to the strspn builtin.
4082    Return 0 if we failed the caller should emit a normal call,
4083    otherwise try to get the result in TARGET, if convenient.  */
4084 
4085 static rtx
4086 expand_builtin_strspn (tree arglist, rtx target, enum machine_mode mode)
4087 {
4088   if (validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
4089     {
4090       tree result = fold_builtin_strspn (arglist);
4091       if (result)
4092 	return expand_expr (result, target, mode, EXPAND_NORMAL);
4093     }
4094   return 0;
4095 }
4096 
4097 /* Expand expression EXP, which is a call to the strcspn builtin.
4098    Return 0 if we failed the caller should emit a normal call,
4099    otherwise try to get the result in TARGET, if convenient.  */
4100 
4101 static rtx
4102 expand_builtin_strcspn (tree arglist, rtx target, enum machine_mode mode)
4103 {
4104   if (validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
4105     {
4106       tree result = fold_builtin_strcspn (arglist);
4107       if (result)
4108 	return expand_expr (result, target, mode, EXPAND_NORMAL);
4109     }
4110   return 0;
4111 }
4112 #endif /* 0 */
4113 
4114 /* Expand a call to __builtin_saveregs, generating the result in TARGET,
4115    if that's convenient.  */
4116 
4117 rtx
expand_builtin_saveregs(void)4118 expand_builtin_saveregs (void)
4119 {
4120   rtx val, seq;
4121 
4122   /* Don't do __builtin_saveregs more than once in a function.
4123      Save the result of the first call and reuse it.  */
4124   if (saveregs_value != 0)
4125     return saveregs_value;
4126 
4127   /* When this function is called, it means that registers must be
4128      saved on entry to this function.  So we migrate the call to the
4129      first insn of this function.  */
4130 
4131   start_sequence ();
4132 
4133   /* Do whatever the machine needs done in this case.  */
4134   val = targetm.calls.expand_builtin_saveregs ();
4135 
4136   seq = get_insns ();
4137   end_sequence ();
4138 
4139   saveregs_value = val;
4140 
4141   /* Put the insns after the NOTE that starts the function.  If this
4142      is inside a start_sequence, make the outer-level insn chain current, so
4143      the code is placed at the start of the function.  */
4144   push_topmost_sequence ();
4145   emit_insn_after (seq, entry_of_function ());
4146   pop_topmost_sequence ();
4147 
4148   return val;
4149 }
4150 
4151 /* __builtin_args_info (N) returns word N of the arg space info
4152    for the current function.  The number and meanings of words
4153    is controlled by the definition of CUMULATIVE_ARGS.  */
4154 
4155 static rtx
expand_builtin_args_info(tree arglist)4156 expand_builtin_args_info (tree arglist)
4157 {
4158   int nwords = sizeof (CUMULATIVE_ARGS) / sizeof (int);
4159   int *word_ptr = (int *) &current_function_args_info;
4160 
4161   gcc_assert (sizeof (CUMULATIVE_ARGS) % sizeof (int) == 0);
4162 
4163   if (arglist != 0)
4164     {
4165       if (!host_integerp (TREE_VALUE (arglist), 0))
4166 	error ("argument of %<__builtin_args_info%> must be constant");
4167       else
4168 	{
4169 	  HOST_WIDE_INT wordnum = tree_low_cst (TREE_VALUE (arglist), 0);
4170 
4171 	  if (wordnum < 0 || wordnum >= nwords)
4172 	    error ("argument of %<__builtin_args_info%> out of range");
4173 	  else
4174 	    return GEN_INT (word_ptr[wordnum]);
4175 	}
4176     }
4177   else
4178     error ("missing argument in %<__builtin_args_info%>");
4179 
4180   return const0_rtx;
4181 }
4182 
4183 /* Expand a call to __builtin_next_arg.  */
4184 
4185 static rtx
expand_builtin_next_arg(void)4186 expand_builtin_next_arg (void)
4187 {
4188   /* Checking arguments is already done in fold_builtin_next_arg
4189      that must be called before this function.  */
4190   return expand_binop (Pmode, add_optab,
4191 		       current_function_internal_arg_pointer,
4192 		       current_function_arg_offset_rtx,
4193 		       NULL_RTX, 0, OPTAB_LIB_WIDEN);
4194 }
4195 
4196 /* Make it easier for the backends by protecting the valist argument
4197    from multiple evaluations.  */
4198 
4199 static tree
stabilize_va_list(tree valist,int needs_lvalue)4200 stabilize_va_list (tree valist, int needs_lvalue)
4201 {
4202   if (TREE_CODE (va_list_type_node) == ARRAY_TYPE)
4203     {
4204       if (TREE_SIDE_EFFECTS (valist))
4205 	valist = save_expr (valist);
4206 
4207       /* For this case, the backends will be expecting a pointer to
4208 	 TREE_TYPE (va_list_type_node), but it's possible we've
4209 	 actually been given an array (an actual va_list_type_node).
4210 	 So fix it.  */
4211       if (TREE_CODE (TREE_TYPE (valist)) == ARRAY_TYPE)
4212 	{
4213 	  tree p1 = build_pointer_type (TREE_TYPE (va_list_type_node));
4214 	  valist = build_fold_addr_expr_with_type (valist, p1);
4215 	}
4216     }
4217   else
4218     {
4219       tree pt;
4220 
4221       if (! needs_lvalue)
4222 	{
4223 	  if (! TREE_SIDE_EFFECTS (valist))
4224 	    return valist;
4225 
4226 	  pt = build_pointer_type (va_list_type_node);
4227 	  valist = fold_build1 (ADDR_EXPR, pt, valist);
4228 	  TREE_SIDE_EFFECTS (valist) = 1;
4229 	}
4230 
4231       if (TREE_SIDE_EFFECTS (valist))
4232 	valist = save_expr (valist);
4233       valist = build_fold_indirect_ref (valist);
4234     }
4235 
4236   return valist;
4237 }
4238 
4239 /* The "standard" definition of va_list is void*.  */
4240 
4241 tree
std_build_builtin_va_list(void)4242 std_build_builtin_va_list (void)
4243 {
4244   return ptr_type_node;
4245 }
4246 
4247 /* The "standard" implementation of va_start: just assign `nextarg' to
4248    the variable.  */
4249 
4250 void
std_expand_builtin_va_start(tree valist,rtx nextarg)4251 std_expand_builtin_va_start (tree valist, rtx nextarg)
4252 {
4253   tree t;
4254 
4255   t = build2 (MODIFY_EXPR, TREE_TYPE (valist), valist,
4256 	      make_tree (ptr_type_node, nextarg));
4257   TREE_SIDE_EFFECTS (t) = 1;
4258 
4259   expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
4260 }
4261 
4262 /* Expand ARGLIST, from a call to __builtin_va_start.  */
4263 
4264 static rtx
expand_builtin_va_start(tree arglist)4265 expand_builtin_va_start (tree arglist)
4266 {
4267   rtx nextarg;
4268   tree chain, valist;
4269 
4270   chain = TREE_CHAIN (arglist);
4271 
4272   if (!chain)
4273     {
4274       error ("too few arguments to function %<va_start%>");
4275       return const0_rtx;
4276     }
4277 
4278   if (fold_builtin_next_arg (chain))
4279     return const0_rtx;
4280 
4281   nextarg = expand_builtin_next_arg ();
4282   valist = stabilize_va_list (TREE_VALUE (arglist), 1);
4283 
4284 #ifdef EXPAND_BUILTIN_VA_START
4285   EXPAND_BUILTIN_VA_START (valist, nextarg);
4286 #else
4287   std_expand_builtin_va_start (valist, nextarg);
4288 #endif
4289 
4290   return const0_rtx;
4291 }
4292 
4293 /* The "standard" implementation of va_arg: read the value from the
4294    current (padded) address and increment by the (padded) size.  */
4295 
4296 tree
std_gimplify_va_arg_expr(tree valist,tree type,tree * pre_p,tree * post_p)4297 std_gimplify_va_arg_expr (tree valist, tree type, tree *pre_p, tree *post_p)
4298 {
4299   tree addr, t, type_size, rounded_size, valist_tmp;
4300   unsigned HOST_WIDE_INT align, boundary;
4301   bool indirect;
4302 
4303 #ifdef ARGS_GROW_DOWNWARD
4304   /* All of the alignment and movement below is for args-grow-up machines.
4305      As of 2004, there are only 3 ARGS_GROW_DOWNWARD targets, and they all
4306      implement their own specialized gimplify_va_arg_expr routines.  */
4307   gcc_unreachable ();
4308 #endif
4309 
4310   indirect = pass_by_reference (NULL, TYPE_MODE (type), type, false);
4311   if (indirect)
4312     type = build_pointer_type (type);
4313 
4314   align = PARM_BOUNDARY / BITS_PER_UNIT;
4315   boundary = FUNCTION_ARG_BOUNDARY (TYPE_MODE (type), type) / BITS_PER_UNIT;
4316 
4317   /* Hoist the valist value into a temporary for the moment.  */
4318   valist_tmp = get_initialized_tmp_var (valist, pre_p, NULL);
4319 
4320   /* va_list pointer is aligned to PARM_BOUNDARY.  If argument actually
4321      requires greater alignment, we must perform dynamic alignment.  */
4322   if (boundary > align
4323       && !integer_zerop (TYPE_SIZE (type)))
4324     {
4325       t = fold_convert (TREE_TYPE (valist), size_int (boundary - 1));
4326       t = build2 (MODIFY_EXPR, TREE_TYPE (valist), valist_tmp,
4327 		  build2 (PLUS_EXPR, TREE_TYPE (valist), valist_tmp, t));
4328       gimplify_and_add (t, pre_p);
4329 
4330       t = fold_convert (TREE_TYPE (valist), size_int (-boundary));
4331       t = build2 (MODIFY_EXPR, TREE_TYPE (valist), valist_tmp,
4332 		  build2 (BIT_AND_EXPR, TREE_TYPE (valist), valist_tmp, t));
4333       gimplify_and_add (t, pre_p);
4334     }
4335   else
4336     boundary = align;
4337 
4338   /* If the actual alignment is less than the alignment of the type,
4339      adjust the type accordingly so that we don't assume strict alignment
4340      when deferencing the pointer.  */
4341   boundary *= BITS_PER_UNIT;
4342   if (boundary < TYPE_ALIGN (type))
4343     {
4344       type = build_variant_type_copy (type);
4345       TYPE_ALIGN (type) = boundary;
4346     }
4347 
4348   /* Compute the rounded size of the type.  */
4349   type_size = size_in_bytes (type);
4350   rounded_size = round_up (type_size, align);
4351 
4352   /* Reduce rounded_size so it's sharable with the postqueue.  */
4353   gimplify_expr (&rounded_size, pre_p, post_p, is_gimple_val, fb_rvalue);
4354 
4355   /* Get AP.  */
4356   addr = valist_tmp;
4357   if (PAD_VARARGS_DOWN && !integer_zerop (rounded_size))
4358     {
4359       /* Small args are padded downward.  */
4360       t = fold_build2 (GT_EXPR, sizetype, rounded_size, size_int (align));
4361       t = fold_build3 (COND_EXPR, sizetype, t, size_zero_node,
4362 		       size_binop (MINUS_EXPR, rounded_size, type_size));
4363       t = fold_convert (TREE_TYPE (addr), t);
4364       addr = fold_build2 (PLUS_EXPR, TREE_TYPE (addr), addr, t);
4365     }
4366 
4367   /* Compute new value for AP.  */
4368   t = fold_convert (TREE_TYPE (valist), rounded_size);
4369   t = build2 (PLUS_EXPR, TREE_TYPE (valist), valist_tmp, t);
4370   t = build2 (MODIFY_EXPR, TREE_TYPE (valist), valist, t);
4371   gimplify_and_add (t, pre_p);
4372 
4373   addr = fold_convert (build_pointer_type (type), addr);
4374 
4375   if (indirect)
4376     addr = build_va_arg_indirect_ref (addr);
4377 
4378   return build_va_arg_indirect_ref (addr);
4379 }
4380 
4381 /* Build an indirect-ref expression over the given TREE, which represents a
4382    piece of a va_arg() expansion.  */
4383 tree
build_va_arg_indirect_ref(tree addr)4384 build_va_arg_indirect_ref (tree addr)
4385 {
4386   addr = build_fold_indirect_ref (addr);
4387 
4388   if (flag_mudflap) /* Don't instrument va_arg INDIRECT_REF.  */
4389     mf_mark (addr);
4390 
4391   return addr;
4392 }
4393 
4394 /* Return a dummy expression of type TYPE in order to keep going after an
4395    error.  */
4396 
4397 static tree
dummy_object(tree type)4398 dummy_object (tree type)
4399 {
4400   tree t = convert (build_pointer_type (type), null_pointer_node);
4401   return build1 (INDIRECT_REF, type, t);
4402 }
4403 
4404 /* Gimplify __builtin_va_arg, aka VA_ARG_EXPR, which is not really a
4405    builtin function, but a very special sort of operator.  */
4406 
4407 enum gimplify_status
gimplify_va_arg_expr(tree * expr_p,tree * pre_p,tree * post_p)4408 gimplify_va_arg_expr (tree *expr_p, tree *pre_p, tree *post_p)
4409 {
4410   tree promoted_type, want_va_type, have_va_type;
4411   tree valist = TREE_OPERAND (*expr_p, 0);
4412   tree type = TREE_TYPE (*expr_p);
4413   tree t;
4414 
4415   /* Verify that valist is of the proper type.  */
4416   want_va_type = va_list_type_node;
4417   have_va_type = TREE_TYPE (valist);
4418 
4419   if (have_va_type == error_mark_node)
4420     return GS_ERROR;
4421 
4422   if (TREE_CODE (want_va_type) == ARRAY_TYPE)
4423     {
4424       /* If va_list is an array type, the argument may have decayed
4425 	 to a pointer type, e.g. by being passed to another function.
4426          In that case, unwrap both types so that we can compare the
4427 	 underlying records.  */
4428       if (TREE_CODE (have_va_type) == ARRAY_TYPE
4429 	  || POINTER_TYPE_P (have_va_type))
4430 	{
4431 	  want_va_type = TREE_TYPE (want_va_type);
4432 	  have_va_type = TREE_TYPE (have_va_type);
4433 	}
4434     }
4435 
4436   if (TYPE_MAIN_VARIANT (want_va_type) != TYPE_MAIN_VARIANT (have_va_type))
4437     {
4438       error ("first argument to %<va_arg%> not of type %<va_list%>");
4439       return GS_ERROR;
4440     }
4441 
4442   /* Generate a diagnostic for requesting data of a type that cannot
4443      be passed through `...' due to type promotion at the call site.  */
4444   else if ((promoted_type = lang_hooks.types.type_promotes_to (type))
4445 	   != type)
4446     {
4447       static bool gave_help;
4448 
4449       /* Unfortunately, this is merely undefined, rather than a constraint
4450 	 violation, so we cannot make this an error.  If this call is never
4451 	 executed, the program is still strictly conforming.  */
4452       warning (0, "%qT is promoted to %qT when passed through %<...%>",
4453 	       type, promoted_type);
4454       if (! gave_help)
4455 	{
4456 	  gave_help = true;
4457 	  warning (0, "(so you should pass %qT not %qT to %<va_arg%>)",
4458 		   promoted_type, type);
4459 	}
4460 
4461       /* We can, however, treat "undefined" any way we please.
4462 	 Call abort to encourage the user to fix the program.  */
4463       inform ("if this code is reached, the program will abort");
4464       t = build_function_call_expr (implicit_built_in_decls[BUILT_IN_TRAP],
4465 				    NULL);
4466       append_to_statement_list (t, pre_p);
4467 
4468       /* This is dead code, but go ahead and finish so that the
4469 	 mode of the result comes out right.  */
4470       *expr_p = dummy_object (type);
4471       return GS_ALL_DONE;
4472     }
4473   else
4474     {
4475       /* Make it easier for the backends by protecting the valist argument
4476          from multiple evaluations.  */
4477       if (TREE_CODE (va_list_type_node) == ARRAY_TYPE)
4478 	{
4479 	  /* For this case, the backends will be expecting a pointer to
4480 	     TREE_TYPE (va_list_type_node), but it's possible we've
4481 	     actually been given an array (an actual va_list_type_node).
4482 	     So fix it.  */
4483 	  if (TREE_CODE (TREE_TYPE (valist)) == ARRAY_TYPE)
4484 	    {
4485 	      tree p1 = build_pointer_type (TREE_TYPE (va_list_type_node));
4486 	      valist = build_fold_addr_expr_with_type (valist, p1);
4487 	    }
4488 	  gimplify_expr (&valist, pre_p, post_p, is_gimple_val, fb_rvalue);
4489 	}
4490       else
4491 	gimplify_expr (&valist, pre_p, post_p, is_gimple_min_lval, fb_lvalue);
4492 
4493       if (!targetm.gimplify_va_arg_expr)
4494 	/* FIXME:Once most targets are converted we should merely
4495 	   assert this is non-null.  */
4496 	return GS_ALL_DONE;
4497 
4498       *expr_p = targetm.gimplify_va_arg_expr (valist, type, pre_p, post_p);
4499       return GS_OK;
4500     }
4501 }
4502 
4503 /* Expand ARGLIST, from a call to __builtin_va_end.  */
4504 
4505 static rtx
expand_builtin_va_end(tree arglist)4506 expand_builtin_va_end (tree arglist)
4507 {
4508   tree valist = TREE_VALUE (arglist);
4509 
4510   /* Evaluate for side effects, if needed.  I hate macros that don't
4511      do that.  */
4512   if (TREE_SIDE_EFFECTS (valist))
4513     expand_expr (valist, const0_rtx, VOIDmode, EXPAND_NORMAL);
4514 
4515   return const0_rtx;
4516 }
4517 
4518 /* Expand ARGLIST, from a call to __builtin_va_copy.  We do this as a
4519    builtin rather than just as an assignment in stdarg.h because of the
4520    nastiness of array-type va_list types.  */
4521 
4522 static rtx
expand_builtin_va_copy(tree arglist)4523 expand_builtin_va_copy (tree arglist)
4524 {
4525   tree dst, src, t;
4526 
4527   dst = TREE_VALUE (arglist);
4528   src = TREE_VALUE (TREE_CHAIN (arglist));
4529 
4530   dst = stabilize_va_list (dst, 1);
4531   src = stabilize_va_list (src, 0);
4532 
4533   if (TREE_CODE (va_list_type_node) != ARRAY_TYPE)
4534     {
4535       t = build2 (MODIFY_EXPR, va_list_type_node, dst, src);
4536       TREE_SIDE_EFFECTS (t) = 1;
4537       expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
4538     }
4539   else
4540     {
4541       rtx dstb, srcb, size;
4542 
4543       /* Evaluate to pointers.  */
4544       dstb = expand_expr (dst, NULL_RTX, Pmode, EXPAND_NORMAL);
4545       srcb = expand_expr (src, NULL_RTX, Pmode, EXPAND_NORMAL);
4546       size = expand_expr (TYPE_SIZE_UNIT (va_list_type_node), NULL_RTX,
4547 			  VOIDmode, EXPAND_NORMAL);
4548 
4549       dstb = convert_memory_address (Pmode, dstb);
4550       srcb = convert_memory_address (Pmode, srcb);
4551 
4552       /* "Dereference" to BLKmode memories.  */
4553       dstb = gen_rtx_MEM (BLKmode, dstb);
4554       set_mem_alias_set (dstb, get_alias_set (TREE_TYPE (TREE_TYPE (dst))));
4555       set_mem_align (dstb, TYPE_ALIGN (va_list_type_node));
4556       srcb = gen_rtx_MEM (BLKmode, srcb);
4557       set_mem_alias_set (srcb, get_alias_set (TREE_TYPE (TREE_TYPE (src))));
4558       set_mem_align (srcb, TYPE_ALIGN (va_list_type_node));
4559 
4560       /* Copy.  */
4561       emit_block_move (dstb, srcb, size, BLOCK_OP_NORMAL);
4562     }
4563 
4564   return const0_rtx;
4565 }
4566 
4567 /* Expand a call to one of the builtin functions __builtin_frame_address or
4568    __builtin_return_address.  */
4569 
4570 static rtx
expand_builtin_frame_address(tree fndecl,tree arglist)4571 expand_builtin_frame_address (tree fndecl, tree arglist)
4572 {
4573   /* The argument must be a nonnegative integer constant.
4574      It counts the number of frames to scan up the stack.
4575      The value is the return address saved in that frame.  */
4576   if (arglist == 0)
4577     /* Warning about missing arg was already issued.  */
4578     return const0_rtx;
4579   else if (! host_integerp (TREE_VALUE (arglist), 1))
4580     {
4581       if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_FRAME_ADDRESS)
4582 	error ("invalid argument to %<__builtin_frame_address%>");
4583       else
4584 	error ("invalid argument to %<__builtin_return_address%>");
4585       return const0_rtx;
4586     }
4587   else
4588     {
4589       rtx tem
4590 	= expand_builtin_return_addr (DECL_FUNCTION_CODE (fndecl),
4591 				      tree_low_cst (TREE_VALUE (arglist), 1));
4592 
4593       /* Some ports cannot access arbitrary stack frames.  */
4594       if (tem == NULL)
4595 	{
4596 	  if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_FRAME_ADDRESS)
4597 	    warning (0, "unsupported argument to %<__builtin_frame_address%>");
4598 	  else
4599 	    warning (0, "unsupported argument to %<__builtin_return_address%>");
4600 	  return const0_rtx;
4601 	}
4602 
4603       /* For __builtin_frame_address, return what we've got.  */
4604       if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_FRAME_ADDRESS)
4605 	return tem;
4606 
4607       if (!REG_P (tem)
4608 	  && ! CONSTANT_P (tem))
4609 	tem = copy_to_mode_reg (Pmode, tem);
4610       return tem;
4611     }
4612 }
4613 
4614 /* Expand a call to the alloca builtin, with arguments ARGLIST.  Return 0 if
4615    we failed and the caller should emit a normal call, otherwise try to get
4616    the result in TARGET, if convenient.  */
4617 
4618 static rtx
expand_builtin_alloca(tree arglist,rtx target)4619 expand_builtin_alloca (tree arglist, rtx target)
4620 {
4621   rtx op0;
4622   rtx result;
4623 
4624   /* In -fmudflap-instrumented code, alloca() and __builtin_alloca()
4625      should always expand to function calls.  These can be intercepted
4626      in libmudflap.  */
4627   if (flag_mudflap)
4628     return 0;
4629 
4630   if (!validate_arglist (arglist, INTEGER_TYPE, VOID_TYPE))
4631     return 0;
4632 
4633   /* Compute the argument.  */
4634   op0 = expand_expr (TREE_VALUE (arglist), NULL_RTX, VOIDmode, 0);
4635 
4636   /* Allocate the desired space.  */
4637   result = allocate_dynamic_stack_space (op0, target, BITS_PER_UNIT);
4638   result = convert_memory_address (ptr_mode, result);
4639 
4640   return result;
4641 }
4642 
4643 /* Expand a call to a unary builtin.  The arguments are in ARGLIST.
4644    Return 0 if a normal call should be emitted rather than expanding the
4645    function in-line.  If convenient, the result should be placed in TARGET.
4646    SUBTARGET may be used as the target for computing one of EXP's operands.  */
4647 
4648 static rtx
expand_builtin_unop(enum machine_mode target_mode,tree arglist,rtx target,rtx subtarget,optab op_optab)4649 expand_builtin_unop (enum machine_mode target_mode, tree arglist, rtx target,
4650 		     rtx subtarget, optab op_optab)
4651 {
4652   rtx op0;
4653   if (!validate_arglist (arglist, INTEGER_TYPE, VOID_TYPE))
4654     return 0;
4655 
4656   /* Compute the argument.  */
4657   op0 = expand_expr (TREE_VALUE (arglist), subtarget, VOIDmode, 0);
4658   /* Compute op, into TARGET if possible.
4659      Set TARGET to wherever the result comes back.  */
4660   target = expand_unop (TYPE_MODE (TREE_TYPE (TREE_VALUE (arglist))),
4661 			op_optab, op0, target, 1);
4662   gcc_assert (target);
4663 
4664   return convert_to_mode (target_mode, target, 0);
4665 }
4666 
4667 #if 0
4668 /* If the string passed to fputs is a constant and is one character
4669    long, we attempt to transform this call into __builtin_fputc().  */
4670 
4671 static rtx
4672 expand_builtin_fputs (tree arglist, rtx target, bool unlocked)
4673 {
4674   /* Verify the arguments in the original call.  */
4675   if (validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
4676     {
4677       tree result = fold_builtin_fputs (arglist, (target == const0_rtx),
4678 					unlocked, NULL_TREE);
4679       if (result)
4680 	return expand_expr (result, target, VOIDmode, EXPAND_NORMAL);
4681     }
4682   return 0;
4683 }
4684 #endif /* 0 */
4685 
4686 /* Expand a call to __builtin_expect.  We return our argument and emit a
4687    NOTE_INSN_EXPECTED_VALUE note.  This is the expansion of __builtin_expect in
4688    a non-jump context.  */
4689 
4690 static rtx
expand_builtin_expect(tree arglist,rtx target)4691 expand_builtin_expect (tree arglist, rtx target)
4692 {
4693   tree exp, c;
4694   rtx note, rtx_c;
4695 
4696   if (arglist == NULL_TREE
4697       || TREE_CHAIN (arglist) == NULL_TREE)
4698     return const0_rtx;
4699   exp = TREE_VALUE (arglist);
4700   c = TREE_VALUE (TREE_CHAIN (arglist));
4701 
4702   if (TREE_CODE (c) != INTEGER_CST)
4703     {
4704       error ("second argument to %<__builtin_expect%> must be a constant");
4705       c = integer_zero_node;
4706     }
4707 
4708   target = expand_expr (exp, target, VOIDmode, EXPAND_NORMAL);
4709 
4710   /* Don't bother with expected value notes for integral constants.  */
4711   if (flag_guess_branch_prob && GET_CODE (target) != CONST_INT)
4712     {
4713       /* We do need to force this into a register so that we can be
4714 	 moderately sure to be able to correctly interpret the branch
4715 	 condition later.  */
4716       target = force_reg (GET_MODE (target), target);
4717 
4718       rtx_c = expand_expr (c, NULL_RTX, GET_MODE (target), EXPAND_NORMAL);
4719 
4720       note = emit_note (NOTE_INSN_EXPECTED_VALUE);
4721       NOTE_EXPECTED_VALUE (note) = gen_rtx_EQ (VOIDmode, target, rtx_c);
4722     }
4723 
4724   return target;
4725 }
4726 
4727 /* Like expand_builtin_expect, except do this in a jump context.  This is
4728    called from do_jump if the conditional is a __builtin_expect.  Return either
4729    a list of insns to emit the jump or NULL if we cannot optimize
4730    __builtin_expect.  We need to optimize this at jump time so that machines
4731    like the PowerPC don't turn the test into a SCC operation, and then jump
4732    based on the test being 0/1.  */
4733 
4734 rtx
expand_builtin_expect_jump(tree exp,rtx if_false_label,rtx if_true_label)4735 expand_builtin_expect_jump (tree exp, rtx if_false_label, rtx if_true_label)
4736 {
4737   tree arglist = TREE_OPERAND (exp, 1);
4738   tree arg0 = TREE_VALUE (arglist);
4739   tree arg1 = TREE_VALUE (TREE_CHAIN (arglist));
4740   rtx ret = NULL_RTX;
4741 
4742   /* Only handle __builtin_expect (test, 0) and
4743      __builtin_expect (test, 1).  */
4744   if (TREE_CODE (TREE_TYPE (arg1)) == INTEGER_TYPE
4745       && (integer_zerop (arg1) || integer_onep (arg1)))
4746     {
4747       rtx insn, drop_through_label, temp;
4748 
4749       /* Expand the jump insns.  */
4750       start_sequence ();
4751       do_jump (arg0, if_false_label, if_true_label);
4752       ret = get_insns ();
4753 
4754       drop_through_label = get_last_insn ();
4755       if (drop_through_label && NOTE_P (drop_through_label))
4756 	drop_through_label = prev_nonnote_insn (drop_through_label);
4757       if (drop_through_label && !LABEL_P (drop_through_label))
4758 	drop_through_label = NULL_RTX;
4759       end_sequence ();
4760 
4761       if (! if_true_label)
4762 	if_true_label = drop_through_label;
4763       if (! if_false_label)
4764 	if_false_label = drop_through_label;
4765 
4766       /* Go through and add the expect's to each of the conditional jumps.  */
4767       insn = ret;
4768       while (insn != NULL_RTX)
4769 	{
4770 	  rtx next = NEXT_INSN (insn);
4771 
4772 	  if (JUMP_P (insn) && any_condjump_p (insn))
4773 	    {
4774 	      rtx ifelse = SET_SRC (pc_set (insn));
4775 	      rtx then_dest = XEXP (ifelse, 1);
4776 	      rtx else_dest = XEXP (ifelse, 2);
4777 	      int taken = -1;
4778 
4779 	      /* First check if we recognize any of the labels.  */
4780 	      if (GET_CODE (then_dest) == LABEL_REF
4781 		  && XEXP (then_dest, 0) == if_true_label)
4782 		taken = 1;
4783 	      else if (GET_CODE (then_dest) == LABEL_REF
4784 		       && XEXP (then_dest, 0) == if_false_label)
4785 		taken = 0;
4786 	      else if (GET_CODE (else_dest) == LABEL_REF
4787 		       && XEXP (else_dest, 0) == if_false_label)
4788 		taken = 1;
4789 	      else if (GET_CODE (else_dest) == LABEL_REF
4790 		       && XEXP (else_dest, 0) == if_true_label)
4791 		taken = 0;
4792 	      /* Otherwise check where we drop through.  */
4793 	      else if (else_dest == pc_rtx)
4794 		{
4795 		  if (next && NOTE_P (next))
4796 		    next = next_nonnote_insn (next);
4797 
4798 		  if (next && JUMP_P (next)
4799 		      && any_uncondjump_p (next))
4800 		    temp = XEXP (SET_SRC (pc_set (next)), 0);
4801 		  else
4802 		    temp = next;
4803 
4804 		  /* TEMP is either a CODE_LABEL, NULL_RTX or something
4805 		     else that can't possibly match either target label.  */
4806 		  if (temp == if_false_label)
4807 		    taken = 1;
4808 		  else if (temp == if_true_label)
4809 		    taken = 0;
4810 		}
4811 	      else if (then_dest == pc_rtx)
4812 		{
4813 		  if (next && NOTE_P (next))
4814 		    next = next_nonnote_insn (next);
4815 
4816 		  if (next && JUMP_P (next)
4817 		      && any_uncondjump_p (next))
4818 		    temp = XEXP (SET_SRC (pc_set (next)), 0);
4819 		  else
4820 		    temp = next;
4821 
4822 		  if (temp == if_false_label)
4823 		    taken = 0;
4824 		  else if (temp == if_true_label)
4825 		    taken = 1;
4826 		}
4827 
4828 	      if (taken != -1)
4829 		{
4830 		  /* If the test is expected to fail, reverse the
4831 		     probabilities.  */
4832 		  if (integer_zerop (arg1))
4833 		    taken = 1 - taken;
4834 	          predict_insn_def (insn, PRED_BUILTIN_EXPECT, taken);
4835 		}
4836 	    }
4837 
4838 	  insn = next;
4839 	}
4840     }
4841 
4842   return ret;
4843 }
4844 
4845 void
expand_builtin_trap(void)4846 expand_builtin_trap (void)
4847 {
4848 #ifdef HAVE_trap
4849   if (HAVE_trap)
4850     emit_insn (gen_trap ());
4851   else
4852 #endif
4853     emit_library_call (abort_libfunc, LCT_NORETURN, VOIDmode, 0);
4854   emit_barrier ();
4855 }
4856 
4857 /* (TIGCC 20050206) Implement ER_throw. */
4858 static void
expand_builtin_ER_throw(tree arglist)4859 expand_builtin_ER_throw (tree arglist)
4860 {
4861   tree arg;
4862   char buffer[40];
4863 
4864   if (!validate_arglist (arglist, INTEGER_TYPE, VOID_TYPE))
4865     {
4866       error ("invalid argument list for ER_throw");
4867       return;
4868     }
4869 
4870   arg = TREE_VALUE (arglist);
4871 
4872   if (TREE_CODE (arg) != INTEGER_CST)
4873     {
4874       error ("argument to ER_throw must be a constant");
4875       return;
4876     }
4877 
4878   sprintf (buffer, ".word _A_LINE+%d", (int) TREE_INT_CST_LOW (arg));
4879 
4880   emit_insn (gen_rtx_ASM_INPUT (VOIDmode, ggc_strdup (buffer)));
4881 
4882   emit_barrier ();
4883 }
4884 
4885 #if 0
4886 /* Expand a call to fabs, fabsf or fabsl with arguments ARGLIST.
4887    Return 0 if a normal call should be emitted rather than expanding
4888    the function inline.  If convenient, the result should be placed
4889    in TARGET.  SUBTARGET may be used as the target for computing
4890    the operand.  */
4891 
4892 static rtx
4893 expand_builtin_fabs (tree arglist, rtx target, rtx subtarget)
4894 {
4895   enum machine_mode mode;
4896   tree arg;
4897   rtx op0;
4898 
4899   if (!validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
4900     return 0;
4901 
4902   arg = TREE_VALUE (arglist);
4903   mode = TYPE_MODE (TREE_TYPE (arg));
4904   op0 = expand_expr (arg, subtarget, VOIDmode, 0);
4905   return expand_abs (mode, op0, target, 0, safe_from_p (target, arg, 1));
4906 }
4907 
4908 /* Expand a call to copysign, copysignf, or copysignl with arguments ARGLIST.
4909    Return NULL is a normal call should be emitted rather than expanding the
4910    function inline.  If convenient, the result should be placed in TARGET.
4911    SUBTARGET may be used as the target for computing the operand.  */
4912 
4913 static rtx
4914 expand_builtin_copysign (tree arglist, rtx target, rtx subtarget)
4915 {
4916   rtx op0, op1;
4917   tree arg;
4918 
4919   if (!validate_arglist (arglist, REAL_TYPE, REAL_TYPE, VOID_TYPE))
4920     return 0;
4921 
4922   arg = TREE_VALUE (arglist);
4923   op0 = expand_expr (arg, subtarget, VOIDmode, 0);
4924 
4925   arg = TREE_VALUE (TREE_CHAIN (arglist));
4926   op1 = expand_expr (arg, NULL, VOIDmode, 0);
4927 
4928   return expand_copysign (op0, op1, target);
4929 }
4930 
4931 /* Create a new constant string literal and return a char* pointer to it.
4932    The STRING_CST value is the LEN characters at STR.  */
4933 static tree
4934 build_string_literal (int len, const char *str)
4935 {
4936   tree t, elem, index, type;
4937 
4938   t = build_string (len, str);
4939   elem = build_type_variant (char_type_node, 1, 0);
4940   index = build_index_type (build_int_cst (NULL_TREE, len - 1));
4941   type = build_array_type (elem, index);
4942   TREE_TYPE (t) = type;
4943   TREE_CONSTANT (t) = 1;
4944   TREE_INVARIANT (t) = 1;
4945   TREE_READONLY (t) = 1;
4946   TREE_STATIC (t) = 1;
4947 
4948   type = build_pointer_type (type);
4949   t = build1 (ADDR_EXPR, type, t);
4950 
4951   type = build_pointer_type (elem);
4952   t = build1 (NOP_EXPR, type, t);
4953   return t;
4954 }
4955 
4956 /* Expand EXP, a call to printf or printf_unlocked.
4957    Return 0 if a normal call should be emitted rather than transforming
4958    the function inline.  If convenient, the result should be placed in
4959    TARGET with mode MODE.  UNLOCKED indicates this is a printf_unlocked
4960    call.  */
4961 static rtx
4962 expand_builtin_printf (tree exp, rtx target, enum machine_mode mode,
4963 		       bool unlocked)
4964 {
4965   tree arglist = TREE_OPERAND (exp, 1);
4966   /* If we're using an unlocked function, assume the other unlocked
4967      functions exist explicitly.  */
4968   tree const fn_putchar = unlocked ? built_in_decls[BUILT_IN_PUTCHAR_UNLOCKED]
4969     : implicit_built_in_decls[BUILT_IN_PUTCHAR];
4970   tree const fn_puts = unlocked ? built_in_decls[BUILT_IN_PUTS_UNLOCKED]
4971     : implicit_built_in_decls[BUILT_IN_PUTS];
4972   const char *fmt_str;
4973   tree fn, fmt, arg;
4974 
4975   /* If the return value is used, don't do the transformation.  */
4976   if (target != const0_rtx)
4977     return 0;
4978 
4979   /* Verify the required arguments in the original call.  */
4980   if (! arglist)
4981     return 0;
4982   fmt = TREE_VALUE (arglist);
4983   if (! POINTER_TYPE_P (TREE_TYPE (fmt)))
4984     return 0;
4985   arglist = TREE_CHAIN (arglist);
4986 
4987   /* Check whether the format is a literal string constant.  */
4988   fmt_str = c_getstr (fmt);
4989   if (fmt_str == NULL)
4990     return 0;
4991 
4992   if (!init_target_chars())
4993     return 0;
4994 
4995   /* If the format specifier was "%s\n", call __builtin_puts(arg).  */
4996   if (strcmp (fmt_str, target_percent_s_newline) == 0)
4997     {
4998       if (! arglist
4999           || ! POINTER_TYPE_P (TREE_TYPE (TREE_VALUE (arglist)))
5000 	  || TREE_CHAIN (arglist))
5001 	return 0;
5002       fn = fn_puts;
5003     }
5004   /* If the format specifier was "%c", call __builtin_putchar(arg).  */
5005   else if (strcmp (fmt_str, target_percent_c) == 0)
5006     {
5007       if (! arglist
5008 	  || TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))) != INTEGER_TYPE
5009 	  || TREE_CHAIN (arglist))
5010 	return 0;
5011       fn = fn_putchar;
5012     }
5013   else
5014     {
5015       /* We can't handle anything else with % args or %% ... yet.  */
5016       if (strchr (fmt_str, target_percent))
5017         return 0;
5018 
5019       if (arglist)
5020 	return 0;
5021 
5022       /* If the format specifier was "", printf does nothing.  */
5023       if (fmt_str[0] == '\0')
5024 	return const0_rtx;
5025       /* If the format specifier has length of 1, call putchar.  */
5026       if (fmt_str[1] == '\0')
5027 	{
5028 	  /* Given printf("c"), (where c is any one character,)
5029 	     convert "c"[0] to an int and pass that to the replacement
5030 	     function.  */
5031 	  arg = build_int_cst (NULL_TREE, fmt_str[0]);
5032 	  arglist = build_tree_list (NULL_TREE, arg);
5033 	  fn = fn_putchar;
5034 	}
5035       else
5036 	{
5037 	  /* If the format specifier was "string\n", call puts("string").  */
5038 	  size_t len = strlen (fmt_str);
5039 	  if ((unsigned char)fmt_str[len - 1] == target_newline)
5040 	    {
5041 	      /* Create a NUL-terminated string that's one char shorter
5042 		 than the original, stripping off the trailing '\n'.  */
5043 	      char *newstr = alloca (len);
5044 	      memcpy (newstr, fmt_str, len - 1);
5045 	      newstr[len - 1] = 0;
5046 
5047 	      arg = build_string_literal (len, newstr);
5048 	      arglist = build_tree_list (NULL_TREE, arg);
5049 	      fn = fn_puts;
5050 	    }
5051 	  else
5052 	    /* We'd like to arrange to call fputs(string,stdout) here,
5053 	       but we need stdout and don't have a way to get it yet.  */
5054 	    return 0;
5055 	}
5056     }
5057 
5058   if (!fn)
5059     return 0;
5060   fn = build_function_call_expr (fn, arglist);
5061   if (TREE_CODE (fn) == CALL_EXPR)
5062     CALL_EXPR_TAILCALL (fn) = CALL_EXPR_TAILCALL (exp);
5063   return expand_expr (fn, target, mode, EXPAND_NORMAL);
5064 }
5065 
5066 /* Expand EXP, a call to fprintf or fprintf_unlocked.
5067    Return 0 if a normal call should be emitted rather than transforming
5068    the function inline.  If convenient, the result should be placed in
5069    TARGET with mode MODE.  UNLOCKED indicates this is a fprintf_unlocked
5070    call.  */
5071 static rtx
5072 expand_builtin_fprintf (tree exp, rtx target, enum machine_mode mode,
5073 		        bool unlocked)
5074 {
5075   tree arglist = TREE_OPERAND (exp, 1);
5076   /* If we're using an unlocked function, assume the other unlocked
5077      functions exist explicitly.  */
5078   tree const fn_fputc = unlocked ? built_in_decls[BUILT_IN_FPUTC_UNLOCKED]
5079     : implicit_built_in_decls[BUILT_IN_FPUTC];
5080   tree const fn_fputs = unlocked ? built_in_decls[BUILT_IN_FPUTS_UNLOCKED]
5081     : implicit_built_in_decls[BUILT_IN_FPUTS];
5082   const char *fmt_str;
5083   tree fn, fmt, fp, arg;
5084 
5085   /* If the return value is used, don't do the transformation.  */
5086   if (target != const0_rtx)
5087     return 0;
5088 
5089   /* Verify the required arguments in the original call.  */
5090   if (! arglist)
5091     return 0;
5092   fp = TREE_VALUE (arglist);
5093   if (! POINTER_TYPE_P (TREE_TYPE (fp)))
5094     return 0;
5095   arglist = TREE_CHAIN (arglist);
5096   if (! arglist)
5097     return 0;
5098   fmt = TREE_VALUE (arglist);
5099   if (! POINTER_TYPE_P (TREE_TYPE (fmt)))
5100     return 0;
5101   arglist = TREE_CHAIN (arglist);
5102 
5103   /* Check whether the format is a literal string constant.  */
5104   fmt_str = c_getstr (fmt);
5105   if (fmt_str == NULL)
5106     return 0;
5107 
5108   if (!init_target_chars())
5109     return 0;
5110 
5111   /* If the format specifier was "%s", call __builtin_fputs(arg,fp).  */
5112   if (strcmp (fmt_str, target_percent_s) == 0)
5113     {
5114       if (! arglist
5115           || ! POINTER_TYPE_P (TREE_TYPE (TREE_VALUE (arglist)))
5116 	  || TREE_CHAIN (arglist))
5117 	return 0;
5118       arg = TREE_VALUE (arglist);
5119       arglist = build_tree_list (NULL_TREE, fp);
5120       arglist = tree_cons (NULL_TREE, arg, arglist);
5121       fn = fn_fputs;
5122     }
5123   /* If the format specifier was "%c", call __builtin_fputc(arg,fp).  */
5124   else if (strcmp (fmt_str, target_percent_c) == 0)
5125     {
5126       if (! arglist
5127 	  || TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))) != INTEGER_TYPE
5128 	  || TREE_CHAIN (arglist))
5129 	return 0;
5130       arg = TREE_VALUE (arglist);
5131       arglist = build_tree_list (NULL_TREE, fp);
5132       arglist = tree_cons (NULL_TREE, arg, arglist);
5133       fn = fn_fputc;
5134     }
5135   else
5136     {
5137       /* We can't handle anything else with % args or %% ... yet.  */
5138       if (strchr (fmt_str, target_percent))
5139         return 0;
5140 
5141       if (arglist)
5142 	return 0;
5143 
5144       /* If the format specifier was "", fprintf does nothing.  */
5145       if (fmt_str[0] == '\0')
5146 	{
5147 	  /* Evaluate and ignore FILE* argument for side-effects.  */
5148 	  expand_expr (fp, const0_rtx, VOIDmode, EXPAND_NORMAL);
5149 	  return const0_rtx;
5150 	}
5151 
5152       /* When "string" doesn't contain %, replace all cases of
5153 	 fprintf(stream,string) with fputs(string,stream).  The fputs
5154 	 builtin will take care of special cases like length == 1.  */
5155       arglist = build_tree_list (NULL_TREE, fp);
5156       arglist = tree_cons (NULL_TREE, fmt, arglist);
5157       fn = fn_fputs;
5158     }
5159 
5160   if (!fn)
5161     return 0;
5162   fn = build_function_call_expr (fn, arglist);
5163   if (TREE_CODE (fn) == CALL_EXPR)
5164     CALL_EXPR_TAILCALL (fn) = CALL_EXPR_TAILCALL (exp);
5165   return expand_expr (fn, target, mode, EXPAND_NORMAL);
5166 }
5167 
5168 /* Expand a call to sprintf with argument list ARGLIST.  Return 0 if
5169    a normal call should be emitted rather than expanding the function
5170    inline.  If convenient, the result should be placed in TARGET with
5171    mode MODE.  */
5172 
5173 static rtx
5174 expand_builtin_sprintf (tree arglist, rtx target, enum machine_mode mode)
5175 {
5176   tree orig_arglist, dest, fmt;
5177   const char *fmt_str;
5178 
5179   orig_arglist = arglist;
5180 
5181   /* Verify the required arguments in the original call.  */
5182   if (! arglist)
5183     return 0;
5184   dest = TREE_VALUE (arglist);
5185   if (! POINTER_TYPE_P (TREE_TYPE (dest)))
5186     return 0;
5187   arglist = TREE_CHAIN (arglist);
5188   if (! arglist)
5189     return 0;
5190   fmt = TREE_VALUE (arglist);
5191   if (! POINTER_TYPE_P (TREE_TYPE (fmt)))
5192     return 0;
5193   arglist = TREE_CHAIN (arglist);
5194 
5195   /* Check whether the format is a literal string constant.  */
5196   fmt_str = c_getstr (fmt);
5197   if (fmt_str == NULL)
5198     return 0;
5199 
5200   if (!init_target_chars())
5201     return 0;
5202 
5203   /* If the format doesn't contain % args or %%, use strcpy.  */
5204   if (strchr (fmt_str, target_percent) == 0)
5205     {
5206       tree fn = implicit_built_in_decls[BUILT_IN_STRCPY];
5207       tree exp;
5208 
5209       if (arglist || ! fn)
5210 	return 0;
5211       expand_expr (build_function_call_expr (fn, orig_arglist),
5212 		   const0_rtx, VOIDmode, EXPAND_NORMAL);
5213       if (target == const0_rtx)
5214 	return const0_rtx;
5215       exp = build_int_cst (NULL_TREE, strlen (fmt_str));
5216       return expand_expr (exp, target, mode, EXPAND_NORMAL);
5217     }
5218   /* If the format is "%s", use strcpy if the result isn't used.  */
5219   else if (strcmp (fmt_str, target_percent_s) == 0)
5220     {
5221       tree fn, arg, len;
5222       fn = implicit_built_in_decls[BUILT_IN_STRCPY];
5223 
5224       if (! fn)
5225 	return 0;
5226 
5227       if (! arglist || TREE_CHAIN (arglist))
5228 	return 0;
5229       arg = TREE_VALUE (arglist);
5230       if (! POINTER_TYPE_P (TREE_TYPE (arg)))
5231 	return 0;
5232 
5233       if (target != const0_rtx)
5234 	{
5235 	  len = c_strlen (arg, 1);
5236 	  if (! len || TREE_CODE (len) != INTEGER_CST)
5237 	    return 0;
5238 	}
5239       else
5240 	len = NULL_TREE;
5241 
5242       arglist = build_tree_list (NULL_TREE, arg);
5243       arglist = tree_cons (NULL_TREE, dest, arglist);
5244       expand_expr (build_function_call_expr (fn, arglist),
5245 		   const0_rtx, VOIDmode, EXPAND_NORMAL);
5246 
5247       if (target == const0_rtx)
5248 	return const0_rtx;
5249       return expand_expr (len, target, mode, EXPAND_NORMAL);
5250     }
5251 
5252   return 0;
5253 }
5254 #endif /* 0 */
5255 
5256 /* Expand a call to either the entry or exit function profiler.  */
5257 
5258 static rtx
expand_builtin_profile_func(bool exitp)5259 expand_builtin_profile_func (bool exitp)
5260 {
5261   rtx this, which;
5262 
5263   this = DECL_RTL (current_function_decl);
5264   gcc_assert (MEM_P (this));
5265   this = XEXP (this, 0);
5266 
5267   if (exitp)
5268     which = profile_function_exit_libfunc;
5269   else
5270     which = profile_function_entry_libfunc;
5271 
5272   emit_library_call (which, LCT_NORMAL, VOIDmode, 2, this, Pmode,
5273 		     expand_builtin_return_addr (BUILT_IN_RETURN_ADDRESS,
5274 						 0),
5275 		     Pmode);
5276 
5277   return const0_rtx;
5278 }
5279 
5280 /* Given a trampoline address, make sure it satisfies TRAMPOLINE_ALIGNMENT.  */
5281 
5282 static rtx
round_trampoline_addr(rtx tramp)5283 round_trampoline_addr (rtx tramp)
5284 {
5285   rtx temp, addend, mask;
5286 
5287   /* If we don't need too much alignment, we'll have been guaranteed
5288      proper alignment by get_trampoline_type.  */
5289   if (TRAMPOLINE_ALIGNMENT <= STACK_BOUNDARY)
5290     return tramp;
5291 
5292   /* Round address up to desired boundary.  */
5293   temp = gen_reg_rtx (Pmode);
5294   addend = GEN_INT (TRAMPOLINE_ALIGNMENT / BITS_PER_UNIT - 1);
5295   mask = GEN_INT (-TRAMPOLINE_ALIGNMENT / BITS_PER_UNIT);
5296 
5297   temp  = expand_simple_binop (Pmode, PLUS, tramp, addend,
5298 			       temp, 0, OPTAB_LIB_WIDEN);
5299   tramp = expand_simple_binop (Pmode, AND, temp, mask,
5300 			       temp, 0, OPTAB_LIB_WIDEN);
5301 
5302   return tramp;
5303 }
5304 
5305 static rtx
expand_builtin_init_trampoline(tree arglist)5306 expand_builtin_init_trampoline (tree arglist)
5307 {
5308   tree t_tramp, t_func, t_chain;
5309   rtx r_tramp, r_func, r_chain;
5310 #ifdef TRAMPOLINE_TEMPLATE
5311   rtx blktramp;
5312 #endif
5313 
5314   if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE,
5315 			 POINTER_TYPE, VOID_TYPE))
5316     return NULL_RTX;
5317 
5318   t_tramp = TREE_VALUE (arglist);
5319   arglist = TREE_CHAIN (arglist);
5320   t_func = TREE_VALUE (arglist);
5321   arglist = TREE_CHAIN (arglist);
5322   t_chain = TREE_VALUE (arglist);
5323 
5324   r_tramp = expand_expr (t_tramp, NULL_RTX, VOIDmode, 0);
5325   r_func = expand_expr (t_func, NULL_RTX, VOIDmode, 0);
5326   r_chain = expand_expr (t_chain, NULL_RTX, VOIDmode, 0);
5327 
5328   /* Generate insns to initialize the trampoline.  */
5329   r_tramp = round_trampoline_addr (r_tramp);
5330 #ifdef TRAMPOLINE_TEMPLATE
5331   blktramp = gen_rtx_MEM (BLKmode, r_tramp);
5332   set_mem_align (blktramp, TRAMPOLINE_ALIGNMENT);
5333   emit_block_move (blktramp, assemble_trampoline_template (),
5334 		   GEN_INT (TRAMPOLINE_SIZE), BLOCK_OP_NORMAL);
5335 #endif
5336   trampolines_created = 1;
5337   INITIALIZE_TRAMPOLINE (r_tramp, r_func, r_chain);
5338 
5339   return const0_rtx;
5340 }
5341 
5342 static rtx
expand_builtin_adjust_trampoline(tree arglist)5343 expand_builtin_adjust_trampoline (tree arglist)
5344 {
5345   rtx tramp;
5346 
5347   if (!validate_arglist (arglist, POINTER_TYPE, VOID_TYPE))
5348     return NULL_RTX;
5349 
5350   tramp = expand_expr (TREE_VALUE (arglist), NULL_RTX, VOIDmode, 0);
5351   tramp = round_trampoline_addr (tramp);
5352 #ifdef TRAMPOLINE_ADJUST_ADDRESS
5353   TRAMPOLINE_ADJUST_ADDRESS (tramp);
5354 #endif
5355 
5356   return tramp;
5357 }
5358 
5359 #if 0
5360 /* Expand a call to the built-in signbit, signbitf or signbitl function.
5361    Return NULL_RTX if a normal call should be emitted rather than expanding
5362    the function in-line.  EXP is the expression that is a call to the builtin
5363    function; if convenient, the result should be placed in TARGET.  */
5364 
5365 static rtx
5366 expand_builtin_signbit (tree exp, rtx target)
5367 {
5368   const struct real_format *fmt;
5369   enum machine_mode fmode, imode, rmode;
5370   HOST_WIDE_INT hi, lo;
5371   tree arg, arglist;
5372   int word, bitpos;
5373   rtx temp;
5374 
5375   arglist = TREE_OPERAND (exp, 1);
5376   if (!validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
5377     return 0;
5378 
5379   arg = TREE_VALUE (arglist);
5380   fmode = TYPE_MODE (TREE_TYPE (arg));
5381   rmode = TYPE_MODE (TREE_TYPE (exp));
5382   fmt = REAL_MODE_FORMAT (fmode);
5383 
5384   /* For floating point formats without a sign bit, implement signbit
5385      as "ARG < 0.0".  */
5386   bitpos = fmt->signbit_ro;
5387   if (bitpos < 0)
5388   {
5389     /* But we can't do this if the format supports signed zero.  */
5390     if (fmt->has_signed_zero && HONOR_SIGNED_ZEROS (fmode))
5391       return 0;
5392 
5393     arg = fold_build2 (LT_EXPR, TREE_TYPE (exp), arg,
5394 		       build_real (TREE_TYPE (arg), dconst0));
5395     return expand_expr (arg, target, VOIDmode, EXPAND_NORMAL);
5396   }
5397 
5398   temp = expand_expr (arg, NULL_RTX, VOIDmode, 0);
5399   if (GET_MODE_SIZE (fmode) <= UNITS_PER_WORD)
5400     {
5401       imode = int_mode_for_mode (fmode);
5402       if (imode == BLKmode)
5403 	return 0;
5404       temp = gen_lowpart (imode, temp);
5405     }
5406   else
5407     {
5408       imode = word_mode;
5409       /* Handle targets with different FP word orders.  */
5410       if (FLOAT_WORDS_BIG_ENDIAN)
5411         word = (GET_MODE_BITSIZE (fmode) - bitpos) / BITS_PER_WORD;
5412       else
5413         word = bitpos / BITS_PER_WORD;
5414       temp = operand_subword_force (temp, word, fmode);
5415       bitpos = bitpos % BITS_PER_WORD;
5416     }
5417 
5418   /* Force the intermediate word_mode (or narrower) result into a
5419      register.  This avoids attempting to create paradoxical SUBREGs
5420      of floating point modes below.  */
5421   temp = force_reg (imode, temp);
5422 
5423   /* If the bitpos is within the "result mode" lowpart, the operation
5424      can be implement with a single bitwise AND.  Otherwise, we need
5425      a right shift and an AND.  */
5426 
5427   if (bitpos < GET_MODE_BITSIZE (rmode))
5428     {
5429       if (bitpos < HOST_BITS_PER_WIDE_INT)
5430 	{
5431 	  hi = 0;
5432 	  lo = (HOST_WIDE_INT) 1 << bitpos;
5433 	}
5434       else
5435 	{
5436 	  hi = (HOST_WIDE_INT) 1 << (bitpos - HOST_BITS_PER_WIDE_INT);
5437 	  lo = 0;
5438 	}
5439 
5440       if (imode != rmode)
5441 	temp = gen_lowpart (rmode, temp);
5442       temp = expand_binop (rmode, and_optab, temp,
5443 			   immed_double_const (lo, hi, rmode),
5444 			   NULL_RTX, 1, OPTAB_LIB_WIDEN);
5445     }
5446   else
5447     {
5448       /* Perform a logical right shift to place the signbit in the least
5449          significant bit, then truncate the result to the desired mode
5450 	 and mask just this bit.  */
5451       temp = expand_shift (RSHIFT_EXPR, imode, temp,
5452 			   build_int_cst (NULL_TREE, bitpos), NULL_RTX, 1);
5453       temp = gen_lowpart (rmode, temp);
5454       temp = expand_binop (rmode, and_optab, temp, const1_rtx,
5455 			   NULL_RTX, 1, OPTAB_LIB_WIDEN);
5456     }
5457 
5458   return temp;
5459 }
5460 
5461 /* Expand fork or exec calls.  TARGET is the desired target of the
5462    call.  ARGLIST is the list of arguments of the call.  FN is the
5463    identificator of the actual function.  IGNORE is nonzero if the
5464    value is to be ignored.  */
5465 
5466 static rtx
5467 expand_builtin_fork_or_exec (tree fn, tree arglist, rtx target, int ignore)
5468 {
5469   tree id, decl;
5470   tree call;
5471 
5472   /* If we are not profiling, just call the function.  */
5473   if (!profile_arc_flag)
5474     return NULL_RTX;
5475 
5476   /* Otherwise call the wrapper.  This should be equivalent for the rest of
5477      compiler, so the code does not diverge, and the wrapper may run the
5478      code necessary for keeping the profiling sane.  */
5479 
5480   switch (DECL_FUNCTION_CODE (fn))
5481     {
5482     case BUILT_IN_FORK:
5483       id = get_identifier ("__gcov_fork");
5484       break;
5485 
5486     case BUILT_IN_EXECL:
5487       id = get_identifier ("__gcov_execl");
5488       break;
5489 
5490     case BUILT_IN_EXECV:
5491       id = get_identifier ("__gcov_execv");
5492       break;
5493 
5494     case BUILT_IN_EXECLP:
5495       id = get_identifier ("__gcov_execlp");
5496       break;
5497 
5498     case BUILT_IN_EXECLE:
5499       id = get_identifier ("__gcov_execle");
5500       break;
5501 
5502     case BUILT_IN_EXECVP:
5503       id = get_identifier ("__gcov_execvp");
5504       break;
5505 
5506     case BUILT_IN_EXECVE:
5507       id = get_identifier ("__gcov_execve");
5508       break;
5509 
5510     default:
5511       gcc_unreachable ();
5512     }
5513 
5514   decl = build_decl (FUNCTION_DECL, id, TREE_TYPE (fn));
5515   DECL_EXTERNAL (decl) = 1;
5516   TREE_PUBLIC (decl) = 1;
5517   DECL_ARTIFICIAL (decl) = 1;
5518   TREE_NOTHROW (decl) = 1;
5519   DECL_VISIBILITY (decl) = VISIBILITY_DEFAULT;
5520   DECL_VISIBILITY_SPECIFIED (decl) = 1;
5521   call = build_function_call_expr (decl, arglist);
5522 
5523   return expand_call (call, target, ignore);
5524 }
5525 
5526 
5527 /* Reconstitute a mode for a __sync intrinsic operation.  Since the type of
5528    the pointer in these functions is void*, the tree optimizers may remove
5529    casts.  The mode computed in expand_builtin isn't reliable either, due
5530    to __sync_bool_compare_and_swap.
5531 
5532    FCODE_DIFF should be fcode - base, where base is the FOO_1 code for the
5533    group of builtins.  This gives us log2 of the mode size.  */
5534 
5535 static inline enum machine_mode
5536 get_builtin_sync_mode (int fcode_diff)
5537 {
5538   /* The size is not negotiable, so ask not to get BLKmode in return
5539      if the target indicates that a smaller size would be better.  */
5540   return mode_for_size (BITS_PER_UNIT << fcode_diff, MODE_INT, 0);
5541 }
5542 
5543 /* Expand the memory expression LOC and return the appropriate memory operand
5544    for the builtin_sync operations.  */
5545 
5546 static rtx
5547 get_builtin_sync_mem (tree loc, enum machine_mode mode)
5548 {
5549   rtx addr, mem;
5550 
5551   addr = expand_expr (loc, NULL, Pmode, EXPAND_SUM);
5552 
5553   /* Note that we explicitly do not want any alias information for this
5554      memory, so that we kill all other live memories.  Otherwise we don't
5555      satisfy the full barrier semantics of the intrinsic.  */
5556   mem = validize_mem (gen_rtx_MEM (mode, addr));
5557 
5558   set_mem_align (mem, get_pointer_alignment (loc, BIGGEST_ALIGNMENT));
5559   set_mem_alias_set (mem, ALIAS_SET_MEMORY_BARRIER);
5560   MEM_VOLATILE_P (mem) = 1;
5561 
5562   return mem;
5563 }
5564 
5565 /* Expand the __sync_xxx_and_fetch and __sync_fetch_and_xxx intrinsics.
5566    ARGLIST is the operands list to the function.  CODE is the rtx code
5567    that corresponds to the arithmetic or logical operation from the name;
5568    an exception here is that NOT actually means NAND.  TARGET is an optional
5569    place for us to store the results; AFTER is true if this is the
5570    fetch_and_xxx form.  IGNORE is true if we don't actually care about
5571    the result of the operation at all.  */
5572 
5573 static rtx
5574 expand_builtin_sync_operation (enum machine_mode mode, tree arglist,
5575 			       enum rtx_code code, bool after,
5576 			       rtx target, bool ignore)
5577 {
5578   rtx val, mem;
5579 
5580   /* Expand the operands.  */
5581   mem = get_builtin_sync_mem (TREE_VALUE (arglist), mode);
5582 
5583   arglist = TREE_CHAIN (arglist);
5584   val = expand_expr (TREE_VALUE (arglist), NULL, mode, EXPAND_NORMAL);
5585 
5586   if (ignore)
5587     return expand_sync_operation (mem, val, code);
5588   else
5589     return expand_sync_fetch_operation (mem, val, code, after, target);
5590 }
5591 
5592 /* Expand the __sync_val_compare_and_swap and __sync_bool_compare_and_swap
5593    intrinsics.  ARGLIST is the operands list to the function.  IS_BOOL is
5594    true if this is the boolean form.  TARGET is a place for us to store the
5595    results; this is NOT optional if IS_BOOL is true.  */
5596 
5597 static rtx
5598 expand_builtin_compare_and_swap (enum machine_mode mode, tree arglist,
5599 				 bool is_bool, rtx target)
5600 {
5601   rtx old_val, new_val, mem;
5602 
5603   /* Expand the operands.  */
5604   mem = get_builtin_sync_mem (TREE_VALUE (arglist), mode);
5605 
5606   arglist = TREE_CHAIN (arglist);
5607   old_val = expand_expr (TREE_VALUE (arglist), NULL, mode, EXPAND_NORMAL);
5608 
5609   arglist = TREE_CHAIN (arglist);
5610   new_val = expand_expr (TREE_VALUE (arglist), NULL, mode, EXPAND_NORMAL);
5611 
5612   if (is_bool)
5613     return expand_bool_compare_and_swap (mem, old_val, new_val, target);
5614   else
5615     return expand_val_compare_and_swap (mem, old_val, new_val, target);
5616 }
5617 
5618 /* Expand the __sync_lock_test_and_set intrinsic.  Note that the most
5619    general form is actually an atomic exchange, and some targets only
5620    support a reduced form with the second argument being a constant 1.
5621    ARGLIST is the operands list to the function; TARGET is an optional
5622    place for us to store the results.  */
5623 
5624 static rtx
5625 expand_builtin_lock_test_and_set (enum machine_mode mode, tree arglist,
5626 				  rtx target)
5627 {
5628   rtx val, mem;
5629 
5630   /* Expand the operands.  */
5631   mem = get_builtin_sync_mem (TREE_VALUE (arglist), mode);
5632 
5633   arglist = TREE_CHAIN (arglist);
5634   val = expand_expr (TREE_VALUE (arglist), NULL, mode, EXPAND_NORMAL);
5635 
5636   return expand_sync_lock_test_and_set (mem, val, target);
5637 }
5638 
5639 /* Expand the __sync_synchronize intrinsic.  */
5640 
5641 static void
5642 expand_builtin_synchronize (void)
5643 {
5644   tree x;
5645 
5646 #ifdef HAVE_memory_barrier
5647   if (HAVE_memory_barrier)
5648     {
5649       emit_insn (gen_memory_barrier ());
5650       return;
5651     }
5652 #endif
5653 
5654   /* If no explicit memory barrier instruction is available, create an
5655      empty asm stmt with a memory clobber.  */
5656   x = build4 (ASM_EXPR, void_type_node, build_string (0, ""), NULL, NULL,
5657 	      tree_cons (NULL, build_string (6, "memory"), NULL));
5658   ASM_VOLATILE_P (x) = 1;
5659   expand_asm_expr (x);
5660 }
5661 
5662 /* Expand the __sync_lock_release intrinsic.  ARGLIST is the operands list
5663    to the function.  */
5664 
5665 static void
5666 expand_builtin_lock_release (enum machine_mode mode, tree arglist)
5667 {
5668   enum insn_code icode;
5669   rtx mem, insn;
5670   rtx val = const0_rtx;
5671 
5672   /* Expand the operands.  */
5673   mem = get_builtin_sync_mem (TREE_VALUE (arglist), mode);
5674 
5675   /* If there is an explicit operation in the md file, use it.  */
5676   icode = sync_lock_release[mode];
5677   if (icode != CODE_FOR_nothing)
5678     {
5679       if (!insn_data[icode].operand[1].predicate (val, mode))
5680 	val = force_reg (mode, val);
5681 
5682       insn = GEN_FCN (icode) (mem, val);
5683       if (insn)
5684 	{
5685 	  emit_insn (insn);
5686 	  return;
5687 	}
5688     }
5689 
5690   /* Otherwise we can implement this operation by emitting a barrier
5691      followed by a store of zero.  */
5692   expand_builtin_synchronize ();
5693   emit_move_insn (mem, val);
5694 }
5695 #endif /* 0 */
5696 
5697 /* Expand an expression EXP that calls a built-in function,
5698    with result going to TARGET if that's convenient
5699    (and in mode MODE if that's convenient).
5700    SUBTARGET may be used as the target for computing one of EXP's operands.
5701    IGNORE is nonzero if the value is to be ignored.  */
5702 
5703 rtx
expand_builtin(tree exp,rtx target,rtx subtarget,enum machine_mode mode,int ignore)5704 expand_builtin (tree exp, rtx target, rtx subtarget, enum machine_mode mode,
5705 		int ignore)
5706 {
5707   tree fndecl = get_callee_fndecl (exp);
5708   tree arglist = TREE_OPERAND (exp, 1);
5709   enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
5710   enum machine_mode target_mode = TYPE_MODE (TREE_TYPE (exp));
5711 
5712   if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_MD)
5713     return targetm.expand_builtin (exp, target, subtarget, mode, ignore);
5714 
5715   /* When not optimizing, generate calls to library functions for a certain
5716      set of builtins.  */
5717   if (!optimize
5718       && !called_as_built_in (fndecl)
5719       && DECL_ASSEMBLER_NAME_SET_P (fndecl)
5720       && fcode != BUILT_IN_ALLOCA)
5721     return expand_call (exp, target, ignore);
5722 
5723   /* The built-in function expanders test for target == const0_rtx
5724      to determine whether the function's result will be ignored.  */
5725   if (ignore)
5726     target = const0_rtx;
5727 
5728   /* If the result of a pure or const built-in function is ignored, and
5729      none of its arguments are volatile, we can avoid expanding the
5730      built-in call and just evaluate the arguments for side-effects.  */
5731   if (target == const0_rtx
5732       && (DECL_IS_PURE (fndecl) || TREE_READONLY (fndecl)))
5733     {
5734       bool volatilep = false;
5735       tree arg;
5736 
5737       for (arg = arglist; arg; arg = TREE_CHAIN (arg))
5738 	if (TREE_THIS_VOLATILE (TREE_VALUE (arg)))
5739 	  {
5740 	    volatilep = true;
5741 	    break;
5742 	  }
5743 
5744       if (! volatilep)
5745 	{
5746 	  for (arg = arglist; arg; arg = TREE_CHAIN (arg))
5747 	    expand_expr (TREE_VALUE (arg), const0_rtx,
5748 			 VOIDmode, EXPAND_NORMAL);
5749 	  return const0_rtx;
5750 	}
5751     }
5752 
5753   switch (fcode)
5754     {
5755 #if 0
5756     case BUILT_IN_FABS:
5757     case BUILT_IN_FABSF:
5758     case BUILT_IN_FABSL:
5759       target = expand_builtin_fabs (arglist, target, subtarget);
5760       if (target)
5761         return target;
5762       break;
5763 
5764     case BUILT_IN_COPYSIGN:
5765     case BUILT_IN_COPYSIGNF:
5766     case BUILT_IN_COPYSIGNL:
5767       target = expand_builtin_copysign (arglist, target, subtarget);
5768       if (target)
5769 	return target;
5770       break;
5771 
5772       /* Just do a normal library call if we were unable to fold
5773 	 the values.  */
5774     case BUILT_IN_CABS:
5775     case BUILT_IN_CABSF:
5776     case BUILT_IN_CABSL:
5777       break;
5778 
5779     case BUILT_IN_EXP:
5780     case BUILT_IN_EXPF:
5781     case BUILT_IN_EXPL:
5782     case BUILT_IN_EXP10:
5783     case BUILT_IN_EXP10F:
5784     case BUILT_IN_EXP10L:
5785     case BUILT_IN_POW10:
5786     case BUILT_IN_POW10F:
5787     case BUILT_IN_POW10L:
5788     case BUILT_IN_EXP2:
5789     case BUILT_IN_EXP2F:
5790     case BUILT_IN_EXP2L:
5791     case BUILT_IN_EXPM1:
5792     case BUILT_IN_EXPM1F:
5793     case BUILT_IN_EXPM1L:
5794     case BUILT_IN_LOGB:
5795     case BUILT_IN_LOGBF:
5796     case BUILT_IN_LOGBL:
5797     case BUILT_IN_ILOGB:
5798     case BUILT_IN_ILOGBF:
5799     case BUILT_IN_ILOGBL:
5800     case BUILT_IN_LOG:
5801     case BUILT_IN_LOGF:
5802     case BUILT_IN_LOGL:
5803     case BUILT_IN_LOG10:
5804     case BUILT_IN_LOG10F:
5805     case BUILT_IN_LOG10L:
5806     case BUILT_IN_LOG2:
5807     case BUILT_IN_LOG2F:
5808     case BUILT_IN_LOG2L:
5809     case BUILT_IN_LOG1P:
5810     case BUILT_IN_LOG1PF:
5811     case BUILT_IN_LOG1PL:
5812     case BUILT_IN_TAN:
5813     case BUILT_IN_TANF:
5814     case BUILT_IN_TANL:
5815     case BUILT_IN_ASIN:
5816     case BUILT_IN_ASINF:
5817     case BUILT_IN_ASINL:
5818     case BUILT_IN_ACOS:
5819     case BUILT_IN_ACOSF:
5820     case BUILT_IN_ACOSL:
5821     case BUILT_IN_ATAN:
5822     case BUILT_IN_ATANF:
5823     case BUILT_IN_ATANL:
5824       /* Treat these like sqrt only if unsafe math optimizations are allowed,
5825 	 because of possible accuracy problems.  */
5826       if (! flag_unsafe_math_optimizations)
5827 	break;
5828     case BUILT_IN_SQRT:
5829     case BUILT_IN_SQRTF:
5830     case BUILT_IN_SQRTL:
5831     case BUILT_IN_FLOOR:
5832     case BUILT_IN_FLOORF:
5833     case BUILT_IN_FLOORL:
5834     case BUILT_IN_CEIL:
5835     case BUILT_IN_CEILF:
5836     case BUILT_IN_CEILL:
5837     case BUILT_IN_TRUNC:
5838     case BUILT_IN_TRUNCF:
5839     case BUILT_IN_TRUNCL:
5840     case BUILT_IN_ROUND:
5841     case BUILT_IN_ROUNDF:
5842     case BUILT_IN_ROUNDL:
5843     case BUILT_IN_NEARBYINT:
5844     case BUILT_IN_NEARBYINTF:
5845     case BUILT_IN_NEARBYINTL:
5846     case BUILT_IN_RINT:
5847     case BUILT_IN_RINTF:
5848     case BUILT_IN_RINTL:
5849     case BUILT_IN_LRINT:
5850     case BUILT_IN_LRINTF:
5851     case BUILT_IN_LRINTL:
5852     case BUILT_IN_LLRINT:
5853     case BUILT_IN_LLRINTF:
5854     case BUILT_IN_LLRINTL:
5855       target = expand_builtin_mathfn (exp, target, subtarget);
5856       if (target)
5857 	return target;
5858       break;
5859 
5860     case BUILT_IN_LCEIL:
5861     case BUILT_IN_LCEILF:
5862     case BUILT_IN_LCEILL:
5863     case BUILT_IN_LLCEIL:
5864     case BUILT_IN_LLCEILF:
5865     case BUILT_IN_LLCEILL:
5866     case BUILT_IN_LFLOOR:
5867     case BUILT_IN_LFLOORF:
5868     case BUILT_IN_LFLOORL:
5869     case BUILT_IN_LLFLOOR:
5870     case BUILT_IN_LLFLOORF:
5871     case BUILT_IN_LLFLOORL:
5872       target = expand_builtin_int_roundingfn (exp, target, subtarget);
5873       if (target)
5874 	return target;
5875       break;
5876 
5877     case BUILT_IN_POW:
5878     case BUILT_IN_POWF:
5879     case BUILT_IN_POWL:
5880       target = expand_builtin_pow (exp, target, subtarget);
5881       if (target)
5882 	return target;
5883       break;
5884 
5885     case BUILT_IN_POWI:
5886     case BUILT_IN_POWIF:
5887     case BUILT_IN_POWIL:
5888       target = expand_builtin_powi (exp, target, subtarget);
5889       if (target)
5890 	return target;
5891       break;
5892 
5893     case BUILT_IN_ATAN2:
5894     case BUILT_IN_ATAN2F:
5895     case BUILT_IN_ATAN2L:
5896     case BUILT_IN_LDEXP:
5897     case BUILT_IN_LDEXPF:
5898     case BUILT_IN_LDEXPL:
5899     case BUILT_IN_FMOD:
5900     case BUILT_IN_FMODF:
5901     case BUILT_IN_FMODL:
5902     case BUILT_IN_DREM:
5903     case BUILT_IN_DREMF:
5904     case BUILT_IN_DREML:
5905       if (! flag_unsafe_math_optimizations)
5906 	break;
5907       target = expand_builtin_mathfn_2 (exp, target, subtarget);
5908       if (target)
5909 	return target;
5910       break;
5911 
5912     case BUILT_IN_SIN:
5913     case BUILT_IN_SINF:
5914     case BUILT_IN_SINL:
5915     case BUILT_IN_COS:
5916     case BUILT_IN_COSF:
5917     case BUILT_IN_COSL:
5918       if (! flag_unsafe_math_optimizations)
5919 	break;
5920       target = expand_builtin_mathfn_3 (exp, target, subtarget);
5921       if (target)
5922 	return target;
5923       break;
5924 #endif /* 0 */
5925 
5926     case BUILT_IN_APPLY_ARGS:
5927       return expand_builtin_apply_args ();
5928 
5929       /* __builtin_apply (FUNCTION, ARGUMENTS, ARGSIZE) invokes
5930 	 FUNCTION with a copy of the parameters described by
5931 	 ARGUMENTS, and ARGSIZE.  It returns a block of memory
5932 	 allocated on the stack into which is stored all the registers
5933 	 that might possibly be used for returning the result of a
5934 	 function.  ARGUMENTS is the value returned by
5935 	 __builtin_apply_args.  ARGSIZE is the number of bytes of
5936 	 arguments that must be copied.  ??? How should this value be
5937 	 computed?  We'll also need a safe worst case value for varargs
5938 	 functions.  */
5939     case BUILT_IN_APPLY:
5940       if (!validate_arglist (arglist, POINTER_TYPE,
5941 			     POINTER_TYPE, INTEGER_TYPE, VOID_TYPE)
5942 	  && !validate_arglist (arglist, REFERENCE_TYPE,
5943 				POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
5944 	return const0_rtx;
5945       else
5946 	{
5947 	  int i;
5948 	  tree t;
5949 	  rtx ops[3];
5950 
5951 	  for (t = arglist, i = 0; t; t = TREE_CHAIN (t), i++)
5952 	    ops[i] = expand_expr (TREE_VALUE (t), NULL_RTX, VOIDmode, 0);
5953 
5954 	  return expand_builtin_apply (ops[0], ops[1], ops[2]);
5955 	}
5956 
5957       /* __builtin_return (RESULT) causes the function to return the
5958 	 value described by RESULT.  RESULT is address of the block of
5959 	 memory returned by __builtin_apply.  */
5960     case BUILT_IN_RETURN:
5961       if (validate_arglist (arglist, POINTER_TYPE, VOID_TYPE))
5962 	expand_builtin_return (expand_expr (TREE_VALUE (arglist),
5963 					    NULL_RTX, VOIDmode, 0));
5964       return const0_rtx;
5965 
5966     case BUILT_IN_SAVEREGS:
5967       return expand_builtin_saveregs ();
5968 
5969     case BUILT_IN_ARGS_INFO:
5970       return expand_builtin_args_info (arglist);
5971 
5972       /* Return the address of the first anonymous stack arg.  */
5973     case BUILT_IN_NEXT_ARG:
5974       if (fold_builtin_next_arg (arglist))
5975         return const0_rtx;
5976       return expand_builtin_next_arg ();
5977 
5978     case BUILT_IN_CLASSIFY_TYPE:
5979       return expand_builtin_classify_type (arglist);
5980 
5981     case BUILT_IN_CONSTANT_P:
5982       return const0_rtx;
5983 
5984     case BUILT_IN_FRAME_ADDRESS:
5985     case BUILT_IN_RETURN_ADDRESS:
5986       return expand_builtin_frame_address (fndecl, arglist);
5987 
5988     /* Returns the address of the area where the structure is returned.
5989        0 otherwise.  */
5990     case BUILT_IN_AGGREGATE_INCOMING_ADDRESS:
5991       if (arglist != 0
5992 	  || ! AGGREGATE_TYPE_P (TREE_TYPE (TREE_TYPE (current_function_decl)))
5993 	  || !MEM_P (DECL_RTL (DECL_RESULT (current_function_decl))))
5994 	return const0_rtx;
5995       else
5996 	return XEXP (DECL_RTL (DECL_RESULT (current_function_decl)), 0);
5997 
5998     case BUILT_IN_ALLOCA:
5999       target = expand_builtin_alloca (arglist, target);
6000       if (target)
6001 	return target;
6002       break;
6003 
6004     case BUILT_IN_STACK_SAVE:
6005       return expand_stack_save ();
6006 
6007     case BUILT_IN_STACK_RESTORE:
6008       expand_stack_restore (TREE_VALUE (arglist));
6009       return const0_rtx;
6010 
6011     case BUILT_IN_FFS:
6012     case BUILT_IN_FFSL:
6013     case BUILT_IN_FFSLL:
6014     case BUILT_IN_FFSIMAX:
6015       target = expand_builtin_unop (target_mode, arglist, target,
6016 				    subtarget, ffs_optab);
6017       if (target)
6018 	return target;
6019       break;
6020 
6021     case BUILT_IN_CLZ:
6022     case BUILT_IN_CLZL:
6023     case BUILT_IN_CLZLL:
6024     case BUILT_IN_CLZIMAX:
6025       target = expand_builtin_unop (target_mode, arglist, target,
6026 				    subtarget, clz_optab);
6027       if (target)
6028 	return target;
6029       break;
6030 
6031     case BUILT_IN_CTZ:
6032     case BUILT_IN_CTZL:
6033     case BUILT_IN_CTZLL:
6034     case BUILT_IN_CTZIMAX:
6035       target = expand_builtin_unop (target_mode, arglist, target,
6036 				    subtarget, ctz_optab);
6037       if (target)
6038 	return target;
6039       break;
6040 
6041     case BUILT_IN_POPCOUNT:
6042     case BUILT_IN_POPCOUNTL:
6043     case BUILT_IN_POPCOUNTLL:
6044     case BUILT_IN_POPCOUNTIMAX:
6045       target = expand_builtin_unop (target_mode, arglist, target,
6046 				    subtarget, popcount_optab);
6047       if (target)
6048 	return target;
6049       break;
6050 
6051     case BUILT_IN_PARITY:
6052     case BUILT_IN_PARITYL:
6053     case BUILT_IN_PARITYLL:
6054     case BUILT_IN_PARITYIMAX:
6055       target = expand_builtin_unop (target_mode, arglist, target,
6056 				    subtarget, parity_optab);
6057       if (target)
6058 	return target;
6059       break;
6060 
6061 #if 0
6062     case BUILT_IN_STRLEN:
6063       target = expand_builtin_strlen (arglist, target, target_mode);
6064       if (target)
6065 	return target;
6066       break;
6067 
6068     case BUILT_IN_STRCPY:
6069       target = expand_builtin_strcpy (fndecl, arglist, target, mode);
6070       if (target)
6071 	return target;
6072       break;
6073 
6074     case BUILT_IN_STRNCPY:
6075       target = expand_builtin_strncpy (exp, target, mode);
6076       if (target)
6077 	return target;
6078       break;
6079 
6080     case BUILT_IN_STPCPY:
6081       target = expand_builtin_stpcpy (exp, target, mode);
6082       if (target)
6083 	return target;
6084       break;
6085 
6086     case BUILT_IN_STRCAT:
6087       target = expand_builtin_strcat (fndecl, arglist, target, mode);
6088       if (target)
6089 	return target;
6090       break;
6091 
6092     case BUILT_IN_STRNCAT:
6093       target = expand_builtin_strncat (arglist, target, mode);
6094       if (target)
6095 	return target;
6096       break;
6097 
6098     case BUILT_IN_STRSPN:
6099       target = expand_builtin_strspn (arglist, target, mode);
6100       if (target)
6101 	return target;
6102       break;
6103 
6104     case BUILT_IN_STRCSPN:
6105       target = expand_builtin_strcspn (arglist, target, mode);
6106       if (target)
6107 	return target;
6108       break;
6109 
6110     case BUILT_IN_STRSTR:
6111       target = expand_builtin_strstr (arglist, TREE_TYPE (exp), target, mode);
6112       if (target)
6113 	return target;
6114       break;
6115 
6116     case BUILT_IN_STRPBRK:
6117       target = expand_builtin_strpbrk (arglist, TREE_TYPE (exp), target, mode);
6118       if (target)
6119 	return target;
6120       break;
6121 
6122     case BUILT_IN_INDEX:
6123     case BUILT_IN_STRCHR:
6124       target = expand_builtin_strchr (arglist, TREE_TYPE (exp), target, mode);
6125       if (target)
6126 	return target;
6127       break;
6128 
6129     case BUILT_IN_RINDEX:
6130     case BUILT_IN_STRRCHR:
6131       target = expand_builtin_strrchr (arglist, TREE_TYPE (exp), target, mode);
6132       if (target)
6133 	return target;
6134       break;
6135 #endif /* 0 */
6136 
6137     case BUILT_IN_MEMCPY:
6138       target = expand_builtin_memcpy (exp, target, mode);
6139       if (target)
6140 	return target;
6141       break;
6142 
6143 #if 0
6144     case BUILT_IN_MEMPCPY:
6145       target = expand_builtin_mempcpy (arglist, TREE_TYPE (exp), target, mode, /*endp=*/ 1);
6146       if (target)
6147 	return target;
6148       break;
6149 
6150     case BUILT_IN_MEMMOVE:
6151       target = expand_builtin_memmove (arglist, TREE_TYPE (exp), target,
6152 				       mode, exp);
6153       if (target)
6154 	return target;
6155       break;
6156 
6157     case BUILT_IN_BCOPY:
6158       target = expand_builtin_bcopy (exp);
6159       if (target)
6160 	return target;
6161       break;
6162 #endif /* 0 */
6163 
6164     case BUILT_IN_MEMSET:
6165       target = expand_builtin_memset (arglist, target, mode, exp);
6166       if (target)
6167 	return target;
6168       break;
6169 
6170 #if 0
6171     case BUILT_IN_BZERO:
6172       target = expand_builtin_bzero (exp);
6173       if (target)
6174 	return target;
6175       break;
6176 
6177     case BUILT_IN_STRCMP:
6178       target = expand_builtin_strcmp (exp, target, mode);
6179       if (target)
6180 	return target;
6181       break;
6182 
6183     case BUILT_IN_STRNCMP:
6184       target = expand_builtin_strncmp (exp, target, mode);
6185       if (target)
6186 	return target;
6187       break;
6188 
6189     case BUILT_IN_BCMP:
6190     case BUILT_IN_MEMCMP:
6191       target = expand_builtin_memcmp (exp, arglist, target, mode);
6192       if (target)
6193 	return target;
6194       break;
6195 #endif /* 0 */
6196 
6197     case BUILT_IN_SETJMP:
6198       target = expand_builtin_setjmp (arglist, target);
6199       if (target)
6200 	return target;
6201       break;
6202 
6203       /* __builtin_longjmp is passed a pointer to an array of five words.
6204 	 It's similar to the C library longjmp function but works with
6205 	 __builtin_setjmp above.  */
6206     case BUILT_IN_LONGJMP:
6207       if (!validate_arglist (arglist, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
6208 	break;
6209       else
6210 	{
6211 	  rtx buf_addr = expand_expr (TREE_VALUE (arglist), subtarget,
6212 				      VOIDmode, 0);
6213 	  rtx value = expand_expr (TREE_VALUE (TREE_CHAIN (arglist)),
6214 				   NULL_RTX, VOIDmode, 0);
6215 
6216 	  if (value != const1_rtx)
6217 	    {
6218 	      error ("%<__builtin_longjmp%> second argument must be 1");
6219 	      return const0_rtx;
6220 	    }
6221 
6222 	  expand_builtin_longjmp (buf_addr, value);
6223 	  return const0_rtx;
6224 	}
6225 
6226     case BUILT_IN_NONLOCAL_GOTO:
6227       target = expand_builtin_nonlocal_goto (arglist);
6228       if (target)
6229 	return target;
6230       break;
6231 
6232       /* This updates the setjmp buffer that is its argument with the value
6233 	 of the current stack pointer.  */
6234     case BUILT_IN_UPDATE_SETJMP_BUF:
6235       if (validate_arglist (arglist, POINTER_TYPE, VOID_TYPE))
6236 	{
6237 	  rtx buf_addr
6238 	    = expand_expr (TREE_VALUE (arglist), NULL_RTX, VOIDmode, 0);
6239 
6240 	  expand_builtin_update_setjmp_buf (buf_addr);
6241 	  return const0_rtx;
6242 	}
6243       break;
6244 
6245     case BUILT_IN_TRAP:
6246       expand_builtin_trap ();
6247       return const0_rtx;
6248 
6249 #if 0
6250     case BUILT_IN_PRINTF:
6251       target = expand_builtin_printf (exp, target, mode, false);
6252       if (target)
6253 	return target;
6254       break;
6255 
6256     case BUILT_IN_PRINTF_UNLOCKED:
6257       target = expand_builtin_printf (exp, target, mode, true);
6258       if (target)
6259 	return target;
6260       break;
6261 
6262     case BUILT_IN_FPUTS:
6263       target = expand_builtin_fputs (arglist, target, false);
6264       if (target)
6265 	return target;
6266       break;
6267     case BUILT_IN_FPUTS_UNLOCKED:
6268       target = expand_builtin_fputs (arglist, target, true);
6269       if (target)
6270 	return target;
6271       break;
6272 
6273     case BUILT_IN_FPRINTF:
6274       target = expand_builtin_fprintf (exp, target, mode, false);
6275       if (target)
6276 	return target;
6277       break;
6278 
6279     case BUILT_IN_FPRINTF_UNLOCKED:
6280       target = expand_builtin_fprintf (exp, target, mode, true);
6281       if (target)
6282 	return target;
6283       break;
6284 
6285     case BUILT_IN_SPRINTF:
6286       target = expand_builtin_sprintf (arglist, target, mode);
6287       if (target)
6288 	return target;
6289       break;
6290 
6291     case BUILT_IN_SIGNBIT:
6292     case BUILT_IN_SIGNBITF:
6293     case BUILT_IN_SIGNBITL:
6294       target = expand_builtin_signbit (exp, target);
6295       if (target)
6296 	return target;
6297       break;
6298 #endif /* 0 */
6299 
6300       /* Various hooks for the DWARF 2 __throw routine.  */
6301     case BUILT_IN_UNWIND_INIT:
6302       expand_builtin_unwind_init ();
6303       return const0_rtx;
6304     case BUILT_IN_DWARF_CFA:
6305       return virtual_cfa_rtx;
6306 #ifdef DWARF2_UNWIND_INFO
6307     case BUILT_IN_DWARF_SP_COLUMN:
6308       return expand_builtin_dwarf_sp_column ();
6309     case BUILT_IN_INIT_DWARF_REG_SIZES:
6310       expand_builtin_init_dwarf_reg_sizes (TREE_VALUE (arglist));
6311       return const0_rtx;
6312 #endif
6313     case BUILT_IN_FROB_RETURN_ADDR:
6314       return expand_builtin_frob_return_addr (TREE_VALUE (arglist));
6315     case BUILT_IN_EXTRACT_RETURN_ADDR:
6316       return expand_builtin_extract_return_addr (TREE_VALUE (arglist));
6317     case BUILT_IN_EH_RETURN:
6318       expand_builtin_eh_return (TREE_VALUE (arglist),
6319 				TREE_VALUE (TREE_CHAIN (arglist)));
6320       return const0_rtx;
6321 #ifdef EH_RETURN_DATA_REGNO
6322     case BUILT_IN_EH_RETURN_DATA_REGNO:
6323       return expand_builtin_eh_return_data_regno (arglist);
6324 #endif
6325     case BUILT_IN_EXTEND_POINTER:
6326       return expand_builtin_extend_pointer (TREE_VALUE (arglist));
6327 
6328     case BUILT_IN_VA_START:
6329     case BUILT_IN_STDARG_START:
6330       return expand_builtin_va_start (arglist);
6331     case BUILT_IN_VA_END:
6332       return expand_builtin_va_end (arglist);
6333     case BUILT_IN_VA_COPY:
6334       return expand_builtin_va_copy (arglist);
6335     case BUILT_IN_EXPECT:
6336       return expand_builtin_expect (arglist, target);
6337     case BUILT_IN_PREFETCH:
6338       expand_builtin_prefetch (arglist);
6339       return const0_rtx;
6340 
6341     case BUILT_IN_PROFILE_FUNC_ENTER:
6342       return expand_builtin_profile_func (false);
6343     case BUILT_IN_PROFILE_FUNC_EXIT:
6344       return expand_builtin_profile_func (true);
6345 
6346     case BUILT_IN_INIT_TRAMPOLINE:
6347       return expand_builtin_init_trampoline (arglist);
6348     case BUILT_IN_ADJUST_TRAMPOLINE:
6349       return expand_builtin_adjust_trampoline (arglist);
6350 
6351 #if 0
6352     case BUILT_IN_FORK:
6353     case BUILT_IN_EXECL:
6354     case BUILT_IN_EXECV:
6355     case BUILT_IN_EXECLP:
6356     case BUILT_IN_EXECLE:
6357     case BUILT_IN_EXECVP:
6358     case BUILT_IN_EXECVE:
6359       target = expand_builtin_fork_or_exec (fndecl, arglist, target, ignore);
6360       if (target)
6361 	return target;
6362       break;
6363 
6364     case BUILT_IN_FETCH_AND_ADD_1:
6365     case BUILT_IN_FETCH_AND_ADD_2:
6366     case BUILT_IN_FETCH_AND_ADD_4:
6367     case BUILT_IN_FETCH_AND_ADD_8:
6368       mode = get_builtin_sync_mode (fcode - BUILT_IN_FETCH_AND_ADD_1);
6369       target = expand_builtin_sync_operation (mode, arglist, PLUS,
6370 					      false, target, ignore);
6371       if (target)
6372 	return target;
6373       break;
6374 
6375     case BUILT_IN_FETCH_AND_SUB_1:
6376     case BUILT_IN_FETCH_AND_SUB_2:
6377     case BUILT_IN_FETCH_AND_SUB_4:
6378     case BUILT_IN_FETCH_AND_SUB_8:
6379       mode = get_builtin_sync_mode (fcode - BUILT_IN_FETCH_AND_SUB_1);
6380       target = expand_builtin_sync_operation (mode, arglist, MINUS,
6381 					      false, target, ignore);
6382       if (target)
6383 	return target;
6384       break;
6385 
6386     case BUILT_IN_FETCH_AND_OR_1:
6387     case BUILT_IN_FETCH_AND_OR_2:
6388     case BUILT_IN_FETCH_AND_OR_4:
6389     case BUILT_IN_FETCH_AND_OR_8:
6390       mode = get_builtin_sync_mode (fcode - BUILT_IN_FETCH_AND_OR_1);
6391       target = expand_builtin_sync_operation (mode, arglist, IOR,
6392 					      false, target, ignore);
6393       if (target)
6394 	return target;
6395       break;
6396 
6397     case BUILT_IN_FETCH_AND_AND_1:
6398     case BUILT_IN_FETCH_AND_AND_2:
6399     case BUILT_IN_FETCH_AND_AND_4:
6400     case BUILT_IN_FETCH_AND_AND_8:
6401       mode = get_builtin_sync_mode (fcode - BUILT_IN_FETCH_AND_AND_1);
6402       target = expand_builtin_sync_operation (mode, arglist, AND,
6403 					      false, target, ignore);
6404       if (target)
6405 	return target;
6406       break;
6407 
6408     case BUILT_IN_FETCH_AND_XOR_1:
6409     case BUILT_IN_FETCH_AND_XOR_2:
6410     case BUILT_IN_FETCH_AND_XOR_4:
6411     case BUILT_IN_FETCH_AND_XOR_8:
6412       mode = get_builtin_sync_mode (fcode - BUILT_IN_FETCH_AND_XOR_1);
6413       target = expand_builtin_sync_operation (mode, arglist, XOR,
6414 					      false, target, ignore);
6415       if (target)
6416 	return target;
6417       break;
6418 
6419     case BUILT_IN_FETCH_AND_NAND_1:
6420     case BUILT_IN_FETCH_AND_NAND_2:
6421     case BUILT_IN_FETCH_AND_NAND_4:
6422     case BUILT_IN_FETCH_AND_NAND_8:
6423       mode = get_builtin_sync_mode (fcode - BUILT_IN_FETCH_AND_NAND_1);
6424       target = expand_builtin_sync_operation (mode, arglist, NOT,
6425 					      false, target, ignore);
6426       if (target)
6427 	return target;
6428       break;
6429 
6430     case BUILT_IN_ADD_AND_FETCH_1:
6431     case BUILT_IN_ADD_AND_FETCH_2:
6432     case BUILT_IN_ADD_AND_FETCH_4:
6433     case BUILT_IN_ADD_AND_FETCH_8:
6434       mode = get_builtin_sync_mode (fcode - BUILT_IN_ADD_AND_FETCH_1);
6435       target = expand_builtin_sync_operation (mode, arglist, PLUS,
6436 					      true, target, ignore);
6437       if (target)
6438 	return target;
6439       break;
6440 
6441     case BUILT_IN_SUB_AND_FETCH_1:
6442     case BUILT_IN_SUB_AND_FETCH_2:
6443     case BUILT_IN_SUB_AND_FETCH_4:
6444     case BUILT_IN_SUB_AND_FETCH_8:
6445       mode = get_builtin_sync_mode (fcode - BUILT_IN_SUB_AND_FETCH_1);
6446       target = expand_builtin_sync_operation (mode, arglist, MINUS,
6447 					      true, target, ignore);
6448       if (target)
6449 	return target;
6450       break;
6451 
6452     case BUILT_IN_OR_AND_FETCH_1:
6453     case BUILT_IN_OR_AND_FETCH_2:
6454     case BUILT_IN_OR_AND_FETCH_4:
6455     case BUILT_IN_OR_AND_FETCH_8:
6456       mode = get_builtin_sync_mode (fcode - BUILT_IN_OR_AND_FETCH_1);
6457       target = expand_builtin_sync_operation (mode, arglist, IOR,
6458 					      true, target, ignore);
6459       if (target)
6460 	return target;
6461       break;
6462 
6463     case BUILT_IN_AND_AND_FETCH_1:
6464     case BUILT_IN_AND_AND_FETCH_2:
6465     case BUILT_IN_AND_AND_FETCH_4:
6466     case BUILT_IN_AND_AND_FETCH_8:
6467       mode = get_builtin_sync_mode (fcode - BUILT_IN_AND_AND_FETCH_1);
6468       target = expand_builtin_sync_operation (mode, arglist, AND,
6469 					      true, target, ignore);
6470       if (target)
6471 	return target;
6472       break;
6473 
6474     case BUILT_IN_XOR_AND_FETCH_1:
6475     case BUILT_IN_XOR_AND_FETCH_2:
6476     case BUILT_IN_XOR_AND_FETCH_4:
6477     case BUILT_IN_XOR_AND_FETCH_8:
6478       mode = get_builtin_sync_mode (fcode - BUILT_IN_XOR_AND_FETCH_1);
6479       target = expand_builtin_sync_operation (mode, arglist, XOR,
6480 					      true, target, ignore);
6481       if (target)
6482 	return target;
6483       break;
6484 
6485     case BUILT_IN_NAND_AND_FETCH_1:
6486     case BUILT_IN_NAND_AND_FETCH_2:
6487     case BUILT_IN_NAND_AND_FETCH_4:
6488     case BUILT_IN_NAND_AND_FETCH_8:
6489       mode = get_builtin_sync_mode (fcode - BUILT_IN_NAND_AND_FETCH_1);
6490       target = expand_builtin_sync_operation (mode, arglist, NOT,
6491 					      true, target, ignore);
6492       if (target)
6493 	return target;
6494       break;
6495 
6496     case BUILT_IN_BOOL_COMPARE_AND_SWAP_1:
6497     case BUILT_IN_BOOL_COMPARE_AND_SWAP_2:
6498     case BUILT_IN_BOOL_COMPARE_AND_SWAP_4:
6499     case BUILT_IN_BOOL_COMPARE_AND_SWAP_8:
6500       if (mode == VOIDmode)
6501 	mode = TYPE_MODE (boolean_type_node);
6502       if (!target || !register_operand (target, mode))
6503 	target = gen_reg_rtx (mode);
6504 
6505       mode = get_builtin_sync_mode (fcode - BUILT_IN_BOOL_COMPARE_AND_SWAP_1);
6506       target = expand_builtin_compare_and_swap (mode, arglist, true, target);
6507       if (target)
6508 	return target;
6509       break;
6510 
6511     case BUILT_IN_VAL_COMPARE_AND_SWAP_1:
6512     case BUILT_IN_VAL_COMPARE_AND_SWAP_2:
6513     case BUILT_IN_VAL_COMPARE_AND_SWAP_4:
6514     case BUILT_IN_VAL_COMPARE_AND_SWAP_8:
6515       mode = get_builtin_sync_mode (fcode - BUILT_IN_VAL_COMPARE_AND_SWAP_1);
6516       target = expand_builtin_compare_and_swap (mode, arglist, false, target);
6517       if (target)
6518 	return target;
6519       break;
6520 
6521     case BUILT_IN_LOCK_TEST_AND_SET_1:
6522     case BUILT_IN_LOCK_TEST_AND_SET_2:
6523     case BUILT_IN_LOCK_TEST_AND_SET_4:
6524     case BUILT_IN_LOCK_TEST_AND_SET_8:
6525       mode = get_builtin_sync_mode (fcode - BUILT_IN_LOCK_TEST_AND_SET_1);
6526       target = expand_builtin_lock_test_and_set (mode, arglist, target);
6527       if (target)
6528 	return target;
6529       break;
6530 
6531     case BUILT_IN_LOCK_RELEASE_1:
6532     case BUILT_IN_LOCK_RELEASE_2:
6533     case BUILT_IN_LOCK_RELEASE_4:
6534     case BUILT_IN_LOCK_RELEASE_8:
6535       mode = get_builtin_sync_mode (fcode - BUILT_IN_LOCK_RELEASE_1);
6536       expand_builtin_lock_release (mode, arglist);
6537       return const0_rtx;
6538 
6539     case BUILT_IN_SYNCHRONIZE:
6540       expand_builtin_synchronize ();
6541       return const0_rtx;
6542 
6543     case BUILT_IN_OBJECT_SIZE:
6544       return expand_builtin_object_size (exp);
6545 
6546     case BUILT_IN_MEMCPY_CHK:
6547     case BUILT_IN_MEMPCPY_CHK:
6548     case BUILT_IN_MEMMOVE_CHK:
6549     case BUILT_IN_MEMSET_CHK:
6550       target = expand_builtin_memory_chk (exp, target, mode, fcode);
6551       if (target)
6552 	return target;
6553       break;
6554 
6555     case BUILT_IN_STRCPY_CHK:
6556     case BUILT_IN_STPCPY_CHK:
6557     case BUILT_IN_STRNCPY_CHK:
6558     case BUILT_IN_STRCAT_CHK:
6559     case BUILT_IN_SNPRINTF_CHK:
6560     case BUILT_IN_VSNPRINTF_CHK:
6561       maybe_emit_chk_warning (exp, fcode);
6562       break;
6563 
6564     case BUILT_IN_SPRINTF_CHK:
6565     case BUILT_IN_VSPRINTF_CHK:
6566       maybe_emit_sprintf_chk_warning (exp, fcode);
6567       break;
6568 #endif /* 0 */
6569 
6570     case BUILT_IN_ER_THROW:
6571       expand_builtin_ER_throw (arglist);
6572       return const0_rtx;
6573 
6574     default:	/* just do library call, if unknown builtin */
6575       break;
6576     }
6577 
6578   /* The switch statement above can drop through to cause the function
6579      to be called normally.  */
6580   return expand_call (exp, target, ignore);
6581 }
6582 
6583 /* Determine whether a tree node represents a call to a built-in
6584    function.  If the tree T is a call to a built-in function with
6585    the right number of arguments of the appropriate types, return
6586    the DECL_FUNCTION_CODE of the call, e.g. BUILT_IN_SQRT.
6587    Otherwise the return value is END_BUILTINS.  */
6588 
6589 enum built_in_function
builtin_mathfn_code(tree t)6590 builtin_mathfn_code (tree t)
6591 {
6592 #if 0
6593   tree fndecl, arglist, parmlist;
6594   tree argtype, parmtype;
6595 
6596   if (TREE_CODE (t) != CALL_EXPR
6597       || TREE_CODE (TREE_OPERAND (t, 0)) != ADDR_EXPR)
6598     return END_BUILTINS;
6599 
6600   fndecl = get_callee_fndecl (t);
6601   if (fndecl == NULL_TREE
6602       || TREE_CODE (fndecl) != FUNCTION_DECL
6603       || ! DECL_BUILT_IN (fndecl)
6604       || DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_MD)
6605     return END_BUILTINS;
6606 
6607   arglist = TREE_OPERAND (t, 1);
6608   parmlist = TYPE_ARG_TYPES (TREE_TYPE (fndecl));
6609   for (; parmlist; parmlist = TREE_CHAIN (parmlist))
6610     {
6611       /* If a function doesn't take a variable number of arguments,
6612 	 the last element in the list will have type `void'.  */
6613       parmtype = TREE_VALUE (parmlist);
6614       if (VOID_TYPE_P (parmtype))
6615 	{
6616 	  if (arglist)
6617 	    return END_BUILTINS;
6618 	  return DECL_FUNCTION_CODE (fndecl);
6619 	}
6620 
6621       if (! arglist)
6622 	return END_BUILTINS;
6623 
6624       argtype = TREE_TYPE (TREE_VALUE (arglist));
6625 
6626       if (SCALAR_FLOAT_TYPE_P (parmtype))
6627 	{
6628 	  if (! SCALAR_FLOAT_TYPE_P (argtype))
6629 	    return END_BUILTINS;
6630 	}
6631       else if (COMPLEX_FLOAT_TYPE_P (parmtype))
6632 	{
6633 	  if (! COMPLEX_FLOAT_TYPE_P (argtype))
6634 	    return END_BUILTINS;
6635 	}
6636       else if (POINTER_TYPE_P (parmtype))
6637 	{
6638 	  if (! POINTER_TYPE_P (argtype))
6639 	    return END_BUILTINS;
6640 	}
6641       else if (INTEGRAL_TYPE_P (parmtype))
6642 	{
6643 	  if (! INTEGRAL_TYPE_P (argtype))
6644 	    return END_BUILTINS;
6645 	}
6646       else
6647 #endif /* 0 */
6648 	return END_BUILTINS;
6649 #if 0
6650 
6651       arglist = TREE_CHAIN (arglist);
6652     }
6653 
6654   /* Variable-length argument list.  */
6655   return DECL_FUNCTION_CODE (fndecl);
6656 #endif /* 0 */
6657 }
6658 
6659 /* Fold a call to __builtin_constant_p, if we know it will evaluate to a
6660    constant.  ARGLIST is the argument list of the call.  */
6661 
6662 static tree
fold_builtin_constant_p(tree arglist)6663 fold_builtin_constant_p (tree arglist)
6664 {
6665   if (arglist == 0)
6666     return 0;
6667 
6668   arglist = TREE_VALUE (arglist);
6669 
6670   /* We return 1 for a numeric type that's known to be a constant
6671      value at compile-time or for an aggregate type that's a
6672      literal constant.  */
6673   STRIP_NOPS (arglist);
6674 
6675   /* If we know this is a constant, emit the constant of one.  */
6676   if (CONSTANT_CLASS_P (arglist)
6677       || (TREE_CODE (arglist) == CONSTRUCTOR
6678 	  && TREE_CONSTANT (arglist)))
6679     return integer_one_node;
6680   if (TREE_CODE (arglist) == ADDR_EXPR)
6681     {
6682        tree op = TREE_OPERAND (arglist, 0);
6683        if (TREE_CODE (op) == STRING_CST
6684 	   || (TREE_CODE (op) == ARRAY_REF
6685 	       && integer_zerop (TREE_OPERAND (op, 1))
6686 	       && TREE_CODE (TREE_OPERAND (op, 0)) == STRING_CST))
6687 	 return integer_one_node;
6688     }
6689 
6690   /* If this expression has side effects, show we don't know it to be a
6691      constant.  Likewise if it's a pointer or aggregate type since in
6692      those case we only want literals, since those are only optimized
6693      when generating RTL, not later.
6694      And finally, if we are compiling an initializer, not code, we
6695      need to return a definite result now; there's not going to be any
6696      more optimization done.  */
6697   if (TREE_SIDE_EFFECTS (arglist)
6698       || AGGREGATE_TYPE_P (TREE_TYPE (arglist))
6699       || POINTER_TYPE_P (TREE_TYPE (arglist))
6700       || cfun == 0)
6701     return integer_zero_node;
6702 
6703   return 0;
6704 }
6705 
6706 /* Fold a call to __builtin_expect, if we expect that a comparison against
6707    the argument will fold to a constant.  In practice, this means a true
6708    constant or the address of a non-weak symbol.  ARGLIST is the argument
6709    list of the call.  */
6710 
6711 static tree
fold_builtin_expect(tree arglist)6712 fold_builtin_expect (tree arglist)
6713 {
6714   tree arg, inner;
6715 
6716   if (arglist == 0)
6717     return 0;
6718 
6719   arg = TREE_VALUE (arglist);
6720 
6721   /* If the argument isn't invariant, then there's nothing we can do.  */
6722   if (!TREE_INVARIANT (arg))
6723     return 0;
6724 
6725   /* If we're looking at an address of a weak decl, then do not fold.  */
6726   inner = arg;
6727   STRIP_NOPS (inner);
6728   if (TREE_CODE (inner) == ADDR_EXPR)
6729     {
6730       do
6731 	{
6732 	  inner = TREE_OPERAND (inner, 0);
6733 	}
6734       while (TREE_CODE (inner) == COMPONENT_REF
6735 	     || TREE_CODE (inner) == ARRAY_REF);
6736       if (DECL_P (inner) && DECL_WEAK (inner))
6737 	return 0;
6738     }
6739 
6740   /* Otherwise, ARG already has the proper type for the return value.  */
6741   return arg;
6742 }
6743 
6744 /* Fold a call to __builtin_classify_type.  */
6745 
6746 static tree
fold_builtin_classify_type(tree arglist)6747 fold_builtin_classify_type (tree arglist)
6748 {
6749   if (arglist == 0)
6750     return build_int_cst (NULL_TREE, no_type_class);
6751 
6752   return build_int_cst (NULL_TREE,
6753 			type_to_class (TREE_TYPE (TREE_VALUE (arglist))));
6754 }
6755 
6756 #if 0
6757 /* Fold a call to __builtin_strlen.  */
6758 
6759 static tree
6760 fold_builtin_strlen (tree arglist)
6761 {
6762   if (!validate_arglist (arglist, POINTER_TYPE, VOID_TYPE))
6763     return NULL_TREE;
6764   else
6765     {
6766       tree len = c_strlen (TREE_VALUE (arglist), 0);
6767 
6768       if (len)
6769 	{
6770 	  /* Convert from the internal "sizetype" type to "size_t".  */
6771 	  if (size_type_node)
6772 	    len = fold_convert (size_type_node, len);
6773 	  return len;
6774 	}
6775 
6776       return NULL_TREE;
6777     }
6778 }
6779 
6780 /* Fold a call to __builtin_inf or __builtin_huge_val.  */
6781 
6782 static tree
6783 fold_builtin_inf (tree type, int warn)
6784 {
6785   REAL_VALUE_TYPE real;
6786 
6787   /* __builtin_inff is intended to be usable to define INFINITY on all
6788      targets.  If an infinity is not available, INFINITY expands "to a
6789      positive constant of type float that overflows at translation
6790      time", footnote "In this case, using INFINITY will violate the
6791      constraint in 6.4.4 and thus require a diagnostic." (C99 7.12#4).
6792      Thus we pedwarn to ensure this constraint violation is
6793      diagnosed.  */
6794   if (!MODE_HAS_INFINITIES (TYPE_MODE (type)) && warn)
6795     pedwarn ("target format does not support infinity");
6796 
6797   real_inf (&real);
6798   return build_real (type, real);
6799 }
6800 
6801 /* Fold a call to __builtin_nan or __builtin_nans.  */
6802 
6803 static tree
6804 fold_builtin_nan (tree arglist, tree type, int quiet)
6805 {
6806   REAL_VALUE_TYPE real;
6807   const char *str;
6808 
6809   if (!validate_arglist (arglist, POINTER_TYPE, VOID_TYPE))
6810     return 0;
6811   str = c_getstr (TREE_VALUE (arglist));
6812   if (!str)
6813     return 0;
6814 
6815   if (!real_nan (&real, str, quiet, TYPE_MODE (type)))
6816     return 0;
6817 
6818   return build_real (type, real);
6819 }
6820 
6821 /* Return true if the floating point expression T has an integer value.
6822    We also allow +Inf, -Inf and NaN to be considered integer values.  */
6823 
6824 static bool
6825 integer_valued_real_p (tree t)
6826 {
6827   switch (TREE_CODE (t))
6828     {
6829     case FLOAT_EXPR:
6830       return true;
6831 
6832     case ABS_EXPR:
6833     case SAVE_EXPR:
6834     case NON_LVALUE_EXPR:
6835       return integer_valued_real_p (TREE_OPERAND (t, 0));
6836 
6837     case COMPOUND_EXPR:
6838     case MODIFY_EXPR:
6839     case BIND_EXPR:
6840       return integer_valued_real_p (TREE_OPERAND (t, 1));
6841 
6842     case PLUS_EXPR:
6843     case MINUS_EXPR:
6844     case MULT_EXPR:
6845     case MIN_EXPR:
6846     case MAX_EXPR:
6847       return integer_valued_real_p (TREE_OPERAND (t, 0))
6848 	     && integer_valued_real_p (TREE_OPERAND (t, 1));
6849 
6850     case COND_EXPR:
6851       return integer_valued_real_p (TREE_OPERAND (t, 1))
6852 	     && integer_valued_real_p (TREE_OPERAND (t, 2));
6853 
6854     case REAL_CST:
6855       if (! TREE_CONSTANT_OVERFLOW (t))
6856       {
6857         REAL_VALUE_TYPE c, cint;
6858 
6859 	c = TREE_REAL_CST (t);
6860 	real_trunc (&cint, TYPE_MODE (TREE_TYPE (t)), &c);
6861 	return real_identical (&c, &cint);
6862       }
6863       break;
6864 
6865     case NOP_EXPR:
6866       {
6867 	tree type = TREE_TYPE (TREE_OPERAND (t, 0));
6868 	if (TREE_CODE (type) == INTEGER_TYPE)
6869 	  return true;
6870 	if (TREE_CODE (type) == REAL_TYPE)
6871 	  return integer_valued_real_p (TREE_OPERAND (t, 0));
6872 	break;
6873       }
6874 
6875     case CALL_EXPR:
6876       switch (builtin_mathfn_code (t))
6877 	{
6878 	case BUILT_IN_CEIL:
6879 	case BUILT_IN_CEILF:
6880 	case BUILT_IN_CEILL:
6881 	case BUILT_IN_FLOOR:
6882 	case BUILT_IN_FLOORF:
6883 	case BUILT_IN_FLOORL:
6884 	case BUILT_IN_NEARBYINT:
6885 	case BUILT_IN_NEARBYINTF:
6886 	case BUILT_IN_NEARBYINTL:
6887 	case BUILT_IN_RINT:
6888 	case BUILT_IN_RINTF:
6889 	case BUILT_IN_RINTL:
6890 	case BUILT_IN_ROUND:
6891 	case BUILT_IN_ROUNDF:
6892 	case BUILT_IN_ROUNDL:
6893 	case BUILT_IN_TRUNC:
6894 	case BUILT_IN_TRUNCF:
6895 	case BUILT_IN_TRUNCL:
6896 	  return true;
6897 
6898 	default:
6899 	  break;
6900 	}
6901       break;
6902 
6903     default:
6904       break;
6905     }
6906   return false;
6907 }
6908 
6909 /* EXP is assumed to be builtin call where truncation can be propagated
6910    across (for instance floor((double)f) == (double)floorf (f).
6911    Do the transformation.  */
6912 
6913 static tree
6914 fold_trunc_transparent_mathfn (tree fndecl, tree arglist)
6915 {
6916   enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
6917   tree arg;
6918 
6919   if (! validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
6920     return 0;
6921 
6922   arg = TREE_VALUE (arglist);
6923   /* Integer rounding functions are idempotent.  */
6924   if (fcode == builtin_mathfn_code (arg))
6925     return arg;
6926 
6927   /* If argument is already integer valued, and we don't need to worry
6928      about setting errno, there's no need to perform rounding.  */
6929   if (! flag_errno_math && integer_valued_real_p (arg))
6930     return arg;
6931 
6932   if (optimize)
6933     {
6934       tree arg0 = strip_float_extensions (arg);
6935       tree ftype = TREE_TYPE (TREE_TYPE (fndecl));
6936       tree newtype = TREE_TYPE (arg0);
6937       tree decl;
6938 
6939       if (TYPE_PRECISION (newtype) < TYPE_PRECISION (ftype)
6940 	  && (decl = mathfn_built_in (newtype, fcode)))
6941 	{
6942 	  arglist =
6943 	    build_tree_list (NULL_TREE, fold_convert (newtype, arg0));
6944 	  return fold_convert (ftype,
6945 			       build_function_call_expr (decl, arglist));
6946 	}
6947     }
6948   return 0;
6949 }
6950 
6951 /* EXP is assumed to be builtin call which can narrow the FP type of
6952    the argument, for instance lround((double)f) -> lroundf (f).  */
6953 
6954 static tree
6955 fold_fixed_mathfn (tree fndecl, tree arglist)
6956 {
6957   enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
6958   tree arg;
6959 
6960   if (! validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
6961     return 0;
6962 
6963   arg = TREE_VALUE (arglist);
6964 
6965   /* If argument is already integer valued, and we don't need to worry
6966      about setting errno, there's no need to perform rounding.  */
6967   if (! flag_errno_math && integer_valued_real_p (arg))
6968     return fold_build1 (FIX_TRUNC_EXPR, TREE_TYPE (TREE_TYPE (fndecl)), arg);
6969 
6970   if (optimize)
6971     {
6972       tree ftype = TREE_TYPE (arg);
6973       tree arg0 = strip_float_extensions (arg);
6974       tree newtype = TREE_TYPE (arg0);
6975       tree decl;
6976 
6977       if (TYPE_PRECISION (newtype) < TYPE_PRECISION (ftype)
6978 	  && (decl = mathfn_built_in (newtype, fcode)))
6979 	{
6980 	  arglist =
6981 	    build_tree_list (NULL_TREE, fold_convert (newtype, arg0));
6982 	  return build_function_call_expr (decl, arglist);
6983 	}
6984     }
6985   return 0;
6986 }
6987 
6988 /* Fold function call to builtin cabs, cabsf or cabsl.  ARGLIST
6989    is the argument list and TYPE is the return type.  Return
6990    NULL_TREE if no if no simplification can be made.  */
6991 
6992 static tree
6993 fold_builtin_cabs (tree arglist, tree type)
6994 {
6995   tree arg;
6996 
6997   if (!arglist || TREE_CHAIN (arglist))
6998     return NULL_TREE;
6999 
7000   arg = TREE_VALUE (arglist);
7001   if (TREE_CODE (TREE_TYPE (arg)) != COMPLEX_TYPE
7002       || TREE_CODE (TREE_TYPE (TREE_TYPE (arg))) != REAL_TYPE)
7003     return NULL_TREE;
7004 
7005   /* Evaluate cabs of a constant at compile-time.  */
7006   if (flag_unsafe_math_optimizations
7007       && TREE_CODE (arg) == COMPLEX_CST
7008       && TREE_CODE (TREE_REALPART (arg)) == REAL_CST
7009       && TREE_CODE (TREE_IMAGPART (arg)) == REAL_CST
7010       && ! TREE_CONSTANT_OVERFLOW (TREE_REALPART (arg))
7011       && ! TREE_CONSTANT_OVERFLOW (TREE_IMAGPART (arg)))
7012     {
7013       REAL_VALUE_TYPE r, i;
7014 
7015       r = TREE_REAL_CST (TREE_REALPART (arg));
7016       i = TREE_REAL_CST (TREE_IMAGPART (arg));
7017 
7018       real_arithmetic (&r, MULT_EXPR, &r, &r);
7019       real_arithmetic (&i, MULT_EXPR, &i, &i);
7020       real_arithmetic (&r, PLUS_EXPR, &r, &i);
7021       if (real_sqrt (&r, TYPE_MODE (type), &r)
7022 	  || ! flag_trapping_math)
7023 	return build_real (type, r);
7024     }
7025 
7026   /* If either part is zero, cabs is fabs of the other.  */
7027   if (TREE_CODE (arg) == COMPLEX_EXPR
7028       && real_zerop (TREE_OPERAND (arg, 0)))
7029     return fold_build1 (ABS_EXPR, type, TREE_OPERAND (arg, 1));
7030   if (TREE_CODE (arg) == COMPLEX_EXPR
7031       && real_zerop (TREE_OPERAND (arg, 1)))
7032     return fold_build1 (ABS_EXPR, type, TREE_OPERAND (arg, 0));
7033 
7034   /* Don't do this when optimizing for size.  */
7035   if (flag_unsafe_math_optimizations
7036       && optimize && !optimize_size)
7037     {
7038       tree sqrtfn = mathfn_built_in (type, BUILT_IN_SQRT);
7039 
7040       if (sqrtfn != NULL_TREE)
7041 	{
7042 	  tree rpart, ipart, result, arglist;
7043 
7044 	  arg = builtin_save_expr (arg);
7045 
7046 	  rpart = fold_build1 (REALPART_EXPR, type, arg);
7047 	  ipart = fold_build1 (IMAGPART_EXPR, type, arg);
7048 
7049 	  rpart = builtin_save_expr (rpart);
7050 	  ipart = builtin_save_expr (ipart);
7051 
7052 	  result = fold_build2 (PLUS_EXPR, type,
7053 				fold_build2 (MULT_EXPR, type,
7054 					     rpart, rpart),
7055 				fold_build2 (MULT_EXPR, type,
7056 					     ipart, ipart));
7057 
7058 	  arglist = build_tree_list (NULL_TREE, result);
7059 	  return build_function_call_expr (sqrtfn, arglist);
7060 	}
7061     }
7062 
7063   return NULL_TREE;
7064 }
7065 
7066 /* Fold a builtin function call to sqrt, sqrtf, or sqrtl.  Return
7067    NULL_TREE if no simplification can be made.  */
7068 
7069 static tree
7070 fold_builtin_sqrt (tree arglist, tree type)
7071 {
7072 
7073   enum built_in_function fcode;
7074   tree arg = TREE_VALUE (arglist);
7075 
7076   if (!validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
7077     return NULL_TREE;
7078 
7079   /* Optimize sqrt of constant value.  */
7080   if (TREE_CODE (arg) == REAL_CST
7081       && ! TREE_CONSTANT_OVERFLOW (arg))
7082     {
7083       REAL_VALUE_TYPE r, x;
7084 
7085       x = TREE_REAL_CST (arg);
7086       if (real_sqrt (&r, TYPE_MODE (type), &x)
7087 	  || (!flag_trapping_math && !flag_errno_math))
7088 	return build_real (type, r);
7089     }
7090 
7091   /* Optimize sqrt(expN(x)) = expN(x*0.5).  */
7092   fcode = builtin_mathfn_code (arg);
7093   if (flag_unsafe_math_optimizations && BUILTIN_EXPONENT_P (fcode))
7094     {
7095       tree expfn = TREE_OPERAND (TREE_OPERAND (arg, 0), 0);
7096       arg = fold_build2 (MULT_EXPR, type,
7097 			 TREE_VALUE (TREE_OPERAND (arg, 1)),
7098 			 build_real (type, dconsthalf));
7099       arglist = build_tree_list (NULL_TREE, arg);
7100       return build_function_call_expr (expfn, arglist);
7101     }
7102 
7103   /* Optimize sqrt(Nroot(x)) -> pow(x,1/(2*N)).  */
7104   if (flag_unsafe_math_optimizations && BUILTIN_ROOT_P (fcode))
7105     {
7106       tree powfn = mathfn_built_in (type, BUILT_IN_POW);
7107 
7108       if (powfn)
7109 	{
7110 	  tree arg0 = TREE_VALUE (TREE_OPERAND (arg, 1));
7111 	  tree tree_root;
7112 	  /* The inner root was either sqrt or cbrt.  */
7113 	  REAL_VALUE_TYPE dconstroot =
7114 	    BUILTIN_SQRT_P (fcode) ? dconsthalf : dconstthird;
7115 
7116 	  /* Adjust for the outer root.  */
7117 	  SET_REAL_EXP (&dconstroot, REAL_EXP (&dconstroot) - 1);
7118 	  dconstroot = real_value_truncate (TYPE_MODE (type), dconstroot);
7119 	  tree_root = build_real (type, dconstroot);
7120 	  arglist = tree_cons (NULL_TREE, arg0,
7121 			       build_tree_list (NULL_TREE, tree_root));
7122 	  return build_function_call_expr (powfn, arglist);
7123 	}
7124     }
7125 
7126   /* Optimize sqrt(pow(x,y)) = pow(|x|,y*0.5).  */
7127   if (flag_unsafe_math_optimizations
7128       && (fcode == BUILT_IN_POW
7129 	  || fcode == BUILT_IN_POWF
7130 	  || fcode == BUILT_IN_POWL))
7131     {
7132       tree powfn = TREE_OPERAND (TREE_OPERAND (arg, 0), 0);
7133       tree arg0 = TREE_VALUE (TREE_OPERAND (arg, 1));
7134       tree arg1 = TREE_VALUE (TREE_CHAIN (TREE_OPERAND (arg, 1)));
7135       tree narg1;
7136       if (!tree_expr_nonnegative_p (arg0))
7137 	arg0 = build1 (ABS_EXPR, type, arg0);
7138       narg1 = fold_build2 (MULT_EXPR, type, arg1,
7139 			   build_real (type, dconsthalf));
7140       arglist = tree_cons (NULL_TREE, arg0,
7141 			   build_tree_list (NULL_TREE, narg1));
7142       return build_function_call_expr (powfn, arglist);
7143     }
7144 
7145   return NULL_TREE;
7146 }
7147 
7148 /* Fold a builtin function call to cbrt, cbrtf, or cbrtl.  Return
7149    NULL_TREE if no simplification can be made.  */
7150 static tree
7151 fold_builtin_cbrt (tree arglist, tree type)
7152 {
7153   tree arg = TREE_VALUE (arglist);
7154   const enum built_in_function fcode = builtin_mathfn_code (arg);
7155 
7156   if (!validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
7157     return NULL_TREE;
7158 
7159   /* Optimize cbrt of constant value.  */
7160   if (real_zerop (arg) || real_onep (arg) || real_minus_onep (arg))
7161     return arg;
7162 
7163   if (flag_unsafe_math_optimizations)
7164     {
7165       /* Optimize cbrt(expN(x)) -> expN(x/3).  */
7166       if (BUILTIN_EXPONENT_P (fcode))
7167         {
7168 	  tree expfn = TREE_OPERAND (TREE_OPERAND (arg, 0), 0);
7169 	  const REAL_VALUE_TYPE third_trunc =
7170 	    real_value_truncate (TYPE_MODE (type), dconstthird);
7171 	  arg = fold_build2 (MULT_EXPR, type,
7172 			     TREE_VALUE (TREE_OPERAND (arg, 1)),
7173 			     build_real (type, third_trunc));
7174 	  arglist = build_tree_list (NULL_TREE, arg);
7175 	  return build_function_call_expr (expfn, arglist);
7176 	}
7177 
7178       /* Optimize cbrt(sqrt(x)) -> pow(x,1/6).  */
7179       if (BUILTIN_SQRT_P (fcode))
7180         {
7181 	  tree powfn = mathfn_built_in (type, BUILT_IN_POW);
7182 
7183 	  if (powfn)
7184 	    {
7185 	      tree arg0 = TREE_VALUE (TREE_OPERAND (arg, 1));
7186 	      tree tree_root;
7187 	      REAL_VALUE_TYPE dconstroot = dconstthird;
7188 
7189 	      SET_REAL_EXP (&dconstroot, REAL_EXP (&dconstroot) - 1);
7190 	      dconstroot = real_value_truncate (TYPE_MODE (type), dconstroot);
7191 	      tree_root = build_real (type, dconstroot);
7192 	      arglist = tree_cons (NULL_TREE, arg0,
7193 				   build_tree_list (NULL_TREE, tree_root));
7194 	      return build_function_call_expr (powfn, arglist);
7195 	    }
7196 	}
7197 
7198       /* Optimize cbrt(cbrt(x)) -> pow(x,1/9) iff x is nonnegative.  */
7199       if (BUILTIN_CBRT_P (fcode))
7200         {
7201 	  tree arg0 = TREE_VALUE (TREE_OPERAND (arg, 1));
7202 	  if (tree_expr_nonnegative_p (arg0))
7203 	    {
7204 	      tree powfn = mathfn_built_in (type, BUILT_IN_POW);
7205 
7206 	      if (powfn)
7207 	        {
7208 		  tree tree_root;
7209 		  REAL_VALUE_TYPE dconstroot;
7210 
7211 		  real_arithmetic (&dconstroot, MULT_EXPR, &dconstthird, &dconstthird);
7212 		  dconstroot = real_value_truncate (TYPE_MODE (type), dconstroot);
7213 		  tree_root = build_real (type, dconstroot);
7214 		  arglist = tree_cons (NULL_TREE, arg0,
7215 				       build_tree_list (NULL_TREE, tree_root));
7216 		  return build_function_call_expr (powfn, arglist);
7217 		}
7218 	    }
7219 	}
7220 
7221       /* Optimize cbrt(pow(x,y)) -> pow(x,y/3) iff x is nonnegative.  */
7222       if (fcode == BUILT_IN_POW || fcode == BUILT_IN_POWF
7223 	  || fcode == BUILT_IN_POWL)
7224         {
7225 	  tree arg00 = TREE_VALUE (TREE_OPERAND (arg, 1));
7226 	  tree arg01 = TREE_VALUE (TREE_CHAIN (TREE_OPERAND (arg, 1)));
7227 	  if (tree_expr_nonnegative_p (arg00))
7228 	    {
7229 	      tree powfn = TREE_OPERAND (TREE_OPERAND (arg, 0), 0);
7230 	      const REAL_VALUE_TYPE dconstroot
7231 		= real_value_truncate (TYPE_MODE (type), dconstthird);
7232 	      tree narg01 = fold_build2 (MULT_EXPR, type, arg01,
7233 					 build_real (type, dconstroot));
7234 	      arglist = tree_cons (NULL_TREE, arg00,
7235 				   build_tree_list (NULL_TREE, narg01));
7236 	      return build_function_call_expr (powfn, arglist);
7237 	    }
7238 	}
7239     }
7240   return NULL_TREE;
7241 }
7242 
7243 /* Fold function call to builtin sin, sinf, or sinl.  Return
7244    NULL_TREE if no simplification can be made.  */
7245 static tree
7246 fold_builtin_sin (tree arglist)
7247 {
7248   tree arg = TREE_VALUE (arglist);
7249 
7250   if (!validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
7251     return NULL_TREE;
7252 
7253   /* Optimize sin (0.0) = 0.0.  */
7254   if (real_zerop (arg))
7255     return arg;
7256 
7257   return NULL_TREE;
7258 }
7259 
7260 /* Fold function call to builtin cos, cosf, or cosl.  Return
7261    NULL_TREE if no simplification can be made.  */
7262 static tree
7263 fold_builtin_cos (tree arglist, tree type, tree fndecl)
7264 {
7265   tree arg = TREE_VALUE (arglist);
7266 
7267   if (!validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
7268     return NULL_TREE;
7269 
7270   /* Optimize cos (0.0) = 1.0.  */
7271   if (real_zerop (arg))
7272     return build_real (type, dconst1);
7273 
7274   /* Optimize cos(-x) into cos (x).  */
7275   if (TREE_CODE (arg) == NEGATE_EXPR)
7276     {
7277       tree args = build_tree_list (NULL_TREE,
7278 				   TREE_OPERAND (arg, 0));
7279       return build_function_call_expr (fndecl, args);
7280     }
7281 
7282   return NULL_TREE;
7283 }
7284 
7285 /* Fold function call to builtin tan, tanf, or tanl.  Return
7286    NULL_TREE if no simplification can be made.  */
7287 static tree
7288 fold_builtin_tan (tree arglist)
7289 {
7290   enum built_in_function fcode;
7291   tree arg = TREE_VALUE (arglist);
7292 
7293   if (!validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
7294     return NULL_TREE;
7295 
7296   /* Optimize tan(0.0) = 0.0.  */
7297   if (real_zerop (arg))
7298     return arg;
7299 
7300   /* Optimize tan(atan(x)) = x.  */
7301   fcode = builtin_mathfn_code (arg);
7302   if (flag_unsafe_math_optimizations
7303       && (fcode == BUILT_IN_ATAN
7304 	  || fcode == BUILT_IN_ATANF
7305 	  || fcode == BUILT_IN_ATANL))
7306     return TREE_VALUE (TREE_OPERAND (arg, 1));
7307 
7308   return NULL_TREE;
7309 }
7310 
7311 /* Fold function call to builtin atan, atanf, or atanl.  Return
7312    NULL_TREE if no simplification can be made.  */
7313 
7314 static tree
7315 fold_builtin_atan (tree arglist, tree type)
7316 {
7317 
7318   tree arg = TREE_VALUE (arglist);
7319 
7320   if (!validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
7321     return NULL_TREE;
7322 
7323   /* Optimize atan(0.0) = 0.0.  */
7324   if (real_zerop (arg))
7325     return arg;
7326 
7327   /* Optimize atan(1.0) = pi/4.  */
7328   if (real_onep (arg))
7329     {
7330       REAL_VALUE_TYPE cst;
7331 
7332       real_convert (&cst, TYPE_MODE (type), &dconstpi);
7333       SET_REAL_EXP (&cst, REAL_EXP (&cst) - 2);
7334       return build_real (type, cst);
7335     }
7336 
7337   return NULL_TREE;
7338 }
7339 
7340 /* Fold function call to builtin trunc, truncf or truncl.  Return
7341    NULL_TREE if no simplification can be made.  */
7342 
7343 static tree
7344 fold_builtin_trunc (tree fndecl, tree arglist)
7345 {
7346   tree arg;
7347 
7348   if (! validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
7349     return 0;
7350 
7351   /* Optimize trunc of constant value.  */
7352   arg = TREE_VALUE (arglist);
7353   if (TREE_CODE (arg) == REAL_CST && ! TREE_CONSTANT_OVERFLOW (arg))
7354     {
7355       REAL_VALUE_TYPE r, x;
7356       tree type = TREE_TYPE (TREE_TYPE (fndecl));
7357 
7358       x = TREE_REAL_CST (arg);
7359       real_trunc (&r, TYPE_MODE (type), &x);
7360       return build_real (type, r);
7361     }
7362 
7363   return fold_trunc_transparent_mathfn (fndecl, arglist);
7364 }
7365 
7366 /* Fold function call to builtin floor, floorf or floorl.  Return
7367    NULL_TREE if no simplification can be made.  */
7368 
7369 static tree
7370 fold_builtin_floor (tree fndecl, tree arglist)
7371 {
7372   tree arg;
7373 
7374   if (! validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
7375     return 0;
7376 
7377   /* Optimize floor of constant value.  */
7378   arg = TREE_VALUE (arglist);
7379   if (TREE_CODE (arg) == REAL_CST && ! TREE_CONSTANT_OVERFLOW (arg))
7380     {
7381       REAL_VALUE_TYPE x;
7382 
7383       x = TREE_REAL_CST (arg);
7384       if (! REAL_VALUE_ISNAN (x) || ! flag_errno_math)
7385 	{
7386 	  tree type = TREE_TYPE (TREE_TYPE (fndecl));
7387 	  REAL_VALUE_TYPE r;
7388 
7389 	  real_floor (&r, TYPE_MODE (type), &x);
7390 	  return build_real (type, r);
7391 	}
7392     }
7393 
7394   return fold_trunc_transparent_mathfn (fndecl, arglist);
7395 }
7396 
7397 /* Fold function call to builtin ceil, ceilf or ceill.  Return
7398    NULL_TREE if no simplification can be made.  */
7399 
7400 static tree
7401 fold_builtin_ceil (tree fndecl, tree arglist)
7402 {
7403   tree arg;
7404 
7405   if (! validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
7406     return 0;
7407 
7408   /* Optimize ceil of constant value.  */
7409   arg = TREE_VALUE (arglist);
7410   if (TREE_CODE (arg) == REAL_CST && ! TREE_CONSTANT_OVERFLOW (arg))
7411     {
7412       REAL_VALUE_TYPE x;
7413 
7414       x = TREE_REAL_CST (arg);
7415       if (! REAL_VALUE_ISNAN (x) || ! flag_errno_math)
7416 	{
7417 	  tree type = TREE_TYPE (TREE_TYPE (fndecl));
7418 	  REAL_VALUE_TYPE r;
7419 
7420 	  real_ceil (&r, TYPE_MODE (type), &x);
7421 	  return build_real (type, r);
7422 	}
7423     }
7424 
7425   return fold_trunc_transparent_mathfn (fndecl, arglist);
7426 }
7427 
7428 /* Fold function call to builtin round, roundf or roundl.  Return
7429    NULL_TREE if no simplification can be made.  */
7430 
7431 static tree
7432 fold_builtin_round (tree fndecl, tree arglist)
7433 {
7434   tree arg;
7435 
7436   if (! validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
7437     return 0;
7438 
7439   /* Optimize round of constant value.  */
7440   arg = TREE_VALUE (arglist);
7441   if (TREE_CODE (arg) == REAL_CST && ! TREE_CONSTANT_OVERFLOW (arg))
7442     {
7443       REAL_VALUE_TYPE x;
7444 
7445       x = TREE_REAL_CST (arg);
7446       if (! REAL_VALUE_ISNAN (x) || ! flag_errno_math)
7447 	{
7448 	  tree type = TREE_TYPE (TREE_TYPE (fndecl));
7449 	  REAL_VALUE_TYPE r;
7450 
7451 	  real_round (&r, TYPE_MODE (type), &x);
7452 	  return build_real (type, r);
7453 	}
7454     }
7455 
7456   return fold_trunc_transparent_mathfn (fndecl, arglist);
7457 }
7458 
7459 /* Fold function call to builtin lround, lroundf or lroundl (or the
7460    corresponding long long versions) and other rounding functions.
7461    Return NULL_TREE if no simplification can be made.  */
7462 
7463 static tree
7464 fold_builtin_int_roundingfn (tree fndecl, tree arglist)
7465 {
7466   tree arg;
7467 
7468   if (! validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
7469     return 0;
7470 
7471   /* Optimize lround of constant value.  */
7472   arg = TREE_VALUE (arglist);
7473   if (TREE_CODE (arg) == REAL_CST && ! TREE_CONSTANT_OVERFLOW (arg))
7474     {
7475       const REAL_VALUE_TYPE x = TREE_REAL_CST (arg);
7476 
7477       if (! REAL_VALUE_ISNAN (x) && ! REAL_VALUE_ISINF (x))
7478 	{
7479 	  tree itype = TREE_TYPE (TREE_TYPE (fndecl));
7480 	  tree ftype = TREE_TYPE (arg), result;
7481 	  HOST_WIDE_INT hi, lo;
7482 	  REAL_VALUE_TYPE r;
7483 
7484 	  switch (DECL_FUNCTION_CODE (fndecl))
7485 	    {
7486 	    case BUILT_IN_LFLOOR:
7487 	    case BUILT_IN_LFLOORF:
7488 	    case BUILT_IN_LFLOORL:
7489 	    case BUILT_IN_LLFLOOR:
7490 	    case BUILT_IN_LLFLOORF:
7491 	    case BUILT_IN_LLFLOORL:
7492 	      real_floor (&r, TYPE_MODE (ftype), &x);
7493 	      break;
7494 
7495 	    case BUILT_IN_LCEIL:
7496 	    case BUILT_IN_LCEILF:
7497 	    case BUILT_IN_LCEILL:
7498 	    case BUILT_IN_LLCEIL:
7499 	    case BUILT_IN_LLCEILF:
7500 	    case BUILT_IN_LLCEILL:
7501 	      real_ceil (&r, TYPE_MODE (ftype), &x);
7502 	      break;
7503 
7504 	    case BUILT_IN_LROUND:
7505 	    case BUILT_IN_LROUNDF:
7506 	    case BUILT_IN_LROUNDL:
7507 	    case BUILT_IN_LLROUND:
7508 	    case BUILT_IN_LLROUNDF:
7509 	    case BUILT_IN_LLROUNDL:
7510 	      real_round (&r, TYPE_MODE (ftype), &x);
7511 	      break;
7512 
7513 	    default:
7514 	      gcc_unreachable ();
7515 	    }
7516 
7517 	  REAL_VALUE_TO_INT (&lo, &hi, r);
7518 	  result = build_int_cst_wide (NULL_TREE, lo, hi);
7519 	  if (int_fits_type_p (result, itype))
7520 	    return fold_convert (itype, result);
7521 	}
7522     }
7523 
7524   return fold_fixed_mathfn (fndecl, arglist);
7525 }
7526 #endif /* 0 */
7527 
7528 /* Fold function call to builtin ffs, clz, ctz, popcount and parity
7529    and their long and long long variants (i.e. ffsl and ffsll).
7530    Return NULL_TREE if no simplification can be made.  */
7531 
7532 static tree
fold_builtin_bitop(tree fndecl,tree arglist)7533 fold_builtin_bitop (tree fndecl, tree arglist)
7534 {
7535   tree arg;
7536 
7537   if (! validate_arglist (arglist, INTEGER_TYPE, VOID_TYPE))
7538     return NULL_TREE;
7539 
7540   /* Optimize for constant argument.  */
7541   arg = TREE_VALUE (arglist);
7542   if (TREE_CODE (arg) == INTEGER_CST && ! TREE_CONSTANT_OVERFLOW (arg))
7543     {
7544       HOST_WIDE_INT hi, width, result;
7545       unsigned HOST_WIDE_INT lo;
7546       tree type;
7547 
7548       type = TREE_TYPE (arg);
7549       width = TYPE_PRECISION (type);
7550       lo = TREE_INT_CST_LOW (arg);
7551 
7552       /* Clear all the bits that are beyond the type's precision.  */
7553       if (width > HOST_BITS_PER_WIDE_INT)
7554 	{
7555 	  hi = TREE_INT_CST_HIGH (arg);
7556 	  if (width < 2 * HOST_BITS_PER_WIDE_INT)
7557 	    hi &= ~((HOST_WIDE_INT) (-1) >> (width - HOST_BITS_PER_WIDE_INT));
7558 	}
7559       else
7560 	{
7561 	  hi = 0;
7562 	  if (width < HOST_BITS_PER_WIDE_INT)
7563 	    lo &= ~((unsigned HOST_WIDE_INT) (-1) << width);
7564 	}
7565 
7566       switch (DECL_FUNCTION_CODE (fndecl))
7567 	{
7568 	case BUILT_IN_FFS:
7569 	case BUILT_IN_FFSL:
7570 	case BUILT_IN_FFSLL:
7571 	  if (lo != 0)
7572 	    result = exact_log2 (lo & -lo) + 1;
7573 	  else if (hi != 0)
7574 	    result = HOST_BITS_PER_WIDE_INT + exact_log2 (hi & -hi) + 1;
7575 	  else
7576 	    result = 0;
7577 	  break;
7578 
7579 	case BUILT_IN_CLZ:
7580 	case BUILT_IN_CLZL:
7581 	case BUILT_IN_CLZLL:
7582 	  if (hi != 0)
7583 	    result = width - floor_log2 (hi) - 1 - HOST_BITS_PER_WIDE_INT;
7584 	  else if (lo != 0)
7585 	    result = width - floor_log2 (lo) - 1;
7586 	  else if (! CLZ_DEFINED_VALUE_AT_ZERO (TYPE_MODE (type), result))
7587 	    result = width;
7588 	  break;
7589 
7590 	case BUILT_IN_CTZ:
7591 	case BUILT_IN_CTZL:
7592 	case BUILT_IN_CTZLL:
7593 	  if (lo != 0)
7594 	    result = exact_log2 (lo & -lo);
7595 	  else if (hi != 0)
7596 	    result = HOST_BITS_PER_WIDE_INT + exact_log2 (hi & -hi);
7597 	  else if (! CTZ_DEFINED_VALUE_AT_ZERO (TYPE_MODE (type), result))
7598 	    result = width;
7599 	  break;
7600 
7601 	case BUILT_IN_POPCOUNT:
7602 	case BUILT_IN_POPCOUNTL:
7603 	case BUILT_IN_POPCOUNTLL:
7604 	  result = 0;
7605 	  while (lo)
7606 	    result++, lo &= lo - 1;
7607 	  while (hi)
7608 	    result++, hi &= hi - 1;
7609 	  break;
7610 
7611 	case BUILT_IN_PARITY:
7612 	case BUILT_IN_PARITYL:
7613 	case BUILT_IN_PARITYLL:
7614 	  result = 0;
7615 	  while (lo)
7616 	    result++, lo &= lo - 1;
7617 	  while (hi)
7618 	    result++, hi &= hi - 1;
7619 	  result &= 1;
7620 	  break;
7621 
7622 	default:
7623 	  gcc_unreachable ();
7624 	}
7625 
7626       return build_int_cst (TREE_TYPE (TREE_TYPE (fndecl)), result);
7627     }
7628 
7629   return NULL_TREE;
7630 }
7631 
7632 #if 0
7633 /* Return true if EXPR is the real constant contained in VALUE.  */
7634 
7635 static bool
7636 real_dconstp (tree expr, const REAL_VALUE_TYPE *value)
7637 {
7638   STRIP_NOPS (expr);
7639 
7640   return ((TREE_CODE (expr) == REAL_CST
7641            && ! TREE_CONSTANT_OVERFLOW (expr)
7642            && REAL_VALUES_EQUAL (TREE_REAL_CST (expr), *value))
7643           || (TREE_CODE (expr) == COMPLEX_CST
7644               && real_dconstp (TREE_REALPART (expr), value)
7645               && real_zerop (TREE_IMAGPART (expr))));
7646 }
7647 
7648 /* A subroutine of fold_builtin to fold the various logarithmic
7649    functions.  EXP is the CALL_EXPR of a call to a builtin logN
7650    function.  VALUE is the base of the logN function.  */
7651 
7652 static tree
7653 fold_builtin_logarithm (tree fndecl, tree arglist,
7654 			const REAL_VALUE_TYPE *value)
7655 {
7656   if (validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
7657     {
7658       tree type = TREE_TYPE (TREE_TYPE (fndecl));
7659       tree arg = TREE_VALUE (arglist);
7660       const enum built_in_function fcode = builtin_mathfn_code (arg);
7661 
7662       /* Optimize logN(1.0) = 0.0.  */
7663       if (real_onep (arg))
7664 	return build_real (type, dconst0);
7665 
7666       /* Optimize logN(N) = 1.0.  If N can't be truncated to MODE
7667          exactly, then only do this if flag_unsafe_math_optimizations.  */
7668       if (exact_real_truncate (TYPE_MODE (type), value)
7669 	  || flag_unsafe_math_optimizations)
7670         {
7671 	  const REAL_VALUE_TYPE value_truncate =
7672 	    real_value_truncate (TYPE_MODE (type), *value);
7673 	  if (real_dconstp (arg, &value_truncate))
7674 	    return build_real (type, dconst1);
7675 	}
7676 
7677       /* Special case, optimize logN(expN(x)) = x.  */
7678       if (flag_unsafe_math_optimizations
7679 	  && ((value == &dconste
7680 	       && (fcode == BUILT_IN_EXP
7681 		   || fcode == BUILT_IN_EXPF
7682 		   || fcode == BUILT_IN_EXPL))
7683 	      || (value == &dconst2
7684 		  && (fcode == BUILT_IN_EXP2
7685 		      || fcode == BUILT_IN_EXP2F
7686 		      || fcode == BUILT_IN_EXP2L))
7687 	      || (value == &dconst10 && (BUILTIN_EXP10_P (fcode)))))
7688 	return fold_convert (type, TREE_VALUE (TREE_OPERAND (arg, 1)));
7689 
7690       /* Optimize logN(func()) for various exponential functions.  We
7691          want to determine the value "x" and the power "exponent" in
7692          order to transform logN(x**exponent) into exponent*logN(x).  */
7693       if (flag_unsafe_math_optimizations)
7694         {
7695 	  tree exponent = 0, x = 0;
7696 
7697 	  switch (fcode)
7698 	  {
7699 	  case BUILT_IN_EXP:
7700 	  case BUILT_IN_EXPF:
7701 	  case BUILT_IN_EXPL:
7702 	    /* Prepare to do logN(exp(exponent) -> exponent*logN(e).  */
7703 	    x = build_real (type,
7704 			    real_value_truncate (TYPE_MODE (type), dconste));
7705 	    exponent = TREE_VALUE (TREE_OPERAND (arg, 1));
7706 	    break;
7707 	  case BUILT_IN_EXP2:
7708 	  case BUILT_IN_EXP2F:
7709 	  case BUILT_IN_EXP2L:
7710 	    /* Prepare to do logN(exp2(exponent) -> exponent*logN(2).  */
7711 	    x = build_real (type, dconst2);
7712 	    exponent = TREE_VALUE (TREE_OPERAND (arg, 1));
7713 	    break;
7714 	  case BUILT_IN_EXP10:
7715 	  case BUILT_IN_EXP10F:
7716 	  case BUILT_IN_EXP10L:
7717 	  case BUILT_IN_POW10:
7718 	  case BUILT_IN_POW10F:
7719 	  case BUILT_IN_POW10L:
7720 	    /* Prepare to do logN(exp10(exponent) -> exponent*logN(10).  */
7721 	    x = build_real (type, dconst10);
7722 	    exponent = TREE_VALUE (TREE_OPERAND (arg, 1));
7723 	    break;
7724 	  case BUILT_IN_SQRT:
7725 	  case BUILT_IN_SQRTF:
7726 	  case BUILT_IN_SQRTL:
7727 	    /* Prepare to do logN(sqrt(x) -> 0.5*logN(x).  */
7728 	    x = TREE_VALUE (TREE_OPERAND (arg, 1));
7729 	    exponent = build_real (type, dconsthalf);
7730 	    break;
7731 	  case BUILT_IN_CBRT:
7732 	  case BUILT_IN_CBRTF:
7733 	  case BUILT_IN_CBRTL:
7734 	    /* Prepare to do logN(cbrt(x) -> (1/3)*logN(x).  */
7735 	    x = TREE_VALUE (TREE_OPERAND (arg, 1));
7736 	    exponent = build_real (type, real_value_truncate (TYPE_MODE (type),
7737 							      dconstthird));
7738 	    break;
7739 	  case BUILT_IN_POW:
7740 	  case BUILT_IN_POWF:
7741 	  case BUILT_IN_POWL:
7742 	    /* Prepare to do logN(pow(x,exponent) -> exponent*logN(x).  */
7743 	    x = TREE_VALUE (TREE_OPERAND (arg, 1));
7744 	    exponent = TREE_VALUE (TREE_CHAIN (TREE_OPERAND (arg, 1)));
7745 	    break;
7746 	  default:
7747 	    break;
7748 	  }
7749 
7750 	  /* Now perform the optimization.  */
7751 	  if (x && exponent)
7752 	    {
7753 	      tree logfn;
7754 	      arglist = build_tree_list (NULL_TREE, x);
7755 	      logfn = build_function_call_expr (fndecl, arglist);
7756 	      return fold_build2 (MULT_EXPR, type, exponent, logfn);
7757 	    }
7758 	}
7759     }
7760 
7761   return 0;
7762 }
7763 
7764 /* Fold a builtin function call to pow, powf, or powl.  Return
7765    NULL_TREE if no simplification can be made.  */
7766 static tree
7767 fold_builtin_pow (tree fndecl, tree arglist, tree type)
7768 {
7769   tree arg0 = TREE_VALUE (arglist);
7770   tree arg1 = TREE_VALUE (TREE_CHAIN (arglist));
7771 
7772   if (!validate_arglist (arglist, REAL_TYPE, REAL_TYPE, VOID_TYPE))
7773     return NULL_TREE;
7774 
7775   /* Optimize pow(1.0,y) = 1.0.  */
7776   if (real_onep (arg0))
7777     return omit_one_operand (type, build_real (type, dconst1), arg1);
7778 
7779   if (TREE_CODE (arg1) == REAL_CST
7780       && ! TREE_CONSTANT_OVERFLOW (arg1))
7781     {
7782       REAL_VALUE_TYPE cint;
7783       REAL_VALUE_TYPE c;
7784       HOST_WIDE_INT n;
7785 
7786       c = TREE_REAL_CST (arg1);
7787 
7788       /* Optimize pow(x,0.0) = 1.0.  */
7789       if (REAL_VALUES_EQUAL (c, dconst0))
7790 	return omit_one_operand (type, build_real (type, dconst1),
7791 				 arg0);
7792 
7793       /* Optimize pow(x,1.0) = x.  */
7794       if (REAL_VALUES_EQUAL (c, dconst1))
7795 	return arg0;
7796 
7797       /* Optimize pow(x,-1.0) = 1.0/x.  */
7798       if (REAL_VALUES_EQUAL (c, dconstm1))
7799 	return fold_build2 (RDIV_EXPR, type,
7800 			    build_real (type, dconst1), arg0);
7801 
7802       /* Optimize pow(x,0.5) = sqrt(x).  */
7803       if (flag_unsafe_math_optimizations
7804 	  && REAL_VALUES_EQUAL (c, dconsthalf))
7805 	{
7806 	  tree sqrtfn = mathfn_built_in (type, BUILT_IN_SQRT);
7807 
7808 	  if (sqrtfn != NULL_TREE)
7809 	    {
7810 	      tree arglist = build_tree_list (NULL_TREE, arg0);
7811 	      return build_function_call_expr (sqrtfn, arglist);
7812 	    }
7813 	}
7814 
7815       /* Check for an integer exponent.  */
7816       n = real_to_integer (&c);
7817       real_from_integer (&cint, VOIDmode, n, n < 0 ? -1 : 0, 0);
7818       if (real_identical (&c, &cint))
7819 	{
7820 	  /* Attempt to evaluate pow at compile-time.  */
7821 	  if (TREE_CODE (arg0) == REAL_CST
7822 	      && ! TREE_CONSTANT_OVERFLOW (arg0))
7823 	    {
7824 	      REAL_VALUE_TYPE x;
7825 	      bool inexact;
7826 
7827 	      x = TREE_REAL_CST (arg0);
7828 	      inexact = real_powi (&x, TYPE_MODE (type), &x, n);
7829 	      if (flag_unsafe_math_optimizations || !inexact)
7830 		return build_real (type, x);
7831 	    }
7832 
7833 	  /* Strip sign ops from even integer powers.  */
7834 	  if ((n & 1) == 0 && flag_unsafe_math_optimizations)
7835 	    {
7836 	      tree narg0 = fold_strip_sign_ops (arg0);
7837 	      if (narg0)
7838 		{
7839 		  arglist = build_tree_list (NULL_TREE, arg1);
7840 		  arglist = tree_cons (NULL_TREE, narg0, arglist);
7841 		  return build_function_call_expr (fndecl, arglist);
7842 		}
7843 	    }
7844 	}
7845     }
7846 
7847   if (flag_unsafe_math_optimizations)
7848     {
7849       const enum built_in_function fcode = builtin_mathfn_code (arg0);
7850 
7851       /* Optimize pow(expN(x),y) = expN(x*y).  */
7852       if (BUILTIN_EXPONENT_P (fcode))
7853         {
7854 	  tree expfn = TREE_OPERAND (TREE_OPERAND (arg0, 0), 0);
7855 	  tree arg = TREE_VALUE (TREE_OPERAND (arg0, 1));
7856 	  arg = fold_build2 (MULT_EXPR, type, arg, arg1);
7857 	  arglist = build_tree_list (NULL_TREE, arg);
7858 	  return build_function_call_expr (expfn, arglist);
7859 	}
7860 
7861       /* Optimize pow(sqrt(x),y) = pow(x,y*0.5).  */
7862       if (BUILTIN_SQRT_P (fcode))
7863         {
7864 	  tree narg0 = TREE_VALUE (TREE_OPERAND (arg0, 1));
7865 	  tree narg1 = fold_build2 (MULT_EXPR, type, arg1,
7866 				    build_real (type, dconsthalf));
7867 
7868 	  arglist = tree_cons (NULL_TREE, narg0,
7869 			       build_tree_list (NULL_TREE, narg1));
7870 	  return build_function_call_expr (fndecl, arglist);
7871 	}
7872 
7873       /* Optimize pow(cbrt(x),y) = pow(x,y/3) iff x is nonnegative.  */
7874       if (BUILTIN_CBRT_P (fcode))
7875         {
7876 	  tree arg = TREE_VALUE (TREE_OPERAND (arg0, 1));
7877 	  if (tree_expr_nonnegative_p (arg))
7878 	    {
7879 	      const REAL_VALUE_TYPE dconstroot
7880 		= real_value_truncate (TYPE_MODE (type), dconstthird);
7881 	      tree narg1 = fold_build2 (MULT_EXPR, type, arg1,
7882 					build_real (type, dconstroot));
7883 	      arglist = tree_cons (NULL_TREE, arg,
7884 				   build_tree_list (NULL_TREE, narg1));
7885 	      return build_function_call_expr (fndecl, arglist);
7886 	    }
7887 	}
7888 
7889       /* Optimize pow(pow(x,y),z) = pow(x,y*z).  */
7890       if (fcode == BUILT_IN_POW || fcode == BUILT_IN_POWF
7891 	   || fcode == BUILT_IN_POWL)
7892         {
7893 	  tree arg00 = TREE_VALUE (TREE_OPERAND (arg0, 1));
7894 	  tree arg01 = TREE_VALUE (TREE_CHAIN (TREE_OPERAND (arg0, 1)));
7895 	  tree narg1 = fold_build2 (MULT_EXPR, type, arg01, arg1);
7896 	  arglist = tree_cons (NULL_TREE, arg00,
7897 			       build_tree_list (NULL_TREE, narg1));
7898 	  return build_function_call_expr (fndecl, arglist);
7899 	}
7900     }
7901 
7902   return NULL_TREE;
7903 }
7904 
7905 /* Fold a builtin function call to powi, powif, or powil.  Return
7906    NULL_TREE if no simplification can be made.  */
7907 static tree
7908 fold_builtin_powi (tree fndecl ATTRIBUTE_UNUSED, tree arglist, tree type)
7909 {
7910   tree arg0 = TREE_VALUE (arglist);
7911   tree arg1 = TREE_VALUE (TREE_CHAIN (arglist));
7912 
7913   if (!validate_arglist (arglist, REAL_TYPE, INTEGER_TYPE, VOID_TYPE))
7914     return NULL_TREE;
7915 
7916   /* Optimize pow(1.0,y) = 1.0.  */
7917   if (real_onep (arg0))
7918     return omit_one_operand (type, build_real (type, dconst1), arg1);
7919 
7920   if (host_integerp (arg1, 0))
7921     {
7922       HOST_WIDE_INT c = TREE_INT_CST_LOW (arg1);
7923 
7924       /* Evaluate powi at compile-time.  */
7925       if (TREE_CODE (arg0) == REAL_CST
7926 	  && ! TREE_CONSTANT_OVERFLOW (arg0))
7927 	{
7928 	  REAL_VALUE_TYPE x;
7929 	  x = TREE_REAL_CST (arg0);
7930 	  real_powi (&x, TYPE_MODE (type), &x, c);
7931 	  return build_real (type, x);
7932 	}
7933 
7934       /* Optimize pow(x,0) = 1.0.  */
7935       if (c == 0)
7936 	return omit_one_operand (type, build_real (type, dconst1),
7937 				 arg0);
7938 
7939       /* Optimize pow(x,1) = x.  */
7940       if (c == 1)
7941 	return arg0;
7942 
7943       /* Optimize pow(x,-1) = 1.0/x.  */
7944       if (c == -1)
7945 	return fold_build2 (RDIV_EXPR, type,
7946 			   build_real (type, dconst1), arg0);
7947     }
7948 
7949   return NULL_TREE;
7950 }
7951 
7952 /* A subroutine of fold_builtin to fold the various exponent
7953    functions.  EXP is the CALL_EXPR of a call to a builtin function.
7954    VALUE is the value which will be raised to a power.  */
7955 
7956 static tree
7957 fold_builtin_exponent (tree fndecl, tree arglist,
7958 		       const REAL_VALUE_TYPE *value)
7959 {
7960   if (validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
7961     {
7962       tree type = TREE_TYPE (TREE_TYPE (fndecl));
7963       tree arg = TREE_VALUE (arglist);
7964 
7965       /* Optimize exp*(0.0) = 1.0.  */
7966       if (real_zerop (arg))
7967 	return build_real (type, dconst1);
7968 
7969       /* Optimize expN(1.0) = N.  */
7970       if (real_onep (arg))
7971         {
7972 	  REAL_VALUE_TYPE cst;
7973 
7974 	  real_convert (&cst, TYPE_MODE (type), value);
7975 	  return build_real (type, cst);
7976 	}
7977 
7978       /* Attempt to evaluate expN(integer) at compile-time.  */
7979       if (flag_unsafe_math_optimizations
7980 	  && TREE_CODE (arg) == REAL_CST
7981 	  && ! TREE_CONSTANT_OVERFLOW (arg))
7982         {
7983 	  REAL_VALUE_TYPE cint;
7984 	  REAL_VALUE_TYPE c;
7985 	  HOST_WIDE_INT n;
7986 
7987 	  c = TREE_REAL_CST (arg);
7988 	  n = real_to_integer (&c);
7989 	  real_from_integer (&cint, VOIDmode, n,
7990 			     n < 0 ? -1 : 0, 0);
7991 	  if (real_identical (&c, &cint))
7992 	    {
7993 	      REAL_VALUE_TYPE x;
7994 
7995 	      real_powi (&x, TYPE_MODE (type), value, n);
7996 	      return build_real (type, x);
7997 	    }
7998 	}
7999 
8000       /* Optimize expN(logN(x)) = x.  */
8001       if (flag_unsafe_math_optimizations)
8002         {
8003 	  const enum built_in_function fcode = builtin_mathfn_code (arg);
8004 
8005 	  if ((value == &dconste
8006 	       && (fcode == BUILT_IN_LOG
8007 		   || fcode == BUILT_IN_LOGF
8008 		   || fcode == BUILT_IN_LOGL))
8009 	      || (value == &dconst2
8010 		  && (fcode == BUILT_IN_LOG2
8011 		      || fcode == BUILT_IN_LOG2F
8012 		      || fcode == BUILT_IN_LOG2L))
8013 	      || (value == &dconst10
8014 		  && (fcode == BUILT_IN_LOG10
8015 		      || fcode == BUILT_IN_LOG10F
8016 		      || fcode == BUILT_IN_LOG10L)))
8017 	    return fold_convert (type, TREE_VALUE (TREE_OPERAND (arg, 1)));
8018 	}
8019     }
8020 
8021   return 0;
8022 }
8023 #endif /* 0 */
8024 
8025 /* Fold function call to builtin memcpy.  Return
8026    NULL_TREE if no simplification can be made.  */
8027 
8028 static tree
fold_builtin_memcpy(tree fndecl,tree arglist)8029 fold_builtin_memcpy (tree fndecl, tree arglist)
8030 {
8031   tree dest, src, len;
8032 
8033   if (!validate_arglist (arglist,
8034 			 POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
8035     return 0;
8036 
8037   dest = TREE_VALUE (arglist);
8038   src = TREE_VALUE (TREE_CHAIN (arglist));
8039   len = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
8040 
8041   /* If the LEN parameter is zero, return DEST.  */
8042   if (integer_zerop (len))
8043     return omit_one_operand (TREE_TYPE (TREE_TYPE (fndecl)), dest, src);
8044 
8045   /* If SRC and DEST are the same (and not volatile), return DEST.  */
8046   if (operand_equal_p (src, dest, 0))
8047     return omit_one_operand (TREE_TYPE (TREE_TYPE (fndecl)), dest, len);
8048 
8049   return 0;
8050 }
8051 
8052 #if 0
8053 /* Fold function call to builtin mempcpy.  Return
8054    NULL_TREE if no simplification can be made.  */
8055 
8056 static tree
8057 fold_builtin_mempcpy (tree arglist, tree type, int endp)
8058 {
8059   if (validate_arglist (arglist,
8060 			POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
8061     {
8062       tree dest = TREE_VALUE (arglist);
8063       tree src = TREE_VALUE (TREE_CHAIN (arglist));
8064       tree len = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
8065 
8066       /* If the LEN parameter is zero, return DEST.  */
8067       if (integer_zerop (len))
8068 	return omit_one_operand (type, dest, src);
8069 
8070       /* If SRC and DEST are the same (and not volatile), return DEST+LEN.  */
8071       if (operand_equal_p (src, dest, 0))
8072         {
8073 	  if (endp == 0)
8074 	    return omit_one_operand (type, dest, len);
8075 
8076 	  if (endp == 2)
8077 	    len = fold_build2 (MINUS_EXPR, TREE_TYPE (len), len,
8078 			       ssize_int (1));
8079 
8080 	  len = fold_convert (TREE_TYPE (dest), len);
8081 	  len = fold_build2 (PLUS_EXPR, TREE_TYPE (dest), dest, len);
8082 	  return fold_convert (type, len);
8083 	}
8084     }
8085   return 0;
8086 }
8087 
8088 /* Fold function call to builtin memmove.  Return
8089    NULL_TREE if no simplification can be made.  */
8090 
8091 static tree
8092 fold_builtin_memmove (tree arglist, tree type)
8093 {
8094   tree dest, src, len;
8095 
8096   if (!validate_arglist (arglist,
8097 			 POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
8098     return 0;
8099 
8100   dest = TREE_VALUE (arglist);
8101   src = TREE_VALUE (TREE_CHAIN (arglist));
8102   len = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
8103 
8104   /* If the LEN parameter is zero, return DEST.  */
8105   if (integer_zerop (len))
8106     return omit_one_operand (type, dest, src);
8107 
8108   /* If SRC and DEST are the same (and not volatile), return DEST.  */
8109   if (operand_equal_p (src, dest, 0))
8110     return omit_one_operand (type, dest, len);
8111 
8112   return 0;
8113 }
8114 
8115 /* Fold function call to builtin strcpy.  If LEN is not NULL, it represents
8116    the length of the string to be copied.  Return NULL_TREE if no
8117    simplification can be made.  */
8118 
8119 tree
8120 fold_builtin_strcpy (tree fndecl, tree arglist, tree len)
8121 {
8122   tree dest, src, fn;
8123 
8124   if (!validate_arglist (arglist,
8125 			 POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
8126     return 0;
8127 
8128   dest = TREE_VALUE (arglist);
8129   src = TREE_VALUE (TREE_CHAIN (arglist));
8130 
8131   /* If SRC and DEST are the same (and not volatile), return DEST.  */
8132   if (operand_equal_p (src, dest, 0))
8133     return fold_convert (TREE_TYPE (TREE_TYPE (fndecl)), dest);
8134 
8135   if (optimize_size)
8136     return 0;
8137 
8138   fn = implicit_built_in_decls[BUILT_IN_MEMCPY];
8139   if (!fn)
8140     return 0;
8141 
8142   if (!len)
8143     {
8144       len = c_strlen (src, 1);
8145       if (! len || TREE_SIDE_EFFECTS (len))
8146 	return 0;
8147     }
8148 
8149   len = size_binop (PLUS_EXPR, len, ssize_int (1));
8150   arglist = build_tree_list (NULL_TREE, len);
8151   arglist = tree_cons (NULL_TREE, src, arglist);
8152   arglist = tree_cons (NULL_TREE, dest, arglist);
8153   return fold_convert (TREE_TYPE (TREE_TYPE (fndecl)),
8154 		       build_function_call_expr (fn, arglist));
8155 }
8156 
8157 /* Fold function call to builtin strncpy.  If SLEN is not NULL, it represents
8158    the length of the source string.  Return NULL_TREE if no simplification
8159    can be made.  */
8160 
8161 tree
8162 fold_builtin_strncpy (tree fndecl, tree arglist, tree slen)
8163 {
8164   tree dest, src, len, fn;
8165 
8166   if (!validate_arglist (arglist,
8167 			 POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
8168     return 0;
8169 
8170   dest = TREE_VALUE (arglist);
8171   src = TREE_VALUE (TREE_CHAIN (arglist));
8172   len = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
8173 
8174   /* If the LEN parameter is zero, return DEST.  */
8175   if (integer_zerop (len))
8176     return omit_one_operand (TREE_TYPE (TREE_TYPE (fndecl)), dest, src);
8177 
8178   /* We can't compare slen with len as constants below if len is not a
8179      constant.  */
8180   if (len == 0 || TREE_CODE (len) != INTEGER_CST)
8181     return 0;
8182 
8183   if (!slen)
8184     slen = c_strlen (src, 1);
8185 
8186   /* Now, we must be passed a constant src ptr parameter.  */
8187   if (slen == 0 || TREE_CODE (slen) != INTEGER_CST)
8188     return 0;
8189 
8190   slen = size_binop (PLUS_EXPR, slen, ssize_int (1));
8191 
8192   /* We do not support simplification of this case, though we do
8193      support it when expanding trees into RTL.  */
8194   /* FIXME: generate a call to __builtin_memset.  */
8195   if (tree_int_cst_lt (slen, len))
8196     return 0;
8197 
8198   /* OK transform into builtin memcpy.  */
8199   fn = implicit_built_in_decls[BUILT_IN_MEMCPY];
8200   if (!fn)
8201     return 0;
8202   return fold_convert (TREE_TYPE (TREE_TYPE (fndecl)),
8203 		       build_function_call_expr (fn, arglist));
8204 }
8205 
8206 /* Fold function call to builtin memcmp.  Return
8207    NULL_TREE if no simplification can be made.  */
8208 
8209 static tree
8210 fold_builtin_memcmp (tree arglist)
8211 {
8212   tree arg1, arg2, len;
8213   const char *p1, *p2;
8214 
8215   if (!validate_arglist (arglist,
8216 			 POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
8217     return 0;
8218 
8219   arg1 = TREE_VALUE (arglist);
8220   arg2 = TREE_VALUE (TREE_CHAIN (arglist));
8221   len = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
8222 
8223   /* If the LEN parameter is zero, return zero.  */
8224   if (integer_zerop (len))
8225     return omit_two_operands (integer_type_node, integer_zero_node,
8226 			      arg1, arg2);
8227 
8228   /* If ARG1 and ARG2 are the same (and not volatile), return zero.  */
8229   if (operand_equal_p (arg1, arg2, 0))
8230     return omit_one_operand (integer_type_node, integer_zero_node, len);
8231 
8232   p1 = c_getstr (arg1);
8233   p2 = c_getstr (arg2);
8234 
8235   /* If all arguments are constant, and the value of len is not greater
8236      than the lengths of arg1 and arg2, evaluate at compile-time.  */
8237   if (host_integerp (len, 1) && p1 && p2
8238       && compare_tree_int (len, strlen (p1) + 1) <= 0
8239       && compare_tree_int (len, strlen (p2) + 1) <= 0)
8240     {
8241       const int r = memcmp (p1, p2, tree_low_cst (len, 1));
8242 
8243       if (r > 0)
8244 	return integer_one_node;
8245       else if (r < 0)
8246 	return integer_minus_one_node;
8247       else
8248 	return integer_zero_node;
8249     }
8250 
8251   /* If len parameter is one, return an expression corresponding to
8252      (*(const unsigned char*)arg1 - (const unsigned char*)arg2).  */
8253   if (host_integerp (len, 1) && tree_low_cst (len, 1) == 1)
8254     {
8255       tree cst_uchar_node = build_type_variant (unsigned_char_type_node, 1, 0);
8256       tree cst_uchar_ptr_node
8257 	= build_pointer_type_for_mode (cst_uchar_node, ptr_mode, true);
8258 
8259       tree ind1 = fold_convert (integer_type_node,
8260 				build1 (INDIRECT_REF, cst_uchar_node,
8261 					fold_convert (cst_uchar_ptr_node,
8262 						      arg1)));
8263       tree ind2 = fold_convert (integer_type_node,
8264 				build1 (INDIRECT_REF, cst_uchar_node,
8265 					fold_convert (cst_uchar_ptr_node,
8266 						      arg2)));
8267       return fold_build2 (MINUS_EXPR, integer_type_node, ind1, ind2);
8268     }
8269 
8270   return 0;
8271 }
8272 
8273 /* Fold function call to builtin strcmp.  Return
8274    NULL_TREE if no simplification can be made.  */
8275 
8276 static tree
8277 fold_builtin_strcmp (tree arglist)
8278 {
8279   tree arg1, arg2;
8280   const char *p1, *p2;
8281 
8282   if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
8283     return 0;
8284 
8285   arg1 = TREE_VALUE (arglist);
8286   arg2 = TREE_VALUE (TREE_CHAIN (arglist));
8287 
8288   /* If ARG1 and ARG2 are the same (and not volatile), return zero.  */
8289   if (operand_equal_p (arg1, arg2, 0))
8290     return integer_zero_node;
8291 
8292   p1 = c_getstr (arg1);
8293   p2 = c_getstr (arg2);
8294 
8295   if (p1 && p2)
8296     {
8297       const int i = strcmp (p1, p2);
8298       if (i < 0)
8299 	return integer_minus_one_node;
8300       else if (i > 0)
8301 	return integer_one_node;
8302       else
8303 	return integer_zero_node;
8304     }
8305 
8306   /* If the second arg is "", return *(const unsigned char*)arg1.  */
8307   if (p2 && *p2 == '\0')
8308     {
8309       tree cst_uchar_node = build_type_variant (unsigned_char_type_node, 1, 0);
8310       tree cst_uchar_ptr_node
8311 	= build_pointer_type_for_mode (cst_uchar_node, ptr_mode, true);
8312 
8313       return fold_convert (integer_type_node,
8314 			   build1 (INDIRECT_REF, cst_uchar_node,
8315 				   fold_convert (cst_uchar_ptr_node,
8316 						 arg1)));
8317     }
8318 
8319   /* If the first arg is "", return -*(const unsigned char*)arg2.  */
8320   if (p1 && *p1 == '\0')
8321     {
8322       tree cst_uchar_node = build_type_variant (unsigned_char_type_node, 1, 0);
8323       tree cst_uchar_ptr_node
8324 	= build_pointer_type_for_mode (cst_uchar_node, ptr_mode, true);
8325 
8326       tree temp = fold_convert (integer_type_node,
8327 				build1 (INDIRECT_REF, cst_uchar_node,
8328 					fold_convert (cst_uchar_ptr_node,
8329 						      arg2)));
8330       return fold_build1 (NEGATE_EXPR, integer_type_node, temp);
8331     }
8332 
8333   return 0;
8334 }
8335 
8336 /* Fold function call to builtin strncmp.  Return
8337    NULL_TREE if no simplification can be made.  */
8338 
8339 static tree
8340 fold_builtin_strncmp (tree arglist)
8341 {
8342   tree arg1, arg2, len;
8343   const char *p1, *p2;
8344 
8345   if (!validate_arglist (arglist,
8346 			 POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
8347     return 0;
8348 
8349   arg1 = TREE_VALUE (arglist);
8350   arg2 = TREE_VALUE (TREE_CHAIN (arglist));
8351   len = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
8352 
8353   /* If the LEN parameter is zero, return zero.  */
8354   if (integer_zerop (len))
8355     return omit_two_operands (integer_type_node, integer_zero_node,
8356 			      arg1, arg2);
8357 
8358   /* If ARG1 and ARG2 are the same (and not volatile), return zero.  */
8359   if (operand_equal_p (arg1, arg2, 0))
8360     return omit_one_operand (integer_type_node, integer_zero_node, len);
8361 
8362   p1 = c_getstr (arg1);
8363   p2 = c_getstr (arg2);
8364 
8365   if (host_integerp (len, 1) && p1 && p2)
8366     {
8367       const int i = strncmp (p1, p2, tree_low_cst (len, 1));
8368       if (i > 0)
8369 	return integer_one_node;
8370       else if (i < 0)
8371 	return integer_minus_one_node;
8372       else
8373 	return integer_zero_node;
8374     }
8375 
8376   /* If the second arg is "", and the length is greater than zero,
8377      return *(const unsigned char*)arg1.  */
8378   if (p2 && *p2 == '\0'
8379       && TREE_CODE (len) == INTEGER_CST
8380       && tree_int_cst_sgn (len) == 1)
8381     {
8382       tree cst_uchar_node = build_type_variant (unsigned_char_type_node, 1, 0);
8383       tree cst_uchar_ptr_node
8384 	= build_pointer_type_for_mode (cst_uchar_node, ptr_mode, true);
8385 
8386       return fold_convert (integer_type_node,
8387 			   build1 (INDIRECT_REF, cst_uchar_node,
8388 				   fold_convert (cst_uchar_ptr_node,
8389 						 arg1)));
8390     }
8391 
8392   /* If the first arg is "", and the length is greater than zero,
8393      return -*(const unsigned char*)arg2.  */
8394   if (p1 && *p1 == '\0'
8395       && TREE_CODE (len) == INTEGER_CST
8396       && tree_int_cst_sgn (len) == 1)
8397     {
8398       tree cst_uchar_node = build_type_variant (unsigned_char_type_node, 1, 0);
8399       tree cst_uchar_ptr_node
8400 	= build_pointer_type_for_mode (cst_uchar_node, ptr_mode, true);
8401 
8402       tree temp = fold_convert (integer_type_node,
8403 				build1 (INDIRECT_REF, cst_uchar_node,
8404 					fold_convert (cst_uchar_ptr_node,
8405 						      arg2)));
8406       return fold_build1 (NEGATE_EXPR, integer_type_node, temp);
8407     }
8408 
8409   /* If len parameter is one, return an expression corresponding to
8410      (*(const unsigned char*)arg1 - (const unsigned char*)arg2).  */
8411   if (host_integerp (len, 1) && tree_low_cst (len, 1) == 1)
8412     {
8413       tree cst_uchar_node = build_type_variant (unsigned_char_type_node, 1, 0);
8414       tree cst_uchar_ptr_node
8415 	= build_pointer_type_for_mode (cst_uchar_node, ptr_mode, true);
8416 
8417       tree ind1 = fold_convert (integer_type_node,
8418 				build1 (INDIRECT_REF, cst_uchar_node,
8419 					fold_convert (cst_uchar_ptr_node,
8420 						      arg1)));
8421       tree ind2 = fold_convert (integer_type_node,
8422 				build1 (INDIRECT_REF, cst_uchar_node,
8423 					fold_convert (cst_uchar_ptr_node,
8424 						      arg2)));
8425       return fold_build2 (MINUS_EXPR, integer_type_node, ind1, ind2);
8426     }
8427 
8428   return 0;
8429 }
8430 
8431 /* Fold function call to builtin signbit, signbitf or signbitl.  Return
8432    NULL_TREE if no simplification can be made.  */
8433 
8434 static tree
8435 fold_builtin_signbit (tree fndecl, tree arglist)
8436 {
8437   tree type = TREE_TYPE (TREE_TYPE (fndecl));
8438   tree arg, temp;
8439 
8440   if (!validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
8441     return NULL_TREE;
8442 
8443   arg = TREE_VALUE (arglist);
8444 
8445   /* If ARG is a compile-time constant, determine the result.  */
8446   if (TREE_CODE (arg) == REAL_CST
8447       && !TREE_CONSTANT_OVERFLOW (arg))
8448     {
8449       REAL_VALUE_TYPE c;
8450 
8451       c = TREE_REAL_CST (arg);
8452       temp = REAL_VALUE_NEGATIVE (c) ? integer_one_node : integer_zero_node;
8453       return fold_convert (type, temp);
8454     }
8455 
8456   /* If ARG is non-negative, the result is always zero.  */
8457   if (tree_expr_nonnegative_p (arg))
8458     return omit_one_operand (type, integer_zero_node, arg);
8459 
8460   /* If ARG's format doesn't have signed zeros, return "arg < 0.0".  */
8461   if (!HONOR_SIGNED_ZEROS (TYPE_MODE (TREE_TYPE (arg))))
8462     return fold_build2 (LT_EXPR, type, arg,
8463 			build_real (TREE_TYPE (arg), dconst0));
8464 
8465   return NULL_TREE;
8466 }
8467 
8468 /* Fold function call to builtin copysign, copysignf or copysignl.
8469    Return NULL_TREE if no simplification can be made.  */
8470 
8471 static tree
8472 fold_builtin_copysign (tree fndecl, tree arglist, tree type)
8473 {
8474   tree arg1, arg2, tem;
8475 
8476   if (!validate_arglist (arglist, REAL_TYPE, REAL_TYPE, VOID_TYPE))
8477     return NULL_TREE;
8478 
8479   arg1 = TREE_VALUE (arglist);
8480   arg2 = TREE_VALUE (TREE_CHAIN (arglist));
8481 
8482   /* copysign(X,X) is X.  */
8483   if (operand_equal_p (arg1, arg2, 0))
8484     return fold_convert (type, arg1);
8485 
8486   /* If ARG1 and ARG2 are compile-time constants, determine the result.  */
8487   if (TREE_CODE (arg1) == REAL_CST
8488       && TREE_CODE (arg2) == REAL_CST
8489       && !TREE_CONSTANT_OVERFLOW (arg1)
8490       && !TREE_CONSTANT_OVERFLOW (arg2))
8491     {
8492       REAL_VALUE_TYPE c1, c2;
8493 
8494       c1 = TREE_REAL_CST (arg1);
8495       c2 = TREE_REAL_CST (arg2);
8496       real_copysign (&c1, &c2);
8497       return build_real (type, c1);
8498       c1.sign = c2.sign;
8499     }
8500 
8501   /* copysign(X, Y) is fabs(X) when Y is always non-negative.
8502      Remember to evaluate Y for side-effects.  */
8503   if (tree_expr_nonnegative_p (arg2))
8504     return omit_one_operand (type,
8505 			     fold_build1 (ABS_EXPR, type, arg1),
8506 			     arg2);
8507 
8508   /* Strip sign changing operations for the first argument.  */
8509   tem = fold_strip_sign_ops (arg1);
8510   if (tem)
8511     {
8512       arglist = tree_cons (NULL_TREE, tem, TREE_CHAIN (arglist));
8513       return build_function_call_expr (fndecl, arglist);
8514     }
8515 
8516   return NULL_TREE;
8517 }
8518 
8519 /* Fold a call to builtin isascii.  */
8520 
8521 static tree
8522 fold_builtin_isascii (tree arglist)
8523 {
8524   if (! validate_arglist (arglist, INTEGER_TYPE, VOID_TYPE))
8525     return 0;
8526   else
8527     {
8528       /* Transform isascii(c) -> ((c & ~0x7f) == 0).  */
8529       tree arg = TREE_VALUE (arglist);
8530 
8531       arg = build2 (BIT_AND_EXPR, integer_type_node, arg,
8532 		    build_int_cst (NULL_TREE,
8533 				   ~ (unsigned HOST_WIDE_INT) 0x7f));
8534       arg = fold_build2 (EQ_EXPR, integer_type_node,
8535 			 arg, integer_zero_node);
8536 
8537       if (in_gimple_form && !TREE_CONSTANT (arg))
8538         return NULL_TREE;
8539       else
8540         return arg;
8541     }
8542 }
8543 
8544 /* Fold a call to builtin toascii.  */
8545 
8546 static tree
8547 fold_builtin_toascii (tree arglist)
8548 {
8549   if (! validate_arglist (arglist, INTEGER_TYPE, VOID_TYPE))
8550     return 0;
8551   else
8552     {
8553       /* Transform toascii(c) -> (c & 0x7f).  */
8554       tree arg = TREE_VALUE (arglist);
8555 
8556       return fold_build2 (BIT_AND_EXPR, integer_type_node, arg,
8557 			  build_int_cst (NULL_TREE, 0x7f));
8558     }
8559 }
8560 
8561 /* Fold a call to builtin isdigit.  */
8562 
8563 static tree
8564 fold_builtin_isdigit (tree arglist)
8565 {
8566   if (! validate_arglist (arglist, INTEGER_TYPE, VOID_TYPE))
8567     return 0;
8568   else
8569     {
8570       /* Transform isdigit(c) -> (unsigned)(c) - '0' <= 9.  */
8571       /* According to the C standard, isdigit is unaffected by locale.
8572 	 However, it definitely is affected by the target character set.  */
8573       tree arg;
8574       unsigned HOST_WIDE_INT target_digit0
8575 	= lang_hooks.to_target_charset ('0');
8576 
8577       if (target_digit0 == 0)
8578 	return NULL_TREE;
8579 
8580       arg = fold_convert (unsigned_type_node, TREE_VALUE (arglist));
8581       arg = build2 (MINUS_EXPR, unsigned_type_node, arg,
8582 		    build_int_cst (unsigned_type_node, target_digit0));
8583       arg = fold_build2 (LE_EXPR, integer_type_node, arg,
8584 			 build_int_cst (unsigned_type_node, 9));
8585       if (in_gimple_form && !TREE_CONSTANT (arg))
8586         return NULL_TREE;
8587       else
8588         return arg;
8589     }
8590 }
8591 
8592 /* Fold a call to fabs, fabsf or fabsl.  */
8593 
8594 static tree
8595 fold_builtin_fabs (tree arglist, tree type)
8596 {
8597   tree arg;
8598 
8599   if (!validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
8600     return 0;
8601 
8602   arg = TREE_VALUE (arglist);
8603   arg = fold_convert (type, arg);
8604   if (TREE_CODE (arg) == REAL_CST)
8605     return fold_abs_const (arg, type);
8606   return fold_build1 (ABS_EXPR, type, arg);
8607 }
8608 
8609 /* Fold a call to abs, labs, llabs or imaxabs.  */
8610 
8611 static tree
8612 fold_builtin_abs (tree arglist, tree type)
8613 {
8614   tree arg;
8615 
8616   if (!validate_arglist (arglist, INTEGER_TYPE, VOID_TYPE))
8617     return 0;
8618 
8619   arg = TREE_VALUE (arglist);
8620   arg = fold_convert (type, arg);
8621   if (TREE_CODE (arg) == INTEGER_CST)
8622     return fold_abs_const (arg, type);
8623   return fold_build1 (ABS_EXPR, type, arg);
8624 }
8625 
8626 /* Fold a call to __builtin_isnan(), __builtin_isinf, __builtin_finite.
8627    EXP is the CALL_EXPR for the call.  */
8628 
8629 static tree
8630 fold_builtin_classify (tree fndecl, tree arglist, int builtin_index)
8631 {
8632   tree type = TREE_TYPE (TREE_TYPE (fndecl));
8633   tree arg;
8634   REAL_VALUE_TYPE r;
8635 
8636   if (!validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
8637     {
8638       /* Check that we have exactly one argument.  */
8639       if (arglist == 0)
8640 	{
8641 	  error ("too few arguments to function %qs",
8642 		 IDENTIFIER_POINTER (DECL_NAME (fndecl)));
8643 	  return error_mark_node;
8644 	}
8645       else if (TREE_CHAIN (arglist) != 0)
8646 	{
8647 	  error ("too many arguments to function %qs",
8648 		 IDENTIFIER_POINTER (DECL_NAME (fndecl)));
8649 	  return error_mark_node;
8650 	}
8651       else
8652 	{
8653 	  error ("non-floating-point argument to function %qs",
8654 		 IDENTIFIER_POINTER (DECL_NAME (fndecl)));
8655 	  return error_mark_node;
8656 	}
8657     }
8658 
8659   arg = TREE_VALUE (arglist);
8660   switch (builtin_index)
8661     {
8662     case BUILT_IN_ISINF:
8663       if (!MODE_HAS_INFINITIES (TYPE_MODE (TREE_TYPE (arg))))
8664         return omit_one_operand (type, integer_zero_node, arg);
8665 
8666       if (TREE_CODE (arg) == REAL_CST)
8667 	{
8668 	  r = TREE_REAL_CST (arg);
8669 	  if (real_isinf (&r))
8670 	    return real_compare (GT_EXPR, &r, &dconst0)
8671 		   ? integer_one_node : integer_minus_one_node;
8672 	  else
8673 	    return integer_zero_node;
8674 	}
8675 
8676       return NULL_TREE;
8677 
8678     case BUILT_IN_FINITE:
8679       if (!MODE_HAS_NANS (TYPE_MODE (TREE_TYPE (arg)))
8680           && !MODE_HAS_INFINITIES (TYPE_MODE (TREE_TYPE (arg))))
8681         return omit_one_operand (type, integer_zero_node, arg);
8682 
8683       if (TREE_CODE (arg) == REAL_CST)
8684 	{
8685 	  r = TREE_REAL_CST (arg);
8686 	  return real_isinf (&r) || real_isnan (&r)
8687 		 ? integer_zero_node : integer_one_node;
8688 	}
8689 
8690       return NULL_TREE;
8691 
8692     case BUILT_IN_ISNAN:
8693       if (!MODE_HAS_NANS (TYPE_MODE (TREE_TYPE (arg))))
8694         return omit_one_operand (type, integer_zero_node, arg);
8695 
8696       if (TREE_CODE (arg) == REAL_CST)
8697 	{
8698 	  r = TREE_REAL_CST (arg);
8699 	  return real_isnan (&r) ? integer_one_node : integer_zero_node;
8700 	}
8701 
8702       arg = builtin_save_expr (arg);
8703       return fold_build2 (UNORDERED_EXPR, type, arg, arg);
8704 
8705     default:
8706       gcc_unreachable ();
8707     }
8708 }
8709 
8710 /* Fold a call to an unordered comparison function such as
8711    __builtin_isgreater().  FNDECL is the FUNCTION_DECL for the function
8712    being called and ARGLIST is the argument list for the call.
8713    UNORDERED_CODE and ORDERED_CODE are comparison codes that give
8714    the opposite of the desired result.  UNORDERED_CODE is used
8715    for modes that can hold NaNs and ORDERED_CODE is used for
8716    the rest.  */
8717 
8718 static tree
8719 fold_builtin_unordered_cmp (tree fndecl, tree arglist,
8720 			    enum tree_code unordered_code,
8721 			    enum tree_code ordered_code)
8722 {
8723   tree type = TREE_TYPE (TREE_TYPE (fndecl));
8724   enum tree_code code;
8725   tree arg0, arg1;
8726   tree type0, type1;
8727   enum tree_code code0, code1;
8728   tree cmp_type = NULL_TREE;
8729 
8730   if (!validate_arglist (arglist, REAL_TYPE, REAL_TYPE, VOID_TYPE))
8731     {
8732       /* Check that we have exactly two arguments.  */
8733       if (arglist == 0 || TREE_CHAIN (arglist) == 0)
8734 	{
8735 	  error ("too few arguments to function %qs",
8736 		 IDENTIFIER_POINTER (DECL_NAME (fndecl)));
8737 	  return error_mark_node;
8738 	}
8739       else if (TREE_CHAIN (TREE_CHAIN (arglist)) != 0)
8740 	{
8741 	  error ("too many arguments to function %qs",
8742 		 IDENTIFIER_POINTER (DECL_NAME (fndecl)));
8743 	  return error_mark_node;
8744 	}
8745     }
8746 
8747   arg0 = TREE_VALUE (arglist);
8748   arg1 = TREE_VALUE (TREE_CHAIN (arglist));
8749 
8750   type0 = TREE_TYPE (arg0);
8751   type1 = TREE_TYPE (arg1);
8752 
8753   code0 = TREE_CODE (type0);
8754   code1 = TREE_CODE (type1);
8755 
8756   if (code0 == REAL_TYPE && code1 == REAL_TYPE)
8757     /* Choose the wider of two real types.  */
8758     cmp_type = TYPE_PRECISION (type0) >= TYPE_PRECISION (type1)
8759       ? type0 : type1;
8760   else if (code0 == REAL_TYPE && code1 == INTEGER_TYPE)
8761     cmp_type = type0;
8762   else if (code0 == INTEGER_TYPE && code1 == REAL_TYPE)
8763     cmp_type = type1;
8764   else
8765     {
8766       error ("non-floating-point argument to function %qs",
8767 		 IDENTIFIER_POINTER (DECL_NAME (fndecl)));
8768       return error_mark_node;
8769     }
8770 
8771   arg0 = fold_convert (cmp_type, arg0);
8772   arg1 = fold_convert (cmp_type, arg1);
8773 
8774   if (unordered_code == UNORDERED_EXPR)
8775     {
8776       if (!MODE_HAS_NANS (TYPE_MODE (TREE_TYPE (arg0))))
8777 	return omit_two_operands (type, integer_zero_node, arg0, arg1);
8778       return fold_build2 (UNORDERED_EXPR, type, arg0, arg1);
8779     }
8780 
8781   code = MODE_HAS_NANS (TYPE_MODE (TREE_TYPE (arg0))) ? unordered_code
8782 						      : ordered_code;
8783   return fold_build1 (TRUTH_NOT_EXPR, type,
8784 		      fold_build2 (code, type, arg0, arg1));
8785 }
8786 #endif /* 0 */
8787 
8788 /* Used by constant folding to simplify calls to builtin functions.  EXP is
8789    the CALL_EXPR of a call to a builtin function.  IGNORE is true if the
8790    result of the function call is ignored.  This function returns NULL_TREE
8791    if no simplification was possible.  */
8792 
8793 static tree
fold_builtin_1(tree fndecl,tree arglist,bool ignore)8794 fold_builtin_1 (tree fndecl, tree arglist, bool ignore)
8795 {
8796   tree type = TREE_TYPE (TREE_TYPE (fndecl));
8797   enum built_in_function fcode;
8798 
8799   if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_MD)
8800     return targetm.fold_builtin (fndecl, arglist, ignore);
8801 
8802   fcode = DECL_FUNCTION_CODE (fndecl);
8803   switch (fcode)
8804     {
8805 #if 0
8806     case BUILT_IN_FPUTS:
8807       return fold_builtin_fputs (arglist, ignore, false, NULL_TREE);
8808 
8809     case BUILT_IN_FPUTS_UNLOCKED:
8810       return fold_builtin_fputs (arglist, ignore, true, NULL_TREE);
8811 
8812     case BUILT_IN_STRSTR:
8813       return fold_builtin_strstr (arglist, type);
8814 
8815     case BUILT_IN_STRCAT:
8816       return fold_builtin_strcat (arglist);
8817 
8818     case BUILT_IN_STRNCAT:
8819       return fold_builtin_strncat (arglist);
8820 
8821     case BUILT_IN_STRSPN:
8822       return fold_builtin_strspn (arglist);
8823 
8824     case BUILT_IN_STRCSPN:
8825       return fold_builtin_strcspn (arglist);
8826 
8827     case BUILT_IN_STRCHR:
8828     case BUILT_IN_INDEX:
8829       return fold_builtin_strchr (arglist, type);
8830 
8831     case BUILT_IN_STRRCHR:
8832     case BUILT_IN_RINDEX:
8833       return fold_builtin_strrchr (arglist, type);
8834 
8835     case BUILT_IN_STRCPY:
8836       return fold_builtin_strcpy (fndecl, arglist, NULL_TREE);
8837 
8838     case BUILT_IN_STRNCPY:
8839       return fold_builtin_strncpy (fndecl, arglist, NULL_TREE);
8840 
8841     case BUILT_IN_STRCMP:
8842       return fold_builtin_strcmp (arglist);
8843 
8844     case BUILT_IN_STRNCMP:
8845       return fold_builtin_strncmp (arglist);
8846 
8847     case BUILT_IN_STRPBRK:
8848       return fold_builtin_strpbrk (arglist, type);
8849 
8850     case BUILT_IN_BCMP:
8851     case BUILT_IN_MEMCMP:
8852       return fold_builtin_memcmp (arglist);
8853 
8854     case BUILT_IN_SPRINTF:
8855       return fold_builtin_sprintf (arglist, ignore);
8856 #endif /* 0 */
8857 
8858     case BUILT_IN_CONSTANT_P:
8859       {
8860 	tree val;
8861 
8862 	val = fold_builtin_constant_p (arglist);
8863 	/* Gimplification will pull the CALL_EXPR for the builtin out of
8864 	   an if condition.  When not optimizing, we'll not CSE it back.
8865 	   To avoid link error types of regressions, return false now.  */
8866 	if (!val && !optimize)
8867 	  val = integer_zero_node;
8868 
8869 	return val;
8870       }
8871 
8872     case BUILT_IN_EXPECT:
8873       return fold_builtin_expect (arglist);
8874 
8875     case BUILT_IN_CLASSIFY_TYPE:
8876       return fold_builtin_classify_type (arglist);
8877 
8878 #if 0
8879     case BUILT_IN_STRLEN:
8880       return fold_builtin_strlen (arglist);
8881 
8882     case BUILT_IN_FABS:
8883     case BUILT_IN_FABSF:
8884     case BUILT_IN_FABSL:
8885       return fold_builtin_fabs (arglist, type);
8886 
8887     case BUILT_IN_ABS:
8888     case BUILT_IN_LABS:
8889     case BUILT_IN_LLABS:
8890     case BUILT_IN_IMAXABS:
8891       return fold_builtin_abs (arglist, type);
8892 
8893     case BUILT_IN_CONJ:
8894     case BUILT_IN_CONJF:
8895     case BUILT_IN_CONJL:
8896       if (validate_arglist (arglist, COMPLEX_TYPE, VOID_TYPE))
8897 	return fold_build1 (CONJ_EXPR, type, TREE_VALUE (arglist));
8898       break;
8899 
8900     case BUILT_IN_CREAL:
8901     case BUILT_IN_CREALF:
8902     case BUILT_IN_CREALL:
8903       if (validate_arglist (arglist, COMPLEX_TYPE, VOID_TYPE))
8904         return non_lvalue (fold_build1 (REALPART_EXPR, type,
8905 					TREE_VALUE (arglist)));
8906       break;
8907 
8908     case BUILT_IN_CIMAG:
8909     case BUILT_IN_CIMAGF:
8910     case BUILT_IN_CIMAGL:
8911       if (validate_arglist (arglist, COMPLEX_TYPE, VOID_TYPE))
8912         return non_lvalue (fold_build1 (IMAGPART_EXPR, type,
8913 					TREE_VALUE (arglist)));
8914       break;
8915 
8916     case BUILT_IN_CABS:
8917     case BUILT_IN_CABSF:
8918     case BUILT_IN_CABSL:
8919       return fold_builtin_cabs (arglist, type);
8920 
8921     case BUILT_IN_SQRT:
8922     case BUILT_IN_SQRTF:
8923     case BUILT_IN_SQRTL:
8924       return fold_builtin_sqrt (arglist, type);
8925 
8926     case BUILT_IN_CBRT:
8927     case BUILT_IN_CBRTF:
8928     case BUILT_IN_CBRTL:
8929       return fold_builtin_cbrt (arglist, type);
8930 
8931     case BUILT_IN_SIN:
8932     case BUILT_IN_SINF:
8933     case BUILT_IN_SINL:
8934       return fold_builtin_sin (arglist);
8935 
8936     case BUILT_IN_COS:
8937     case BUILT_IN_COSF:
8938     case BUILT_IN_COSL:
8939       return fold_builtin_cos (arglist, type, fndecl);
8940 
8941     case BUILT_IN_EXP:
8942     case BUILT_IN_EXPF:
8943     case BUILT_IN_EXPL:
8944       return fold_builtin_exponent (fndecl, arglist, &dconste);
8945 
8946     case BUILT_IN_EXP2:
8947     case BUILT_IN_EXP2F:
8948     case BUILT_IN_EXP2L:
8949       return fold_builtin_exponent (fndecl, arglist, &dconst2);
8950 
8951     case BUILT_IN_EXP10:
8952     case BUILT_IN_EXP10F:
8953     case BUILT_IN_EXP10L:
8954     case BUILT_IN_POW10:
8955     case BUILT_IN_POW10F:
8956     case BUILT_IN_POW10L:
8957       return fold_builtin_exponent (fndecl, arglist, &dconst10);
8958 
8959     case BUILT_IN_LOG:
8960     case BUILT_IN_LOGF:
8961     case BUILT_IN_LOGL:
8962       return fold_builtin_logarithm (fndecl, arglist, &dconste);
8963 
8964     case BUILT_IN_LOG2:
8965     case BUILT_IN_LOG2F:
8966     case BUILT_IN_LOG2L:
8967       return fold_builtin_logarithm (fndecl, arglist, &dconst2);
8968 
8969     case BUILT_IN_LOG10:
8970     case BUILT_IN_LOG10F:
8971     case BUILT_IN_LOG10L:
8972       return fold_builtin_logarithm (fndecl, arglist, &dconst10);
8973 
8974     case BUILT_IN_TAN:
8975     case BUILT_IN_TANF:
8976     case BUILT_IN_TANL:
8977       return fold_builtin_tan (arglist);
8978 
8979     case BUILT_IN_ATAN:
8980     case BUILT_IN_ATANF:
8981     case BUILT_IN_ATANL:
8982       return fold_builtin_atan (arglist, type);
8983 
8984     case BUILT_IN_POW:
8985     case BUILT_IN_POWF:
8986     case BUILT_IN_POWL:
8987       return fold_builtin_pow (fndecl, arglist, type);
8988 
8989     case BUILT_IN_POWI:
8990     case BUILT_IN_POWIF:
8991     case BUILT_IN_POWIL:
8992       return fold_builtin_powi (fndecl, arglist, type);
8993 
8994     case BUILT_IN_INF:
8995     case BUILT_IN_INFF:
8996     case BUILT_IN_INFL:
8997       return fold_builtin_inf (type, true);
8998 
8999     case BUILT_IN_HUGE_VAL:
9000     case BUILT_IN_HUGE_VALF:
9001     case BUILT_IN_HUGE_VALL:
9002       return fold_builtin_inf (type, false);
9003 
9004     case BUILT_IN_NAN:
9005     case BUILT_IN_NANF:
9006     case BUILT_IN_NANL:
9007       return fold_builtin_nan (arglist, type, true);
9008 
9009     case BUILT_IN_NANS:
9010     case BUILT_IN_NANSF:
9011     case BUILT_IN_NANSL:
9012       return fold_builtin_nan (arglist, type, false);
9013 
9014     case BUILT_IN_FLOOR:
9015     case BUILT_IN_FLOORF:
9016     case BUILT_IN_FLOORL:
9017       return fold_builtin_floor (fndecl, arglist);
9018 
9019     case BUILT_IN_CEIL:
9020     case BUILT_IN_CEILF:
9021     case BUILT_IN_CEILL:
9022       return fold_builtin_ceil (fndecl, arglist);
9023 
9024     case BUILT_IN_TRUNC:
9025     case BUILT_IN_TRUNCF:
9026     case BUILT_IN_TRUNCL:
9027       return fold_builtin_trunc (fndecl, arglist);
9028 
9029     case BUILT_IN_ROUND:
9030     case BUILT_IN_ROUNDF:
9031     case BUILT_IN_ROUNDL:
9032       return fold_builtin_round (fndecl, arglist);
9033 
9034     case BUILT_IN_NEARBYINT:
9035     case BUILT_IN_NEARBYINTF:
9036     case BUILT_IN_NEARBYINTL:
9037     case BUILT_IN_RINT:
9038     case BUILT_IN_RINTF:
9039     case BUILT_IN_RINTL:
9040       return fold_trunc_transparent_mathfn (fndecl, arglist);
9041 
9042     case BUILT_IN_LCEIL:
9043     case BUILT_IN_LCEILF:
9044     case BUILT_IN_LCEILL:
9045     case BUILT_IN_LLCEIL:
9046     case BUILT_IN_LLCEILF:
9047     case BUILT_IN_LLCEILL:
9048     case BUILT_IN_LFLOOR:
9049     case BUILT_IN_LFLOORF:
9050     case BUILT_IN_LFLOORL:
9051     case BUILT_IN_LLFLOOR:
9052     case BUILT_IN_LLFLOORF:
9053     case BUILT_IN_LLFLOORL:
9054     case BUILT_IN_LROUND:
9055     case BUILT_IN_LROUNDF:
9056     case BUILT_IN_LROUNDL:
9057     case BUILT_IN_LLROUND:
9058     case BUILT_IN_LLROUNDF:
9059     case BUILT_IN_LLROUNDL:
9060       return fold_builtin_int_roundingfn (fndecl, arglist);
9061 
9062     case BUILT_IN_LRINT:
9063     case BUILT_IN_LRINTF:
9064     case BUILT_IN_LRINTL:
9065     case BUILT_IN_LLRINT:
9066     case BUILT_IN_LLRINTF:
9067     case BUILT_IN_LLRINTL:
9068       return fold_fixed_mathfn (fndecl, arglist);
9069 #endif /* 0 */
9070 
9071     case BUILT_IN_FFS:
9072     case BUILT_IN_FFSL:
9073     case BUILT_IN_FFSLL:
9074     case BUILT_IN_CLZ:
9075     case BUILT_IN_CLZL:
9076     case BUILT_IN_CLZLL:
9077     case BUILT_IN_CTZ:
9078     case BUILT_IN_CTZL:
9079     case BUILT_IN_CTZLL:
9080     case BUILT_IN_POPCOUNT:
9081     case BUILT_IN_POPCOUNTL:
9082     case BUILT_IN_POPCOUNTLL:
9083     case BUILT_IN_PARITY:
9084     case BUILT_IN_PARITYL:
9085     case BUILT_IN_PARITYLL:
9086       return fold_builtin_bitop (fndecl, arglist);
9087 
9088     case BUILT_IN_MEMCPY:
9089       return fold_builtin_memcpy (fndecl, arglist);
9090 
9091 #if 0
9092     case BUILT_IN_MEMPCPY:
9093       return fold_builtin_mempcpy (arglist, type, /*endp=*/1);
9094 
9095     case BUILT_IN_MEMMOVE:
9096       return fold_builtin_memmove (arglist, type);
9097 
9098     case BUILT_IN_SIGNBIT:
9099     case BUILT_IN_SIGNBITF:
9100     case BUILT_IN_SIGNBITL:
9101       return fold_builtin_signbit (fndecl, arglist);
9102 
9103     case BUILT_IN_ISASCII:
9104       return fold_builtin_isascii (arglist);
9105 
9106     case BUILT_IN_TOASCII:
9107       return fold_builtin_toascii (arglist);
9108 
9109     case BUILT_IN_ISDIGIT:
9110       return fold_builtin_isdigit (arglist);
9111 
9112     case BUILT_IN_COPYSIGN:
9113     case BUILT_IN_COPYSIGNF:
9114     case BUILT_IN_COPYSIGNL:
9115       return fold_builtin_copysign (fndecl, arglist, type);
9116 
9117     case BUILT_IN_FINITE:
9118     case BUILT_IN_FINITEF:
9119     case BUILT_IN_FINITEL:
9120       return fold_builtin_classify (fndecl, arglist, BUILT_IN_FINITE);
9121 
9122     case BUILT_IN_ISINF:
9123     case BUILT_IN_ISINFF:
9124     case BUILT_IN_ISINFL:
9125       return fold_builtin_classify (fndecl, arglist, BUILT_IN_ISINF);
9126 
9127     case BUILT_IN_ISNAN:
9128     case BUILT_IN_ISNANF:
9129     case BUILT_IN_ISNANL:
9130       return fold_builtin_classify (fndecl, arglist, BUILT_IN_ISNAN);
9131 
9132     case BUILT_IN_ISGREATER:
9133       return fold_builtin_unordered_cmp (fndecl, arglist, UNLE_EXPR, LE_EXPR);
9134     case BUILT_IN_ISGREATEREQUAL:
9135       return fold_builtin_unordered_cmp (fndecl, arglist, UNLT_EXPR, LT_EXPR);
9136     case BUILT_IN_ISLESS:
9137       return fold_builtin_unordered_cmp (fndecl, arglist, UNGE_EXPR, GE_EXPR);
9138     case BUILT_IN_ISLESSEQUAL:
9139       return fold_builtin_unordered_cmp (fndecl, arglist, UNGT_EXPR, GT_EXPR);
9140     case BUILT_IN_ISLESSGREATER:
9141       return fold_builtin_unordered_cmp (fndecl, arglist, UNEQ_EXPR, EQ_EXPR);
9142     case BUILT_IN_ISUNORDERED:
9143       return fold_builtin_unordered_cmp (fndecl, arglist, UNORDERED_EXPR,
9144 					 NOP_EXPR);
9145 #endif /* 0 */
9146 
9147       /* We do the folding for va_start in the expander.  */
9148     case BUILT_IN_VA_START:
9149       break;
9150 
9151 #if 0
9152     case BUILT_IN_OBJECT_SIZE:
9153       return fold_builtin_object_size (arglist);
9154     case BUILT_IN_MEMCPY_CHK:
9155     case BUILT_IN_MEMPCPY_CHK:
9156     case BUILT_IN_MEMMOVE_CHK:
9157     case BUILT_IN_MEMSET_CHK:
9158       return fold_builtin_memory_chk (fndecl, arglist, NULL_TREE, ignore,
9159 				      DECL_FUNCTION_CODE (fndecl));
9160     case BUILT_IN_STRCPY_CHK:
9161     case BUILT_IN_STPCPY_CHK:
9162       return fold_builtin_stxcpy_chk (fndecl, arglist, NULL_TREE, ignore,
9163 				      DECL_FUNCTION_CODE (fndecl));
9164     case BUILT_IN_STRNCPY_CHK:
9165       return fold_builtin_strncpy_chk (arglist, NULL_TREE);
9166     case BUILT_IN_STRCAT_CHK:
9167       return fold_builtin_strcat_chk (fndecl, arglist);
9168     case BUILT_IN_STRNCAT_CHK:
9169       return fold_builtin_strncat_chk (fndecl, arglist);
9170     case BUILT_IN_SPRINTF_CHK:
9171     case BUILT_IN_VSPRINTF_CHK:
9172       return fold_builtin_sprintf_chk (arglist, DECL_FUNCTION_CODE (fndecl));
9173     case BUILT_IN_SNPRINTF_CHK:
9174     case BUILT_IN_VSNPRINTF_CHK:
9175       return fold_builtin_snprintf_chk (arglist, NULL_TREE,
9176 					DECL_FUNCTION_CODE (fndecl));
9177 
9178     case BUILT_IN_PRINTF:
9179     case BUILT_IN_PRINTF_UNLOCKED:
9180     case BUILT_IN_VPRINTF:
9181     case BUILT_IN_PRINTF_CHK:
9182     case BUILT_IN_VPRINTF_CHK:
9183       return fold_builtin_printf (fndecl, arglist, ignore,
9184 				  DECL_FUNCTION_CODE (fndecl));
9185 
9186     case BUILT_IN_FPRINTF:
9187     case BUILT_IN_FPRINTF_UNLOCKED:
9188     case BUILT_IN_VFPRINTF:
9189     case BUILT_IN_FPRINTF_CHK:
9190     case BUILT_IN_VFPRINTF_CHK:
9191       return fold_builtin_fprintf (fndecl, arglist, ignore,
9192 				   DECL_FUNCTION_CODE (fndecl));
9193 #endif /* 0 */
9194 
9195     default:
9196       break;
9197     }
9198 
9199   return 0;
9200 }
9201 
9202 /* A wrapper function for builtin folding that prevents warnings for
9203    "statement without effect" and the like, caused by removing the
9204    call node earlier than the warning is generated.  */
9205 
9206 tree
fold_builtin(tree fndecl,tree arglist,bool ignore)9207 fold_builtin (tree fndecl, tree arglist, bool ignore)
9208 {
9209   tree exp = fold_builtin_1 (fndecl, arglist, ignore);
9210   if (exp)
9211     {
9212       exp = build1 (NOP_EXPR, TREE_TYPE (exp), exp);
9213       TREE_NO_WARNING (exp) = 1;
9214     }
9215 
9216   return exp;
9217 }
9218 
9219 /* Conveniently construct a function call expression.  */
9220 
9221 tree
build_function_call_expr(tree fn,tree arglist)9222 build_function_call_expr (tree fn, tree arglist)
9223 {
9224   tree call_expr;
9225 
9226   call_expr = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (fn)), fn);
9227   return fold_build3 (CALL_EXPR, TREE_TYPE (TREE_TYPE (fn)),
9228 		      call_expr, arglist, NULL_TREE);
9229 }
9230 
9231 /* This function validates the types of a function call argument list
9232    represented as a tree chain of parameters against a specified list
9233    of tree_codes.  If the last specifier is a 0, that represents an
9234    ellipses, otherwise the last specifier must be a VOID_TYPE.  */
9235 
9236 static int
validate_arglist(tree arglist,...)9237 validate_arglist (tree arglist, ...)
9238 {
9239   enum tree_code code;
9240   int res = 0;
9241   va_list ap;
9242 
9243   va_start (ap, arglist);
9244 
9245   do
9246     {
9247       code = va_arg (ap, enum tree_code);
9248       switch (code)
9249 	{
9250 	case 0:
9251 	  /* This signifies an ellipses, any further arguments are all ok.  */
9252 	  res = 1;
9253 	  goto end;
9254 	case VOID_TYPE:
9255 	  /* This signifies an endlink, if no arguments remain, return
9256 	     true, otherwise return false.  */
9257 	  res = arglist == 0;
9258 	  goto end;
9259 	default:
9260 	  /* If no parameters remain or the parameter's code does not
9261 	     match the specified code, return false.  Otherwise continue
9262 	     checking any remaining arguments.  */
9263 	  if (arglist == 0)
9264 	    goto end;
9265 	  if (code == POINTER_TYPE)
9266 	    {
9267 	      if (! POINTER_TYPE_P (TREE_TYPE (TREE_VALUE (arglist))))
9268 		goto end;
9269 	    }
9270 	  else if (code != TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))))
9271 	    goto end;
9272 	  break;
9273 	}
9274       arglist = TREE_CHAIN (arglist);
9275     }
9276   while (1);
9277 
9278   /* We need gotos here since we can only have one VA_CLOSE in a
9279      function.  */
9280  end: ;
9281   va_end (ap);
9282 
9283   return res;
9284 }
9285 
9286 /* Default target-specific builtin expander that does nothing.  */
9287 
9288 rtx
default_expand_builtin(tree exp ATTRIBUTE_UNUSED,rtx target ATTRIBUTE_UNUSED,rtx subtarget ATTRIBUTE_UNUSED,enum machine_mode mode ATTRIBUTE_UNUSED,int ignore ATTRIBUTE_UNUSED)9289 default_expand_builtin (tree exp ATTRIBUTE_UNUSED,
9290 			rtx target ATTRIBUTE_UNUSED,
9291 			rtx subtarget ATTRIBUTE_UNUSED,
9292 			enum machine_mode mode ATTRIBUTE_UNUSED,
9293 			int ignore ATTRIBUTE_UNUSED)
9294 {
9295   return NULL_RTX;
9296 }
9297 
9298 /* Returns true is EXP represents data that would potentially reside
9299    in a readonly section.  */
9300 
9301 static bool
readonly_data_expr(tree exp)9302 readonly_data_expr (tree exp)
9303 {
9304   STRIP_NOPS (exp);
9305 
9306   if (TREE_CODE (exp) != ADDR_EXPR)
9307     return false;
9308 
9309   exp = get_base_address (TREE_OPERAND (exp, 0));
9310   if (!exp)
9311     return false;
9312 
9313   /* Make sure we call decl_readonly_section only for trees it
9314      can handle (since it returns true for everything it doesn't
9315      understand).  */
9316   if (TREE_CODE (exp) == STRING_CST
9317       || TREE_CODE (exp) == CONSTRUCTOR
9318       || (TREE_CODE (exp) == VAR_DECL && TREE_STATIC (exp)))
9319     return decl_readonly_section (exp, 0);
9320   else
9321     return false;
9322 }
9323 
9324 #if 0
9325 /* Simplify a call to the strstr builtin.
9326 
9327    Return 0 if no simplification was possible, otherwise return the
9328    simplified form of the call as a tree.
9329 
9330    The simplified form may be a constant or other expression which
9331    computes the same value, but in a more efficient manner (including
9332    calls to other builtin functions).
9333 
9334    The call may contain arguments which need to be evaluated, but
9335    which are not useful to determine the result of the call.  In
9336    this case we return a chain of COMPOUND_EXPRs.  The LHS of each
9337    COMPOUND_EXPR will be an argument which must be evaluated.
9338    COMPOUND_EXPRs are chained through their RHS.  The RHS of the last
9339    COMPOUND_EXPR in the chain will contain the tree for the simplified
9340    form of the builtin function call.  */
9341 
9342 static tree
9343 fold_builtin_strstr (tree arglist, tree type)
9344 {
9345   if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
9346     return 0;
9347   else
9348     {
9349       tree s1 = TREE_VALUE (arglist), s2 = TREE_VALUE (TREE_CHAIN (arglist));
9350       tree fn;
9351       const char *p1, *p2;
9352 
9353       p2 = c_getstr (s2);
9354       if (p2 == NULL)
9355 	return 0;
9356 
9357       p1 = c_getstr (s1);
9358       if (p1 != NULL)
9359 	{
9360 	  const char *r = strstr (p1, p2);
9361 	  tree tem;
9362 
9363 	  if (r == NULL)
9364 	    return build_int_cst (TREE_TYPE (s1), 0);
9365 
9366 	  /* Return an offset into the constant string argument.  */
9367 	  tem = fold_build2 (PLUS_EXPR, TREE_TYPE (s1),
9368 			     s1, build_int_cst (TREE_TYPE (s1), r - p1));
9369 	  return fold_convert (type, tem);
9370 	}
9371 
9372       /* The argument is const char *, and the result is char *, so we need
9373 	 a type conversion here to avoid a warning.  */
9374       if (p2[0] == '\0')
9375 	return fold_convert (type, s1);
9376 
9377       if (p2[1] != '\0')
9378 	return 0;
9379 
9380       fn = implicit_built_in_decls[BUILT_IN_STRCHR];
9381       if (!fn)
9382 	return 0;
9383 
9384       /* New argument list transforming strstr(s1, s2) to
9385 	 strchr(s1, s2[0]).  */
9386       arglist = build_tree_list (NULL_TREE,
9387 				 build_int_cst (NULL_TREE, p2[0]));
9388       arglist = tree_cons (NULL_TREE, s1, arglist);
9389       return build_function_call_expr (fn, arglist);
9390     }
9391 }
9392 
9393 /* Simplify a call to the strchr builtin.
9394 
9395    Return 0 if no simplification was possible, otherwise return the
9396    simplified form of the call as a tree.
9397 
9398    The simplified form may be a constant or other expression which
9399    computes the same value, but in a more efficient manner (including
9400    calls to other builtin functions).
9401 
9402    The call may contain arguments which need to be evaluated, but
9403    which are not useful to determine the result of the call.  In
9404    this case we return a chain of COMPOUND_EXPRs.  The LHS of each
9405    COMPOUND_EXPR will be an argument which must be evaluated.
9406    COMPOUND_EXPRs are chained through their RHS.  The RHS of the last
9407    COMPOUND_EXPR in the chain will contain the tree for the simplified
9408    form of the builtin function call.  */
9409 
9410 static tree
9411 fold_builtin_strchr (tree arglist, tree type)
9412 {
9413   if (!validate_arglist (arglist, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
9414     return 0;
9415   else
9416     {
9417       tree s1 = TREE_VALUE (arglist), s2 = TREE_VALUE (TREE_CHAIN (arglist));
9418       const char *p1;
9419 
9420       if (TREE_CODE (s2) != INTEGER_CST)
9421 	return 0;
9422 
9423       p1 = c_getstr (s1);
9424       if (p1 != NULL)
9425 	{
9426 	  char c;
9427 	  const char *r;
9428 	  tree tem;
9429 
9430 	  if (target_char_cast (s2, &c))
9431 	    return 0;
9432 
9433 	  r = strchr (p1, c);
9434 
9435 	  if (r == NULL)
9436 	    return build_int_cst (TREE_TYPE (s1), 0);
9437 
9438 	  /* Return an offset into the constant string argument.  */
9439 	  tem = fold_build2 (PLUS_EXPR, TREE_TYPE (s1),
9440 			     s1, build_int_cst (TREE_TYPE (s1), r - p1));
9441 	  return fold_convert (type, tem);
9442 	}
9443       return 0;
9444     }
9445 }
9446 
9447 /* Simplify a call to the strrchr builtin.
9448 
9449    Return 0 if no simplification was possible, otherwise return the
9450    simplified form of the call as a tree.
9451 
9452    The simplified form may be a constant or other expression which
9453    computes the same value, but in a more efficient manner (including
9454    calls to other builtin functions).
9455 
9456    The call may contain arguments which need to be evaluated, but
9457    which are not useful to determine the result of the call.  In
9458    this case we return a chain of COMPOUND_EXPRs.  The LHS of each
9459    COMPOUND_EXPR will be an argument which must be evaluated.
9460    COMPOUND_EXPRs are chained through their RHS.  The RHS of the last
9461    COMPOUND_EXPR in the chain will contain the tree for the simplified
9462    form of the builtin function call.  */
9463 
9464 static tree
9465 fold_builtin_strrchr (tree arglist, tree type)
9466 {
9467   if (!validate_arglist (arglist, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
9468     return 0;
9469   else
9470     {
9471       tree s1 = TREE_VALUE (arglist), s2 = TREE_VALUE (TREE_CHAIN (arglist));
9472       tree fn;
9473       const char *p1;
9474 
9475       if (TREE_CODE (s2) != INTEGER_CST)
9476 	return 0;
9477 
9478       p1 = c_getstr (s1);
9479       if (p1 != NULL)
9480 	{
9481 	  char c;
9482 	  const char *r;
9483 	  tree tem;
9484 
9485 	  if (target_char_cast (s2, &c))
9486 	    return 0;
9487 
9488 	  r = strrchr (p1, c);
9489 
9490 	  if (r == NULL)
9491 	    return build_int_cst (TREE_TYPE (s1), 0);
9492 
9493 	  /* Return an offset into the constant string argument.  */
9494 	  tem = fold_build2 (PLUS_EXPR, TREE_TYPE (s1),
9495 			     s1, build_int_cst (TREE_TYPE (s1), r - p1));
9496 	  return fold_convert (type, tem);
9497 	}
9498 
9499       if (! integer_zerop (s2))
9500 	return 0;
9501 
9502       fn = implicit_built_in_decls[BUILT_IN_STRCHR];
9503       if (!fn)
9504 	return 0;
9505 
9506       /* Transform strrchr(s1, '\0') to strchr(s1, '\0').  */
9507       return build_function_call_expr (fn, arglist);
9508     }
9509 }
9510 
9511 /* Simplify a call to the strpbrk builtin.
9512 
9513    Return 0 if no simplification was possible, otherwise return the
9514    simplified form of the call as a tree.
9515 
9516    The simplified form may be a constant or other expression which
9517    computes the same value, but in a more efficient manner (including
9518    calls to other builtin functions).
9519 
9520    The call may contain arguments which need to be evaluated, but
9521    which are not useful to determine the result of the call.  In
9522    this case we return a chain of COMPOUND_EXPRs.  The LHS of each
9523    COMPOUND_EXPR will be an argument which must be evaluated.
9524    COMPOUND_EXPRs are chained through their RHS.  The RHS of the last
9525    COMPOUND_EXPR in the chain will contain the tree for the simplified
9526    form of the builtin function call.  */
9527 
9528 static tree
9529 fold_builtin_strpbrk (tree arglist, tree type)
9530 {
9531   if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
9532     return 0;
9533   else
9534     {
9535       tree s1 = TREE_VALUE (arglist), s2 = TREE_VALUE (TREE_CHAIN (arglist));
9536       tree fn;
9537       const char *p1, *p2;
9538 
9539       p2 = c_getstr (s2);
9540       if (p2 == NULL)
9541 	return 0;
9542 
9543       p1 = c_getstr (s1);
9544       if (p1 != NULL)
9545 	{
9546 	  const char *r = strpbrk (p1, p2);
9547 	  tree tem;
9548 
9549 	  if (r == NULL)
9550 	    return build_int_cst (TREE_TYPE (s1), 0);
9551 
9552 	  /* Return an offset into the constant string argument.  */
9553 	  tem = fold_build2 (PLUS_EXPR, TREE_TYPE (s1),
9554 			     s1, build_int_cst (TREE_TYPE (s1), r - p1));
9555 	  return fold_convert (type, tem);
9556 	}
9557 
9558       if (p2[0] == '\0')
9559 	/* strpbrk(x, "") == NULL.
9560 	   Evaluate and ignore s1 in case it had side-effects.  */
9561 	return omit_one_operand (TREE_TYPE (s1), integer_zero_node, s1);
9562 
9563       if (p2[1] != '\0')
9564 	return 0;  /* Really call strpbrk.  */
9565 
9566       fn = implicit_built_in_decls[BUILT_IN_STRCHR];
9567       if (!fn)
9568 	return 0;
9569 
9570       /* New argument list transforming strpbrk(s1, s2) to
9571 	 strchr(s1, s2[0]).  */
9572       arglist = build_tree_list (NULL_TREE,
9573 				 build_int_cst (NULL_TREE, p2[0]));
9574       arglist = tree_cons (NULL_TREE, s1, arglist);
9575       return build_function_call_expr (fn, arglist);
9576     }
9577 }
9578 
9579 /* Simplify a call to the strcat builtin.
9580 
9581    Return 0 if no simplification was possible, otherwise return the
9582    simplified form of the call as a tree.
9583 
9584    The simplified form may be a constant or other expression which
9585    computes the same value, but in a more efficient manner (including
9586    calls to other builtin functions).
9587 
9588    The call may contain arguments which need to be evaluated, but
9589    which are not useful to determine the result of the call.  In
9590    this case we return a chain of COMPOUND_EXPRs.  The LHS of each
9591    COMPOUND_EXPR will be an argument which must be evaluated.
9592    COMPOUND_EXPRs are chained through their RHS.  The RHS of the last
9593    COMPOUND_EXPR in the chain will contain the tree for the simplified
9594    form of the builtin function call.  */
9595 
9596 static tree
9597 fold_builtin_strcat (tree arglist)
9598 {
9599   if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
9600     return 0;
9601   else
9602     {
9603       tree dst = TREE_VALUE (arglist),
9604 	src = TREE_VALUE (TREE_CHAIN (arglist));
9605       const char *p = c_getstr (src);
9606 
9607       /* If the string length is zero, return the dst parameter.  */
9608       if (p && *p == '\0')
9609 	return dst;
9610 
9611       return 0;
9612     }
9613 }
9614 
9615 /* Simplify a call to the strncat builtin.
9616 
9617    Return 0 if no simplification was possible, otherwise return the
9618    simplified form of the call as a tree.
9619 
9620    The simplified form may be a constant or other expression which
9621    computes the same value, but in a more efficient manner (including
9622    calls to other builtin functions).
9623 
9624    The call may contain arguments which need to be evaluated, but
9625    which are not useful to determine the result of the call.  In
9626    this case we return a chain of COMPOUND_EXPRs.  The LHS of each
9627    COMPOUND_EXPR will be an argument which must be evaluated.
9628    COMPOUND_EXPRs are chained through their RHS.  The RHS of the last
9629    COMPOUND_EXPR in the chain will contain the tree for the simplified
9630    form of the builtin function call.  */
9631 
9632 static tree
9633 fold_builtin_strncat (tree arglist)
9634 {
9635   if (!validate_arglist (arglist,
9636 			 POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
9637     return 0;
9638   else
9639     {
9640       tree dst = TREE_VALUE (arglist);
9641       tree src = TREE_VALUE (TREE_CHAIN (arglist));
9642       tree len = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
9643       const char *p = c_getstr (src);
9644 
9645       /* If the requested length is zero, or the src parameter string
9646 	 length is zero, return the dst parameter.  */
9647       if (integer_zerop (len) || (p && *p == '\0'))
9648         return omit_two_operands (TREE_TYPE (dst), dst, src, len);
9649 
9650       /* If the requested len is greater than or equal to the string
9651          length, call strcat.  */
9652       if (TREE_CODE (len) == INTEGER_CST && p
9653 	  && compare_tree_int (len, strlen (p)) >= 0)
9654 	{
9655 	  tree newarglist
9656 	    = tree_cons (NULL_TREE, dst, build_tree_list (NULL_TREE, src));
9657 	  tree fn = implicit_built_in_decls[BUILT_IN_STRCAT];
9658 
9659 	  /* If the replacement _DECL isn't initialized, don't do the
9660 	     transformation.  */
9661 	  if (!fn)
9662 	    return 0;
9663 
9664 	  return build_function_call_expr (fn, newarglist);
9665 	}
9666       return 0;
9667     }
9668 }
9669 
9670 /* Simplify a call to the strspn builtin.
9671 
9672    Return 0 if no simplification was possible, otherwise return the
9673    simplified form of the call as a tree.
9674 
9675    The simplified form may be a constant or other expression which
9676    computes the same value, but in a more efficient manner (including
9677    calls to other builtin functions).
9678 
9679    The call may contain arguments which need to be evaluated, but
9680    which are not useful to determine the result of the call.  In
9681    this case we return a chain of COMPOUND_EXPRs.  The LHS of each
9682    COMPOUND_EXPR will be an argument which must be evaluated.
9683    COMPOUND_EXPRs are chained through their RHS.  The RHS of the last
9684    COMPOUND_EXPR in the chain will contain the tree for the simplified
9685    form of the builtin function call.  */
9686 
9687 static tree
9688 fold_builtin_strspn (tree arglist)
9689 {
9690   if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
9691     return 0;
9692   else
9693     {
9694       tree s1 = TREE_VALUE (arglist), s2 = TREE_VALUE (TREE_CHAIN (arglist));
9695       const char *p1 = c_getstr (s1), *p2 = c_getstr (s2);
9696 
9697       /* If both arguments are constants, evaluate at compile-time.  */
9698       if (p1 && p2)
9699 	{
9700 	  const size_t r = strspn (p1, p2);
9701 	  return size_int (r);
9702 	}
9703 
9704       /* If either argument is "", return 0.  */
9705       if ((p1 && *p1 == '\0') || (p2 && *p2 == '\0'))
9706 	/* Evaluate and ignore both arguments in case either one has
9707 	   side-effects.  */
9708 	return omit_two_operands (integer_type_node, integer_zero_node,
9709 				  s1, s2);
9710       return 0;
9711     }
9712 }
9713 
9714 /* Simplify a call to the strcspn builtin.
9715 
9716    Return 0 if no simplification was possible, otherwise return the
9717    simplified form of the call as a tree.
9718 
9719    The simplified form may be a constant or other expression which
9720    computes the same value, but in a more efficient manner (including
9721    calls to other builtin functions).
9722 
9723    The call may contain arguments which need to be evaluated, but
9724    which are not useful to determine the result of the call.  In
9725    this case we return a chain of COMPOUND_EXPRs.  The LHS of each
9726    COMPOUND_EXPR will be an argument which must be evaluated.
9727    COMPOUND_EXPRs are chained through their RHS.  The RHS of the last
9728    COMPOUND_EXPR in the chain will contain the tree for the simplified
9729    form of the builtin function call.  */
9730 
9731 static tree
9732 fold_builtin_strcspn (tree arglist)
9733 {
9734   if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
9735     return 0;
9736   else
9737     {
9738       tree s1 = TREE_VALUE (arglist), s2 = TREE_VALUE (TREE_CHAIN (arglist));
9739       const char *p1 = c_getstr (s1), *p2 = c_getstr (s2);
9740 
9741       /* If both arguments are constants, evaluate at compile-time.  */
9742       if (p1 && p2)
9743 	{
9744 	  const size_t r = strcspn (p1, p2);
9745 	  return size_int (r);
9746 	}
9747 
9748       /* If the first argument is "", return 0.  */
9749       if (p1 && *p1 == '\0')
9750 	{
9751 	  /* Evaluate and ignore argument s2 in case it has
9752 	     side-effects.  */
9753 	  return omit_one_operand (integer_type_node,
9754 				   integer_zero_node, s2);
9755 	}
9756 
9757       /* If the second argument is "", return __builtin_strlen(s1).  */
9758       if (p2 && *p2 == '\0')
9759 	{
9760 	  tree newarglist = build_tree_list (NULL_TREE, s1),
9761 	    fn = implicit_built_in_decls[BUILT_IN_STRLEN];
9762 
9763 	  /* If the replacement _DECL isn't initialized, don't do the
9764 	     transformation.  */
9765 	  if (!fn)
9766 	    return 0;
9767 
9768 	  return build_function_call_expr (fn, newarglist);
9769 	}
9770       return 0;
9771     }
9772 }
9773 
9774 /* Fold a call to the fputs builtin.  IGNORE is true if the value returned
9775    by the builtin will be ignored.  UNLOCKED is true is true if this
9776    actually a call to fputs_unlocked.  If LEN in non-NULL, it represents
9777    the known length of the string.  Return NULL_TREE if no simplification
9778    was possible.  */
9779 
9780 tree
9781 fold_builtin_fputs (tree arglist, bool ignore, bool unlocked, tree len)
9782 {
9783   tree fn;
9784   /* If we're using an unlocked function, assume the other unlocked
9785      functions exist explicitly.  */
9786   tree const fn_fputc = unlocked ? built_in_decls[BUILT_IN_FPUTC_UNLOCKED]
9787     : implicit_built_in_decls[BUILT_IN_FPUTC];
9788   tree const fn_fwrite = unlocked ? built_in_decls[BUILT_IN_FWRITE_UNLOCKED]
9789     : implicit_built_in_decls[BUILT_IN_FWRITE];
9790 
9791   /* If the return value is used, don't do the transformation.  */
9792   if (!ignore)
9793     return 0;
9794 
9795   /* Verify the arguments in the original call.  */
9796   if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
9797     return 0;
9798 
9799   if (! len)
9800     len = c_strlen (TREE_VALUE (arglist), 0);
9801 
9802   /* Get the length of the string passed to fputs.  If the length
9803      can't be determined, punt.  */
9804   if (!len
9805       || TREE_CODE (len) != INTEGER_CST)
9806     return 0;
9807 
9808   switch (compare_tree_int (len, 1))
9809     {
9810     case -1: /* length is 0, delete the call entirely .  */
9811       return omit_one_operand (integer_type_node, integer_zero_node,
9812 			       TREE_VALUE (TREE_CHAIN (arglist)));
9813 
9814     case 0: /* length is 1, call fputc.  */
9815       {
9816 	const char *p = c_getstr (TREE_VALUE (arglist));
9817 
9818 	if (p != NULL)
9819 	  {
9820 	    /* New argument list transforming fputs(string, stream) to
9821 	       fputc(string[0], stream).  */
9822 	    arglist = build_tree_list (NULL_TREE,
9823 				       TREE_VALUE (TREE_CHAIN (arglist)));
9824 	    arglist = tree_cons (NULL_TREE,
9825 				 build_int_cst (NULL_TREE, p[0]),
9826 				 arglist);
9827 	    fn = fn_fputc;
9828 	    break;
9829 	  }
9830       }
9831       /* FALLTHROUGH */
9832     case 1: /* length is greater than 1, call fwrite.  */
9833       {
9834 	tree string_arg;
9835 
9836 	/* If optimizing for size keep fputs.  */
9837 	if (optimize_size)
9838 	  return 0;
9839 	string_arg = TREE_VALUE (arglist);
9840 	/* New argument list transforming fputs(string, stream) to
9841 	   fwrite(string, 1, len, stream).  */
9842 	arglist = build_tree_list (NULL_TREE,
9843 				   TREE_VALUE (TREE_CHAIN (arglist)));
9844 	arglist = tree_cons (NULL_TREE, len, arglist);
9845 	arglist = tree_cons (NULL_TREE, size_one_node, arglist);
9846 	arglist = tree_cons (NULL_TREE, string_arg, arglist);
9847 	fn = fn_fwrite;
9848 	break;
9849       }
9850     default:
9851       gcc_unreachable ();
9852     }
9853 
9854   /* If the replacement _DECL isn't initialized, don't do the
9855      transformation.  */
9856   if (!fn)
9857     return 0;
9858 
9859   /* These optimizations are only performed when the result is ignored,
9860      hence there's no need to cast the result to integer_type_node.  */
9861   return build_function_call_expr (fn, arglist);
9862 }
9863 #endif /* 0 */
9864 
9865 /* Fold the new_arg's arguments (ARGLIST). Returns true if there was an error
9866    produced.  False otherwise.  This is done so that we don't output the error
9867    or warning twice or three times.  */
9868 bool
fold_builtin_next_arg(tree arglist)9869 fold_builtin_next_arg (tree arglist)
9870 {
9871   tree fntype = TREE_TYPE (current_function_decl);
9872 
9873   if (TYPE_ARG_TYPES (fntype) == 0
9874       || (TREE_VALUE (tree_last (TYPE_ARG_TYPES (fntype)))
9875 	  == void_type_node))
9876     {
9877       error ("%<va_start%> used in function with fixed args");
9878       return true;
9879     }
9880   else if (!arglist)
9881     {
9882       /* Evidently an out of date version of <stdarg.h>; can't validate
9883 	 va_start's second argument, but can still work as intended.  */
9884       warning (0, "%<__builtin_next_arg%> called without an argument");
9885       return true;
9886     }
9887   /* We use __builtin_va_start (ap, 0, 0) or __builtin_next_arg (0, 0)
9888      when we checked the arguments and if needed issued a warning.  */
9889   else if (!TREE_CHAIN (arglist)
9890            || !integer_zerop (TREE_VALUE (arglist))
9891            || !integer_zerop (TREE_VALUE (TREE_CHAIN (arglist)))
9892            || TREE_CHAIN (TREE_CHAIN (arglist)))
9893     {
9894       tree last_parm = tree_last (DECL_ARGUMENTS (current_function_decl));
9895       tree arg = TREE_VALUE (arglist);
9896 
9897       if (TREE_CHAIN (arglist))
9898         {
9899           error ("%<va_start%> used with too many arguments");
9900           return true;
9901         }
9902 
9903       /* Strip off all nops for the sake of the comparison.  This
9904 	 is not quite the same as STRIP_NOPS.  It does more.
9905 	 We must also strip off INDIRECT_EXPR for C++ reference
9906 	 parameters.  */
9907       while (TREE_CODE (arg) == NOP_EXPR
9908 	     || TREE_CODE (arg) == CONVERT_EXPR
9909 	     || TREE_CODE (arg) == NON_LVALUE_EXPR
9910 	     || TREE_CODE (arg) == INDIRECT_REF)
9911 	arg = TREE_OPERAND (arg, 0);
9912       if (arg != last_parm)
9913         {
9914 	  /* FIXME: Sometimes with the tree optimizers we can get the
9915 	     not the last argument even though the user used the last
9916 	     argument.  We just warn and set the arg to be the last
9917 	     argument so that we will get wrong-code because of
9918 	     it.  */
9919 	  warning (0, "second parameter of %<va_start%> not last named argument");
9920 	}
9921       /* We want to verify the second parameter just once before the tree
9922          optimizers are run and then avoid keeping it in the tree,
9923          as otherwise we could warn even for correct code like:
9924          void foo (int i, ...)
9925          { va_list ap; i++; va_start (ap, i); va_end (ap); }  */
9926       TREE_VALUE (arglist) = integer_zero_node;
9927       TREE_CHAIN (arglist) = build_tree_list (NULL, integer_zero_node);
9928     }
9929   return false;
9930 }
9931 
9932 
9933 #if 0
9934 /* Simplify a call to the sprintf builtin.
9935 
9936    Return 0 if no simplification was possible, otherwise return the
9937    simplified form of the call as a tree.  If IGNORED is true, it means that
9938    the caller does not use the returned value of the function.  */
9939 
9940 static tree
9941 fold_builtin_sprintf (tree arglist, int ignored)
9942 {
9943   tree call, retval, dest, fmt;
9944   const char *fmt_str = NULL;
9945 
9946   /* Verify the required arguments in the original call.  We deal with two
9947      types of sprintf() calls: 'sprintf (str, fmt)' and
9948      'sprintf (dest, "%s", orig)'.  */
9949   if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE)
9950       && !validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, POINTER_TYPE,
9951 			    VOID_TYPE))
9952     return NULL_TREE;
9953 
9954   /* Get the destination string and the format specifier.  */
9955   dest = TREE_VALUE (arglist);
9956   fmt = TREE_VALUE (TREE_CHAIN (arglist));
9957 
9958   /* Check whether the format is a literal string constant.  */
9959   fmt_str = c_getstr (fmt);
9960   if (fmt_str == NULL)
9961     return NULL_TREE;
9962 
9963   call = NULL_TREE;
9964   retval = NULL_TREE;
9965 
9966   if (!init_target_chars())
9967     return 0;
9968 
9969   /* If the format doesn't contain % args or %%, use strcpy.  */
9970   if (strchr (fmt_str, target_percent) == NULL)
9971     {
9972       tree fn = implicit_built_in_decls[BUILT_IN_STRCPY];
9973 
9974       if (!fn)
9975 	return NULL_TREE;
9976 
9977       /* Convert sprintf (str, fmt) into strcpy (str, fmt) when
9978 	 'format' is known to contain no % formats.  */
9979       arglist = build_tree_list (NULL_TREE, fmt);
9980       arglist = tree_cons (NULL_TREE, dest, arglist);
9981       call = build_function_call_expr (fn, arglist);
9982       if (!ignored)
9983 	retval = build_int_cst (NULL_TREE, strlen (fmt_str));
9984     }
9985 
9986   /* If the format is "%s", use strcpy if the result isn't used.  */
9987   else if (fmt_str && strcmp (fmt_str, target_percent_s) == 0)
9988     {
9989       tree fn, orig;
9990       fn = implicit_built_in_decls[BUILT_IN_STRCPY];
9991 
9992       if (!fn)
9993 	return NULL_TREE;
9994 
9995       /* Convert sprintf (str1, "%s", str2) into strcpy (str1, str2).  */
9996       orig = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
9997       arglist = build_tree_list (NULL_TREE, orig);
9998       arglist = tree_cons (NULL_TREE, dest, arglist);
9999       if (!ignored)
10000 	{
10001 	  retval = c_strlen (orig, 1);
10002 	  if (!retval || TREE_CODE (retval) != INTEGER_CST)
10003 	    return NULL_TREE;
10004 	}
10005       call = build_function_call_expr (fn, arglist);
10006     }
10007 
10008   if (call && retval)
10009     {
10010       retval = convert
10011 	(TREE_TYPE (TREE_TYPE (implicit_built_in_decls[BUILT_IN_SPRINTF])),
10012 	 retval);
10013       return build2 (COMPOUND_EXPR, TREE_TYPE (retval), call, retval);
10014     }
10015   else
10016     return call;
10017 }
10018 
10019 /* Expand a call to __builtin_object_size.  */
10020 
10021 rtx
10022 expand_builtin_object_size (tree exp)
10023 {
10024   tree ost;
10025   int object_size_type;
10026   tree fndecl = get_callee_fndecl (exp);
10027   tree arglist = TREE_OPERAND (exp, 1);
10028   location_t locus = EXPR_LOCATION (exp);
10029 
10030   if (!validate_arglist (arglist, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
10031     {
10032       error ("%Hfirst argument of %D must be a pointer, second integer constant",
10033 	     &locus, fndecl);
10034       expand_builtin_trap ();
10035       return const0_rtx;
10036     }
10037 
10038   ost = TREE_VALUE (TREE_CHAIN (arglist));
10039   STRIP_NOPS (ost);
10040 
10041   if (TREE_CODE (ost) != INTEGER_CST
10042       || tree_int_cst_sgn (ost) < 0
10043       || compare_tree_int (ost, 3) > 0)
10044     {
10045       error ("%Hlast argument of %D is not integer constant between 0 and 3",
10046 	     &locus, fndecl);
10047       expand_builtin_trap ();
10048       return const0_rtx;
10049     }
10050 
10051   object_size_type = tree_low_cst (ost, 0);
10052 
10053   return object_size_type < 2 ? constm1_rtx : const0_rtx;
10054 }
10055 
10056 /* Expand EXP, a call to the __mem{cpy,pcpy,move,set}_chk builtin.
10057    FCODE is the BUILT_IN_* to use.
10058    Return 0 if we failed; the caller should emit a normal call,
10059    otherwise try to get the result in TARGET, if convenient (and in
10060    mode MODE if that's convenient).  */
10061 
10062 static rtx
10063 expand_builtin_memory_chk (tree exp, rtx target, enum machine_mode mode,
10064 			   enum built_in_function fcode)
10065 {
10066   tree arglist = TREE_OPERAND (exp, 1);
10067   tree dest, src, len, size;
10068 
10069   if (!validate_arglist (arglist,
10070 			 POINTER_TYPE,
10071 			 fcode == BUILT_IN_MEMSET_CHK
10072 			 ? INTEGER_TYPE : POINTER_TYPE,
10073 			 INTEGER_TYPE, INTEGER_TYPE, VOID_TYPE))
10074     return 0;
10075 
10076   dest = TREE_VALUE (arglist);
10077   src = TREE_VALUE (TREE_CHAIN (arglist));
10078   len = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
10079   size = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (arglist))));
10080 
10081   if (! host_integerp (size, 1))
10082     return 0;
10083 
10084   if (host_integerp (len, 1) || integer_all_onesp (size))
10085     {
10086       tree fn;
10087 
10088       if (! integer_all_onesp (size) && tree_int_cst_lt (size, len))
10089 	{
10090 	  location_t locus = EXPR_LOCATION (exp);
10091 	  warning (0, "%Hcall to %D will always overflow destination buffer",
10092 		   &locus, get_callee_fndecl (exp));
10093 	  return 0;
10094 	}
10095 
10096       arglist = build_tree_list (NULL_TREE, len);
10097       arglist = tree_cons (NULL_TREE, src, arglist);
10098       arglist = tree_cons (NULL_TREE, dest, arglist);
10099 
10100       fn = NULL_TREE;
10101       /* If __builtin_mem{cpy,pcpy,move,set}_chk is used, assume
10102 	 mem{cpy,pcpy,move,set} is available.  */
10103       switch (fcode)
10104 	{
10105 	case BUILT_IN_MEMCPY_CHK:
10106 	  fn = built_in_decls[BUILT_IN_MEMCPY];
10107 	  break;
10108 	case BUILT_IN_MEMPCPY_CHK:
10109 	  fn = built_in_decls[BUILT_IN_MEMPCPY];
10110 	  break;
10111 	case BUILT_IN_MEMMOVE_CHK:
10112 	  fn = built_in_decls[BUILT_IN_MEMMOVE];
10113 	  break;
10114 	case BUILT_IN_MEMSET_CHK:
10115 	  fn = built_in_decls[BUILT_IN_MEMSET];
10116 	  break;
10117 	default:
10118 	  break;
10119 	}
10120 
10121       if (! fn)
10122 	return 0;
10123 
10124       fn = build_function_call_expr (fn, arglist);
10125       if (TREE_CODE (fn) == CALL_EXPR)
10126 	CALL_EXPR_TAILCALL (fn) = CALL_EXPR_TAILCALL (exp);
10127       return expand_expr (fn, target, mode, EXPAND_NORMAL);
10128     }
10129   else if (fcode == BUILT_IN_MEMSET_CHK)
10130     return 0;
10131   else
10132     {
10133       unsigned int dest_align
10134 	= get_pointer_alignment (dest, BIGGEST_ALIGNMENT);
10135 
10136       /* If DEST is not a pointer type, call the normal function.  */
10137       if (dest_align == 0)
10138 	return 0;
10139 
10140       /* If SRC and DEST are the same (and not volatile), do nothing.  */
10141       if (operand_equal_p (src, dest, 0))
10142 	{
10143 	  tree expr;
10144 
10145 	  if (fcode != BUILT_IN_MEMPCPY_CHK)
10146 	    {
10147 	      /* Evaluate and ignore LEN in case it has side-effects.  */
10148 	      expand_expr (len, const0_rtx, VOIDmode, EXPAND_NORMAL);
10149 	      return expand_expr (dest, target, mode, EXPAND_NORMAL);
10150 	    }
10151 
10152 	  len = fold_convert (TREE_TYPE (dest), len);
10153 	  expr = fold_build2 (PLUS_EXPR, TREE_TYPE (dest), dest, len);
10154 	  return expand_expr (expr, target, mode, EXPAND_NORMAL);
10155 	}
10156 
10157       /* __memmove_chk special case.  */
10158       if (fcode == BUILT_IN_MEMMOVE_CHK)
10159 	{
10160 	  unsigned int src_align
10161 	    = get_pointer_alignment (src, BIGGEST_ALIGNMENT);
10162 
10163 	  if (src_align == 0)
10164 	    return 0;
10165 
10166 	  /* If src is categorized for a readonly section we can use
10167 	     normal __memcpy_chk.  */
10168 	  if (readonly_data_expr (src))
10169 	    {
10170 	      tree fn = built_in_decls[BUILT_IN_MEMCPY_CHK];
10171 	      if (!fn)
10172 		return 0;
10173 	      fn = build_function_call_expr (fn, arglist);
10174 	      if (TREE_CODE (fn) == CALL_EXPR)
10175 		CALL_EXPR_TAILCALL (fn) = CALL_EXPR_TAILCALL (exp);
10176 	      return expand_expr (fn, target, mode, EXPAND_NORMAL);
10177 	    }
10178 	}
10179       return 0;
10180     }
10181 }
10182 
10183 /* Emit warning if a buffer overflow is detected at compile time.  */
10184 
10185 static void
10186 maybe_emit_chk_warning (tree exp, enum built_in_function fcode)
10187 {
10188   int arg_mask, is_strlen = 0;
10189   tree arglist = TREE_OPERAND (exp, 1), a;
10190   tree len, size;
10191   location_t locus;
10192 
10193   switch (fcode)
10194     {
10195     case BUILT_IN_STRCPY_CHK:
10196     case BUILT_IN_STPCPY_CHK:
10197     /* For __strcat_chk the warning will be emitted only if overflowing
10198        by at least strlen (dest) + 1 bytes.  */
10199     case BUILT_IN_STRCAT_CHK:
10200       arg_mask = 6;
10201       is_strlen = 1;
10202       break;
10203     case BUILT_IN_STRNCPY_CHK:
10204       arg_mask = 12;
10205       break;
10206     case BUILT_IN_SNPRINTF_CHK:
10207     case BUILT_IN_VSNPRINTF_CHK:
10208       arg_mask = 10;
10209       break;
10210     default:
10211       gcc_unreachable ();
10212     }
10213 
10214   len = NULL_TREE;
10215   size = NULL_TREE;
10216   for (a = arglist; a && arg_mask; a = TREE_CHAIN (a), arg_mask >>= 1)
10217     if (arg_mask & 1)
10218       {
10219 	if (len)
10220 	  size = a;
10221 	else
10222 	  len = a;
10223       }
10224 
10225   if (!len || !size)
10226     return;
10227 
10228   len = TREE_VALUE (len);
10229   size = TREE_VALUE (size);
10230 
10231   if (! host_integerp (size, 1) || integer_all_onesp (size))
10232     return;
10233 
10234   if (is_strlen)
10235     {
10236       len = c_strlen (len, 1);
10237       if (! len || ! host_integerp (len, 1) || tree_int_cst_lt (len, size))
10238 	return;
10239     }
10240   else if (! host_integerp (len, 1) || ! tree_int_cst_lt (size, len))
10241     return;
10242 
10243   locus = EXPR_LOCATION (exp);
10244   warning (0, "%Hcall to %D will always overflow destination buffer",
10245 	   &locus, get_callee_fndecl (exp));
10246 }
10247 
10248 /* Emit warning if a buffer overflow is detected at compile time
10249    in __sprintf_chk/__vsprintf_chk calls.  */
10250 
10251 static void
10252 maybe_emit_sprintf_chk_warning (tree exp, enum built_in_function fcode)
10253 {
10254   tree arglist = TREE_OPERAND (exp, 1);
10255   tree dest, size, len, fmt, flag;
10256   const char *fmt_str;
10257 
10258   /* Verify the required arguments in the original call.  */
10259   if (! arglist)
10260     return;
10261   dest = TREE_VALUE (arglist);
10262   arglist = TREE_CHAIN (arglist);
10263   if (! arglist)
10264     return;
10265   flag = TREE_VALUE (arglist);
10266   arglist = TREE_CHAIN (arglist);
10267   if (! arglist)
10268     return;
10269   size = TREE_VALUE (arglist);
10270   arglist = TREE_CHAIN (arglist);
10271   if (! arglist)
10272     return;
10273   fmt = TREE_VALUE (arglist);
10274   arglist = TREE_CHAIN (arglist);
10275 
10276   if (! host_integerp (size, 1) || integer_all_onesp (size))
10277     return;
10278 
10279   /* Check whether the format is a literal string constant.  */
10280   fmt_str = c_getstr (fmt);
10281   if (fmt_str == NULL)
10282     return;
10283 
10284   if (!init_target_chars())
10285     return;
10286 
10287   /* If the format doesn't contain % args or %%, we know its size.  */
10288   if (strchr (fmt_str, target_percent) == 0)
10289     len = build_int_cstu (size_type_node, strlen (fmt_str));
10290   /* If the format is "%s" and first ... argument is a string literal,
10291      we know it too.  */
10292   else if (fcode == BUILT_IN_SPRINTF_CHK && strcmp (fmt_str, target_percent_s) == 0)
10293     {
10294       tree arg;
10295 
10296       if (! arglist)
10297 	return;
10298       arg = TREE_VALUE (arglist);
10299       if (! POINTER_TYPE_P (TREE_TYPE (arg)))
10300 	return;
10301 
10302       len = c_strlen (arg, 1);
10303       if (!len || ! host_integerp (len, 1))
10304 	return;
10305     }
10306   else
10307     return;
10308 
10309   if (! tree_int_cst_lt (len, size))
10310     {
10311       location_t locus = EXPR_LOCATION (exp);
10312       warning (0, "%Hcall to %D will always overflow destination buffer",
10313 	       &locus, get_callee_fndecl (exp));
10314     }
10315 }
10316 
10317 /* Fold a call to __builtin_object_size, if possible.  */
10318 
10319 tree
10320 fold_builtin_object_size (tree arglist)
10321 {
10322   tree ptr, ost, ret = 0;
10323   int object_size_type;
10324 
10325   if (!validate_arglist (arglist, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
10326     return 0;
10327 
10328   ptr = TREE_VALUE (arglist);
10329   ost = TREE_VALUE (TREE_CHAIN (arglist));
10330   STRIP_NOPS (ost);
10331 
10332   if (TREE_CODE (ost) != INTEGER_CST
10333       || tree_int_cst_sgn (ost) < 0
10334       || compare_tree_int (ost, 3) > 0)
10335     return 0;
10336 
10337   object_size_type = tree_low_cst (ost, 0);
10338 
10339   /* __builtin_object_size doesn't evaluate side-effects in its arguments;
10340      if there are any side-effects, it returns (size_t) -1 for types 0 and 1
10341      and (size_t) 0 for types 2 and 3.  */
10342   if (TREE_SIDE_EFFECTS (ptr))
10343     return fold_convert (size_type_node,
10344 			 object_size_type < 2
10345 			 ? integer_minus_one_node : integer_zero_node);
10346 
10347   if (TREE_CODE (ptr) == ADDR_EXPR)
10348     ret = build_int_cstu (size_type_node,
10349 			compute_builtin_object_size (ptr, object_size_type));
10350 
10351   else if (TREE_CODE (ptr) == SSA_NAME)
10352     {
10353       unsigned HOST_WIDE_INT bytes;
10354 
10355       /* If object size is not known yet, delay folding until
10356        later.  Maybe subsequent passes will help determining
10357        it.  */
10358       bytes = compute_builtin_object_size (ptr, object_size_type);
10359       if (bytes != (unsigned HOST_WIDE_INT) (object_size_type < 2
10360 					     ? -1 : 0))
10361 	ret = build_int_cstu (size_type_node, bytes);
10362     }
10363 
10364   if (ret)
10365     {
10366       ret = force_fit_type (ret, -1, false, false);
10367       if (TREE_CONSTANT_OVERFLOW (ret))
10368 	ret = 0;
10369     }
10370 
10371   return ret;
10372 }
10373 
10374 /* Fold a call to the __mem{cpy,pcpy,move,set}_chk builtin.
10375    IGNORE is true, if return value can be ignored.  FCODE is the BUILT_IN_*
10376    code of the builtin.  If MAXLEN is not NULL, it is maximum length
10377    passed as third argument.  */
10378 
10379 tree
10380 fold_builtin_memory_chk (tree fndecl, tree arglist, tree maxlen, bool ignore,
10381 			 enum built_in_function fcode)
10382 {
10383   tree dest, src, len, size, fn;
10384 
10385   if (!validate_arglist (arglist,
10386 			 POINTER_TYPE,
10387 			 fcode == BUILT_IN_MEMSET_CHK
10388 			 ? INTEGER_TYPE : POINTER_TYPE,
10389 			 INTEGER_TYPE, INTEGER_TYPE, VOID_TYPE))
10390     return 0;
10391 
10392   dest = TREE_VALUE (arglist);
10393   /* Actually val for __memset_chk, but it doesn't matter.  */
10394   src = TREE_VALUE (TREE_CHAIN (arglist));
10395   len = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
10396   size = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (arglist))));
10397 
10398   /* If SRC and DEST are the same (and not volatile), return DEST
10399      (resp. DEST+LEN for __mempcpy_chk).  */
10400   if (fcode != BUILT_IN_MEMSET_CHK && operand_equal_p (src, dest, 0))
10401     {
10402       if (fcode != BUILT_IN_MEMPCPY_CHK)
10403 	return omit_one_operand (TREE_TYPE (TREE_TYPE (fndecl)), dest, len);
10404       else
10405 	{
10406 	  tree temp = fold_convert (TREE_TYPE (dest), len);
10407 	  temp = fold_build2 (PLUS_EXPR, TREE_TYPE (dest), dest, temp);
10408 	  return fold_convert (TREE_TYPE (TREE_TYPE (fndecl)), temp);
10409 	}
10410     }
10411 
10412   if (! host_integerp (size, 1))
10413     return 0;
10414 
10415   if (! integer_all_onesp (size))
10416     {
10417       if (! host_integerp (len, 1))
10418 	{
10419 	  /* If LEN is not constant, try MAXLEN too.
10420 	     For MAXLEN only allow optimizing into non-_ocs function
10421 	     if SIZE is >= MAXLEN, never convert to __ocs_fail ().  */
10422 	  if (maxlen == NULL_TREE || ! host_integerp (maxlen, 1))
10423 	    {
10424 	      if (fcode == BUILT_IN_MEMPCPY_CHK && ignore)
10425 		{
10426 		  /* (void) __mempcpy_chk () can be optimized into
10427 		     (void) __memcpy_chk ().  */
10428 		  fn = built_in_decls[BUILT_IN_MEMCPY_CHK];
10429 		  if (!fn)
10430 		    return 0;
10431 
10432 		  return build_function_call_expr (fn, arglist);
10433 		}
10434 	      return 0;
10435 	    }
10436 	}
10437       else
10438 	maxlen = len;
10439 
10440       if (tree_int_cst_lt (size, maxlen))
10441 	return 0;
10442     }
10443 
10444   arglist = build_tree_list (NULL_TREE, len);
10445   arglist = tree_cons (NULL_TREE, src, arglist);
10446   arglist = tree_cons (NULL_TREE, dest, arglist);
10447 
10448   fn = NULL_TREE;
10449   /* If __builtin_mem{cpy,pcpy,move,set}_chk is used, assume
10450      mem{cpy,pcpy,move,set} is available.  */
10451   switch (fcode)
10452     {
10453     case BUILT_IN_MEMCPY_CHK:
10454       fn = built_in_decls[BUILT_IN_MEMCPY];
10455       break;
10456     case BUILT_IN_MEMPCPY_CHK:
10457       fn = built_in_decls[BUILT_IN_MEMPCPY];
10458       break;
10459     case BUILT_IN_MEMMOVE_CHK:
10460       fn = built_in_decls[BUILT_IN_MEMMOVE];
10461       break;
10462     case BUILT_IN_MEMSET_CHK:
10463       fn = built_in_decls[BUILT_IN_MEMSET];
10464       break;
10465     default:
10466       break;
10467     }
10468 
10469   if (!fn)
10470     return 0;
10471 
10472   return build_function_call_expr (fn, arglist);
10473 }
10474 
10475 /* Fold a call to the __st[rp]cpy_chk builtin.
10476    IGNORE is true, if return value can be ignored.  FCODE is the BUILT_IN_*
10477    code of the builtin.  If MAXLEN is not NULL, it is maximum length of
10478    strings passed as second argument.  */
10479 
10480 tree
10481 fold_builtin_stxcpy_chk (tree fndecl, tree arglist, tree maxlen, bool ignore,
10482 			 enum built_in_function fcode)
10483 {
10484   tree dest, src, size, len, fn;
10485 
10486   if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE,
10487 			 VOID_TYPE))
10488     return 0;
10489 
10490   dest = TREE_VALUE (arglist);
10491   src = TREE_VALUE (TREE_CHAIN (arglist));
10492   size = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
10493 
10494   /* If SRC and DEST are the same (and not volatile), return DEST.  */
10495   if (fcode == BUILT_IN_STRCPY_CHK && operand_equal_p (src, dest, 0))
10496     return fold_convert (TREE_TYPE (TREE_TYPE (fndecl)), dest);
10497 
10498   if (! host_integerp (size, 1))
10499     return 0;
10500 
10501   if (! integer_all_onesp (size))
10502     {
10503       len = c_strlen (src, 1);
10504       if (! len || ! host_integerp (len, 1))
10505 	{
10506 	  /* If LEN is not constant, try MAXLEN too.
10507 	     For MAXLEN only allow optimizing into non-_ocs function
10508 	     if SIZE is >= MAXLEN, never convert to __ocs_fail ().  */
10509 	  if (maxlen == NULL_TREE || ! host_integerp (maxlen, 1))
10510 	    {
10511 	      if (fcode == BUILT_IN_STPCPY_CHK)
10512 		{
10513 		  if (! ignore)
10514 		    return 0;
10515 
10516 		  /* If return value of __stpcpy_chk is ignored,
10517 		     optimize into __strcpy_chk.  */
10518 		  fn = built_in_decls[BUILT_IN_STRCPY_CHK];
10519 		  if (!fn)
10520 		    return 0;
10521 
10522 		  return build_function_call_expr (fn, arglist);
10523 		}
10524 
10525 	      if (! len || TREE_SIDE_EFFECTS (len))
10526 		return 0;
10527 
10528 	      /* If c_strlen returned something, but not a constant,
10529 		 transform __strcpy_chk into __memcpy_chk.  */
10530 	      fn = built_in_decls[BUILT_IN_MEMCPY_CHK];
10531 	      if (!fn)
10532 		return 0;
10533 
10534 	      len = size_binop (PLUS_EXPR, len, ssize_int (1));
10535 	      arglist = build_tree_list (NULL_TREE, size);
10536 	      arglist = tree_cons (NULL_TREE, len, arglist);
10537 	      arglist = tree_cons (NULL_TREE, src, arglist);
10538 	      arglist = tree_cons (NULL_TREE, dest, arglist);
10539 	      return fold_convert (TREE_TYPE (TREE_TYPE (fndecl)),
10540 				   build_function_call_expr (fn, arglist));
10541 	    }
10542 	}
10543       else
10544 	maxlen = len;
10545 
10546       if (! tree_int_cst_lt (maxlen, size))
10547 	return 0;
10548     }
10549 
10550   arglist = build_tree_list (NULL_TREE, src);
10551   arglist = tree_cons (NULL_TREE, dest, arglist);
10552 
10553   /* If __builtin_st{r,p}cpy_chk is used, assume st{r,p}cpy is available.  */
10554   fn = built_in_decls[fcode == BUILT_IN_STPCPY_CHK
10555 		      ? BUILT_IN_STPCPY : BUILT_IN_STRCPY];
10556   if (!fn)
10557     return 0;
10558 
10559   return build_function_call_expr (fn, arglist);
10560 }
10561 
10562 /* Fold a call to the __strncpy_chk builtin.
10563    If MAXLEN is not NULL, it is maximum length passed as third argument.  */
10564 
10565 tree
10566 fold_builtin_strncpy_chk (tree arglist, tree maxlen)
10567 {
10568   tree dest, src, size, len, fn;
10569 
10570   if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE,
10571 			 INTEGER_TYPE, VOID_TYPE))
10572     return 0;
10573 
10574   dest = TREE_VALUE (arglist);
10575   src = TREE_VALUE (TREE_CHAIN (arglist));
10576   len = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
10577   size = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (arglist))));
10578 
10579   if (! host_integerp (size, 1))
10580     return 0;
10581 
10582   if (! integer_all_onesp (size))
10583     {
10584       if (! host_integerp (len, 1))
10585 	{
10586 	  /* If LEN is not constant, try MAXLEN too.
10587 	     For MAXLEN only allow optimizing into non-_ocs function
10588 	     if SIZE is >= MAXLEN, never convert to __ocs_fail ().  */
10589 	  if (maxlen == NULL_TREE || ! host_integerp (maxlen, 1))
10590 	    return 0;
10591 	}
10592       else
10593 	maxlen = len;
10594 
10595       if (tree_int_cst_lt (size, maxlen))
10596 	return 0;
10597     }
10598 
10599   arglist = build_tree_list (NULL_TREE, len);
10600   arglist = tree_cons (NULL_TREE, src, arglist);
10601   arglist = tree_cons (NULL_TREE, dest, arglist);
10602 
10603   /* If __builtin_strncpy_chk is used, assume strncpy is available.  */
10604   fn = built_in_decls[BUILT_IN_STRNCPY];
10605   if (!fn)
10606     return 0;
10607 
10608   return build_function_call_expr (fn, arglist);
10609 }
10610 
10611 /* Fold a call to the __strcat_chk builtin FNDECL with ARGLIST.  */
10612 
10613 static tree
10614 fold_builtin_strcat_chk (tree fndecl, tree arglist)
10615 {
10616   tree dest, src, size, fn;
10617   const char *p;
10618 
10619   if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE,
10620 			 VOID_TYPE))
10621     return 0;
10622 
10623   dest = TREE_VALUE (arglist);
10624   src = TREE_VALUE (TREE_CHAIN (arglist));
10625   size = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
10626 
10627   p = c_getstr (src);
10628   /* If the SRC parameter is "", return DEST.  */
10629   if (p && *p == '\0')
10630     return omit_one_operand (TREE_TYPE (TREE_TYPE (fndecl)), dest, src);
10631 
10632   if (! host_integerp (size, 1) || ! integer_all_onesp (size))
10633     return 0;
10634 
10635   arglist = build_tree_list (NULL_TREE, src);
10636   arglist = tree_cons (NULL_TREE, dest, arglist);
10637 
10638   /* If __builtin_strcat_chk is used, assume strcat is available.  */
10639   fn = built_in_decls[BUILT_IN_STRCAT];
10640   if (!fn)
10641     return 0;
10642 
10643   return build_function_call_expr (fn, arglist);
10644 }
10645 
10646 /* Fold a call to the __strncat_chk builtin EXP.  */
10647 
10648 static tree
10649 fold_builtin_strncat_chk (tree fndecl, tree arglist)
10650 {
10651   tree dest, src, size, len, fn;
10652   const char *p;
10653 
10654   if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE,
10655 			 INTEGER_TYPE, VOID_TYPE))
10656     return 0;
10657 
10658   dest = TREE_VALUE (arglist);
10659   src = TREE_VALUE (TREE_CHAIN (arglist));
10660   len = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
10661   size = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (arglist))));
10662 
10663   p = c_getstr (src);
10664   /* If the SRC parameter is "" or if LEN is 0, return DEST.  */
10665   if (p && *p == '\0')
10666     return omit_one_operand (TREE_TYPE (TREE_TYPE (fndecl)), dest, len);
10667   else if (integer_zerop (len))
10668     return omit_one_operand (TREE_TYPE (TREE_TYPE (fndecl)), dest, src);
10669 
10670   if (! host_integerp (size, 1))
10671     return 0;
10672 
10673   if (! integer_all_onesp (size))
10674     {
10675       tree src_len = c_strlen (src, 1);
10676       if (src_len
10677 	  && host_integerp (src_len, 1)
10678 	  && host_integerp (len, 1)
10679 	  && ! tree_int_cst_lt (len, src_len))
10680 	{
10681 	  /* If LEN >= strlen (SRC), optimize into __strcat_chk.  */
10682 	  fn = built_in_decls[BUILT_IN_STRCAT_CHK];
10683 	  if (!fn)
10684 	    return 0;
10685 
10686 	  arglist = build_tree_list (NULL_TREE, size);
10687 	  arglist = tree_cons (NULL_TREE, src, arglist);
10688 	  arglist = tree_cons (NULL_TREE, dest, arglist);
10689 	  return build_function_call_expr (fn, arglist);
10690 	}
10691       return 0;
10692     }
10693 
10694   arglist = build_tree_list (NULL_TREE, len);
10695   arglist = tree_cons (NULL_TREE, src, arglist);
10696   arglist = tree_cons (NULL_TREE, dest, arglist);
10697 
10698   /* If __builtin_strncat_chk is used, assume strncat is available.  */
10699   fn = built_in_decls[BUILT_IN_STRNCAT];
10700   if (!fn)
10701     return 0;
10702 
10703   return build_function_call_expr (fn, arglist);
10704 }
10705 
10706 /* Fold a call to __{,v}sprintf_chk with argument list ARGLIST.  Return 0 if
10707    a normal call should be emitted rather than expanding the function
10708    inline.  FCODE is either BUILT_IN_SPRINTF_CHK or BUILT_IN_VSPRINTF_CHK.  */
10709 
10710 static tree
10711 fold_builtin_sprintf_chk (tree arglist, enum built_in_function fcode)
10712 {
10713   tree dest, size, len, fn, fmt, flag;
10714   const char *fmt_str;
10715 
10716   /* Verify the required arguments in the original call.  */
10717   if (! arglist)
10718     return 0;
10719   dest = TREE_VALUE (arglist);
10720   if (! POINTER_TYPE_P (TREE_TYPE (dest)))
10721     return 0;
10722   arglist = TREE_CHAIN (arglist);
10723   if (! arglist)
10724     return 0;
10725   flag = TREE_VALUE (arglist);
10726   if (TREE_CODE (TREE_TYPE (flag)) != INTEGER_TYPE)
10727     return 0;
10728   arglist = TREE_CHAIN (arglist);
10729   if (! arglist)
10730     return 0;
10731   size = TREE_VALUE (arglist);
10732   if (TREE_CODE (TREE_TYPE (size)) != INTEGER_TYPE)
10733     return 0;
10734   arglist = TREE_CHAIN (arglist);
10735   if (! arglist)
10736     return 0;
10737   fmt = TREE_VALUE (arglist);
10738   if (! POINTER_TYPE_P (TREE_TYPE (fmt)))
10739     return 0;
10740   arglist = TREE_CHAIN (arglist);
10741 
10742   if (! host_integerp (size, 1))
10743     return 0;
10744 
10745   len = NULL_TREE;
10746 
10747   if (!init_target_chars())
10748     return 0;
10749 
10750   /* Check whether the format is a literal string constant.  */
10751   fmt_str = c_getstr (fmt);
10752   if (fmt_str != NULL)
10753     {
10754       /* If the format doesn't contain % args or %%, we know the size.  */
10755       if (strchr (fmt_str, target_percent) == 0)
10756 	{
10757 	  if (fcode != BUILT_IN_SPRINTF_CHK || arglist == NULL_TREE)
10758 	    len = build_int_cstu (size_type_node, strlen (fmt_str));
10759 	}
10760       /* If the format is "%s" and first ... argument is a string literal,
10761 	 we know the size too.  */
10762       else if (fcode == BUILT_IN_SPRINTF_CHK && strcmp (fmt_str, target_percent_s) == 0)
10763 	{
10764 	  tree arg;
10765 
10766 	  if (arglist && !TREE_CHAIN (arglist))
10767 	    {
10768 	      arg = TREE_VALUE (arglist);
10769 	      if (POINTER_TYPE_P (TREE_TYPE (arg)))
10770 		{
10771 		  len = c_strlen (arg, 1);
10772 		  if (! len || ! host_integerp (len, 1))
10773 		    len = NULL_TREE;
10774 		}
10775 	    }
10776 	}
10777     }
10778 
10779   if (! integer_all_onesp (size))
10780     {
10781       if (! len || ! tree_int_cst_lt (len, size))
10782 	return 0;
10783     }
10784 
10785   /* Only convert __{,v}sprintf_chk to {,v}sprintf if flag is 0
10786      or if format doesn't contain % chars or is "%s".  */
10787   if (! integer_zerop (flag))
10788     {
10789       if (fmt_str == NULL)
10790 	return 0;
10791       if (strchr (fmt_str, target_percent) != NULL && strcmp (fmt_str, target_percent_s))
10792 	return 0;
10793     }
10794 
10795   arglist = tree_cons (NULL_TREE, fmt, arglist);
10796   arglist = tree_cons (NULL_TREE, dest, arglist);
10797 
10798   /* If __builtin_{,v}sprintf_chk is used, assume {,v}sprintf is available.  */
10799   fn = built_in_decls[fcode == BUILT_IN_VSPRINTF_CHK
10800 		      ? BUILT_IN_VSPRINTF : BUILT_IN_SPRINTF];
10801   if (!fn)
10802     return 0;
10803 
10804   return build_function_call_expr (fn, arglist);
10805 }
10806 
10807 /* Fold a call to {,v}snprintf with argument list ARGLIST.  Return 0 if
10808    a normal call should be emitted rather than expanding the function
10809    inline.  FCODE is either BUILT_IN_SNPRINTF_CHK or
10810    BUILT_IN_VSNPRINTF_CHK.  If MAXLEN is not NULL, it is maximum length
10811    passed as second argument.  */
10812 
10813 tree
10814 fold_builtin_snprintf_chk (tree arglist, tree maxlen,
10815 			   enum built_in_function fcode)
10816 {
10817   tree dest, size, len, fn, fmt, flag;
10818   const char *fmt_str;
10819 
10820   /* Verify the required arguments in the original call.  */
10821   if (! arglist)
10822     return 0;
10823   dest = TREE_VALUE (arglist);
10824   if (! POINTER_TYPE_P (TREE_TYPE (dest)))
10825     return 0;
10826   arglist = TREE_CHAIN (arglist);
10827   if (! arglist)
10828     return 0;
10829   len = TREE_VALUE (arglist);
10830   if (TREE_CODE (TREE_TYPE (len)) != INTEGER_TYPE)
10831     return 0;
10832   arglist = TREE_CHAIN (arglist);
10833   if (! arglist)
10834     return 0;
10835   flag = TREE_VALUE (arglist);
10836   if (TREE_CODE (TREE_TYPE (len)) != INTEGER_TYPE)
10837     return 0;
10838   arglist = TREE_CHAIN (arglist);
10839   if (! arglist)
10840     return 0;
10841   size = TREE_VALUE (arglist);
10842   if (TREE_CODE (TREE_TYPE (size)) != INTEGER_TYPE)
10843     return 0;
10844   arglist = TREE_CHAIN (arglist);
10845   if (! arglist)
10846     return 0;
10847   fmt = TREE_VALUE (arglist);
10848   if (! POINTER_TYPE_P (TREE_TYPE (fmt)))
10849     return 0;
10850   arglist = TREE_CHAIN (arglist);
10851 
10852   if (! host_integerp (size, 1))
10853     return 0;
10854 
10855   if (! integer_all_onesp (size))
10856     {
10857       if (! host_integerp (len, 1))
10858 	{
10859 	  /* If LEN is not constant, try MAXLEN too.
10860 	     For MAXLEN only allow optimizing into non-_ocs function
10861 	     if SIZE is >= MAXLEN, never convert to __ocs_fail ().  */
10862 	  if (maxlen == NULL_TREE || ! host_integerp (maxlen, 1))
10863 	    return 0;
10864 	}
10865       else
10866 	maxlen = len;
10867 
10868       if (tree_int_cst_lt (size, maxlen))
10869 	return 0;
10870     }
10871 
10872   if (!init_target_chars())
10873     return 0;
10874 
10875   /* Only convert __{,v}snprintf_chk to {,v}snprintf if flag is 0
10876      or if format doesn't contain % chars or is "%s".  */
10877   if (! integer_zerop (flag))
10878     {
10879       fmt_str = c_getstr (fmt);
10880       if (fmt_str == NULL)
10881 	return 0;
10882       if (strchr (fmt_str, target_percent) != NULL && strcmp (fmt_str, target_percent_s))
10883 	return 0;
10884     }
10885 
10886   arglist = tree_cons (NULL_TREE, fmt, arglist);
10887   arglist = tree_cons (NULL_TREE, len, arglist);
10888   arglist = tree_cons (NULL_TREE, dest, arglist);
10889 
10890   /* If __builtin_{,v}snprintf_chk is used, assume {,v}snprintf is
10891      available.  */
10892   fn = built_in_decls[fcode == BUILT_IN_VSNPRINTF_CHK
10893 		      ? BUILT_IN_VSNPRINTF : BUILT_IN_SNPRINTF];
10894   if (!fn)
10895     return 0;
10896 
10897   return build_function_call_expr (fn, arglist);
10898 }
10899 
10900 /* Fold a call to the {,v}printf{,_unlocked} and __{,v}printf_chk builtins.
10901 
10902    Return 0 if no simplification was possible, otherwise return the
10903    simplified form of the call as a tree.  FCODE is the BUILT_IN_*
10904    code of the function to be simplified.  */
10905 
10906 static tree
10907 fold_builtin_printf (tree fndecl, tree arglist, bool ignore,
10908 		     enum built_in_function fcode)
10909 {
10910   tree fmt, fn = NULL_TREE, fn_putchar, fn_puts, arg, call;
10911   const char *fmt_str = NULL;
10912 
10913   /* If the return value is used, don't do the transformation.  */
10914   if (! ignore)
10915     return 0;
10916 
10917   /* Verify the required arguments in the original call.  */
10918   if (fcode == BUILT_IN_PRINTF_CHK || fcode == BUILT_IN_VPRINTF_CHK)
10919     {
10920       tree flag;
10921 
10922       if (! arglist)
10923 	return 0;
10924       flag = TREE_VALUE (arglist);
10925       if (TREE_CODE (TREE_TYPE (flag)) != INTEGER_TYPE
10926 	  || TREE_SIDE_EFFECTS (flag))
10927 	return 0;
10928       arglist = TREE_CHAIN (arglist);
10929     }
10930 
10931   if (! arglist)
10932     return 0;
10933   fmt = TREE_VALUE (arglist);
10934   if (! POINTER_TYPE_P (TREE_TYPE (fmt)))
10935     return 0;
10936   arglist = TREE_CHAIN (arglist);
10937 
10938   /* Check whether the format is a literal string constant.  */
10939   fmt_str = c_getstr (fmt);
10940   if (fmt_str == NULL)
10941     return NULL_TREE;
10942 
10943   if (fcode == BUILT_IN_PRINTF_UNLOCKED)
10944     {
10945       /* If we're using an unlocked function, assume the other
10946 	 unlocked functions exist explicitly.  */
10947       fn_putchar = built_in_decls[BUILT_IN_PUTCHAR_UNLOCKED];
10948       fn_puts = built_in_decls[BUILT_IN_PUTS_UNLOCKED];
10949     }
10950   else
10951     {
10952       fn_putchar = implicit_built_in_decls[BUILT_IN_PUTCHAR];
10953       fn_puts = implicit_built_in_decls[BUILT_IN_PUTS];
10954     }
10955 
10956   if (!init_target_chars())
10957     return 0;
10958 
10959   if (strcmp (fmt_str, target_percent_s) == 0 || strchr (fmt_str, target_percent) == NULL)
10960     {
10961       const char *str;
10962 
10963       if (strcmp (fmt_str, target_percent_s) == 0)
10964 	{
10965 	  if (fcode == BUILT_IN_VPRINTF || fcode == BUILT_IN_VPRINTF_CHK)
10966 	    return 0;
10967 
10968 	  if (! arglist
10969 	      || ! POINTER_TYPE_P (TREE_TYPE (TREE_VALUE (arglist)))
10970 	      || TREE_CHAIN (arglist))
10971 	    return 0;
10972 
10973 	  str = c_getstr (TREE_VALUE (arglist));
10974 	  if (str == NULL)
10975 	    return 0;
10976 	}
10977       else
10978 	{
10979 	  /* The format specifier doesn't contain any '%' characters.  */
10980 	  if (fcode != BUILT_IN_VPRINTF && fcode != BUILT_IN_VPRINTF_CHK
10981 	      && arglist)
10982 	    return 0;
10983 	  str = fmt_str;
10984 	}
10985 
10986       /* If the string was "", printf does nothing.  */
10987       if (str[0] == '\0')
10988 	return build_int_cst (TREE_TYPE (TREE_TYPE (fndecl)), 0);
10989 
10990       /* If the string has length of 1, call putchar.  */
10991       if (str[1] == '\0')
10992 	{
10993 	  /* Given printf("c"), (where c is any one character,)
10994 	     convert "c"[0] to an int and pass that to the replacement
10995 	     function.  */
10996 	  arg = build_int_cst (NULL_TREE, str[0]);
10997 	  arglist = build_tree_list (NULL_TREE, arg);
10998 	  fn = fn_putchar;
10999 	}
11000       else
11001 	{
11002 	  /* If the string was "string\n", call puts("string").  */
11003 	  size_t len = strlen (str);
11004 	  if ((unsigned char)str[len - 1] == target_newline)
11005 	    {
11006 	      /* Create a NUL-terminated string that's one char shorter
11007 		 than the original, stripping off the trailing '\n'.  */
11008 	      char *newstr = alloca (len);
11009 	      memcpy (newstr, str, len - 1);
11010 	      newstr[len - 1] = 0;
11011 
11012 	      arg = build_string_literal (len, newstr);
11013 	      arglist = build_tree_list (NULL_TREE, arg);
11014 	      fn = fn_puts;
11015 	    }
11016 	  else
11017 	    /* We'd like to arrange to call fputs(string,stdout) here,
11018 	       but we need stdout and don't have a way to get it yet.  */
11019 	    return 0;
11020 	}
11021     }
11022 
11023   /* The other optimizations can be done only on the non-va_list variants.  */
11024   else if (fcode == BUILT_IN_VPRINTF || fcode == BUILT_IN_VPRINTF_CHK)
11025     return 0;
11026 
11027   /* If the format specifier was "%s\n", call __builtin_puts(arg).  */
11028   else if (strcmp (fmt_str, target_percent_s_newline) == 0)
11029     {
11030       if (! arglist
11031 	  || ! POINTER_TYPE_P (TREE_TYPE (TREE_VALUE (arglist)))
11032 	  || TREE_CHAIN (arglist))
11033 	return 0;
11034       fn = fn_puts;
11035     }
11036 
11037   /* If the format specifier was "%c", call __builtin_putchar(arg).  */
11038   else if (strcmp (fmt_str, target_percent_c) == 0)
11039     {
11040       if (! arglist
11041 	  || TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))) != INTEGER_TYPE
11042 	  || TREE_CHAIN (arglist))
11043 	return 0;
11044       fn = fn_putchar;
11045     }
11046 
11047   if (!fn)
11048     return 0;
11049 
11050   call = build_function_call_expr (fn, arglist);
11051   return fold_convert (TREE_TYPE (TREE_TYPE (fndecl)), call);
11052 }
11053 
11054 /* Fold a call to the {,v}fprintf{,_unlocked} and __{,v}printf_chk builtins.
11055 
11056    Return 0 if no simplification was possible, otherwise return the
11057    simplified form of the call as a tree.  FCODE is the BUILT_IN_*
11058    code of the function to be simplified.  */
11059 
11060 static tree
11061 fold_builtin_fprintf (tree fndecl, tree arglist, bool ignore,
11062 		      enum built_in_function fcode)
11063 {
11064   tree fp, fmt, fn = NULL_TREE, fn_fputc, fn_fputs, arg, call;
11065   const char *fmt_str = NULL;
11066 
11067   /* If the return value is used, don't do the transformation.  */
11068   if (! ignore)
11069     return 0;
11070 
11071   /* Verify the required arguments in the original call.  */
11072   if (! arglist)
11073     return 0;
11074   fp = TREE_VALUE (arglist);
11075   if (! POINTER_TYPE_P (TREE_TYPE (fp)))
11076     return 0;
11077   arglist = TREE_CHAIN (arglist);
11078 
11079   if (fcode == BUILT_IN_FPRINTF_CHK || fcode == BUILT_IN_VFPRINTF_CHK)
11080     {
11081       tree flag;
11082 
11083       if (! arglist)
11084 	return 0;
11085       flag = TREE_VALUE (arglist);
11086       if (TREE_CODE (TREE_TYPE (flag)) != INTEGER_TYPE
11087 	  || TREE_SIDE_EFFECTS (flag))
11088 	return 0;
11089       arglist = TREE_CHAIN (arglist);
11090     }
11091 
11092   if (! arglist)
11093     return 0;
11094   fmt = TREE_VALUE (arglist);
11095   if (! POINTER_TYPE_P (TREE_TYPE (fmt)))
11096     return 0;
11097   arglist = TREE_CHAIN (arglist);
11098 
11099   /* Check whether the format is a literal string constant.  */
11100   fmt_str = c_getstr (fmt);
11101   if (fmt_str == NULL)
11102     return NULL_TREE;
11103 
11104   if (fcode == BUILT_IN_FPRINTF_UNLOCKED)
11105     {
11106       /* If we're using an unlocked function, assume the other
11107 	 unlocked functions exist explicitly.  */
11108       fn_fputc = built_in_decls[BUILT_IN_FPUTC_UNLOCKED];
11109       fn_fputs = built_in_decls[BUILT_IN_FPUTS_UNLOCKED];
11110     }
11111   else
11112     {
11113       fn_fputc = implicit_built_in_decls[BUILT_IN_FPUTC];
11114       fn_fputs = implicit_built_in_decls[BUILT_IN_FPUTS];
11115     }
11116 
11117   if (!init_target_chars())
11118     return 0;
11119 
11120   /* If the format doesn't contain % args or %%, use strcpy.  */
11121   if (strchr (fmt_str, target_percent) == NULL)
11122     {
11123       if (fcode != BUILT_IN_VFPRINTF && fcode != BUILT_IN_VFPRINTF_CHK
11124 	  && arglist)
11125 	return 0;
11126 
11127       /* If the format specifier was "", fprintf does nothing.  */
11128       if (fmt_str[0] == '\0')
11129 	{
11130 	  /* If FP has side-effects, just wait until gimplification is
11131 	     done.  */
11132 	  if (TREE_SIDE_EFFECTS (fp))
11133 	    return 0;
11134 
11135 	  return build_int_cst (TREE_TYPE (TREE_TYPE (fndecl)), 0);
11136 	}
11137 
11138       /* When "string" doesn't contain %, replace all cases of
11139 	 fprintf (fp, string) with fputs (string, fp).  The fputs
11140 	 builtin will take care of special cases like length == 1.  */
11141       arglist = build_tree_list (NULL_TREE, fp);
11142       arglist = tree_cons (NULL_TREE, fmt, arglist);
11143       fn = fn_fputs;
11144     }
11145 
11146   /* The other optimizations can be done only on the non-va_list variants.  */
11147   else if (fcode == BUILT_IN_VFPRINTF || fcode == BUILT_IN_VFPRINTF_CHK)
11148     return 0;
11149 
11150   /* If the format specifier was "%s", call __builtin_fputs (arg, fp).  */
11151   else if (strcmp (fmt_str, target_percent_s) == 0)
11152     {
11153       if (! arglist
11154 	  || ! POINTER_TYPE_P (TREE_TYPE (TREE_VALUE (arglist)))
11155 	  || TREE_CHAIN (arglist))
11156 	return 0;
11157       arg = TREE_VALUE (arglist);
11158       arglist = build_tree_list (NULL_TREE, fp);
11159       arglist = tree_cons (NULL_TREE, arg, arglist);
11160       fn = fn_fputs;
11161     }
11162 
11163   /* If the format specifier was "%c", call __builtin_fputc (arg, fp).  */
11164   else if (strcmp (fmt_str, target_percent_c) == 0)
11165     {
11166       if (! arglist
11167 	  || TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))) != INTEGER_TYPE
11168 	  || TREE_CHAIN (arglist))
11169 	return 0;
11170       arg = TREE_VALUE (arglist);
11171       arglist = build_tree_list (NULL_TREE, fp);
11172       arglist = tree_cons (NULL_TREE, arg, arglist);
11173       fn = fn_fputc;
11174     }
11175 
11176   if (!fn)
11177     return 0;
11178 
11179   call = build_function_call_expr (fn, arglist);
11180   return fold_convert (TREE_TYPE (TREE_TYPE (fndecl)), call);
11181 }
11182 
11183 /* Initialize format string characters in the target charset.  */
11184 
11185 static bool
11186 init_target_chars (void)
11187 {
11188   static bool init;
11189   if (!init)
11190     {
11191       target_newline = lang_hooks.to_target_charset ('\n');
11192       target_percent = lang_hooks.to_target_charset ('%');
11193       target_c = lang_hooks.to_target_charset ('c');
11194       target_s = lang_hooks.to_target_charset ('s');
11195       if (target_newline == 0 || target_percent == 0 || target_c == 0
11196 	  || target_s == 0)
11197 	return false;
11198 
11199       target_percent_c[0] = target_percent;
11200       target_percent_c[1] = target_c;
11201       target_percent_c[2] = '\0';
11202 
11203       target_percent_s[0] = target_percent;
11204       target_percent_s[1] = target_s;
11205       target_percent_s[2] = '\0';
11206 
11207       target_percent_s_newline[0] = target_percent;
11208       target_percent_s_newline[1] = target_s;
11209       target_percent_s_newline[2] = target_newline;
11210       target_percent_s_newline[3] = '\0';
11211 
11212       init = true;
11213     }
11214   return true;
11215 }
11216 #endif /* 0 */
11217 
11218