OSDN Git Service

292f50dbf5850df2d1e6394b2f2c0b51b565e6b7
[pf3gnuchains/gcc-fork.git] / gcc / builtins.c
1 /* Expand builtin functions.
2    Copyright (C) 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
3    2000, 2001, 2002, 2003, 2004 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, 59 Temple Place - Suite 330, Boston, MA
20 02111-1307, 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
50 #define CALLED_AS_BUILT_IN(NODE) \
51    (!strncmp (IDENTIFIER_POINTER (DECL_NAME (NODE)), "__builtin_", 10))
52
53 #ifndef PAD_VARARGS_DOWN
54 #define PAD_VARARGS_DOWN BYTES_BIG_ENDIAN
55 #endif
56
57 /* Define the names of the builtin function types and codes.  */
58 const char *const built_in_class_names[4]
59   = {"NOT_BUILT_IN", "BUILT_IN_FRONTEND", "BUILT_IN_MD", "BUILT_IN_NORMAL"};
60
61 #define DEF_BUILTIN(X, N, C, T, LT, B, F, NA, AT, IM) #X,
62 const char *const built_in_names[(int) END_BUILTINS] =
63 {
64 #include "builtins.def"
65 };
66 #undef DEF_BUILTIN
67
68 /* Setup an array of _DECL trees, make sure each element is
69    initialized to NULL_TREE.  */
70 tree built_in_decls[(int) END_BUILTINS];
71 /* Declarations used when constructing the builtin implicitly in the compiler.
72    It may be NULL_TREE when this is invalid (for instance runtime is not
73    required to implement the function call in all cases).  */
74 tree implicit_built_in_decls[(int) END_BUILTINS];
75
76 static int get_pointer_alignment (tree, unsigned int);
77 static const char *c_getstr (tree);
78 static rtx c_readstr (const char *, enum machine_mode);
79 static int target_char_cast (tree, char *);
80 static rtx get_memory_rtx (tree);
81 static tree build_string_literal (int, const char *);
82 static int apply_args_size (void);
83 static int apply_result_size (void);
84 #if defined (HAVE_untyped_call) || defined (HAVE_untyped_return)
85 static rtx result_vector (int, rtx);
86 #endif
87 static rtx expand_builtin_setjmp (tree, rtx);
88 static void expand_builtin_update_setjmp_buf (rtx);
89 static void expand_builtin_prefetch (tree);
90 static rtx expand_builtin_apply_args (void);
91 static rtx expand_builtin_apply_args_1 (void);
92 static rtx expand_builtin_apply (rtx, rtx, rtx);
93 static void expand_builtin_return (rtx);
94 static enum type_class type_to_class (tree);
95 static rtx expand_builtin_classify_type (tree);
96 static void expand_errno_check (tree, rtx);
97 static rtx expand_builtin_mathfn (tree, rtx, rtx);
98 static rtx expand_builtin_mathfn_2 (tree, rtx, rtx);
99 static rtx expand_builtin_mathfn_3 (tree, rtx, rtx);
100 static rtx expand_builtin_args_info (tree);
101 static rtx expand_builtin_next_arg (tree);
102 static rtx expand_builtin_va_start (tree);
103 static rtx expand_builtin_va_end (tree);
104 static rtx expand_builtin_va_copy (tree);
105 static rtx expand_builtin_memcmp (tree, tree, rtx, enum machine_mode);
106 static rtx expand_builtin_strcmp (tree, rtx, enum machine_mode);
107 static rtx expand_builtin_strncmp (tree, rtx, enum machine_mode);
108 static rtx builtin_memcpy_read_str (void *, HOST_WIDE_INT, enum machine_mode);
109 static rtx expand_builtin_strcat (tree, rtx, enum machine_mode);
110 static rtx expand_builtin_strncat (tree, rtx, enum machine_mode);
111 static rtx expand_builtin_strspn (tree, rtx, enum machine_mode);
112 static rtx expand_builtin_strcspn (tree, rtx, enum machine_mode);
113 static rtx expand_builtin_memcpy (tree, rtx, enum machine_mode);
114 static rtx expand_builtin_mempcpy (tree, rtx, enum machine_mode, int);
115 static rtx expand_builtin_memmove (tree, rtx, enum machine_mode);
116 static rtx expand_builtin_bcopy (tree);
117 static rtx expand_builtin_strcpy (tree, rtx, enum machine_mode);
118 static rtx expand_builtin_stpcpy (tree, rtx, enum machine_mode);
119 static rtx builtin_strncpy_read_str (void *, HOST_WIDE_INT, enum machine_mode);
120 static rtx expand_builtin_strncpy (tree, rtx, enum machine_mode);
121 static rtx builtin_memset_read_str (void *, HOST_WIDE_INT, enum machine_mode);
122 static rtx builtin_memset_gen_str (void *, HOST_WIDE_INT, enum machine_mode);
123 static rtx expand_builtin_memset (tree, rtx, enum machine_mode);
124 static rtx expand_builtin_bzero (tree);
125 static rtx expand_builtin_strlen (tree, rtx, enum machine_mode);
126 static rtx expand_builtin_strstr (tree, rtx, enum machine_mode);
127 static rtx expand_builtin_strpbrk (tree, rtx, enum machine_mode);
128 static rtx expand_builtin_strchr (tree, rtx, enum machine_mode);
129 static rtx expand_builtin_strrchr (tree, rtx, enum machine_mode);
130 static rtx expand_builtin_alloca (tree, rtx);
131 static rtx expand_builtin_unop (enum machine_mode, tree, rtx, rtx, optab);
132 static rtx expand_builtin_frame_address (tree, tree);
133 static rtx expand_builtin_fputs (tree, rtx, bool);
134 static rtx expand_builtin_printf (tree, rtx, enum machine_mode, bool);
135 static rtx expand_builtin_fprintf (tree, rtx, enum machine_mode, bool);
136 static rtx expand_builtin_sprintf (tree, rtx, enum machine_mode);
137 static tree stabilize_va_list (tree, int);
138 static rtx expand_builtin_expect (tree, rtx);
139 static tree fold_builtin_constant_p (tree);
140 static tree fold_builtin_classify_type (tree);
141 static tree fold_builtin_inf (tree, int);
142 static tree fold_builtin_nan (tree, tree, int);
143 static int validate_arglist (tree, ...);
144 static bool integer_valued_real_p (tree);
145 static tree fold_trunc_transparent_mathfn (tree);
146 static bool readonly_data_expr (tree);
147 static rtx expand_builtin_fabs (tree, rtx, rtx);
148 static rtx expand_builtin_cabs (tree, rtx);
149 static rtx expand_builtin_signbit (tree, rtx);
150 static tree fold_builtin_cabs (tree, tree);
151 static tree fold_builtin_trunc (tree);
152 static tree fold_builtin_floor (tree);
153 static tree fold_builtin_ceil (tree);
154 static tree fold_builtin_round (tree);
155 static tree fold_builtin_bitop (tree);
156 static tree fold_builtin_memcpy (tree);
157 static tree fold_builtin_mempcpy (tree);
158 static tree fold_builtin_memmove (tree);
159 static tree fold_builtin_strchr (tree, bool);
160 static tree fold_builtin_memcmp (tree);
161 static tree fold_builtin_strcmp (tree);
162 static tree fold_builtin_strncmp (tree);
163 static tree fold_builtin_signbit (tree);
164 static tree fold_builtin_copysign (tree, tree);
165 static tree fold_builtin_isascii (tree);
166 static tree fold_builtin_toascii (tree);
167 static tree fold_builtin_isdigit (tree);
168 static tree fold_builtin_fabs (tree, tree);
169 static tree fold_builtin_abs (tree, tree);
170 static tree fold_builtin_unordered_cmp (tree, enum tree_code, enum tree_code);
171 static tree fold_builtin_1 (tree, bool);
172
173 static tree simplify_builtin_memcmp (tree);
174 static tree simplify_builtin_strcmp (tree);
175 static tree simplify_builtin_strncmp (tree);
176 static tree simplify_builtin_strpbrk (tree);
177 static tree simplify_builtin_strstr (tree);
178 static tree simplify_builtin_strchr (tree);
179 static tree simplify_builtin_strrchr (tree);
180 static tree simplify_builtin_strcat (tree);
181 static tree simplify_builtin_strncat (tree);
182 static tree simplify_builtin_strspn (tree);
183 static tree simplify_builtin_strcspn (tree);
184 static void simplify_builtin_next_arg (tree);
185 static void simplify_builtin_va_start (tree);
186 static tree simplify_builtin_sprintf (tree, int);
187
188
189 /* Return the alignment in bits of EXP, a pointer valued expression.
190    But don't return more than MAX_ALIGN no matter what.
191    The alignment returned is, by default, the alignment of the thing that
192    EXP points to.  If it is not a POINTER_TYPE, 0 is returned.
193
194    Otherwise, look at the expression to see if we can do better, i.e., if the
195    expression is actually pointing at an object whose alignment is tighter.  */
196
197 static int
198 get_pointer_alignment (tree exp, unsigned int max_align)
199 {
200   unsigned int align, inner;
201
202   if (TREE_CODE (TREE_TYPE (exp)) != POINTER_TYPE)
203     return 0;
204
205   align = TYPE_ALIGN (TREE_TYPE (TREE_TYPE (exp)));
206   align = MIN (align, max_align);
207
208   while (1)
209     {
210       switch (TREE_CODE (exp))
211         {
212         case NOP_EXPR:
213         case CONVERT_EXPR:
214         case NON_LVALUE_EXPR:
215           exp = TREE_OPERAND (exp, 0);
216           if (TREE_CODE (TREE_TYPE (exp)) != POINTER_TYPE)
217             return align;
218
219           inner = TYPE_ALIGN (TREE_TYPE (TREE_TYPE (exp)));
220           align = MIN (inner, max_align);
221           break;
222
223         case PLUS_EXPR:
224           /* If sum of pointer + int, restrict our maximum alignment to that
225              imposed by the integer.  If not, we can't do any better than
226              ALIGN.  */
227           if (! host_integerp (TREE_OPERAND (exp, 1), 1))
228             return align;
229
230           while (((tree_low_cst (TREE_OPERAND (exp, 1), 1))
231                   & (max_align / BITS_PER_UNIT - 1))
232                  != 0)
233             max_align >>= 1;
234
235           exp = TREE_OPERAND (exp, 0);
236           break;
237
238         case ADDR_EXPR:
239           /* See what we are pointing at and look at its alignment.  */
240           exp = TREE_OPERAND (exp, 0);
241           if (TREE_CODE (exp) == FUNCTION_DECL)
242             align = FUNCTION_BOUNDARY;
243           else if (DECL_P (exp))
244             align = DECL_ALIGN (exp);
245 #ifdef CONSTANT_ALIGNMENT
246           else if (TREE_CODE_CLASS (TREE_CODE (exp)) == 'c')
247             align = CONSTANT_ALIGNMENT (exp, align);
248 #endif
249           return MIN (align, max_align);
250
251         default:
252           return align;
253         }
254     }
255 }
256
257 /* Compute the length of a C string.  TREE_STRING_LENGTH is not the right
258    way, because it could contain a zero byte in the middle.
259    TREE_STRING_LENGTH is the size of the character array, not the string.
260
261    ONLY_VALUE should be nonzero if the result is not going to be emitted
262    into the instruction stream and zero if it is going to be expanded.
263    E.g. with i++ ? "foo" : "bar", if ONLY_VALUE is nonzero, constant 3
264    is returned, otherwise NULL, since
265    len = c_strlen (src, 1); if (len) expand_expr (len, ...); would not
266    evaluate the side-effects.
267
268    The value returned is of type `ssizetype'.
269
270    Unfortunately, string_constant can't access the values of const char
271    arrays with initializers, so neither can we do so here.  */
272
273 tree
274 c_strlen (tree src, int only_value)
275 {
276   tree offset_node;
277   HOST_WIDE_INT offset;
278   int max;
279   const char *ptr;
280
281   STRIP_NOPS (src);
282   if (TREE_CODE (src) == COND_EXPR
283       && (only_value || !TREE_SIDE_EFFECTS (TREE_OPERAND (src, 0))))
284     {
285       tree len1, len2;
286
287       len1 = c_strlen (TREE_OPERAND (src, 1), only_value);
288       len2 = c_strlen (TREE_OPERAND (src, 2), only_value);
289       if (tree_int_cst_equal (len1, len2))
290         return len1;
291     }
292
293   if (TREE_CODE (src) == COMPOUND_EXPR
294       && (only_value || !TREE_SIDE_EFFECTS (TREE_OPERAND (src, 0))))
295     return c_strlen (TREE_OPERAND (src, 1), only_value);
296
297   src = string_constant (src, &offset_node);
298   if (src == 0)
299     return 0;
300
301   max = TREE_STRING_LENGTH (src) - 1;
302   ptr = TREE_STRING_POINTER (src);
303
304   if (offset_node && TREE_CODE (offset_node) != INTEGER_CST)
305     {
306       /* If the string has an internal zero byte (e.g., "foo\0bar"), we can't
307          compute the offset to the following null if we don't know where to
308          start searching for it.  */
309       int i;
310
311       for (i = 0; i < max; i++)
312         if (ptr[i] == 0)
313           return 0;
314
315       /* We don't know the starting offset, but we do know that the string
316          has no internal zero bytes.  We can assume that the offset falls
317          within the bounds of the string; otherwise, the programmer deserves
318          what he gets.  Subtract the offset from the length of the string,
319          and return that.  This would perhaps not be valid if we were dealing
320          with named arrays in addition to literal string constants.  */
321
322       return size_diffop (size_int (max), offset_node);
323     }
324
325   /* We have a known offset into the string.  Start searching there for
326      a null character if we can represent it as a single HOST_WIDE_INT.  */
327   if (offset_node == 0)
328     offset = 0;
329   else if (! host_integerp (offset_node, 0))
330     offset = -1;
331   else
332     offset = tree_low_cst (offset_node, 0);
333
334   /* If the offset is known to be out of bounds, warn, and call strlen at
335      runtime.  */
336   if (offset < 0 || offset > max)
337     {
338       warning ("offset outside bounds of constant string");
339       return 0;
340     }
341
342   /* Use strlen to search for the first zero byte.  Since any strings
343      constructed with build_string will have nulls appended, we win even
344      if we get handed something like (char[4])"abcd".
345
346      Since OFFSET is our starting index into the string, no further
347      calculation is needed.  */
348   return ssize_int (strlen (ptr + offset));
349 }
350
351 /* Return a char pointer for a C string if it is a string constant
352    or sum of string constant and integer constant.  */
353
354 static const char *
355 c_getstr (tree src)
356 {
357   tree offset_node;
358
359   src = string_constant (src, &offset_node);
360   if (src == 0)
361     return 0;
362
363   if (offset_node == 0)
364     return TREE_STRING_POINTER (src);
365   else if (!host_integerp (offset_node, 1)
366            || compare_tree_int (offset_node, TREE_STRING_LENGTH (src) - 1) > 0)
367     return 0;
368
369   return TREE_STRING_POINTER (src) + tree_low_cst (offset_node, 1);
370 }
371
372 /* Return a CONST_INT or CONST_DOUBLE corresponding to target reading
373    GET_MODE_BITSIZE (MODE) bits from string constant STR.  */
374
375 static rtx
376 c_readstr (const char *str, enum machine_mode mode)
377 {
378   HOST_WIDE_INT c[2];
379   HOST_WIDE_INT ch;
380   unsigned int i, j;
381
382   if (GET_MODE_CLASS (mode) != MODE_INT)
383     abort ();
384   c[0] = 0;
385   c[1] = 0;
386   ch = 1;
387   for (i = 0; i < GET_MODE_SIZE (mode); i++)
388     {
389       j = i;
390       if (WORDS_BIG_ENDIAN)
391         j = GET_MODE_SIZE (mode) - i - 1;
392       if (BYTES_BIG_ENDIAN != WORDS_BIG_ENDIAN
393           && GET_MODE_SIZE (mode) > UNITS_PER_WORD)
394         j = j + UNITS_PER_WORD - 2 * (j % UNITS_PER_WORD) - 1;
395       j *= BITS_PER_UNIT;
396       if (j > 2 * HOST_BITS_PER_WIDE_INT)
397         abort ();
398       if (ch)
399         ch = (unsigned char) str[i];
400       c[j / HOST_BITS_PER_WIDE_INT] |= ch << (j % HOST_BITS_PER_WIDE_INT);
401     }
402   return immed_double_const (c[0], c[1], mode);
403 }
404
405 /* Cast a target constant CST to target CHAR and if that value fits into
406    host char type, return zero and put that value into variable pointed by
407    P.  */
408
409 static int
410 target_char_cast (tree cst, char *p)
411 {
412   unsigned HOST_WIDE_INT val, hostval;
413
414   if (!host_integerp (cst, 1)
415       || CHAR_TYPE_SIZE > HOST_BITS_PER_WIDE_INT)
416     return 1;
417
418   val = tree_low_cst (cst, 1);
419   if (CHAR_TYPE_SIZE < HOST_BITS_PER_WIDE_INT)
420     val &= (((unsigned HOST_WIDE_INT) 1) << CHAR_TYPE_SIZE) - 1;
421
422   hostval = val;
423   if (HOST_BITS_PER_CHAR < HOST_BITS_PER_WIDE_INT)
424     hostval &= (((unsigned HOST_WIDE_INT) 1) << HOST_BITS_PER_CHAR) - 1;
425
426   if (val != hostval)
427     return 1;
428
429   *p = hostval;
430   return 0;
431 }
432
433 /* Similar to save_expr, but assumes that arbitrary code is not executed
434    in between the multiple evaluations.  In particular, we assume that a
435    non-addressable local variable will not be modified.  */
436
437 static tree
438 builtin_save_expr (tree exp)
439 {
440   if (TREE_ADDRESSABLE (exp) == 0
441       && (TREE_CODE (exp) == PARM_DECL
442           || (TREE_CODE (exp) == VAR_DECL && !TREE_STATIC (exp))))
443     return exp;
444
445   return save_expr (exp);
446 }
447
448 /* Given TEM, a pointer to a stack frame, follow the dynamic chain COUNT
449    times to get the address of either a higher stack frame, or a return
450    address located within it (depending on FNDECL_CODE).  */
451
452 rtx
453 expand_builtin_return_addr (enum built_in_function fndecl_code, int count,
454                             rtx tem)
455 {
456   int i;
457
458   /* Some machines need special handling before we can access
459      arbitrary frames.  For example, on the sparc, we must first flush
460      all register windows to the stack.  */
461 #ifdef SETUP_FRAME_ADDRESSES
462   if (count > 0)
463     SETUP_FRAME_ADDRESSES ();
464 #endif
465
466   /* On the sparc, the return address is not in the frame, it is in a
467      register.  There is no way to access it off of the current frame
468      pointer, but it can be accessed off the previous frame pointer by
469      reading the value from the register window save area.  */
470 #ifdef RETURN_ADDR_IN_PREVIOUS_FRAME
471   if (fndecl_code == BUILT_IN_RETURN_ADDRESS)
472     count--;
473 #endif
474
475   /* Scan back COUNT frames to the specified frame.  */
476   for (i = 0; i < count; i++)
477     {
478       /* Assume the dynamic chain pointer is in the word that the
479          frame address points to, unless otherwise specified.  */
480 #ifdef DYNAMIC_CHAIN_ADDRESS
481       tem = DYNAMIC_CHAIN_ADDRESS (tem);
482 #endif
483       tem = memory_address (Pmode, tem);
484       tem = gen_rtx_MEM (Pmode, tem);
485       set_mem_alias_set (tem, get_frame_alias_set ());
486       tem = copy_to_reg (tem);
487     }
488
489   /* For __builtin_frame_address, return what we've got.  */
490   if (fndecl_code == BUILT_IN_FRAME_ADDRESS)
491     return tem;
492
493   /* For __builtin_return_address, Get the return address from that
494      frame.  */
495 #ifdef RETURN_ADDR_RTX
496   tem = RETURN_ADDR_RTX (count, tem);
497 #else
498   tem = memory_address (Pmode,
499                         plus_constant (tem, GET_MODE_SIZE (Pmode)));
500   tem = gen_rtx_MEM (Pmode, tem);
501   set_mem_alias_set (tem, get_frame_alias_set ());
502 #endif
503   return tem;
504 }
505
506 /* Alias set used for setjmp buffer.  */
507 static HOST_WIDE_INT setjmp_alias_set = -1;
508
509 /* Construct the leading half of a __builtin_setjmp call.  Control will
510    return to RECEIVER_LABEL.  This is used directly by sjlj exception
511    handling code.  */
512
513 void
514 expand_builtin_setjmp_setup (rtx buf_addr, rtx receiver_label)
515 {
516   enum machine_mode sa_mode = STACK_SAVEAREA_MODE (SAVE_NONLOCAL);
517   rtx stack_save;
518   rtx mem;
519
520   if (setjmp_alias_set == -1)
521     setjmp_alias_set = new_alias_set ();
522
523   buf_addr = convert_memory_address (Pmode, buf_addr);
524
525   buf_addr = force_reg (Pmode, force_operand (buf_addr, NULL_RTX));
526
527   emit_queue ();
528
529   /* We store the frame pointer and the address of receiver_label in
530      the buffer and use the rest of it for the stack save area, which
531      is machine-dependent.  */
532
533   mem = gen_rtx_MEM (Pmode, buf_addr);
534   set_mem_alias_set (mem, setjmp_alias_set);
535   emit_move_insn (mem, targetm.builtin_setjmp_frame_value ());
536
537   mem = gen_rtx_MEM (Pmode, plus_constant (buf_addr, GET_MODE_SIZE (Pmode))),
538   set_mem_alias_set (mem, setjmp_alias_set);
539
540   emit_move_insn (validize_mem (mem),
541                   force_reg (Pmode, gen_rtx_LABEL_REF (Pmode, receiver_label)));
542
543   stack_save = gen_rtx_MEM (sa_mode,
544                             plus_constant (buf_addr,
545                                            2 * GET_MODE_SIZE (Pmode)));
546   set_mem_alias_set (stack_save, setjmp_alias_set);
547   emit_stack_save (SAVE_NONLOCAL, &stack_save, NULL_RTX);
548
549   /* If there is further processing to do, do it.  */
550 #ifdef HAVE_builtin_setjmp_setup
551   if (HAVE_builtin_setjmp_setup)
552     emit_insn (gen_builtin_setjmp_setup (buf_addr));
553 #endif
554
555   /* Tell optimize_save_area_alloca that extra work is going to
556      need to go on during alloca.  */
557   current_function_calls_setjmp = 1;
558
559   /* Set this so all the registers get saved in our frame; we need to be
560      able to copy the saved values for any registers from frames we unwind.  */
561   current_function_has_nonlocal_label = 1;
562 }
563
564 /* Construct the trailing part of a __builtin_setjmp call.
565    This is used directly by sjlj exception handling code.  */
566
567 void
568 expand_builtin_setjmp_receiver (rtx receiver_label ATTRIBUTE_UNUSED)
569 {
570   /* Clobber the FP when we get here, so we have to make sure it's
571      marked as used by this function.  */
572   emit_insn (gen_rtx_USE (VOIDmode, hard_frame_pointer_rtx));
573
574   /* Mark the static chain as clobbered here so life information
575      doesn't get messed up for it.  */
576   emit_insn (gen_rtx_CLOBBER (VOIDmode, static_chain_rtx));
577
578   /* Now put in the code to restore the frame pointer, and argument
579      pointer, if needed.  The code below is from expand_end_bindings
580      in stmt.c; see detailed documentation there.  */
581 #ifdef HAVE_nonlocal_goto
582   if (! HAVE_nonlocal_goto)
583 #endif
584     emit_move_insn (virtual_stack_vars_rtx, hard_frame_pointer_rtx);
585
586 #if ARG_POINTER_REGNUM != HARD_FRAME_POINTER_REGNUM
587   if (fixed_regs[ARG_POINTER_REGNUM])
588     {
589 #ifdef ELIMINABLE_REGS
590       size_t i;
591       static const struct elims {const int from, to;} elim_regs[] = ELIMINABLE_REGS;
592
593       for (i = 0; i < ARRAY_SIZE (elim_regs); i++)
594         if (elim_regs[i].from == ARG_POINTER_REGNUM
595             && elim_regs[i].to == HARD_FRAME_POINTER_REGNUM)
596           break;
597
598       if (i == ARRAY_SIZE (elim_regs))
599 #endif
600         {
601           /* Now restore our arg pointer from the address at which it
602              was saved in our stack frame.  */
603           emit_move_insn (virtual_incoming_args_rtx,
604                           copy_to_reg (get_arg_pointer_save_area (cfun)));
605         }
606     }
607 #endif
608
609 #ifdef HAVE_builtin_setjmp_receiver
610   if (HAVE_builtin_setjmp_receiver)
611     emit_insn (gen_builtin_setjmp_receiver (receiver_label));
612   else
613 #endif
614 #ifdef HAVE_nonlocal_goto_receiver
615     if (HAVE_nonlocal_goto_receiver)
616       emit_insn (gen_nonlocal_goto_receiver ());
617     else
618 #endif
619       { /* Nothing */ }
620
621   /* @@@ This is a kludge.  Not all machine descriptions define a blockage
622      insn, but we must not allow the code we just generated to be reordered
623      by scheduling.  Specifically, the update of the frame pointer must
624      happen immediately, not later.  So emit an ASM_INPUT to act as blockage
625      insn.  */
626   emit_insn (gen_rtx_ASM_INPUT (VOIDmode, ""));
627 }
628
629 /* __builtin_setjmp is passed a pointer to an array of five words (not
630    all will be used on all machines).  It operates similarly to the C
631    library function of the same name, but is more efficient.  Much of
632    the code below (and for longjmp) is copied from the handling of
633    non-local gotos.
634
635    NOTE: This is intended for use by GNAT and the exception handling
636    scheme in the compiler and will only work in the method used by
637    them.  */
638
639 static rtx
640 expand_builtin_setjmp (tree arglist, rtx target)
641 {
642   rtx buf_addr, next_lab, cont_lab;
643
644   if (!validate_arglist (arglist, POINTER_TYPE, VOID_TYPE))
645     return NULL_RTX;
646
647   if (target == 0 || !REG_P (target)
648       || REGNO (target) < FIRST_PSEUDO_REGISTER)
649     target = gen_reg_rtx (TYPE_MODE (integer_type_node));
650
651   buf_addr = expand_expr (TREE_VALUE (arglist), NULL_RTX, VOIDmode, 0);
652
653   next_lab = gen_label_rtx ();
654   cont_lab = gen_label_rtx ();
655
656   expand_builtin_setjmp_setup (buf_addr, next_lab);
657
658   /* Set TARGET to zero and branch to the continue label.  Use emit_jump to
659      ensure that pending stack adjustments are flushed.  */
660   emit_move_insn (target, const0_rtx);
661   emit_jump (cont_lab);
662
663   emit_label (next_lab);
664
665   expand_builtin_setjmp_receiver (next_lab);
666
667   /* Set TARGET to one.  */
668   emit_move_insn (target, const1_rtx);
669   emit_label (cont_lab);
670
671   /* Tell flow about the strange goings on.  Putting `next_lab' on
672      `nonlocal_goto_handler_labels' to indicates that function
673      calls may traverse the arc back to this label.  */
674
675   current_function_has_nonlocal_label = 1;
676   nonlocal_goto_handler_labels
677     = gen_rtx_EXPR_LIST (VOIDmode, next_lab, nonlocal_goto_handler_labels);
678
679   return target;
680 }
681
682 /* __builtin_longjmp is passed a pointer to an array of five words (not
683    all will be used on all machines).  It operates similarly to the C
684    library function of the same name, but is more efficient.  Much of
685    the code below is copied from the handling of non-local gotos.
686
687    NOTE: This is intended for use by GNAT and the exception handling
688    scheme in the compiler and will only work in the method used by
689    them.  */
690
691 void
692 expand_builtin_longjmp (rtx buf_addr, rtx value)
693 {
694   rtx fp, lab, stack, insn, last;
695   enum machine_mode sa_mode = STACK_SAVEAREA_MODE (SAVE_NONLOCAL);
696
697   if (setjmp_alias_set == -1)
698     setjmp_alias_set = new_alias_set ();
699
700   buf_addr = convert_memory_address (Pmode, buf_addr);
701
702   buf_addr = force_reg (Pmode, buf_addr);
703
704   /* We used to store value in static_chain_rtx, but that fails if pointers
705      are smaller than integers.  We instead require that the user must pass
706      a second argument of 1, because that is what builtin_setjmp will
707      return.  This also makes EH slightly more efficient, since we are no
708      longer copying around a value that we don't care about.  */
709   if (value != const1_rtx)
710     abort ();
711
712   current_function_calls_longjmp = 1;
713
714   last = get_last_insn ();
715 #ifdef HAVE_builtin_longjmp
716   if (HAVE_builtin_longjmp)
717     emit_insn (gen_builtin_longjmp (buf_addr));
718   else
719 #endif
720     {
721       fp = gen_rtx_MEM (Pmode, buf_addr);
722       lab = gen_rtx_MEM (Pmode, plus_constant (buf_addr,
723                                                GET_MODE_SIZE (Pmode)));
724
725       stack = gen_rtx_MEM (sa_mode, plus_constant (buf_addr,
726                                                    2 * GET_MODE_SIZE (Pmode)));
727       set_mem_alias_set (fp, setjmp_alias_set);
728       set_mem_alias_set (lab, setjmp_alias_set);
729       set_mem_alias_set (stack, setjmp_alias_set);
730
731       /* Pick up FP, label, and SP from the block and jump.  This code is
732          from expand_goto in stmt.c; see there for detailed comments.  */
733 #if HAVE_nonlocal_goto
734       if (HAVE_nonlocal_goto)
735         /* We have to pass a value to the nonlocal_goto pattern that will
736            get copied into the static_chain pointer, but it does not matter
737            what that value is, because builtin_setjmp does not use it.  */
738         emit_insn (gen_nonlocal_goto (value, lab, stack, fp));
739       else
740 #endif
741         {
742           lab = copy_to_reg (lab);
743
744           emit_insn (gen_rtx_CLOBBER (VOIDmode,
745                                       gen_rtx_MEM (BLKmode,
746                                                    gen_rtx_SCRATCH (VOIDmode))));
747           emit_insn (gen_rtx_CLOBBER (VOIDmode,
748                                       gen_rtx_MEM (BLKmode,
749                                                    hard_frame_pointer_rtx)));
750
751           emit_move_insn (hard_frame_pointer_rtx, fp);
752           emit_stack_restore (SAVE_NONLOCAL, stack, NULL_RTX);
753
754           emit_insn (gen_rtx_USE (VOIDmode, hard_frame_pointer_rtx));
755           emit_insn (gen_rtx_USE (VOIDmode, stack_pointer_rtx));
756           emit_indirect_jump (lab);
757         }
758     }
759
760   /* Search backwards and mark the jump insn as a non-local goto.
761      Note that this precludes the use of __builtin_longjmp to a
762      __builtin_setjmp target in the same function.  However, we've
763      already cautioned the user that these functions are for
764      internal exception handling use only.  */
765   for (insn = get_last_insn (); insn; insn = PREV_INSN (insn))
766     {
767       if (insn == last)
768         abort ();
769       if (JUMP_P (insn))
770         {
771           REG_NOTES (insn) = alloc_EXPR_LIST (REG_NON_LOCAL_GOTO, const0_rtx,
772                                               REG_NOTES (insn));
773           break;
774         }
775       else if (CALL_P (insn))
776         break;
777     }
778 }
779
780 /* Expand a call to __builtin_nonlocal_goto.  We're passed the target label
781    and the address of the save area.  */
782
783 static rtx
784 expand_builtin_nonlocal_goto (tree arglist)
785 {
786   tree t_label, t_save_area;
787   rtx r_label, r_save_area, r_fp, r_sp, insn;
788
789   if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
790     return NULL_RTX;
791
792   t_label = TREE_VALUE (arglist);
793   arglist = TREE_CHAIN (arglist);
794   t_save_area = TREE_VALUE (arglist);
795
796   r_label = expand_expr (t_label, NULL_RTX, VOIDmode, 0);
797   r_label = convert_memory_address (Pmode, r_label);
798   r_save_area = expand_expr (t_save_area, NULL_RTX, VOIDmode, 0);
799   r_save_area = convert_memory_address (Pmode, r_save_area);
800   r_fp = gen_rtx_MEM (Pmode, r_save_area);
801   r_sp = gen_rtx_MEM (STACK_SAVEAREA_MODE (SAVE_NONLOCAL),
802                       plus_constant (r_save_area, GET_MODE_SIZE (Pmode)));
803
804   current_function_has_nonlocal_goto = 1;
805
806 #if HAVE_nonlocal_goto
807   /* ??? We no longer need to pass the static chain value, afaik.  */
808   if (HAVE_nonlocal_goto)
809     emit_insn (gen_nonlocal_goto (const0_rtx, r_label, r_sp, r_fp));
810   else
811 #endif
812     {
813       r_label = copy_to_reg (r_label);
814
815       emit_insn (gen_rtx_CLOBBER (VOIDmode,
816                                   gen_rtx_MEM (BLKmode,
817                                                gen_rtx_SCRATCH (VOIDmode))));
818
819       emit_insn (gen_rtx_CLOBBER (VOIDmode,
820                                   gen_rtx_MEM (BLKmode,
821                                                hard_frame_pointer_rtx)));
822  
823       /* Restore frame pointer for containing function.
824          This sets the actual hard register used for the frame pointer
825          to the location of the function's incoming static chain info.
826          The non-local goto handler will then adjust it to contain the
827          proper value and reload the argument pointer, if needed.  */
828       emit_move_insn (hard_frame_pointer_rtx, r_fp);
829       emit_stack_restore (SAVE_NONLOCAL, r_sp, NULL_RTX);
830  
831       /* USE of hard_frame_pointer_rtx added for consistency;
832          not clear if really needed.  */
833       emit_insn (gen_rtx_USE (VOIDmode, hard_frame_pointer_rtx));
834       emit_insn (gen_rtx_USE (VOIDmode, stack_pointer_rtx));
835       emit_indirect_jump (r_label);
836     }
837  
838   /* Search backwards to the jump insn and mark it as a
839      non-local goto.  */
840   for (insn = get_last_insn (); insn; insn = PREV_INSN (insn))
841     {
842       if (JUMP_P (insn))
843         {
844           REG_NOTES (insn) = alloc_EXPR_LIST (REG_NON_LOCAL_GOTO,
845                                               const0_rtx, REG_NOTES (insn));
846           break;
847         }
848       else if (CALL_P (insn))
849         break;
850     }
851
852   return const0_rtx;
853 }
854
855 /* __builtin_update_setjmp_buf is passed a pointer to an array of five words
856    (not all will be used on all machines) that was passed to __builtin_setjmp.
857    It updates the stack pointer in that block to correspond to the current
858    stack pointer.  */
859
860 static void
861 expand_builtin_update_setjmp_buf (rtx buf_addr)
862 {
863   enum machine_mode sa_mode = Pmode;
864   rtx stack_save;
865
866
867 #ifdef HAVE_save_stack_nonlocal
868   if (HAVE_save_stack_nonlocal)
869     sa_mode = insn_data[(int) CODE_FOR_save_stack_nonlocal].operand[0].mode;
870 #endif
871 #ifdef STACK_SAVEAREA_MODE
872   sa_mode = STACK_SAVEAREA_MODE (SAVE_NONLOCAL);
873 #endif
874
875   stack_save
876     = gen_rtx_MEM (sa_mode,
877                    memory_address
878                    (sa_mode,
879                     plus_constant (buf_addr, 2 * GET_MODE_SIZE (Pmode))));
880
881 #ifdef HAVE_setjmp
882   if (HAVE_setjmp)
883     emit_insn (gen_setjmp ());
884 #endif
885
886   emit_stack_save (SAVE_NONLOCAL, &stack_save, NULL_RTX);
887 }
888
889 /* Expand a call to __builtin_prefetch.  For a target that does not support
890    data prefetch, evaluate the memory address argument in case it has side
891    effects.  */
892
893 static void
894 expand_builtin_prefetch (tree arglist)
895 {
896   tree arg0, arg1, arg2;
897   rtx op0, op1, op2;
898
899   if (!validate_arglist (arglist, POINTER_TYPE, 0))
900     return;
901
902   arg0 = TREE_VALUE (arglist);
903   /* Arguments 1 and 2 are optional; argument 1 (read/write) defaults to
904      zero (read) and argument 2 (locality) defaults to 3 (high degree of
905      locality).  */
906   if (TREE_CHAIN (arglist))
907     {
908       arg1 = TREE_VALUE (TREE_CHAIN (arglist));
909       if (TREE_CHAIN (TREE_CHAIN (arglist)))
910         arg2 = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
911       else
912         arg2 = build_int_2 (3, 0);
913     }
914   else
915     {
916       arg1 = integer_zero_node;
917       arg2 = build_int_2 (3, 0);
918     }
919
920   /* Argument 0 is an address.  */
921   op0 = expand_expr (arg0, NULL_RTX, Pmode, EXPAND_NORMAL);
922
923   /* Argument 1 (read/write flag) must be a compile-time constant int.  */
924   if (TREE_CODE (arg1) != INTEGER_CST)
925     {
926       error ("second arg to `__builtin_prefetch' must be a constant");
927       arg1 = integer_zero_node;
928     }
929   op1 = expand_expr (arg1, NULL_RTX, VOIDmode, 0);
930   /* Argument 1 must be either zero or one.  */
931   if (INTVAL (op1) != 0 && INTVAL (op1) != 1)
932     {
933       warning ("invalid second arg to __builtin_prefetch; using zero");
934       op1 = const0_rtx;
935     }
936
937   /* Argument 2 (locality) must be a compile-time constant int.  */
938   if (TREE_CODE (arg2) != INTEGER_CST)
939     {
940       error ("third arg to `__builtin_prefetch' must be a constant");
941       arg2 = integer_zero_node;
942     }
943   op2 = expand_expr (arg2, NULL_RTX, VOIDmode, 0);
944   /* Argument 2 must be 0, 1, 2, or 3.  */
945   if (INTVAL (op2) < 0 || INTVAL (op2) > 3)
946     {
947       warning ("invalid third arg to __builtin_prefetch; using zero");
948       op2 = const0_rtx;
949     }
950
951 #ifdef HAVE_prefetch
952   if (HAVE_prefetch)
953     {
954       if ((! (*insn_data[(int) CODE_FOR_prefetch].operand[0].predicate)
955              (op0,
956               insn_data[(int) CODE_FOR_prefetch].operand[0].mode))
957           || (GET_MODE (op0) != Pmode))
958         {
959           op0 = convert_memory_address (Pmode, op0);
960           op0 = force_reg (Pmode, op0);
961         }
962       emit_insn (gen_prefetch (op0, op1, op2));
963     }
964   else
965 #endif
966     op0 = protect_from_queue (op0, 0);
967   /* Don't do anything with direct references to volatile memory, but
968      generate code to handle other side effects.  */
969   if (!MEM_P (op0) && side_effects_p (op0))
970     emit_insn (op0);
971 }
972
973 /* Get a MEM rtx for expression EXP which is the address of an operand
974    to be used to be used in a string instruction (cmpstrsi, movmemsi, ..).  */
975
976 static rtx
977 get_memory_rtx (tree exp)
978 {
979   rtx addr = expand_expr (exp, NULL_RTX, ptr_mode, EXPAND_SUM);
980   rtx mem;
981
982   addr = convert_memory_address (Pmode, addr);
983
984   mem = gen_rtx_MEM (BLKmode, memory_address (BLKmode, addr));
985
986   /* Get an expression we can use to find the attributes to assign to MEM.
987      If it is an ADDR_EXPR, use the operand.  Otherwise, dereference it if
988      we can.  First remove any nops.  */
989   while ((TREE_CODE (exp) == NOP_EXPR || TREE_CODE (exp) == CONVERT_EXPR
990           || TREE_CODE (exp) == NON_LVALUE_EXPR)
991          && POINTER_TYPE_P (TREE_TYPE (TREE_OPERAND (exp, 0))))
992     exp = TREE_OPERAND (exp, 0);
993
994   if (TREE_CODE (exp) == ADDR_EXPR)
995     {
996       exp = TREE_OPERAND (exp, 0);
997       set_mem_attributes (mem, exp, 0);
998     }
999   else if (POINTER_TYPE_P (TREE_TYPE (exp)))
1000     {
1001       exp = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (exp)), exp);
1002       /* memcpy, memset and other builtin stringops can alias with anything.  */
1003       set_mem_alias_set (mem, 0);
1004     }
1005
1006   return mem;
1007 }
1008 \f
1009 /* Built-in functions to perform an untyped call and return.  */
1010
1011 /* For each register that may be used for calling a function, this
1012    gives a mode used to copy the register's value.  VOIDmode indicates
1013    the register is not used for calling a function.  If the machine
1014    has register windows, this gives only the outbound registers.
1015    INCOMING_REGNO gives the corresponding inbound register.  */
1016 static enum machine_mode apply_args_mode[FIRST_PSEUDO_REGISTER];
1017
1018 /* For each register that may be used for returning values, this gives
1019    a mode used to copy the register's value.  VOIDmode indicates the
1020    register is not used for returning values.  If the machine has
1021    register windows, this gives only the outbound registers.
1022    INCOMING_REGNO gives the corresponding inbound register.  */
1023 static enum machine_mode apply_result_mode[FIRST_PSEUDO_REGISTER];
1024
1025 /* For each register that may be used for calling a function, this
1026    gives the offset of that register into the block returned by
1027    __builtin_apply_args.  0 indicates that the register is not
1028    used for calling a function.  */
1029 static int apply_args_reg_offset[FIRST_PSEUDO_REGISTER];
1030
1031 /* Return the size required for the block returned by __builtin_apply_args,
1032    and initialize apply_args_mode.  */
1033
1034 static int
1035 apply_args_size (void)
1036 {
1037   static int size = -1;
1038   int align;
1039   unsigned int regno;
1040   enum machine_mode mode;
1041
1042   /* The values computed by this function never change.  */
1043   if (size < 0)
1044     {
1045       /* The first value is the incoming arg-pointer.  */
1046       size = GET_MODE_SIZE (Pmode);
1047
1048       /* The second value is the structure value address unless this is
1049          passed as an "invisible" first argument.  */
1050       if (targetm.calls.struct_value_rtx (cfun ? TREE_TYPE (cfun->decl) : 0, 0))
1051         size += GET_MODE_SIZE (Pmode);
1052
1053       for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
1054         if (FUNCTION_ARG_REGNO_P (regno))
1055           {
1056             mode = reg_raw_mode[regno];
1057
1058             if (mode == VOIDmode)
1059               abort ();
1060
1061             align = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT;
1062             if (size % align != 0)
1063               size = CEIL (size, align) * align;
1064             apply_args_reg_offset[regno] = size;
1065             size += GET_MODE_SIZE (mode);
1066             apply_args_mode[regno] = mode;
1067           }
1068         else
1069           {
1070             apply_args_mode[regno] = VOIDmode;
1071             apply_args_reg_offset[regno] = 0;
1072           }
1073     }
1074   return size;
1075 }
1076
1077 /* Return the size required for the block returned by __builtin_apply,
1078    and initialize apply_result_mode.  */
1079
1080 static int
1081 apply_result_size (void)
1082 {
1083   static int size = -1;
1084   int align, regno;
1085   enum machine_mode mode;
1086
1087   /* The values computed by this function never change.  */
1088   if (size < 0)
1089     {
1090       size = 0;
1091
1092       for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
1093         if (FUNCTION_VALUE_REGNO_P (regno))
1094           {
1095             mode = reg_raw_mode[regno];
1096
1097             if (mode == VOIDmode)
1098               abort ();
1099
1100             align = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT;
1101             if (size % align != 0)
1102               size = CEIL (size, align) * align;
1103             size += GET_MODE_SIZE (mode);
1104             apply_result_mode[regno] = mode;
1105           }
1106         else
1107           apply_result_mode[regno] = VOIDmode;
1108
1109       /* Allow targets that use untyped_call and untyped_return to override
1110          the size so that machine-specific information can be stored here.  */
1111 #ifdef APPLY_RESULT_SIZE
1112       size = APPLY_RESULT_SIZE;
1113 #endif
1114     }
1115   return size;
1116 }
1117
1118 #if defined (HAVE_untyped_call) || defined (HAVE_untyped_return)
1119 /* Create a vector describing the result block RESULT.  If SAVEP is true,
1120    the result block is used to save the values; otherwise it is used to
1121    restore the values.  */
1122
1123 static rtx
1124 result_vector (int savep, rtx result)
1125 {
1126   int regno, size, align, nelts;
1127   enum machine_mode mode;
1128   rtx reg, mem;
1129   rtx *savevec = alloca (FIRST_PSEUDO_REGISTER * sizeof (rtx));
1130
1131   size = nelts = 0;
1132   for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
1133     if ((mode = apply_result_mode[regno]) != VOIDmode)
1134       {
1135         align = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT;
1136         if (size % align != 0)
1137           size = CEIL (size, align) * align;
1138         reg = gen_rtx_REG (mode, savep ? regno : INCOMING_REGNO (regno));
1139         mem = adjust_address (result, mode, size);
1140         savevec[nelts++] = (savep
1141                             ? gen_rtx_SET (VOIDmode, mem, reg)
1142                             : gen_rtx_SET (VOIDmode, reg, mem));
1143         size += GET_MODE_SIZE (mode);
1144       }
1145   return gen_rtx_PARALLEL (VOIDmode, gen_rtvec_v (nelts, savevec));
1146 }
1147 #endif /* HAVE_untyped_call or HAVE_untyped_return */
1148
1149 /* Save the state required to perform an untyped call with the same
1150    arguments as were passed to the current function.  */
1151
1152 static rtx
1153 expand_builtin_apply_args_1 (void)
1154 {
1155   rtx registers, tem;
1156   int size, align, regno;
1157   enum machine_mode mode;
1158   rtx struct_incoming_value = targetm.calls.struct_value_rtx (cfun ? TREE_TYPE (cfun->decl) : 0, 1);
1159
1160   /* Create a block where the arg-pointer, structure value address,
1161      and argument registers can be saved.  */
1162   registers = assign_stack_local (BLKmode, apply_args_size (), -1);
1163
1164   /* Walk past the arg-pointer and structure value address.  */
1165   size = GET_MODE_SIZE (Pmode);
1166   if (targetm.calls.struct_value_rtx (cfun ? TREE_TYPE (cfun->decl) : 0, 0))
1167     size += GET_MODE_SIZE (Pmode);
1168
1169   /* Save each register used in calling a function to the block.  */
1170   for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
1171     if ((mode = apply_args_mode[regno]) != VOIDmode)
1172       {
1173         align = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT;
1174         if (size % align != 0)
1175           size = CEIL (size, align) * align;
1176
1177         tem = gen_rtx_REG (mode, INCOMING_REGNO (regno));
1178
1179         emit_move_insn (adjust_address (registers, mode, size), tem);
1180         size += GET_MODE_SIZE (mode);
1181       }
1182
1183   /* Save the arg pointer to the block.  */
1184   tem = copy_to_reg (virtual_incoming_args_rtx);
1185 #ifdef STACK_GROWS_DOWNWARD
1186   /* We need the pointer as the caller actually passed them to us, not
1187      as we might have pretended they were passed.  Make sure it's a valid
1188      operand, as emit_move_insn isn't expected to handle a PLUS.  */
1189   tem
1190     = force_operand (plus_constant (tem, current_function_pretend_args_size),
1191                      NULL_RTX);
1192 #endif
1193   emit_move_insn (adjust_address (registers, Pmode, 0), tem);
1194
1195   size = GET_MODE_SIZE (Pmode);
1196
1197   /* Save the structure value address unless this is passed as an
1198      "invisible" first argument.  */
1199   if (struct_incoming_value)
1200     {
1201       emit_move_insn (adjust_address (registers, Pmode, size),
1202                       copy_to_reg (struct_incoming_value));
1203       size += GET_MODE_SIZE (Pmode);
1204     }
1205
1206   /* Return the address of the block.  */
1207   return copy_addr_to_reg (XEXP (registers, 0));
1208 }
1209
1210 /* __builtin_apply_args returns block of memory allocated on
1211    the stack into which is stored the arg pointer, structure
1212    value address, static chain, and all the registers that might
1213    possibly be used in performing a function call.  The code is
1214    moved to the start of the function so the incoming values are
1215    saved.  */
1216
1217 static rtx
1218 expand_builtin_apply_args (void)
1219 {
1220   /* Don't do __builtin_apply_args more than once in a function.
1221      Save the result of the first call and reuse it.  */
1222   if (apply_args_value != 0)
1223     return apply_args_value;
1224   {
1225     /* When this function is called, it means that registers must be
1226        saved on entry to this function.  So we migrate the
1227        call to the first insn of this function.  */
1228     rtx temp;
1229     rtx seq;
1230
1231     start_sequence ();
1232     temp = expand_builtin_apply_args_1 ();
1233     seq = get_insns ();
1234     end_sequence ();
1235
1236     apply_args_value = temp;
1237
1238     /* Put the insns after the NOTE that starts the function.
1239        If this is inside a start_sequence, make the outer-level insn
1240        chain current, so the code is placed at the start of the
1241        function.  */
1242     push_topmost_sequence ();
1243     emit_insn_before (seq, NEXT_INSN (entry_of_function ()));
1244     pop_topmost_sequence ();
1245     return temp;
1246   }
1247 }
1248
1249 /* Perform an untyped call and save the state required to perform an
1250    untyped return of whatever value was returned by the given function.  */
1251
1252 static rtx
1253 expand_builtin_apply (rtx function, rtx arguments, rtx argsize)
1254 {
1255   int size, align, regno;
1256   enum machine_mode mode;
1257   rtx incoming_args, result, reg, dest, src, call_insn;
1258   rtx old_stack_level = 0;
1259   rtx call_fusage = 0;
1260   rtx struct_value = targetm.calls.struct_value_rtx (cfun ? TREE_TYPE (cfun->decl) : 0, 0);
1261
1262   arguments = convert_memory_address (Pmode, arguments);
1263
1264   /* Create a block where the return registers can be saved.  */
1265   result = assign_stack_local (BLKmode, apply_result_size (), -1);
1266
1267   /* Fetch the arg pointer from the ARGUMENTS block.  */
1268   incoming_args = gen_reg_rtx (Pmode);
1269   emit_move_insn (incoming_args, gen_rtx_MEM (Pmode, arguments));
1270 #ifndef STACK_GROWS_DOWNWARD
1271   incoming_args = expand_simple_binop (Pmode, MINUS, incoming_args, argsize,
1272                                        incoming_args, 0, OPTAB_LIB_WIDEN);
1273 #endif
1274
1275   /* Perform postincrements before actually calling the function.  */
1276   emit_queue ();
1277
1278   /* Push a new argument block and copy the arguments.  Do not allow
1279      the (potential) memcpy call below to interfere with our stack
1280      manipulations.  */
1281   do_pending_stack_adjust ();
1282   NO_DEFER_POP;
1283
1284   /* Save the stack with nonlocal if available.  */
1285 #ifdef HAVE_save_stack_nonlocal
1286   if (HAVE_save_stack_nonlocal)
1287     emit_stack_save (SAVE_NONLOCAL, &old_stack_level, NULL_RTX);
1288   else
1289 #endif
1290     emit_stack_save (SAVE_BLOCK, &old_stack_level, NULL_RTX);
1291
1292   /* Allocate a block of memory onto the stack and copy the memory
1293      arguments to the outgoing arguments address.  */
1294   allocate_dynamic_stack_space (argsize, 0, BITS_PER_UNIT);
1295   dest = virtual_outgoing_args_rtx;
1296 #ifndef STACK_GROWS_DOWNWARD
1297   if (GET_CODE (argsize) == CONST_INT)
1298     dest = plus_constant (dest, -INTVAL (argsize));
1299   else
1300     dest = gen_rtx_PLUS (Pmode, dest, negate_rtx (Pmode, argsize));
1301 #endif
1302   dest = gen_rtx_MEM (BLKmode, dest);
1303   set_mem_align (dest, PARM_BOUNDARY);
1304   src = gen_rtx_MEM (BLKmode, incoming_args);
1305   set_mem_align (src, PARM_BOUNDARY);
1306   emit_block_move (dest, src, argsize, BLOCK_OP_NORMAL);
1307
1308   /* Refer to the argument block.  */
1309   apply_args_size ();
1310   arguments = gen_rtx_MEM (BLKmode, arguments);
1311   set_mem_align (arguments, PARM_BOUNDARY);
1312
1313   /* Walk past the arg-pointer and structure value address.  */
1314   size = GET_MODE_SIZE (Pmode);
1315   if (struct_value)
1316     size += GET_MODE_SIZE (Pmode);
1317
1318   /* Restore each of the registers previously saved.  Make USE insns
1319      for each of these registers for use in making the call.  */
1320   for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
1321     if ((mode = apply_args_mode[regno]) != VOIDmode)
1322       {
1323         align = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT;
1324         if (size % align != 0)
1325           size = CEIL (size, align) * align;
1326         reg = gen_rtx_REG (mode, regno);
1327         emit_move_insn (reg, adjust_address (arguments, mode, size));
1328         use_reg (&call_fusage, reg);
1329         size += GET_MODE_SIZE (mode);
1330       }
1331
1332   /* Restore the structure value address unless this is passed as an
1333      "invisible" first argument.  */
1334   size = GET_MODE_SIZE (Pmode);
1335   if (struct_value)
1336     {
1337       rtx value = gen_reg_rtx (Pmode);
1338       emit_move_insn (value, adjust_address (arguments, Pmode, size));
1339       emit_move_insn (struct_value, value);
1340       if (REG_P (struct_value))
1341         use_reg (&call_fusage, struct_value);
1342       size += GET_MODE_SIZE (Pmode);
1343     }
1344
1345   /* All arguments and registers used for the call are set up by now!  */
1346   function = prepare_call_address (function, NULL, &call_fusage, 0, 0);
1347
1348   /* Ensure address is valid.  SYMBOL_REF is already valid, so no need,
1349      and we don't want to load it into a register as an optimization,
1350      because prepare_call_address already did it if it should be done.  */
1351   if (GET_CODE (function) != SYMBOL_REF)
1352     function = memory_address (FUNCTION_MODE, function);
1353
1354   /* Generate the actual call instruction and save the return value.  */
1355 #ifdef HAVE_untyped_call
1356   if (HAVE_untyped_call)
1357     emit_call_insn (gen_untyped_call (gen_rtx_MEM (FUNCTION_MODE, function),
1358                                       result, result_vector (1, result)));
1359   else
1360 #endif
1361 #ifdef HAVE_call_value
1362   if (HAVE_call_value)
1363     {
1364       rtx valreg = 0;
1365
1366       /* Locate the unique return register.  It is not possible to
1367          express a call that sets more than one return register using
1368          call_value; use untyped_call for that.  In fact, untyped_call
1369          only needs to save the return registers in the given block.  */
1370       for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
1371         if ((mode = apply_result_mode[regno]) != VOIDmode)
1372           {
1373             if (valreg)
1374               abort (); /* HAVE_untyped_call required.  */
1375             valreg = gen_rtx_REG (mode, regno);
1376           }
1377
1378       emit_call_insn (GEN_CALL_VALUE (valreg,
1379                                       gen_rtx_MEM (FUNCTION_MODE, function),
1380                                       const0_rtx, NULL_RTX, const0_rtx));
1381
1382       emit_move_insn (adjust_address (result, GET_MODE (valreg), 0), valreg);
1383     }
1384   else
1385 #endif
1386     abort ();
1387
1388   /* Find the CALL insn we just emitted, and attach the register usage
1389      information.  */
1390   call_insn = last_call_insn ();
1391   add_function_usage_to (call_insn, call_fusage);
1392
1393   /* Restore the stack.  */
1394 #ifdef HAVE_save_stack_nonlocal
1395   if (HAVE_save_stack_nonlocal)
1396     emit_stack_restore (SAVE_NONLOCAL, old_stack_level, NULL_RTX);
1397   else
1398 #endif
1399     emit_stack_restore (SAVE_BLOCK, old_stack_level, NULL_RTX);
1400
1401   OK_DEFER_POP;
1402
1403   /* Return the address of the result block.  */
1404   result = copy_addr_to_reg (XEXP (result, 0));
1405   return convert_memory_address (ptr_mode, result);
1406 }
1407
1408 /* Perform an untyped return.  */
1409
1410 static void
1411 expand_builtin_return (rtx result)
1412 {
1413   int size, align, regno;
1414   enum machine_mode mode;
1415   rtx reg;
1416   rtx call_fusage = 0;
1417
1418   result = convert_memory_address (Pmode, result);
1419
1420   apply_result_size ();
1421   result = gen_rtx_MEM (BLKmode, result);
1422
1423 #ifdef HAVE_untyped_return
1424   if (HAVE_untyped_return)
1425     {
1426       emit_jump_insn (gen_untyped_return (result, result_vector (0, result)));
1427       emit_barrier ();
1428       return;
1429     }
1430 #endif
1431
1432   /* Restore the return value and note that each value is used.  */
1433   size = 0;
1434   for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
1435     if ((mode = apply_result_mode[regno]) != VOIDmode)
1436       {
1437         align = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT;
1438         if (size % align != 0)
1439           size = CEIL (size, align) * align;
1440         reg = gen_rtx_REG (mode, INCOMING_REGNO (regno));
1441         emit_move_insn (reg, adjust_address (result, mode, size));
1442
1443         push_to_sequence (call_fusage);
1444         emit_insn (gen_rtx_USE (VOIDmode, reg));
1445         call_fusage = get_insns ();
1446         end_sequence ();
1447         size += GET_MODE_SIZE (mode);
1448       }
1449
1450   /* Put the USE insns before the return.  */
1451   emit_insn (call_fusage);
1452
1453   /* Return whatever values was restored by jumping directly to the end
1454      of the function.  */
1455   expand_naked_return ();
1456 }
1457
1458 /* Used by expand_builtin_classify_type and fold_builtin_classify_type.  */
1459
1460 static enum type_class
1461 type_to_class (tree type)
1462 {
1463   switch (TREE_CODE (type))
1464     {
1465     case VOID_TYPE:        return void_type_class;
1466     case INTEGER_TYPE:     return integer_type_class;
1467     case CHAR_TYPE:        return char_type_class;
1468     case ENUMERAL_TYPE:    return enumeral_type_class;
1469     case BOOLEAN_TYPE:     return boolean_type_class;
1470     case POINTER_TYPE:     return pointer_type_class;
1471     case REFERENCE_TYPE:   return reference_type_class;
1472     case OFFSET_TYPE:      return offset_type_class;
1473     case REAL_TYPE:        return real_type_class;
1474     case COMPLEX_TYPE:     return complex_type_class;
1475     case FUNCTION_TYPE:    return function_type_class;
1476     case METHOD_TYPE:      return method_type_class;
1477     case RECORD_TYPE:      return record_type_class;
1478     case UNION_TYPE:
1479     case QUAL_UNION_TYPE:  return union_type_class;
1480     case ARRAY_TYPE:       return (TYPE_STRING_FLAG (type)
1481                                    ? string_type_class : array_type_class);
1482     case SET_TYPE:         return set_type_class;
1483     case FILE_TYPE:        return file_type_class;
1484     case LANG_TYPE:        return lang_type_class;
1485     default:               return no_type_class;
1486     }
1487 }
1488
1489 /* Expand a call to __builtin_classify_type with arguments found in
1490    ARGLIST.  */
1491
1492 static rtx
1493 expand_builtin_classify_type (tree arglist)
1494 {
1495   if (arglist != 0)
1496     return GEN_INT (type_to_class (TREE_TYPE (TREE_VALUE (arglist))));
1497   return GEN_INT (no_type_class);
1498 }
1499
1500 /* This helper macro, meant to be used in mathfn_built_in below,
1501    determines which among a set of three builtin math functions is
1502    appropriate for a given type mode.  The `F' and `L' cases are
1503    automatically generated from the `double' case.  */
1504 #define CASE_MATHFN(BUILT_IN_MATHFN) \
1505   case BUILT_IN_MATHFN: case BUILT_IN_MATHFN##F: case BUILT_IN_MATHFN##L: \
1506   fcode = BUILT_IN_MATHFN; fcodef = BUILT_IN_MATHFN##F ; \
1507   fcodel = BUILT_IN_MATHFN##L ; break;
1508
1509 /* Return mathematic function equivalent to FN but operating directly
1510    on TYPE, if available.  If we can't do the conversion, return zero.  */
1511 tree
1512 mathfn_built_in (tree type, enum built_in_function fn)
1513 {
1514   enum built_in_function fcode, fcodef, fcodel;
1515
1516   switch (fn)
1517     {
1518       CASE_MATHFN (BUILT_IN_ACOS)
1519       CASE_MATHFN (BUILT_IN_ACOSH)
1520       CASE_MATHFN (BUILT_IN_ASIN)
1521       CASE_MATHFN (BUILT_IN_ASINH)
1522       CASE_MATHFN (BUILT_IN_ATAN)
1523       CASE_MATHFN (BUILT_IN_ATAN2)
1524       CASE_MATHFN (BUILT_IN_ATANH)
1525       CASE_MATHFN (BUILT_IN_CBRT)
1526       CASE_MATHFN (BUILT_IN_CEIL)
1527       CASE_MATHFN (BUILT_IN_COPYSIGN)
1528       CASE_MATHFN (BUILT_IN_COS)
1529       CASE_MATHFN (BUILT_IN_COSH)
1530       CASE_MATHFN (BUILT_IN_DREM)
1531       CASE_MATHFN (BUILT_IN_ERF)
1532       CASE_MATHFN (BUILT_IN_ERFC)
1533       CASE_MATHFN (BUILT_IN_EXP)
1534       CASE_MATHFN (BUILT_IN_EXP10)
1535       CASE_MATHFN (BUILT_IN_EXP2)
1536       CASE_MATHFN (BUILT_IN_EXPM1)
1537       CASE_MATHFN (BUILT_IN_FABS)
1538       CASE_MATHFN (BUILT_IN_FDIM)
1539       CASE_MATHFN (BUILT_IN_FLOOR)
1540       CASE_MATHFN (BUILT_IN_FMA)
1541       CASE_MATHFN (BUILT_IN_FMAX)
1542       CASE_MATHFN (BUILT_IN_FMIN)
1543       CASE_MATHFN (BUILT_IN_FMOD)
1544       CASE_MATHFN (BUILT_IN_FREXP)
1545       CASE_MATHFN (BUILT_IN_GAMMA)
1546       CASE_MATHFN (BUILT_IN_HUGE_VAL)
1547       CASE_MATHFN (BUILT_IN_HYPOT)
1548       CASE_MATHFN (BUILT_IN_ILOGB)
1549       CASE_MATHFN (BUILT_IN_INF)
1550       CASE_MATHFN (BUILT_IN_J0)
1551       CASE_MATHFN (BUILT_IN_J1)
1552       CASE_MATHFN (BUILT_IN_JN)
1553       CASE_MATHFN (BUILT_IN_LDEXP)
1554       CASE_MATHFN (BUILT_IN_LGAMMA)
1555       CASE_MATHFN (BUILT_IN_LLRINT)
1556       CASE_MATHFN (BUILT_IN_LLROUND)
1557       CASE_MATHFN (BUILT_IN_LOG)
1558       CASE_MATHFN (BUILT_IN_LOG10)
1559       CASE_MATHFN (BUILT_IN_LOG1P)
1560       CASE_MATHFN (BUILT_IN_LOG2)
1561       CASE_MATHFN (BUILT_IN_LOGB)
1562       CASE_MATHFN (BUILT_IN_LRINT)
1563       CASE_MATHFN (BUILT_IN_LROUND)
1564       CASE_MATHFN (BUILT_IN_MODF)
1565       CASE_MATHFN (BUILT_IN_NAN)
1566       CASE_MATHFN (BUILT_IN_NANS)
1567       CASE_MATHFN (BUILT_IN_NEARBYINT)
1568       CASE_MATHFN (BUILT_IN_NEXTAFTER)
1569       CASE_MATHFN (BUILT_IN_NEXTTOWARD)
1570       CASE_MATHFN (BUILT_IN_POW)
1571       CASE_MATHFN (BUILT_IN_POW10)
1572       CASE_MATHFN (BUILT_IN_REMAINDER)
1573       CASE_MATHFN (BUILT_IN_REMQUO)
1574       CASE_MATHFN (BUILT_IN_RINT)
1575       CASE_MATHFN (BUILT_IN_ROUND)
1576       CASE_MATHFN (BUILT_IN_SCALB)
1577       CASE_MATHFN (BUILT_IN_SCALBLN)
1578       CASE_MATHFN (BUILT_IN_SCALBN)
1579       CASE_MATHFN (BUILT_IN_SIGNIFICAND)
1580       CASE_MATHFN (BUILT_IN_SIN)
1581       CASE_MATHFN (BUILT_IN_SINCOS)
1582       CASE_MATHFN (BUILT_IN_SINH)
1583       CASE_MATHFN (BUILT_IN_SQRT)
1584       CASE_MATHFN (BUILT_IN_TAN)
1585       CASE_MATHFN (BUILT_IN_TANH)
1586       CASE_MATHFN (BUILT_IN_TGAMMA)
1587       CASE_MATHFN (BUILT_IN_TRUNC)
1588       CASE_MATHFN (BUILT_IN_Y0)
1589       CASE_MATHFN (BUILT_IN_Y1)
1590       CASE_MATHFN (BUILT_IN_YN)
1591
1592       default:
1593         return 0;
1594       }
1595
1596   if (TYPE_MAIN_VARIANT (type) == double_type_node)
1597     return implicit_built_in_decls[fcode];
1598   else if (TYPE_MAIN_VARIANT (type) == float_type_node)
1599     return implicit_built_in_decls[fcodef];
1600   else if (TYPE_MAIN_VARIANT (type) == long_double_type_node)
1601     return implicit_built_in_decls[fcodel];
1602   else
1603     return 0;
1604 }
1605
1606 /* If errno must be maintained, expand the RTL to check if the result,
1607    TARGET, of a built-in function call, EXP, is NaN, and if so set
1608    errno to EDOM.  */
1609
1610 static void
1611 expand_errno_check (tree exp, rtx target)
1612 {
1613   rtx lab = gen_label_rtx ();
1614
1615   /* Test the result; if it is NaN, set errno=EDOM because
1616      the argument was not in the domain.  */
1617   emit_cmp_and_jump_insns (target, target, EQ, 0, GET_MODE (target),
1618                            0, lab);
1619
1620 #ifdef TARGET_EDOM
1621   /* If this built-in doesn't throw an exception, set errno directly.  */
1622   if (TREE_NOTHROW (TREE_OPERAND (TREE_OPERAND (exp, 0), 0)))
1623     {
1624 #ifdef GEN_ERRNO_RTX
1625       rtx errno_rtx = GEN_ERRNO_RTX;
1626 #else
1627       rtx errno_rtx
1628           = gen_rtx_MEM (word_mode, gen_rtx_SYMBOL_REF (Pmode, "errno"));
1629 #endif
1630       emit_move_insn (errno_rtx, GEN_INT (TARGET_EDOM));
1631       emit_label (lab);
1632       return;
1633     }
1634 #endif
1635
1636   /* We can't set errno=EDOM directly; let the library call do it.
1637      Pop the arguments right away in case the call gets deleted.  */
1638   NO_DEFER_POP;
1639   expand_call (exp, target, 0);
1640   OK_DEFER_POP;
1641   emit_label (lab);
1642 }
1643
1644
1645 /* Expand a call to one of the builtin math functions (sqrt, exp, or log).
1646    Return 0 if a normal call should be emitted rather than expanding the
1647    function in-line.  EXP is the expression that is a call to the builtin
1648    function; if convenient, the result should be placed in TARGET.
1649    SUBTARGET may be used as the target for computing one of EXP's operands.  */
1650
1651 static rtx
1652 expand_builtin_mathfn (tree exp, rtx target, rtx subtarget)
1653 {
1654   optab builtin_optab;
1655   rtx op0, insns, before_call;
1656   tree fndecl = get_callee_fndecl (exp);
1657   tree arglist = TREE_OPERAND (exp, 1);
1658   enum machine_mode mode;
1659   bool errno_set = false;
1660   tree arg, narg;
1661
1662   if (!validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
1663     return 0;
1664
1665   arg = TREE_VALUE (arglist);
1666
1667   switch (DECL_FUNCTION_CODE (fndecl))
1668     {
1669     case BUILT_IN_SQRT:
1670     case BUILT_IN_SQRTF:
1671     case BUILT_IN_SQRTL:
1672       errno_set = ! tree_expr_nonnegative_p (arg);
1673       builtin_optab = sqrt_optab;
1674       break;
1675     case BUILT_IN_EXP:
1676     case BUILT_IN_EXPF:
1677     case BUILT_IN_EXPL:
1678       errno_set = true; builtin_optab = exp_optab; break;
1679     case BUILT_IN_EXP10:
1680     case BUILT_IN_EXP10F:
1681     case BUILT_IN_EXP10L:
1682     case BUILT_IN_POW10:
1683     case BUILT_IN_POW10F:
1684     case BUILT_IN_POW10L:
1685       errno_set = true; builtin_optab = exp10_optab; break;
1686     case BUILT_IN_EXP2:
1687     case BUILT_IN_EXP2F:
1688     case BUILT_IN_EXP2L:
1689       errno_set = true; builtin_optab = exp2_optab; break;
1690     case BUILT_IN_EXPM1:
1691     case BUILT_IN_EXPM1F:
1692     case BUILT_IN_EXPM1L:
1693       errno_set = true; builtin_optab = expm1_optab; break;
1694     case BUILT_IN_LOGB:
1695     case BUILT_IN_LOGBF:
1696     case BUILT_IN_LOGBL:
1697       errno_set = true; builtin_optab = logb_optab; break;
1698     case BUILT_IN_ILOGB:
1699     case BUILT_IN_ILOGBF:
1700     case BUILT_IN_ILOGBL:
1701       errno_set = true; builtin_optab = ilogb_optab; break;
1702     case BUILT_IN_LOG:
1703     case BUILT_IN_LOGF:
1704     case BUILT_IN_LOGL:
1705       errno_set = true; builtin_optab = log_optab; break;
1706     case BUILT_IN_LOG10:
1707     case BUILT_IN_LOG10F:
1708     case BUILT_IN_LOG10L:
1709       errno_set = true; builtin_optab = log10_optab; break;
1710     case BUILT_IN_LOG2:
1711     case BUILT_IN_LOG2F:
1712     case BUILT_IN_LOG2L:
1713       errno_set = true; builtin_optab = log2_optab; break;
1714     case BUILT_IN_LOG1P:
1715     case BUILT_IN_LOG1PF:
1716     case BUILT_IN_LOG1PL:
1717       errno_set = true; builtin_optab = log1p_optab; break;
1718     case BUILT_IN_ASIN:
1719     case BUILT_IN_ASINF:
1720     case BUILT_IN_ASINL:
1721       builtin_optab = asin_optab; break;
1722     case BUILT_IN_ACOS:
1723     case BUILT_IN_ACOSF:
1724     case BUILT_IN_ACOSL:
1725       builtin_optab = acos_optab; break;
1726     case BUILT_IN_TAN:
1727     case BUILT_IN_TANF:
1728     case BUILT_IN_TANL:
1729       builtin_optab = tan_optab; break;
1730     case BUILT_IN_ATAN:
1731     case BUILT_IN_ATANF:
1732     case BUILT_IN_ATANL:
1733       builtin_optab = atan_optab; break;
1734     case BUILT_IN_FLOOR:
1735     case BUILT_IN_FLOORF:
1736     case BUILT_IN_FLOORL:
1737       builtin_optab = floor_optab; break;
1738     case BUILT_IN_CEIL:
1739     case BUILT_IN_CEILF:
1740     case BUILT_IN_CEILL:
1741       builtin_optab = ceil_optab; break;
1742     case BUILT_IN_TRUNC:
1743     case BUILT_IN_TRUNCF:
1744     case BUILT_IN_TRUNCL:
1745       builtin_optab = btrunc_optab; break;
1746     case BUILT_IN_ROUND:
1747     case BUILT_IN_ROUNDF:
1748     case BUILT_IN_ROUNDL:
1749       builtin_optab = round_optab; break;
1750     case BUILT_IN_NEARBYINT:
1751     case BUILT_IN_NEARBYINTF:
1752     case BUILT_IN_NEARBYINTL:
1753       builtin_optab = nearbyint_optab; break;
1754     default:
1755       abort ();
1756     }
1757
1758   /* Make a suitable register to place result in.  */
1759   mode = TYPE_MODE (TREE_TYPE (exp));
1760
1761   if (! flag_errno_math || ! HONOR_NANS (mode))
1762     errno_set = false;
1763
1764   /* Before working hard, check whether the instruction is available.  */
1765   if (builtin_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing)
1766     {
1767       target = gen_reg_rtx (mode);
1768
1769       /* Wrap the computation of the argument in a SAVE_EXPR, as we may
1770          need to expand the argument again.  This way, we will not perform
1771          side-effects more the once.  */
1772       narg = builtin_save_expr (arg);
1773       if (narg != arg)
1774         {
1775           arglist = build_tree_list (NULL_TREE, arg);
1776           exp = build_function_call_expr (fndecl, arglist);
1777         }
1778
1779       op0 = expand_expr (arg, subtarget, VOIDmode, 0);
1780
1781       emit_queue ();
1782       start_sequence ();
1783
1784       /* Compute into TARGET.
1785          Set TARGET to wherever the result comes back.  */
1786       target = expand_unop (mode, builtin_optab, op0, target, 0);
1787
1788       if (target != 0)
1789         {
1790           if (errno_set)
1791             expand_errno_check (exp, target);
1792
1793           /* Output the entire sequence.  */
1794           insns = get_insns ();
1795           end_sequence ();
1796           emit_insn (insns);
1797           return target;
1798         }
1799
1800       /* If we were unable to expand via the builtin, stop the sequence
1801          (without outputting the insns) and call to the library function
1802          with the stabilized argument list.  */
1803       end_sequence ();
1804     }
1805
1806   before_call = get_last_insn ();
1807
1808   target = expand_call (exp, target, target == const0_rtx);
1809
1810   /* If this is a sqrt operation and we don't care about errno, try to
1811      attach a REG_EQUAL note with a SQRT rtx to the emitted libcall.
1812      This allows the semantics of the libcall to be visible to the RTL
1813      optimizers.  */
1814   if (builtin_optab == sqrt_optab && !errno_set)
1815     {
1816       /* Search backwards through the insns emitted by expand_call looking
1817          for the instruction with the REG_RETVAL note.  */
1818       rtx last = get_last_insn ();
1819       while (last != before_call)
1820         {
1821           if (find_reg_note (last, REG_RETVAL, NULL))
1822             {
1823               rtx note = find_reg_note (last, REG_EQUAL, NULL);
1824               /* Check that the REQ_EQUAL note is an EXPR_LIST with
1825                  two elements, i.e. symbol_ref(sqrt) and the operand.  */
1826               if (note
1827                   && GET_CODE (note) == EXPR_LIST
1828                   && GET_CODE (XEXP (note, 0)) == EXPR_LIST
1829                   && XEXP (XEXP (note, 0), 1) != NULL_RTX
1830                   && XEXP (XEXP (XEXP (note, 0), 1), 1) == NULL_RTX)
1831                 {
1832                   rtx operand = XEXP (XEXP (XEXP (note, 0), 1), 0);
1833                   /* Check operand is a register with expected mode.  */
1834                   if (operand
1835                       && REG_P (operand)
1836                       && GET_MODE (operand) == mode)
1837                     {
1838                       /* Replace the REG_EQUAL note with a SQRT rtx.  */
1839                       rtx equiv = gen_rtx_SQRT (mode, operand);
1840                       set_unique_reg_note (last, REG_EQUAL, equiv);
1841                     }
1842                 }
1843               break;
1844             }
1845           last = PREV_INSN (last);
1846         }
1847     }
1848
1849   return target;
1850 }
1851
1852 /* Expand a call to the builtin binary math functions (pow and atan2).
1853    Return 0 if a normal call should be emitted rather than expanding the
1854    function in-line.  EXP is the expression that is a call to the builtin
1855    function; if convenient, the result should be placed in TARGET.
1856    SUBTARGET may be used as the target for computing one of EXP's
1857    operands.  */
1858
1859 static rtx
1860 expand_builtin_mathfn_2 (tree exp, rtx target, rtx subtarget)
1861 {
1862   optab builtin_optab;
1863   rtx op0, op1, insns;
1864   tree fndecl = get_callee_fndecl (exp);
1865   tree arglist = TREE_OPERAND (exp, 1);
1866   tree arg0, arg1, temp, narg;
1867   enum machine_mode mode;
1868   bool errno_set = true;
1869   bool stable = true;
1870
1871   if (!validate_arglist (arglist, REAL_TYPE, REAL_TYPE, VOID_TYPE))
1872     return 0;
1873
1874   arg0 = TREE_VALUE (arglist);
1875   arg1 = TREE_VALUE (TREE_CHAIN (arglist));
1876
1877   switch (DECL_FUNCTION_CODE (fndecl))
1878     {
1879     case BUILT_IN_POW:
1880     case BUILT_IN_POWF:
1881     case BUILT_IN_POWL:
1882       builtin_optab = pow_optab; break;
1883     case BUILT_IN_ATAN2:
1884     case BUILT_IN_ATAN2F:
1885     case BUILT_IN_ATAN2L:
1886       builtin_optab = atan2_optab; break;
1887     case BUILT_IN_FMOD:
1888     case BUILT_IN_FMODF:
1889     case BUILT_IN_FMODL:
1890       builtin_optab = fmod_optab; break;
1891     case BUILT_IN_DREM:
1892     case BUILT_IN_DREMF:
1893     case BUILT_IN_DREML:
1894       builtin_optab = drem_optab; break;
1895     default:
1896       abort ();
1897     }
1898
1899   /* Make a suitable register to place result in.  */
1900   mode = TYPE_MODE (TREE_TYPE (exp));
1901
1902   /* Before working hard, check whether the instruction is available.  */
1903   if (builtin_optab->handlers[(int) mode].insn_code == CODE_FOR_nothing)
1904     return 0;
1905
1906   target = gen_reg_rtx (mode);
1907
1908   if (! flag_errno_math || ! HONOR_NANS (mode))
1909     errno_set = false;
1910
1911   /* Always stabilize the argument list.  */
1912   narg = builtin_save_expr (arg1);
1913   if (narg != arg1)
1914     {
1915       temp = build_tree_list (NULL_TREE, narg);
1916       stable = false;
1917     }
1918   else
1919     temp = TREE_CHAIN (arglist);
1920
1921   narg = builtin_save_expr (arg0);
1922   if (narg != arg0)
1923     {
1924       arglist = tree_cons (NULL_TREE, narg, temp);
1925       stable = false;
1926     }
1927   else if (! stable)
1928     arglist = tree_cons (NULL_TREE, arg0, temp);
1929
1930   if (! stable)
1931     exp = build_function_call_expr (fndecl, arglist);
1932
1933   op0 = expand_expr (arg0, subtarget, VOIDmode, 0);
1934   op1 = expand_expr (arg1, 0, VOIDmode, 0);
1935
1936   emit_queue ();
1937   start_sequence ();
1938
1939   /* Compute into TARGET.
1940      Set TARGET to wherever the result comes back.  */
1941   target = expand_binop (mode, builtin_optab, op0, op1,
1942                          target, 0, OPTAB_DIRECT);
1943
1944   /* If we were unable to expand via the builtin, stop the sequence
1945      (without outputting the insns) and call to the library function
1946      with the stabilized argument list.  */
1947   if (target == 0)
1948     {
1949       end_sequence ();
1950       return expand_call (exp, target, target == const0_rtx);
1951     }
1952
1953   if (errno_set)
1954     expand_errno_check (exp, target);
1955
1956   /* Output the entire sequence.  */
1957   insns = get_insns ();
1958   end_sequence ();
1959   emit_insn (insns);
1960
1961   return target;
1962 }
1963
1964 /* Expand a call to the builtin sin and cos math functions.
1965    Return 0 if a normal call should be emitted rather than expanding the
1966    function in-line.  EXP is the expression that is a call to the builtin
1967    function; if convenient, the result should be placed in TARGET.
1968    SUBTARGET may be used as the target for computing one of EXP's
1969    operands.  */
1970
1971 static rtx
1972 expand_builtin_mathfn_3 (tree exp, rtx target, rtx subtarget)
1973 {
1974   optab builtin_optab;
1975   rtx op0, insns, before_call;
1976   tree fndecl = get_callee_fndecl (exp);
1977   tree arglist = TREE_OPERAND (exp, 1);
1978   enum machine_mode mode;
1979   bool errno_set = false;
1980   tree arg, narg;
1981
1982   if (!validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
1983     return 0;
1984
1985   arg = TREE_VALUE (arglist);
1986
1987   switch (DECL_FUNCTION_CODE (fndecl))
1988     {
1989     case BUILT_IN_SIN:
1990     case BUILT_IN_SINF:
1991     case BUILT_IN_SINL:
1992     case BUILT_IN_COS:
1993     case BUILT_IN_COSF:
1994     case BUILT_IN_COSL:
1995       builtin_optab = sincos_optab; break;
1996     default:
1997       abort ();
1998     }
1999
2000   /* Make a suitable register to place result in.  */
2001   mode = TYPE_MODE (TREE_TYPE (exp));
2002
2003   if (! flag_errno_math || ! HONOR_NANS (mode))
2004     errno_set = false;
2005
2006   /* Check if sincos insn is available, otherwise fallback
2007      to sin or cos insn.  */
2008   if (builtin_optab->handlers[(int) mode].insn_code == CODE_FOR_nothing) {
2009     switch (DECL_FUNCTION_CODE (fndecl))
2010       {
2011       case BUILT_IN_SIN:
2012       case BUILT_IN_SINF:
2013       case BUILT_IN_SINL:
2014         builtin_optab = sin_optab; break;
2015       case BUILT_IN_COS:
2016       case BUILT_IN_COSF:
2017       case BUILT_IN_COSL:
2018         builtin_optab = cos_optab; break;
2019       default:
2020         abort();
2021       }
2022   }
2023
2024   /* Before working hard, check whether the instruction is available.  */
2025   if (builtin_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing)
2026     {
2027       target = gen_reg_rtx (mode);
2028
2029       /* Wrap the computation of the argument in a SAVE_EXPR, as we may
2030          need to expand the argument again.  This way, we will not perform
2031          side-effects more the once.  */
2032       narg = save_expr (arg);
2033       if (narg != arg)
2034         {
2035           arglist = build_tree_list (NULL_TREE, arg);
2036           exp = build_function_call_expr (fndecl, arglist);
2037         }
2038
2039       op0 = expand_expr (arg, subtarget, VOIDmode, 0);
2040
2041       emit_queue ();
2042       start_sequence ();
2043
2044       /* Compute into TARGET.
2045          Set TARGET to wherever the result comes back.  */
2046       if (builtin_optab == sincos_optab)
2047         {
2048           switch (DECL_FUNCTION_CODE (fndecl))
2049             {
2050             case BUILT_IN_SIN:
2051             case BUILT_IN_SINF:
2052             case BUILT_IN_SINL:
2053               if (!expand_twoval_unop (builtin_optab, op0, 0, target, 0))    
2054                 abort();
2055               break;
2056             case BUILT_IN_COS:
2057             case BUILT_IN_COSF:
2058             case BUILT_IN_COSL:
2059               if (!expand_twoval_unop (builtin_optab, op0, target, 0, 0))
2060                 abort();
2061               break;
2062             default:
2063               abort();
2064             }
2065         }
2066       else
2067         {
2068           target = expand_unop (mode, builtin_optab, op0, target, 0);
2069         }
2070
2071       if (target != 0)
2072         {
2073           if (errno_set)
2074             expand_errno_check (exp, target);
2075
2076           /* Output the entire sequence.  */
2077           insns = get_insns ();
2078           end_sequence ();
2079           emit_insn (insns);
2080           return target;
2081         }
2082
2083       /* If we were unable to expand via the builtin, stop the sequence
2084          (without outputting the insns) and call to the library function
2085          with the stabilized argument list.  */
2086       end_sequence ();
2087     }
2088
2089   before_call = get_last_insn ();
2090
2091   target = expand_call (exp, target, target == const0_rtx);
2092
2093   return target;
2094 }
2095
2096 /* To evaluate powi(x,n), the floating point value x raised to the
2097    constant integer exponent n, we use a hybrid algorithm that
2098    combines the "window method" with look-up tables.  For an
2099    introduction to exponentiation algorithms and "addition chains",
2100    see section 4.6.3, "Evaluation of Powers" of Donald E. Knuth,
2101    "Seminumerical Algorithms", Vol. 2, "The Art of Computer Programming",
2102    3rd Edition, 1998, and Daniel M. Gordon, "A Survey of Fast Exponentiation
2103    Methods", Journal of Algorithms, Vol. 27, pp. 129-146, 1998.  */
2104
2105 /* Provide a default value for POWI_MAX_MULTS, the maximum number of
2106    multiplications to inline before calling the system library's pow
2107    function.  powi(x,n) requires at worst 2*bits(n)-2 multiplications,
2108    so this default never requires calling pow, powf or powl.  */
2109
2110 #ifndef POWI_MAX_MULTS
2111 #define POWI_MAX_MULTS  (2*HOST_BITS_PER_WIDE_INT-2)
2112 #endif
2113
2114 /* The size of the "optimal power tree" lookup table.  All
2115    exponents less than this value are simply looked up in the
2116    powi_table below.  This threshold is also used to size the
2117    cache of pseudo registers that hold intermediate results.  */
2118 #define POWI_TABLE_SIZE 256
2119
2120 /* The size, in bits of the window, used in the "window method"
2121    exponentiation algorithm.  This is equivalent to a radix of
2122    (1<<POWI_WINDOW_SIZE) in the corresponding "m-ary method".  */
2123 #define POWI_WINDOW_SIZE 3
2124
2125 /* The following table is an efficient representation of an
2126    "optimal power tree".  For each value, i, the corresponding
2127    value, j, in the table states than an optimal evaluation
2128    sequence for calculating pow(x,i) can be found by evaluating
2129    pow(x,j)*pow(x,i-j).  An optimal power tree for the first
2130    100 integers is given in Knuth's "Seminumerical algorithms".  */
2131
2132 static const unsigned char powi_table[POWI_TABLE_SIZE] =
2133   {
2134       0,   1,   1,   2,   2,   3,   3,   4,  /*   0 -   7 */
2135       4,   6,   5,   6,   6,  10,   7,   9,  /*   8 -  15 */
2136       8,  16,   9,  16,  10,  12,  11,  13,  /*  16 -  23 */
2137      12,  17,  13,  18,  14,  24,  15,  26,  /*  24 -  31 */
2138      16,  17,  17,  19,  18,  33,  19,  26,  /*  32 -  39 */
2139      20,  25,  21,  40,  22,  27,  23,  44,  /*  40 -  47 */
2140      24,  32,  25,  34,  26,  29,  27,  44,  /*  48 -  55 */
2141      28,  31,  29,  34,  30,  60,  31,  36,  /*  56 -  63 */
2142      32,  64,  33,  34,  34,  46,  35,  37,  /*  64 -  71 */
2143      36,  65,  37,  50,  38,  48,  39,  69,  /*  72 -  79 */
2144      40,  49,  41,  43,  42,  51,  43,  58,  /*  80 -  87 */
2145      44,  64,  45,  47,  46,  59,  47,  76,  /*  88 -  95 */
2146      48,  65,  49,  66,  50,  67,  51,  66,  /*  96 - 103 */
2147      52,  70,  53,  74,  54, 104,  55,  74,  /* 104 - 111 */
2148      56,  64,  57,  69,  58,  78,  59,  68,  /* 112 - 119 */
2149      60,  61,  61,  80,  62,  75,  63,  68,  /* 120 - 127 */
2150      64,  65,  65, 128,  66, 129,  67,  90,  /* 128 - 135 */
2151      68,  73,  69, 131,  70,  94,  71,  88,  /* 136 - 143 */
2152      72, 128,  73,  98,  74, 132,  75, 121,  /* 144 - 151 */
2153      76, 102,  77, 124,  78, 132,  79, 106,  /* 152 - 159 */
2154      80,  97,  81, 160,  82,  99,  83, 134,  /* 160 - 167 */
2155      84,  86,  85,  95,  86, 160,  87, 100,  /* 168 - 175 */
2156      88, 113,  89,  98,  90, 107,  91, 122,  /* 176 - 183 */
2157      92, 111,  93, 102,  94, 126,  95, 150,  /* 184 - 191 */
2158      96, 128,  97, 130,  98, 133,  99, 195,  /* 192 - 199 */
2159     100, 128, 101, 123, 102, 164, 103, 138,  /* 200 - 207 */
2160     104, 145, 105, 146, 106, 109, 107, 149,  /* 208 - 215 */
2161     108, 200, 109, 146, 110, 170, 111, 157,  /* 216 - 223 */
2162     112, 128, 113, 130, 114, 182, 115, 132,  /* 224 - 231 */
2163     116, 200, 117, 132, 118, 158, 119, 206,  /* 232 - 239 */
2164     120, 240, 121, 162, 122, 147, 123, 152,  /* 240 - 247 */
2165     124, 166, 125, 214, 126, 138, 127, 153,  /* 248 - 255 */
2166   };
2167
2168
2169 /* Return the number of multiplications required to calculate
2170    powi(x,n) where n is less than POWI_TABLE_SIZE.  This is a
2171    subroutine of powi_cost.  CACHE is an array indicating
2172    which exponents have already been calculated.  */
2173
2174 static int
2175 powi_lookup_cost (unsigned HOST_WIDE_INT n, bool *cache)
2176 {
2177   /* If we've already calculated this exponent, then this evaluation
2178      doesn't require any additional multiplications.  */
2179   if (cache[n])
2180     return 0;
2181
2182   cache[n] = true;
2183   return powi_lookup_cost (n - powi_table[n], cache)
2184          + powi_lookup_cost (powi_table[n], cache) + 1;
2185 }
2186
2187 /* Return the number of multiplications required to calculate
2188    powi(x,n) for an arbitrary x, given the exponent N.  This
2189    function needs to be kept in sync with expand_powi below.  */
2190
2191 static int
2192 powi_cost (HOST_WIDE_INT n)
2193 {
2194   bool cache[POWI_TABLE_SIZE];
2195   unsigned HOST_WIDE_INT digit;
2196   unsigned HOST_WIDE_INT val;
2197   int result;
2198
2199   if (n == 0)
2200     return 0;
2201
2202   /* Ignore the reciprocal when calculating the cost.  */
2203   val = (n < 0) ? -n : n;
2204
2205   /* Initialize the exponent cache.  */
2206   memset (cache, 0, POWI_TABLE_SIZE * sizeof (bool));
2207   cache[1] = true;
2208
2209   result = 0;
2210
2211   while (val >= POWI_TABLE_SIZE)
2212     {
2213       if (val & 1)
2214         {
2215           digit = val & ((1 << POWI_WINDOW_SIZE) - 1);
2216           result += powi_lookup_cost (digit, cache)
2217                     + POWI_WINDOW_SIZE + 1;
2218           val >>= POWI_WINDOW_SIZE;
2219         }
2220       else
2221         {
2222           val >>= 1;
2223           result++;
2224         }
2225     }
2226
2227   return result + powi_lookup_cost (val, cache);
2228 }
2229
2230 /* Recursive subroutine of expand_powi.  This function takes the array,
2231    CACHE, of already calculated exponents and an exponent N and returns
2232    an RTX that corresponds to CACHE[1]**N, as calculated in mode MODE.  */
2233
2234 static rtx
2235 expand_powi_1 (enum machine_mode mode, unsigned HOST_WIDE_INT n, rtx *cache)
2236 {
2237   unsigned HOST_WIDE_INT digit;
2238   rtx target, result;
2239   rtx op0, op1;
2240
2241   if (n < POWI_TABLE_SIZE)
2242     {
2243       if (cache[n])
2244         return cache[n];
2245
2246       target = gen_reg_rtx (mode);
2247       cache[n] = target;
2248
2249       op0 = expand_powi_1 (mode, n - powi_table[n], cache);
2250       op1 = expand_powi_1 (mode, powi_table[n], cache);
2251     }
2252   else if (n & 1)
2253     {
2254       target = gen_reg_rtx (mode);
2255       digit = n & ((1 << POWI_WINDOW_SIZE) - 1);
2256       op0 = expand_powi_1 (mode, n - digit, cache);
2257       op1 = expand_powi_1 (mode, digit, cache);
2258     }
2259   else
2260     {
2261       target = gen_reg_rtx (mode);
2262       op0 = expand_powi_1 (mode, n >> 1, cache);
2263       op1 = op0;
2264     }
2265
2266   result = expand_mult (mode, op0, op1, target, 0);
2267   if (result != target)
2268     emit_move_insn (target, result);
2269   return target;
2270 }
2271
2272 /* Expand the RTL to evaluate powi(x,n) in mode MODE.  X is the
2273    floating point operand in mode MODE, and N is the exponent.  This
2274    function needs to be kept in sync with powi_cost above.  */
2275
2276 static rtx
2277 expand_powi (rtx x, enum machine_mode mode, HOST_WIDE_INT n)
2278 {
2279   unsigned HOST_WIDE_INT val;
2280   rtx cache[POWI_TABLE_SIZE];
2281   rtx result;
2282
2283   if (n == 0)
2284     return CONST1_RTX (mode);
2285
2286   val = (n < 0) ? -n : n;
2287
2288   memset (cache, 0, sizeof (cache));
2289   cache[1] = x;
2290
2291   result = expand_powi_1 (mode, (n < 0) ? -n : n, cache);
2292
2293   /* If the original exponent was negative, reciprocate the result.  */
2294   if (n < 0)
2295     result = expand_binop (mode, sdiv_optab, CONST1_RTX (mode),
2296                            result, NULL_RTX, 0, OPTAB_LIB_WIDEN);
2297
2298   return result;
2299 }
2300
2301 /* Expand a call to the pow built-in mathematical function.  Return 0 if
2302    a normal call should be emitted rather than expanding the function
2303    in-line.  EXP is the expression that is a call to the builtin
2304    function; if convenient, the result should be placed in TARGET.  */
2305
2306 static rtx
2307 expand_builtin_pow (tree exp, rtx target, rtx subtarget)
2308 {
2309   tree arglist = TREE_OPERAND (exp, 1);
2310   tree arg0, arg1;
2311
2312   if (! validate_arglist (arglist, REAL_TYPE, REAL_TYPE, VOID_TYPE))
2313     return 0;
2314
2315   arg0 = TREE_VALUE (arglist);
2316   arg1 = TREE_VALUE (TREE_CHAIN (arglist));
2317
2318   if (TREE_CODE (arg1) == REAL_CST
2319       && ! TREE_CONSTANT_OVERFLOW (arg1))
2320     {
2321       REAL_VALUE_TYPE cint;
2322       REAL_VALUE_TYPE c;
2323       HOST_WIDE_INT n;
2324
2325       c = TREE_REAL_CST (arg1);
2326       n = real_to_integer (&c);
2327       real_from_integer (&cint, VOIDmode, n, n < 0 ? -1 : 0, 0);
2328       if (real_identical (&c, &cint))
2329         {
2330           /* If the exponent is -1, 0, 1 or 2, then expand_powi is exact.
2331              Otherwise, check the number of multiplications required.
2332              Note that pow never sets errno for an integer exponent.  */
2333           if ((n >= -1 && n <= 2)
2334               || (flag_unsafe_math_optimizations
2335                   && ! optimize_size
2336                   && powi_cost (n) <= POWI_MAX_MULTS))
2337             {
2338               enum machine_mode mode = TYPE_MODE (TREE_TYPE (exp));
2339               rtx op = expand_expr (arg0, subtarget, VOIDmode, 0);
2340               op = force_reg (mode, op);
2341               return expand_powi (op, mode, n);
2342             }
2343         }
2344     }
2345
2346   if (! flag_unsafe_math_optimizations)
2347     return NULL_RTX;
2348   return expand_builtin_mathfn_2 (exp, target, subtarget);
2349 }
2350
2351 /* Expand expression EXP which is a call to the strlen builtin.  Return 0
2352    if we failed the caller should emit a normal call, otherwise
2353    try to get the result in TARGET, if convenient.  */
2354
2355 static rtx
2356 expand_builtin_strlen (tree arglist, rtx target,
2357                        enum machine_mode target_mode)
2358 {
2359   if (!validate_arglist (arglist, POINTER_TYPE, VOID_TYPE))
2360     return 0;
2361   else
2362     {
2363       rtx pat;
2364       tree len, src = TREE_VALUE (arglist);
2365       rtx result, src_reg, char_rtx, before_strlen;
2366       enum machine_mode insn_mode = target_mode, char_mode;
2367       enum insn_code icode = CODE_FOR_nothing;
2368       int align;
2369
2370       /* If the length can be computed at compile-time, return it.  */
2371       len = c_strlen (src, 0);
2372       if (len)
2373         return expand_expr (len, target, target_mode, EXPAND_NORMAL);
2374
2375       /* If the length can be computed at compile-time and is constant
2376          integer, but there are side-effects in src, evaluate
2377          src for side-effects, then return len.
2378          E.g. x = strlen (i++ ? "xfoo" + 1 : "bar");
2379          can be optimized into: i++; x = 3;  */
2380       len = c_strlen (src, 1);
2381       if (len && TREE_CODE (len) == INTEGER_CST)
2382         {
2383           expand_expr (src, const0_rtx, VOIDmode, EXPAND_NORMAL);
2384           return expand_expr (len, target, target_mode, EXPAND_NORMAL);
2385         }
2386
2387       align = get_pointer_alignment (src, BIGGEST_ALIGNMENT) / BITS_PER_UNIT;
2388
2389       /* If SRC is not a pointer type, don't do this operation inline.  */
2390       if (align == 0)
2391         return 0;
2392
2393       /* Bail out if we can't compute strlen in the right mode.  */
2394       while (insn_mode != VOIDmode)
2395         {
2396           icode = strlen_optab->handlers[(int) insn_mode].insn_code;
2397           if (icode != CODE_FOR_nothing)
2398             break;
2399
2400           insn_mode = GET_MODE_WIDER_MODE (insn_mode);
2401         }
2402       if (insn_mode == VOIDmode)
2403         return 0;
2404
2405       /* Make a place to write the result of the instruction.  */
2406       result = target;
2407       if (! (result != 0
2408              && REG_P (result)
2409              && GET_MODE (result) == insn_mode
2410              && REGNO (result) >= FIRST_PSEUDO_REGISTER))
2411         result = gen_reg_rtx (insn_mode);
2412
2413       /* Make a place to hold the source address.  We will not expand
2414          the actual source until we are sure that the expansion will
2415          not fail -- there are trees that cannot be expanded twice.  */
2416       src_reg = gen_reg_rtx (Pmode);
2417
2418       /* Mark the beginning of the strlen sequence so we can emit the
2419          source operand later.  */
2420       before_strlen = get_last_insn ();
2421
2422       char_rtx = const0_rtx;
2423       char_mode = insn_data[(int) icode].operand[2].mode;
2424       if (! (*insn_data[(int) icode].operand[2].predicate) (char_rtx,
2425                                                             char_mode))
2426         char_rtx = copy_to_mode_reg (char_mode, char_rtx);
2427
2428       pat = GEN_FCN (icode) (result, gen_rtx_MEM (BLKmode, src_reg),
2429                              char_rtx, GEN_INT (align));
2430       if (! pat)
2431         return 0;
2432       emit_insn (pat);
2433
2434       /* Now that we are assured of success, expand the source.  */
2435       start_sequence ();
2436       pat = memory_address (BLKmode,
2437                             expand_expr (src, src_reg, ptr_mode, EXPAND_SUM));
2438       if (pat != src_reg)
2439         emit_move_insn (src_reg, pat);
2440       pat = get_insns ();
2441       end_sequence ();
2442
2443       if (before_strlen)
2444         emit_insn_after (pat, before_strlen);
2445       else
2446         emit_insn_before (pat, get_insns ());
2447
2448       /* Return the value in the proper mode for this function.  */
2449       if (GET_MODE (result) == target_mode)
2450         target = result;
2451       else if (target != 0)
2452         convert_move (target, result, 0);
2453       else
2454         target = convert_to_mode (target_mode, result, 0);
2455
2456       return target;
2457     }
2458 }
2459
2460 /* Expand a call to the strstr builtin.  Return 0 if we failed the
2461    caller should emit a normal call, otherwise try to get the result
2462    in TARGET, if convenient (and in mode MODE if that's convenient).  */
2463
2464 static rtx
2465 expand_builtin_strstr (tree arglist, rtx target, enum machine_mode mode)
2466 {
2467   if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
2468     return 0;
2469   else
2470     {
2471       tree s1 = TREE_VALUE (arglist), s2 = TREE_VALUE (TREE_CHAIN (arglist));
2472       tree fn, tmp;
2473       const char *p1, *p2;
2474
2475       p2 = c_getstr (s2);
2476       if (p2 == NULL)
2477         return 0;
2478
2479       p1 = c_getstr (s1);
2480       if (p1 != NULL)
2481         {
2482           const char *r = strstr (p1, p2);
2483
2484           if (r == NULL)
2485             return const0_rtx;
2486
2487           /* Return an offset into the constant string argument.  */
2488           tmp = fold (build2 (PLUS_EXPR, TREE_TYPE (s1), s1,
2489                               fold_convert (TREE_TYPE (s1),
2490                                             ssize_int (r - p1))));
2491           return expand_expr (tmp, target, mode, EXPAND_NORMAL);
2492         }
2493
2494       if (p2[0] == '\0')
2495         return expand_expr (s1, target, mode, EXPAND_NORMAL);
2496
2497       if (p2[1] != '\0')
2498         return 0;
2499
2500       fn = implicit_built_in_decls[BUILT_IN_STRCHR];
2501       if (!fn)
2502         return 0;
2503
2504       /* New argument list transforming strstr(s1, s2) to
2505          strchr(s1, s2[0]).  */
2506       arglist =
2507         build_tree_list (NULL_TREE, build_int_2 (p2[0], 0));
2508       arglist = tree_cons (NULL_TREE, s1, arglist);
2509       return expand_expr (build_function_call_expr (fn, arglist),
2510                           target, mode, EXPAND_NORMAL);
2511     }
2512 }
2513
2514 /* Expand a call to the strchr builtin.  Return 0 if we failed the
2515    caller should emit a normal call, otherwise try to get the result
2516    in TARGET, if convenient (and in mode MODE if that's convenient).  */
2517
2518 static rtx
2519 expand_builtin_strchr (tree arglist, rtx target, enum machine_mode mode)
2520 {
2521   if (!validate_arglist (arglist, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
2522     return 0;
2523   else
2524     {
2525       tree s1 = TREE_VALUE (arglist), s2 = TREE_VALUE (TREE_CHAIN (arglist));
2526       const char *p1;
2527
2528       if (TREE_CODE (s2) != INTEGER_CST)
2529         return 0;
2530
2531       p1 = c_getstr (s1);
2532       if (p1 != NULL)
2533         {
2534           char c;
2535           const char *r;
2536           tree tmp;
2537
2538           if (target_char_cast (s2, &c))
2539             return 0;
2540
2541           r = strchr (p1, c);
2542
2543           if (r == NULL)
2544             return const0_rtx;
2545
2546           /* Return an offset into the constant string argument.  */
2547           tmp = fold (build2 (PLUS_EXPR, TREE_TYPE (s1), s1,
2548                               fold_convert (TREE_TYPE (s1),
2549                                             ssize_int (r - p1))));
2550           return expand_expr (tmp, target, mode, EXPAND_NORMAL);
2551         }
2552
2553       /* FIXME: Should use here strchrM optab so that ports can optimize
2554          this.  */
2555       return 0;
2556     }
2557 }
2558
2559 /* Expand a call to the strrchr builtin.  Return 0 if we failed the
2560    caller should emit a normal call, otherwise try to get the result
2561    in TARGET, if convenient (and in mode MODE if that's convenient).  */
2562
2563 static rtx
2564 expand_builtin_strrchr (tree arglist, rtx target, enum machine_mode mode)
2565 {
2566   if (!validate_arglist (arglist, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
2567     return 0;
2568   else
2569     {
2570       tree s1 = TREE_VALUE (arglist), s2 = TREE_VALUE (TREE_CHAIN (arglist));
2571       tree fn, tmp;
2572       const char *p1;
2573
2574       if (TREE_CODE (s2) != INTEGER_CST)
2575         return 0;
2576
2577       p1 = c_getstr (s1);
2578       if (p1 != NULL)
2579         {
2580           char c;
2581           const char *r;
2582
2583           if (target_char_cast (s2, &c))
2584             return 0;
2585
2586           r = strrchr (p1, c);
2587
2588           if (r == NULL)
2589             return const0_rtx;
2590
2591           /* Return an offset into the constant string argument.  */
2592           tmp = fold (build2 (PLUS_EXPR, TREE_TYPE (s1), s1,
2593                               fold_convert (TREE_TYPE (s1),
2594                                             ssize_int (r - p1))));
2595           return expand_expr (tmp, target, mode, EXPAND_NORMAL);
2596         }
2597
2598       if (! integer_zerop (s2))
2599         return 0;
2600
2601       fn = implicit_built_in_decls[BUILT_IN_STRCHR];
2602       if (!fn)
2603         return 0;
2604
2605       /* Transform strrchr(s1, '\0') to strchr(s1, '\0').  */
2606       return expand_expr (build_function_call_expr (fn, arglist),
2607                           target, mode, EXPAND_NORMAL);
2608     }
2609 }
2610
2611 /* Expand a call to the strpbrk builtin.  Return 0 if we failed the
2612    caller should emit a normal call, otherwise try to get the result
2613    in TARGET, if convenient (and in mode MODE if that's convenient).  */
2614
2615 static rtx
2616 expand_builtin_strpbrk (tree arglist, rtx target, enum machine_mode mode)
2617 {
2618   if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
2619     return 0;
2620   else
2621     {
2622       tree s1 = TREE_VALUE (arglist), s2 = TREE_VALUE (TREE_CHAIN (arglist));
2623       tree fn, tmp;
2624       const char *p1, *p2;
2625
2626       p2 = c_getstr (s2);
2627       if (p2 == NULL)
2628         return 0;
2629
2630       p1 = c_getstr (s1);
2631       if (p1 != NULL)
2632         {
2633           const char *r = strpbrk (p1, p2);
2634
2635           if (r == NULL)
2636             return const0_rtx;
2637
2638           /* Return an offset into the constant string argument.  */
2639           tmp = fold (build2 (PLUS_EXPR, TREE_TYPE (s1), s1,
2640                               fold_convert (TREE_TYPE (s1),
2641                                             ssize_int (r - p1))));
2642           return expand_expr (tmp, target, mode, EXPAND_NORMAL);
2643         }
2644
2645       if (p2[0] == '\0')
2646         {
2647           /* strpbrk(x, "") == NULL.
2648              Evaluate and ignore the arguments in case they had
2649              side-effects.  */
2650           expand_expr (s1, const0_rtx, VOIDmode, EXPAND_NORMAL);
2651           return const0_rtx;
2652         }
2653
2654       if (p2[1] != '\0')
2655         return 0;  /* Really call strpbrk.  */
2656
2657       fn = implicit_built_in_decls[BUILT_IN_STRCHR];
2658       if (!fn)
2659         return 0;
2660
2661       /* New argument list transforming strpbrk(s1, s2) to
2662          strchr(s1, s2[0]).  */
2663       arglist =
2664         build_tree_list (NULL_TREE, build_int_2 (p2[0], 0));
2665       arglist = tree_cons (NULL_TREE, s1, arglist);
2666       return expand_expr (build_function_call_expr (fn, arglist),
2667                           target, mode, EXPAND_NORMAL);
2668     }
2669 }
2670
2671 /* Callback routine for store_by_pieces.  Read GET_MODE_BITSIZE (MODE)
2672    bytes from constant string DATA + OFFSET and return it as target
2673    constant.  */
2674
2675 static rtx
2676 builtin_memcpy_read_str (void *data, HOST_WIDE_INT offset,
2677                          enum machine_mode mode)
2678 {
2679   const char *str = (const char *) data;
2680
2681   if (offset < 0
2682       || ((unsigned HOST_WIDE_INT) offset + GET_MODE_SIZE (mode)
2683           > strlen (str) + 1))
2684     abort ();  /* Attempt to read past the end of constant string.  */
2685
2686   return c_readstr (str + offset, mode);
2687 }
2688
2689 /* Expand a call to the memcpy builtin, with arguments in ARGLIST.
2690    Return 0 if we failed, the caller should emit a normal call,
2691    otherwise try to get the result in TARGET, if convenient (and in
2692    mode MODE if that's convenient).  */
2693 static rtx
2694 expand_builtin_memcpy (tree arglist, rtx target, enum machine_mode mode)
2695 {
2696   if (!validate_arglist (arglist,
2697                          POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
2698     return 0;
2699   else
2700     {
2701       tree dest = TREE_VALUE (arglist);
2702       tree src = TREE_VALUE (TREE_CHAIN (arglist));
2703       tree len = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
2704       const char *src_str;
2705       unsigned int src_align = get_pointer_alignment (src, BIGGEST_ALIGNMENT);
2706       unsigned int dest_align
2707         = get_pointer_alignment (dest, BIGGEST_ALIGNMENT);
2708       rtx dest_mem, src_mem, dest_addr, len_rtx;
2709
2710       /* If DEST is not a pointer type, call the normal function.  */
2711       if (dest_align == 0)
2712         return 0;
2713
2714       /* If the LEN parameter is zero, return DEST.  */
2715       if (integer_zerop (len))
2716         {
2717           /* Evaluate and ignore SRC in case it has side-effects.  */
2718           expand_expr (src, const0_rtx, VOIDmode, EXPAND_NORMAL);
2719           return expand_expr (dest, target, mode, EXPAND_NORMAL);
2720         }
2721
2722       /* If SRC and DEST are the same (and not volatile), return DEST.  */
2723       if (operand_equal_p (src, dest, 0))
2724         {
2725           /* Evaluate and ignore LEN in case it has side-effects.  */
2726           expand_expr (len, const0_rtx, VOIDmode, EXPAND_NORMAL);
2727           return expand_expr (dest, target, mode, EXPAND_NORMAL);
2728         }
2729
2730       /* If either SRC is not a pointer type, don't do this
2731          operation in-line.  */
2732       if (src_align == 0)
2733         return 0;
2734
2735       dest_mem = get_memory_rtx (dest);
2736       set_mem_align (dest_mem, dest_align);
2737       len_rtx = expand_expr (len, NULL_RTX, VOIDmode, 0);
2738       src_str = c_getstr (src);
2739
2740       /* If SRC is a string constant and block move would be done
2741          by pieces, we can avoid loading the string from memory
2742          and only stored the computed constants.  */
2743       if (src_str
2744           && GET_CODE (len_rtx) == CONST_INT
2745           && (unsigned HOST_WIDE_INT) INTVAL (len_rtx) <= strlen (src_str) + 1
2746           && can_store_by_pieces (INTVAL (len_rtx), builtin_memcpy_read_str,
2747                                   (void *) src_str, dest_align))
2748         {
2749           dest_mem = store_by_pieces (dest_mem, INTVAL (len_rtx),
2750                                       builtin_memcpy_read_str,
2751                                       (void *) src_str, dest_align, 0);
2752           dest_mem = force_operand (XEXP (dest_mem, 0), NULL_RTX);
2753           dest_mem = convert_memory_address (ptr_mode, dest_mem);
2754           return dest_mem;
2755         }
2756
2757       src_mem = get_memory_rtx (src);
2758       set_mem_align (src_mem, src_align);
2759
2760       /* Copy word part most expediently.  */
2761       dest_addr = emit_block_move (dest_mem, src_mem, len_rtx,
2762                                    BLOCK_OP_NORMAL);
2763
2764       if (dest_addr == 0)
2765         {
2766           dest_addr = force_operand (XEXP (dest_mem, 0), NULL_RTX);
2767           dest_addr = convert_memory_address (ptr_mode, dest_addr);
2768         }
2769       return dest_addr;
2770     }
2771 }
2772
2773 /* Expand a call to the mempcpy builtin, with arguments in ARGLIST.
2774    Return 0 if we failed the caller should emit a normal call,
2775    otherwise try to get the result in TARGET, if convenient (and in
2776    mode MODE if that's convenient).  If ENDP is 0 return the
2777    destination pointer, if ENDP is 1 return the end pointer ala
2778    mempcpy, and if ENDP is 2 return the end pointer minus one ala
2779    stpcpy.  */
2780
2781 static rtx
2782 expand_builtin_mempcpy (tree arglist, rtx target, enum machine_mode mode,
2783                         int endp)
2784 {
2785   if (!validate_arglist (arglist,
2786                          POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
2787     return 0;
2788   /* If return value is ignored, transform mempcpy into memcpy.  */
2789   else if (target == const0_rtx)
2790     {
2791       tree fn = implicit_built_in_decls[BUILT_IN_MEMCPY];
2792
2793       if (!fn)
2794         return 0;
2795
2796       return expand_expr (build_function_call_expr (fn, arglist),
2797                           target, mode, EXPAND_NORMAL);
2798     }
2799   else
2800     {
2801       tree dest = TREE_VALUE (arglist);
2802       tree src = TREE_VALUE (TREE_CHAIN (arglist));
2803       tree len = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
2804       const char *src_str;
2805       unsigned int src_align = get_pointer_alignment (src, BIGGEST_ALIGNMENT);
2806       unsigned int dest_align
2807         = get_pointer_alignment (dest, BIGGEST_ALIGNMENT);
2808       rtx dest_mem, src_mem, len_rtx;
2809
2810       /* If DEST is not a pointer type, call the normal function.  */
2811       if (dest_align == 0)
2812         return 0;
2813
2814       /* If SRC and DEST are the same (and not volatile), do nothing.  */
2815       if (operand_equal_p (src, dest, 0))
2816         {
2817           tree expr;
2818
2819           if (endp == 0)
2820             {
2821               /* Evaluate and ignore LEN in case it has side-effects.  */
2822               expand_expr (len, const0_rtx, VOIDmode, EXPAND_NORMAL);
2823               return expand_expr (dest, target, mode, EXPAND_NORMAL);
2824             }
2825
2826           if (endp == 2)
2827             len = fold (build2 (MINUS_EXPR, TREE_TYPE (len), len,
2828                                 integer_one_node));
2829           len = fold_convert (TREE_TYPE (dest), len);
2830           expr = fold (build2 (PLUS_EXPR, TREE_TYPE (dest), dest, len));
2831           return expand_expr (expr, target, mode, EXPAND_NORMAL);
2832         }
2833
2834       /* If LEN is not constant, call the normal function.  */
2835       if (! host_integerp (len, 1))
2836         return 0;
2837
2838       /* If the LEN parameter is zero, return DEST.  */
2839       if (tree_low_cst (len, 1) == 0)
2840         {
2841           /* Evaluate and ignore SRC in case it has side-effects.  */
2842           expand_expr (src, const0_rtx, VOIDmode, EXPAND_NORMAL);
2843           return expand_expr (dest, target, mode, EXPAND_NORMAL);
2844         }
2845
2846       /* If either SRC is not a pointer type, don't do this
2847          operation in-line.  */
2848       if (src_align == 0)
2849         return 0;
2850
2851       len_rtx = expand_expr (len, NULL_RTX, VOIDmode, 0);
2852       src_str = c_getstr (src);
2853
2854       /* If SRC is a string constant and block move would be done
2855          by pieces, we can avoid loading the string from memory
2856          and only stored the computed constants.  */
2857       if (src_str
2858           && GET_CODE (len_rtx) == CONST_INT
2859           && (unsigned HOST_WIDE_INT) INTVAL (len_rtx) <= strlen (src_str) + 1
2860           && can_store_by_pieces (INTVAL (len_rtx), builtin_memcpy_read_str,
2861                                   (void *) src_str, dest_align))
2862         {
2863           dest_mem = get_memory_rtx (dest);
2864           set_mem_align (dest_mem, dest_align);
2865           dest_mem = store_by_pieces (dest_mem, INTVAL (len_rtx),
2866                                       builtin_memcpy_read_str,
2867                                       (void *) src_str, dest_align, endp);
2868           dest_mem = force_operand (XEXP (dest_mem, 0), NULL_RTX);
2869           dest_mem = convert_memory_address (ptr_mode, dest_mem);
2870           return dest_mem;
2871         }
2872
2873       if (GET_CODE (len_rtx) == CONST_INT
2874           && can_move_by_pieces (INTVAL (len_rtx),
2875                                  MIN (dest_align, src_align)))
2876         {
2877           dest_mem = get_memory_rtx (dest);
2878           set_mem_align (dest_mem, dest_align);
2879           src_mem = get_memory_rtx (src);
2880           set_mem_align (src_mem, src_align);
2881           dest_mem = move_by_pieces (dest_mem, src_mem, INTVAL (len_rtx),
2882                                      MIN (dest_align, src_align), endp);
2883           dest_mem = force_operand (XEXP (dest_mem, 0), NULL_RTX);
2884           dest_mem = convert_memory_address (ptr_mode, dest_mem);
2885           return dest_mem;
2886         }
2887
2888       return 0;
2889     }
2890 }
2891
2892 /* Expand expression EXP, which is a call to the memmove builtin.  Return 0
2893    if we failed the caller should emit a normal call.  */
2894
2895 static rtx
2896 expand_builtin_memmove (tree arglist, rtx target, enum machine_mode mode)
2897 {
2898   if (!validate_arglist (arglist,
2899                          POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
2900     return 0;
2901   else
2902     {
2903       tree dest = TREE_VALUE (arglist);
2904       tree src = TREE_VALUE (TREE_CHAIN (arglist));
2905       tree len = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
2906
2907       unsigned int src_align = get_pointer_alignment (src, BIGGEST_ALIGNMENT);
2908       unsigned int dest_align
2909         = get_pointer_alignment (dest, BIGGEST_ALIGNMENT);
2910
2911       /* If DEST is not a pointer type, call the normal function.  */
2912       if (dest_align == 0)
2913         return 0;
2914
2915       /* If the LEN parameter is zero, return DEST.  */
2916       if (integer_zerop (len))
2917         {
2918           /* Evaluate and ignore SRC in case it has side-effects.  */
2919           expand_expr (src, const0_rtx, VOIDmode, EXPAND_NORMAL);
2920           return expand_expr (dest, target, mode, EXPAND_NORMAL);
2921         }
2922
2923       /* If SRC and DEST are the same (and not volatile), return DEST.  */
2924       if (operand_equal_p (src, dest, 0))
2925         {
2926           /* Evaluate and ignore LEN in case it has side-effects.  */
2927           expand_expr (len, const0_rtx, VOIDmode, EXPAND_NORMAL);
2928           return expand_expr (dest, target, mode, EXPAND_NORMAL);
2929         }
2930
2931       /* If either SRC is not a pointer type, don't do this
2932          operation in-line.  */
2933       if (src_align == 0)
2934         return 0;
2935
2936       /* If src is categorized for a readonly section we can use
2937          normal memcpy.  */
2938       if (readonly_data_expr (src))
2939         {
2940           tree const fn = implicit_built_in_decls[BUILT_IN_MEMCPY];
2941           if (!fn)
2942             return 0;
2943           return expand_expr (build_function_call_expr (fn, arglist),
2944                               target, mode, EXPAND_NORMAL);
2945         }
2946
2947       /* Otherwise, call the normal function.  */
2948       return 0;
2949    }
2950 }
2951
2952 /* Expand expression EXP, which is a call to the bcopy builtin.  Return 0
2953    if we failed the caller should emit a normal call.  */
2954
2955 static rtx
2956 expand_builtin_bcopy (tree arglist)
2957 {
2958   tree src, dest, size, newarglist;
2959
2960   if (!validate_arglist (arglist,
2961                          POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
2962     return NULL_RTX;
2963
2964   src = TREE_VALUE (arglist);
2965   dest = TREE_VALUE (TREE_CHAIN (arglist));
2966   size = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
2967
2968   /* New argument list transforming bcopy(ptr x, ptr y, int z) to
2969      memmove(ptr y, ptr x, size_t z).   This is done this way
2970      so that if it isn't expanded inline, we fallback to
2971      calling bcopy instead of memmove.  */
2972
2973   newarglist = build_tree_list (NULL_TREE, fold_convert (sizetype, size));
2974   newarglist = tree_cons (NULL_TREE, src, newarglist);
2975   newarglist = tree_cons (NULL_TREE, dest, newarglist);
2976
2977   return expand_builtin_memmove (newarglist, const0_rtx, VOIDmode);
2978 }
2979
2980 #ifndef HAVE_movstr
2981 # define HAVE_movstr 0
2982 # define CODE_FOR_movstr CODE_FOR_nothing
2983 #endif
2984
2985 /* Expand into a movstr instruction, if one is available.  Return 0 if
2986    we failed, the caller should emit a normal call, otherwise try to
2987    get the result in TARGET, if convenient.  If ENDP is 0 return the
2988    destination pointer, if ENDP is 1 return the end pointer ala
2989    mempcpy, and if ENDP is 2 return the end pointer minus one ala
2990    stpcpy.  */
2991
2992 static rtx
2993 expand_movstr (tree dest, tree src, rtx target, int endp)
2994 {
2995   rtx end;
2996   rtx dest_mem;
2997   rtx src_mem;
2998   rtx insn;
2999   const struct insn_data * data;
3000
3001   if (!HAVE_movstr)
3002     return 0;
3003
3004   dest_mem = get_memory_rtx (dest);
3005   src_mem = get_memory_rtx (src);
3006   if (!endp)
3007     {
3008       target = force_reg (Pmode, XEXP (dest_mem, 0));
3009       dest_mem = replace_equiv_address (dest_mem, target);
3010       end = gen_reg_rtx (Pmode);
3011     }
3012   else
3013     {
3014       if (target == 0 || target == const0_rtx)
3015         {
3016           end = gen_reg_rtx (Pmode);
3017           if (target == 0)
3018             target = end;
3019         }
3020       else
3021         end = target;
3022     }
3023
3024   data = insn_data + CODE_FOR_movstr;
3025
3026   if (data->operand[0].mode != VOIDmode)
3027     end = gen_lowpart (data->operand[0].mode, end);
3028
3029   insn = data->genfun (end, dest_mem, src_mem);
3030
3031   if (insn == 0)
3032     abort ();
3033
3034   emit_insn (insn);
3035
3036   /* movstr is supposed to set end to the address of the NUL
3037      terminator.  If the caller requested a mempcpy-like return value,
3038      adjust it.  */
3039   if (endp == 1 && target != const0_rtx)
3040     emit_move_insn (target, plus_constant (gen_lowpart (GET_MODE (target),
3041                                                         end), 1));
3042
3043   return target;
3044 }
3045
3046 /* Expand expression EXP, which is a call to the strcpy builtin.  Return 0
3047    if we failed the caller should emit a normal call, otherwise try to get
3048    the result in TARGET, if convenient (and in mode MODE if that's
3049    convenient).  */
3050
3051 static rtx
3052 expand_builtin_strcpy (tree arglist, rtx target, enum machine_mode mode)
3053 {
3054   tree fn, len, src, dst;
3055
3056   if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
3057     return 0;
3058
3059   src = TREE_VALUE (TREE_CHAIN (arglist));
3060   dst = TREE_VALUE (arglist);
3061
3062   /* If SRC and DST are equal (and not volatile), return DST.  */
3063   if (operand_equal_p (src, dst, 0))
3064     return expand_expr (dst, target, mode, EXPAND_NORMAL);
3065
3066   len = c_strlen (src, 1);
3067   if (len == 0 || TREE_SIDE_EFFECTS (len))
3068     return expand_movstr (TREE_VALUE (arglist),
3069                           TREE_VALUE (TREE_CHAIN (arglist)),
3070                           target, /*endp=*/0);
3071
3072   fn = implicit_built_in_decls[BUILT_IN_MEMCPY];
3073   if (!fn)
3074     return 0;
3075
3076   len = size_binop (PLUS_EXPR, len, ssize_int (1));
3077   arglist = build_tree_list (NULL_TREE, len);
3078   arglist = tree_cons (NULL_TREE, src, arglist);
3079   arglist = tree_cons (NULL_TREE, dst, arglist);
3080   return expand_expr (build_function_call_expr (fn, arglist),
3081                       target, mode, EXPAND_NORMAL);
3082 }
3083
3084 /* Expand a call to the stpcpy builtin, with arguments in ARGLIST.
3085    Return 0 if we failed the caller should emit a normal call,
3086    otherwise try to get the result in TARGET, if convenient (and in
3087    mode MODE if that's convenient).  */
3088
3089 static rtx
3090 expand_builtin_stpcpy (tree arglist, rtx target, enum machine_mode mode)
3091 {
3092   /* If return value is ignored, transform stpcpy into strcpy.  */
3093   if (target == const0_rtx)
3094     {
3095       tree fn = implicit_built_in_decls[BUILT_IN_STRCPY];
3096       if (!fn)
3097         return 0;
3098
3099       return expand_expr (build_function_call_expr (fn, arglist),
3100                           target, mode, EXPAND_NORMAL);
3101     }
3102
3103   if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
3104     return 0;
3105   else
3106     {
3107       tree dst, src, len, lenp1;
3108       tree narglist;
3109       rtx ret;
3110
3111       /* Ensure we get an actual string whose length can be evaluated at
3112          compile-time, not an expression containing a string.  This is
3113          because the latter will potentially produce pessimized code
3114          when used to produce the return value.  */
3115       src = TREE_VALUE (TREE_CHAIN (arglist));
3116       if (! c_getstr (src) || ! (len = c_strlen (src, 0)))
3117         return expand_movstr (TREE_VALUE (arglist),
3118                               TREE_VALUE (TREE_CHAIN (arglist)),
3119                               target, /*endp=*/2);
3120
3121       dst = TREE_VALUE (arglist);
3122       lenp1 = size_binop (PLUS_EXPR, len, ssize_int (1));
3123       narglist = build_tree_list (NULL_TREE, lenp1);
3124       narglist = tree_cons (NULL_TREE, src, narglist);
3125       narglist = tree_cons (NULL_TREE, dst, narglist);
3126       ret = expand_builtin_mempcpy (narglist, target, mode, /*endp=*/2);
3127
3128       if (ret)
3129         return ret;
3130
3131       if (TREE_CODE (len) == INTEGER_CST)
3132         {
3133           rtx len_rtx = expand_expr (len, NULL_RTX, VOIDmode, 0);
3134
3135           if (GET_CODE (len_rtx) == CONST_INT)
3136             {
3137               ret = expand_builtin_strcpy (arglist, target, mode);
3138
3139               if (ret)
3140                 {
3141                   if (! target)
3142                     target = gen_reg_rtx (mode);
3143                   if (GET_MODE (target) != GET_MODE (ret))
3144                     ret = gen_lowpart (GET_MODE (target), ret);
3145
3146                   ret = emit_move_insn (target,
3147                                         plus_constant (ret,
3148                                                        INTVAL (len_rtx)));
3149                   if (! ret)
3150                     abort ();
3151
3152                   return target;
3153                 }
3154             }
3155         }
3156
3157       return expand_movstr (TREE_VALUE (arglist),
3158                             TREE_VALUE (TREE_CHAIN (arglist)),
3159                             target, /*endp=*/2);
3160     }
3161 }
3162
3163 /* Callback routine for store_by_pieces.  Read GET_MODE_BITSIZE (MODE)
3164    bytes from constant string DATA + OFFSET and return it as target
3165    constant.  */
3166
3167 static rtx
3168 builtin_strncpy_read_str (void *data, HOST_WIDE_INT offset,
3169                           enum machine_mode mode)
3170 {
3171   const char *str = (const char *) data;
3172
3173   if ((unsigned HOST_WIDE_INT) offset > strlen (str))
3174     return const0_rtx;
3175
3176   return c_readstr (str + offset, mode);
3177 }
3178
3179 /* Expand expression EXP, which is a call to the strncpy builtin.  Return 0
3180    if we failed the caller should emit a normal call.  */
3181
3182 static rtx
3183 expand_builtin_strncpy (tree arglist, rtx target, enum machine_mode mode)
3184 {
3185   if (!validate_arglist (arglist,
3186                          POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
3187     return 0;
3188   else
3189     {
3190       tree slen = c_strlen (TREE_VALUE (TREE_CHAIN (arglist)), 1);
3191       tree len = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
3192       tree fn;
3193
3194       /* We must be passed a constant len parameter.  */
3195       if (TREE_CODE (len) != INTEGER_CST)
3196         return 0;
3197
3198       /* If the len parameter is zero, return the dst parameter.  */
3199       if (integer_zerop (len))
3200         {
3201           /* Evaluate and ignore the src argument in case it has
3202              side-effects.  */
3203           expand_expr (TREE_VALUE (TREE_CHAIN (arglist)), const0_rtx,
3204                        VOIDmode, EXPAND_NORMAL);
3205           /* Return the dst parameter.  */
3206           return expand_expr (TREE_VALUE (arglist), target, mode,
3207                               EXPAND_NORMAL);
3208         }
3209
3210       /* Now, we must be passed a constant src ptr parameter.  */
3211       if (slen == 0 || TREE_CODE (slen) != INTEGER_CST)
3212         return 0;
3213
3214       slen = size_binop (PLUS_EXPR, slen, ssize_int (1));
3215
3216       /* We're required to pad with trailing zeros if the requested
3217          len is greater than strlen(s2)+1.  In that case try to
3218          use store_by_pieces, if it fails, punt.  */
3219       if (tree_int_cst_lt (slen, len))
3220         {
3221           tree dest = TREE_VALUE (arglist);
3222           unsigned int dest_align
3223             = get_pointer_alignment (dest, BIGGEST_ALIGNMENT);
3224           const char *p = c_getstr (TREE_VALUE (TREE_CHAIN (arglist)));
3225           rtx dest_mem;
3226
3227           if (!p || dest_align == 0 || !host_integerp (len, 1)
3228               || !can_store_by_pieces (tree_low_cst (len, 1),
3229                                        builtin_strncpy_read_str,
3230                                        (void *) p, dest_align))
3231             return 0;
3232
3233           dest_mem = get_memory_rtx (dest);
3234           store_by_pieces (dest_mem, tree_low_cst (len, 1),
3235                            builtin_strncpy_read_str,
3236                            (void *) p, dest_align, 0);
3237           dest_mem = force_operand (XEXP (dest_mem, 0), NULL_RTX);
3238           dest_mem = convert_memory_address (ptr_mode, dest_mem);
3239           return dest_mem;
3240         }
3241
3242       /* OK transform into builtin memcpy.  */
3243       fn = implicit_built_in_decls[BUILT_IN_MEMCPY];
3244       if (!fn)
3245         return 0;
3246       return expand_expr (build_function_call_expr (fn, arglist),
3247                           target, mode, EXPAND_NORMAL);
3248     }
3249 }
3250
3251 /* Callback routine for store_by_pieces.  Read GET_MODE_BITSIZE (MODE)
3252    bytes from constant string DATA + OFFSET and return it as target
3253    constant.  */
3254
3255 static rtx
3256 builtin_memset_read_str (void *data, HOST_WIDE_INT offset ATTRIBUTE_UNUSED,
3257                          enum machine_mode mode)
3258 {
3259   const char *c = (const char *) data;
3260   char *p = alloca (GET_MODE_SIZE (mode));
3261
3262   memset (p, *c, GET_MODE_SIZE (mode));
3263
3264   return c_readstr (p, mode);
3265 }
3266
3267 /* Callback routine for store_by_pieces.  Return the RTL of a register
3268    containing GET_MODE_SIZE (MODE) consecutive copies of the unsigned
3269    char value given in the RTL register data.  For example, if mode is
3270    4 bytes wide, return the RTL for 0x01010101*data.  */
3271
3272 static rtx
3273 builtin_memset_gen_str (void *data, HOST_WIDE_INT offset ATTRIBUTE_UNUSED,
3274                         enum machine_mode mode)
3275 {
3276   rtx target, coeff;
3277   size_t size;
3278   char *p;
3279
3280   size = GET_MODE_SIZE (mode);
3281   if (size == 1)
3282     return (rtx) data;
3283
3284   p = alloca (size);
3285   memset (p, 1, size);
3286   coeff = c_readstr (p, mode);
3287
3288   target = convert_to_mode (mode, (rtx) data, 1);
3289   target = expand_mult (mode, target, coeff, NULL_RTX, 1);
3290   return force_reg (mode, target);
3291 }
3292
3293 /* Expand expression EXP, which is a call to the memset builtin.  Return 0
3294    if we failed the caller should emit a normal call, otherwise try to get
3295    the result in TARGET, if convenient (and in mode MODE if that's
3296    convenient).  */
3297
3298 static rtx
3299 expand_builtin_memset (tree arglist, rtx target, enum machine_mode mode)
3300 {
3301   if (!validate_arglist (arglist,
3302                          POINTER_TYPE, INTEGER_TYPE, INTEGER_TYPE, VOID_TYPE))
3303     return 0;
3304   else
3305     {
3306       tree dest = TREE_VALUE (arglist);
3307       tree val = TREE_VALUE (TREE_CHAIN (arglist));
3308       tree len = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
3309       char c;
3310
3311       unsigned int dest_align
3312         = get_pointer_alignment (dest, BIGGEST_ALIGNMENT);
3313       rtx dest_mem, dest_addr, len_rtx;
3314
3315       /* If DEST is not a pointer type, don't do this
3316          operation in-line.  */
3317       if (dest_align == 0)
3318         return 0;
3319
3320       /* If the LEN parameter is zero, return DEST.  */
3321       if (integer_zerop (len))
3322         {
3323           /* Evaluate and ignore VAL in case it has side-effects.  */
3324           expand_expr (val, const0_rtx, VOIDmode, EXPAND_NORMAL);
3325           return expand_expr (dest, target, mode, EXPAND_NORMAL);
3326         }
3327
3328       if (TREE_CODE (val) != INTEGER_CST)
3329         {
3330           rtx val_rtx;
3331
3332           if (!host_integerp (len, 1))
3333             return 0;
3334
3335           if (optimize_size && tree_low_cst (len, 1) > 1)
3336             return 0;
3337
3338           /* Assume that we can memset by pieces if we can store the
3339            * the coefficients by pieces (in the required modes).
3340            * We can't pass builtin_memset_gen_str as that emits RTL.  */
3341           c = 1;
3342           if (!can_store_by_pieces (tree_low_cst (len, 1),
3343                                     builtin_memset_read_str,
3344                                     &c, dest_align))
3345             return 0;
3346
3347           val = fold (build1 (CONVERT_EXPR, unsigned_char_type_node, val));
3348           val_rtx = expand_expr (val, NULL_RTX, VOIDmode, 0);
3349           val_rtx = force_reg (TYPE_MODE (unsigned_char_type_node),
3350                                val_rtx);
3351           dest_mem = get_memory_rtx (dest);
3352           store_by_pieces (dest_mem, tree_low_cst (len, 1),
3353                            builtin_memset_gen_str,
3354                            val_rtx, dest_align, 0);
3355           dest_mem = force_operand (XEXP (dest_mem, 0), NULL_RTX);
3356           dest_mem = convert_memory_address (ptr_mode, dest_mem);
3357           return dest_mem;
3358         }
3359
3360       if (target_char_cast (val, &c))
3361         return 0;
3362
3363       if (c)
3364         {
3365           if (!host_integerp (len, 1))
3366             return 0;
3367           if (!can_store_by_pieces (tree_low_cst (len, 1),
3368                                     builtin_memset_read_str, &c,
3369                                     dest_align))
3370             return 0;
3371
3372           dest_mem = get_memory_rtx (dest);
3373           store_by_pieces (dest_mem, tree_low_cst (len, 1),
3374                            builtin_memset_read_str,
3375                            &c, dest_align, 0);
3376           dest_mem = force_operand (XEXP (dest_mem, 0), NULL_RTX);
3377           dest_mem = convert_memory_address (ptr_mode, dest_mem);
3378           return dest_mem;
3379         }
3380
3381       len_rtx = expand_expr (len, NULL_RTX, VOIDmode, 0);
3382
3383       dest_mem = get_memory_rtx (dest);
3384       set_mem_align (dest_mem, dest_align);
3385       dest_addr = clear_storage (dest_mem, len_rtx);
3386
3387       if (dest_addr == 0)
3388         {
3389           dest_addr = force_operand (XEXP (dest_mem, 0), NULL_RTX);
3390           dest_addr = convert_memory_address (ptr_mode, dest_addr);
3391         }
3392
3393       return dest_addr;
3394     }
3395 }
3396
3397 /* Expand expression EXP, which is a call to the bzero builtin.  Return 0
3398    if we failed the caller should emit a normal call.  */
3399
3400 static rtx
3401 expand_builtin_bzero (tree arglist)
3402 {
3403   tree dest, size, newarglist;
3404
3405   if (!validate_arglist (arglist, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
3406     return NULL_RTX;
3407
3408   dest = TREE_VALUE (arglist);
3409   size = TREE_VALUE (TREE_CHAIN (arglist));
3410
3411   /* New argument list transforming bzero(ptr x, int y) to
3412      memset(ptr x, int 0, size_t y).   This is done this way
3413      so that if it isn't expanded inline, we fallback to
3414      calling bzero instead of memset.  */
3415
3416   newarglist = build_tree_list (NULL_TREE, fold_convert (sizetype, size));
3417   newarglist = tree_cons (NULL_TREE, integer_zero_node, newarglist);
3418   newarglist = tree_cons (NULL_TREE, dest, newarglist);
3419
3420   return expand_builtin_memset (newarglist, const0_rtx, VOIDmode);
3421 }
3422
3423 /* Expand expression EXP, which is a call to the memcmp built-in function.
3424    ARGLIST is the argument list for this call.  Return 0 if we failed and the
3425    caller should emit a normal call, otherwise try to get the result in
3426    TARGET, if convenient (and in mode MODE, if that's convenient).  */
3427
3428 static rtx
3429 expand_builtin_memcmp (tree exp ATTRIBUTE_UNUSED, tree arglist, rtx target,
3430                        enum machine_mode mode)
3431 {
3432   tree arg1, arg2, len;
3433   const char *p1, *p2;
3434
3435   if (!validate_arglist (arglist,
3436                          POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
3437     return 0;
3438
3439   arg1 = TREE_VALUE (arglist);
3440   arg2 = TREE_VALUE (TREE_CHAIN (arglist));
3441   len = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
3442
3443   /* If the len parameter is zero, return zero.  */
3444   if (integer_zerop (len))
3445     {
3446       /* Evaluate and ignore arg1 and arg2 in case they have
3447          side-effects.  */
3448       expand_expr (arg1, const0_rtx, VOIDmode, EXPAND_NORMAL);
3449       expand_expr (arg2, const0_rtx, VOIDmode, EXPAND_NORMAL);
3450       return const0_rtx;
3451     }
3452
3453   /* If both arguments are equal (and not volatile), return zero.  */
3454   if (operand_equal_p (arg1, arg2, 0))
3455     {
3456       /* Evaluate and ignore len in case it has side-effects.  */
3457       expand_expr (len, const0_rtx, VOIDmode, EXPAND_NORMAL);
3458       return const0_rtx;
3459     }
3460
3461   p1 = c_getstr (arg1);
3462   p2 = c_getstr (arg2);
3463
3464   /* If all arguments are constant, and the value of len is not greater
3465      than the lengths of arg1 and arg2, evaluate at compile-time.  */
3466   if (host_integerp (len, 1) && p1 && p2
3467       && compare_tree_int (len, strlen (p1) + 1) <= 0
3468       && compare_tree_int (len, strlen (p2) + 1) <= 0)
3469     {
3470       const int r = memcmp (p1, p2, tree_low_cst (len, 1));
3471
3472       return (r < 0 ? constm1_rtx : (r > 0 ? const1_rtx : const0_rtx));
3473     }
3474
3475   /* If len parameter is one, return an expression corresponding to
3476      (*(const unsigned char*)arg1 - (const unsigned char*)arg2).  */
3477   if (integer_onep (len))
3478     {
3479       tree cst_uchar_node = build_type_variant (unsigned_char_type_node, 1, 0);
3480       tree cst_uchar_ptr_node = build_pointer_type (cst_uchar_node);
3481       tree ind1 =
3482       fold (build1 (CONVERT_EXPR, integer_type_node,
3483                     build1 (INDIRECT_REF, cst_uchar_node,
3484                             fold_convert (cst_uchar_ptr_node, arg1))));
3485       tree ind2 =
3486       fold (build1 (CONVERT_EXPR, integer_type_node,
3487                     build1 (INDIRECT_REF, cst_uchar_node,
3488                             fold_convert (cst_uchar_ptr_node, arg2))));
3489       tree result = fold (build2 (MINUS_EXPR, integer_type_node, ind1, ind2));
3490       return expand_expr (result, target, mode, EXPAND_NORMAL);
3491     }
3492
3493 #if defined HAVE_cmpmemsi || defined HAVE_cmpstrsi
3494   {
3495     rtx arg1_rtx, arg2_rtx, arg3_rtx;
3496     rtx result;
3497     rtx insn;
3498
3499     int arg1_align
3500       = get_pointer_alignment (arg1, BIGGEST_ALIGNMENT) / BITS_PER_UNIT;
3501     int arg2_align
3502       = get_pointer_alignment (arg2, BIGGEST_ALIGNMENT) / BITS_PER_UNIT;
3503     enum machine_mode insn_mode;
3504
3505 #ifdef HAVE_cmpmemsi
3506     if (HAVE_cmpmemsi)
3507       insn_mode = insn_data[(int) CODE_FOR_cmpmemsi].operand[0].mode;
3508     else
3509 #endif
3510 #ifdef HAVE_cmpstrsi
3511     if (HAVE_cmpstrsi)
3512       insn_mode = insn_data[(int) CODE_FOR_cmpstrsi].operand[0].mode;
3513     else
3514 #endif
3515       return 0;
3516
3517     /* If we don't have POINTER_TYPE, call the function.  */
3518     if (arg1_align == 0 || arg2_align == 0)
3519       return 0;
3520
3521     /* Make a place to write the result of the instruction.  */
3522     result = target;
3523     if (! (result != 0
3524            && REG_P (result) && GET_MODE (result) == insn_mode
3525            && REGNO (result) >= FIRST_PSEUDO_REGISTER))
3526       result = gen_reg_rtx (insn_mode);
3527
3528     arg1_rtx = get_memory_rtx (arg1);
3529     arg2_rtx = get_memory_rtx (arg2);
3530     arg3_rtx = expand_expr (len, NULL_RTX, VOIDmode, 0);
3531 #ifdef HAVE_cmpmemsi
3532     if (HAVE_cmpmemsi)
3533       insn = gen_cmpmemsi (result, arg1_rtx, arg2_rtx, arg3_rtx,
3534                            GEN_INT (MIN (arg1_align, arg2_align)));
3535     else
3536 #endif
3537 #ifdef HAVE_cmpstrsi
3538     if (HAVE_cmpstrsi)
3539       insn = gen_cmpstrsi (result, arg1_rtx, arg2_rtx, arg3_rtx,
3540                            GEN_INT (MIN (arg1_align, arg2_align)));
3541     else
3542 #endif
3543       abort ();
3544
3545     if (insn)
3546       emit_insn (insn);
3547     else
3548       emit_library_call_value (memcmp_libfunc, result, LCT_PURE_MAKE_BLOCK,
3549                                TYPE_MODE (integer_type_node), 3,
3550                                XEXP (arg1_rtx, 0), Pmode,
3551                                XEXP (arg2_rtx, 0), Pmode,
3552                                convert_to_mode (TYPE_MODE (sizetype), arg3_rtx,
3553                                                 TYPE_UNSIGNED (sizetype)),
3554                                TYPE_MODE (sizetype));
3555
3556     /* Return the value in the proper mode for this function.  */
3557     mode = TYPE_MODE (TREE_TYPE (exp));
3558     if (GET_MODE (result) == mode)
3559       return result;
3560     else if (target != 0)
3561       {
3562         convert_move (target, result, 0);
3563         return target;
3564       }
3565     else
3566       return convert_to_mode (mode, result, 0);
3567   }
3568 #endif
3569
3570   return 0;
3571 }
3572
3573 /* Expand expression EXP, which is a call to the strcmp builtin.  Return 0
3574    if we failed the caller should emit a normal call, otherwise try to get
3575    the result in TARGET, if convenient.  */
3576
3577 static rtx
3578 expand_builtin_strcmp (tree exp, rtx target, enum machine_mode mode)
3579 {
3580   tree arglist = TREE_OPERAND (exp, 1);
3581   tree arg1, arg2;
3582   const char *p1, *p2;
3583
3584   if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
3585     return 0;
3586
3587   arg1 = TREE_VALUE (arglist);
3588   arg2 = TREE_VALUE (TREE_CHAIN (arglist));
3589
3590   /* If both arguments are equal (and not volatile), return zero.  */
3591   if (operand_equal_p (arg1, arg2, 0))
3592     return const0_rtx;
3593
3594   p1 = c_getstr (arg1);
3595   p2 = c_getstr (arg2);
3596
3597   if (p1 && p2)
3598     {
3599       const int i = strcmp (p1, p2);
3600       return (i < 0 ? constm1_rtx : (i > 0 ? const1_rtx : const0_rtx));
3601     }
3602
3603   /* If either arg is "", return an expression corresponding to
3604      (*(const unsigned char*)arg1 - (const unsigned char*)arg2).  */
3605   if ((p1 && *p1 == '\0') || (p2 && *p2 == '\0'))
3606     {
3607       tree cst_uchar_node = build_type_variant (unsigned_char_type_node, 1, 0);
3608       tree cst_uchar_ptr_node = build_pointer_type (cst_uchar_node);
3609       tree ind1 =
3610         fold (build1 (CONVERT_EXPR, integer_type_node,
3611                       build1 (INDIRECT_REF, cst_uchar_node,
3612                               fold_convert (cst_uchar_ptr_node, arg1))));
3613       tree ind2 =
3614         fold (build1 (CONVERT_EXPR, integer_type_node,
3615                       build1 (INDIRECT_REF, cst_uchar_node,
3616                               fold_convert (cst_uchar_ptr_node, arg2))));
3617       tree result = fold (build2 (MINUS_EXPR, integer_type_node, ind1, ind2));
3618       return expand_expr (result, target, mode, EXPAND_NORMAL);
3619     }
3620
3621 #ifdef HAVE_cmpstrsi
3622   if (HAVE_cmpstrsi)
3623   {
3624     tree len, len1, len2;
3625     rtx arg1_rtx, arg2_rtx, arg3_rtx;
3626     rtx result, insn;
3627     tree fndecl;
3628
3629     int arg1_align
3630       = get_pointer_alignment (arg1, BIGGEST_ALIGNMENT) / BITS_PER_UNIT;
3631     int arg2_align
3632       = get_pointer_alignment (arg2, BIGGEST_ALIGNMENT) / BITS_PER_UNIT;
3633     enum machine_mode insn_mode
3634       = insn_data[(int) CODE_FOR_cmpstrsi].operand[0].mode;
3635
3636     len1 = c_strlen (arg1, 1);
3637     len2 = c_strlen (arg2, 1);
3638
3639     if (len1)
3640       len1 = size_binop (PLUS_EXPR, ssize_int (1), len1);
3641     if (len2)
3642       len2 = size_binop (PLUS_EXPR, ssize_int (1), len2);
3643
3644     /* If we don't have a constant length for the first, use the length
3645        of the second, if we know it.  We don't require a constant for
3646        this case; some cost analysis could be done if both are available
3647        but neither is constant.  For now, assume they're equally cheap,
3648        unless one has side effects.  If both strings have constant lengths,
3649        use the smaller.  */
3650
3651     if (!len1)
3652       len = len2;
3653     else if (!len2)
3654       len = len1;
3655     else if (TREE_SIDE_EFFECTS (len1))
3656       len = len2;
3657     else if (TREE_SIDE_EFFECTS (len2))
3658       len = len1;
3659     else if (TREE_CODE (len1) != INTEGER_CST)
3660       len = len2;
3661     else if (TREE_CODE (len2) != INTEGER_CST)
3662       len = len1;
3663     else if (tree_int_cst_lt (len1, len2))
3664       len = len1;
3665     else
3666       len = len2;
3667
3668     /* If both arguments have side effects, we cannot optimize.  */
3669     if (!len || TREE_SIDE_EFFECTS (len))
3670       return 0;
3671
3672     /* If we don't have POINTER_TYPE, call the function.  */
3673     if (arg1_align == 0 || arg2_align == 0)
3674       return 0;
3675
3676     /* Make a place to write the result of the instruction.  */
3677     result = target;
3678     if (! (result != 0
3679            && REG_P (result) && GET_MODE (result) == insn_mode
3680            && REGNO (result) >= FIRST_PSEUDO_REGISTER))
3681       result = gen_reg_rtx (insn_mode);
3682
3683     /* Stabilize the arguments in case gen_cmpstrsi fails.  */
3684     arg1 = builtin_save_expr (arg1);
3685     arg2 = builtin_save_expr (arg2);
3686
3687     arg1_rtx = get_memory_rtx (arg1);
3688     arg2_rtx = get_memory_rtx (arg2);
3689     arg3_rtx = expand_expr (len, NULL_RTX, VOIDmode, 0);
3690     insn = gen_cmpstrsi (result, arg1_rtx, arg2_rtx, arg3_rtx,
3691                          GEN_INT (MIN (arg1_align, arg2_align)));
3692     if (insn)
3693       {
3694         emit_insn (insn);
3695
3696         /* Return the value in the proper mode for this function.  */
3697         mode = TYPE_MODE (TREE_TYPE (exp));
3698         if (GET_MODE (result) == mode)
3699           return result;
3700         if (target == 0)
3701           return convert_to_mode (mode, result, 0);
3702         convert_move (target, result, 0);
3703         return target;
3704       }
3705
3706     /* Expand the library call ourselves using a stabilized argument
3707        list to avoid re-evaluating the function's arguments twice.  */
3708     arglist = build_tree_list (NULL_TREE, arg2);
3709     arglist = tree_cons (NULL_TREE, arg1, arglist);
3710     fndecl = get_callee_fndecl (exp);
3711     exp = build_function_call_expr (fndecl, arglist);
3712     return expand_call (exp, target, target == const0_rtx);
3713   }
3714 #endif
3715   return 0;
3716 }
3717
3718 /* Expand expression EXP, which is a call to the strncmp builtin.  Return 0
3719    if we failed the caller should emit a normal call, otherwise try to get
3720    the result in TARGET, if convenient.  */
3721
3722 static rtx
3723 expand_builtin_strncmp (tree exp, rtx target, enum machine_mode mode)
3724 {
3725   tree arglist = TREE_OPERAND (exp, 1);
3726   tree arg1, arg2, arg3;
3727   const char *p1, *p2;
3728
3729   if (!validate_arglist (arglist,
3730                          POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
3731     return 0;
3732
3733   arg1 = TREE_VALUE (arglist);
3734   arg2 = TREE_VALUE (TREE_CHAIN (arglist));
3735   arg3 = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
3736
3737   /* If the len parameter is zero, return zero.  */
3738   if (integer_zerop (arg3))
3739     {
3740       /* Evaluate and ignore arg1 and arg2 in case they have
3741          side-effects.  */
3742       expand_expr (arg1, const0_rtx, VOIDmode, EXPAND_NORMAL);
3743       expand_expr (arg2, const0_rtx, VOIDmode, EXPAND_NORMAL);
3744       return const0_rtx;
3745     }
3746
3747   /* If arg1 and arg2 are equal (and not volatile), return zero.  */
3748   if (operand_equal_p (arg1, arg2, 0))
3749     {
3750       /* Evaluate and ignore arg3 in case it has side-effects.  */
3751       expand_expr (arg3, const0_rtx, VOIDmode, EXPAND_NORMAL);
3752       return const0_rtx;
3753     }
3754
3755   p1 = c_getstr (arg1);
3756   p2 = c_getstr (arg2);
3757
3758   /* If all arguments are constant, evaluate at compile-time.  */
3759   if (host_integerp (arg3, 1) && p1 && p2)
3760     {
3761       const int r = strncmp (p1, p2, tree_low_cst (arg3, 1));
3762       return (r < 0 ? constm1_rtx : (r > 0 ? const1_rtx : const0_rtx));
3763     }
3764
3765   /* If len == 1 or (either string parameter is "" and (len >= 1)),
3766       return (*(const u_char*)arg1 - *(const u_char*)arg2).  */
3767   if (host_integerp (arg3, 1)
3768       && (tree_low_cst (arg3, 1) == 1
3769           || (tree_low_cst (arg3, 1) > 1
3770               && ((p1 && *p1 == '\0') || (p2 && *p2 == '\0')))))
3771     {
3772       tree cst_uchar_node = build_type_variant (unsigned_char_type_node, 1, 0);
3773       tree cst_uchar_ptr_node = build_pointer_type (cst_uchar_node);
3774       tree ind1 =
3775         fold (build1 (CONVERT_EXPR, integer_type_node,
3776                       build1 (INDIRECT_REF, cst_uchar_node,
3777                               fold_convert (cst_uchar_ptr_node, arg1))));
3778       tree ind2 =
3779         fold (build1 (CONVERT_EXPR, integer_type_node,
3780                       build1 (INDIRECT_REF, cst_uchar_node,
3781                               fold_convert (cst_uchar_ptr_node, arg2))));
3782       tree result = fold (build2 (MINUS_EXPR, integer_type_node, ind1, ind2));
3783       return expand_expr (result, target, mode, EXPAND_NORMAL);
3784     }
3785
3786   /* If c_strlen can determine an expression for one of the string
3787      lengths, and it doesn't have side effects, then emit cmpstrsi
3788      using length MIN(strlen(string)+1, arg3).  */
3789 #ifdef HAVE_cmpstrsi
3790   if (HAVE_cmpstrsi)
3791   {
3792     tree len, len1, len2;
3793     rtx arg1_rtx, arg2_rtx, arg3_rtx;
3794     rtx result, insn;
3795     tree fndecl;
3796
3797     int arg1_align
3798       = get_pointer_alignment (arg1, BIGGEST_ALIGNMENT) / BITS_PER_UNIT;
3799     int arg2_align
3800       = get_pointer_alignment (arg2, BIGGEST_ALIGNMENT) / BITS_PER_UNIT;
3801     enum machine_mode insn_mode
3802       = insn_data[(int) CODE_FOR_cmpstrsi].operand[0].mode;
3803
3804     len1 = c_strlen (arg1, 1);
3805     len2 = c_strlen (arg2, 1);
3806
3807     if (len1)
3808       len1 = size_binop (PLUS_EXPR, ssize_int (1), len1);
3809     if (len2)
3810       len2 = size_binop (PLUS_EXPR, ssize_int (1), len2);
3811
3812     /* If we don't have a constant length for the first, use the length
3813        of the second, if we know it.  We don't require a constant for
3814        this case; some cost analysis could be done if both are available
3815        but neither is constant.  For now, assume they're equally cheap,
3816        unless one has side effects.  If both strings have constant lengths,
3817        use the smaller.  */
3818
3819     if (!len1)
3820       len = len2;
3821     else if (!len2)
3822       len = len1;
3823     else if (TREE_SIDE_EFFECTS (len1))
3824       len = len2;
3825     else if (TREE_SIDE_EFFECTS (len2))
3826       len = len1;
3827     else if (TREE_CODE (len1) != INTEGER_CST)
3828       len = len2;
3829     else if (TREE_CODE (len2) != INTEGER_CST)
3830       len = len1;
3831     else if (tree_int_cst_lt (len1, len2))
3832       len = len1;
3833     else
3834       len = len2;
3835
3836     /* If both arguments have side effects, we cannot optimize.  */
3837     if (!len || TREE_SIDE_EFFECTS (len))
3838       return 0;
3839
3840     /* The actual new length parameter is MIN(len,arg3).  */
3841     len = fold (build2 (MIN_EXPR, TREE_TYPE (len), len, arg3));
3842
3843     /* If we don't have POINTER_TYPE, call the function.  */
3844     if (arg1_align == 0 || arg2_align == 0)
3845       return 0;
3846
3847     /* Make a place to write the result of the instruction.  */
3848     result = target;
3849     if (! (result != 0
3850            && REG_P (result) && GET_MODE (result) == insn_mode
3851            && REGNO (result) >= FIRST_PSEUDO_REGISTER))
3852       result = gen_reg_rtx (insn_mode);
3853
3854     /* Stabilize the arguments in case gen_cmpstrsi fails.  */
3855     arg1 = builtin_save_expr (arg1);
3856     arg2 = builtin_save_expr (arg2);
3857     len = builtin_save_expr (len);
3858
3859     arg1_rtx = get_memory_rtx (arg1);
3860     arg2_rtx = get_memory_rtx (arg2);
3861     arg3_rtx = expand_expr (len, NULL_RTX, VOIDmode, 0);
3862     insn = gen_cmpstrsi (result, arg1_rtx, arg2_rtx, arg3_rtx,
3863                          GEN_INT (MIN (arg1_align, arg2_align)));
3864     if (insn)
3865       {
3866         emit_insn (insn);
3867
3868         /* Return the value in the proper mode for this function.  */
3869         mode = TYPE_MODE (TREE_TYPE (exp));
3870         if (GET_MODE (result) == mode)
3871           return result;
3872         if (target == 0)
3873           return convert_to_mode (mode, result, 0);
3874         convert_move (target, result, 0);
3875         return target;
3876       }
3877
3878     /* Expand the library call ourselves using a stabilized argument
3879        list to avoid re-evaluating the function's arguments twice.  */
3880     arglist = build_tree_list (NULL_TREE, len);
3881     arglist = tree_cons (NULL_TREE, arg2, arglist);
3882     arglist = tree_cons (NULL_TREE, arg1, arglist);
3883     fndecl = get_callee_fndecl (exp);
3884     exp = build_function_call_expr (fndecl, arglist);
3885     return expand_call (exp, target, target == const0_rtx);
3886   }
3887 #endif
3888   return 0;
3889 }
3890
3891 /* Expand expression EXP, which is a call to the strcat builtin.
3892    Return 0 if we failed the caller should emit a normal call,
3893    otherwise try to get the result in TARGET, if convenient.  */
3894
3895 static rtx
3896 expand_builtin_strcat (tree arglist, rtx target, enum machine_mode mode)
3897 {
3898   if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
3899     return 0;
3900   else
3901     {
3902       tree dst = TREE_VALUE (arglist),
3903         src = TREE_VALUE (TREE_CHAIN (arglist));
3904       const char *p = c_getstr (src);
3905
3906       if (p)
3907         {
3908           /* If the string length is zero, return the dst parameter.  */
3909           if (*p == '\0')
3910             return expand_expr (dst, target, mode, EXPAND_NORMAL);
3911           else if (!optimize_size)
3912             {
3913               /* Otherwise if !optimize_size, see if we can store by
3914                  pieces into (dst + strlen(dst)).  */
3915               tree newdst, arglist,
3916                 strlen_fn = implicit_built_in_decls[BUILT_IN_STRLEN];
3917
3918               /* This is the length argument.  */
3919               arglist = build_tree_list (NULL_TREE,
3920                                          fold (size_binop (PLUS_EXPR,
3921                                                            c_strlen (src, 0),
3922                                                            ssize_int (1))));
3923               /* Prepend src argument.  */
3924               arglist = tree_cons (NULL_TREE, src, arglist);
3925
3926               /* We're going to use dst more than once.  */
3927               dst = builtin_save_expr (dst);
3928
3929               /* Create strlen (dst).  */
3930               newdst =
3931                 fold (build_function_call_expr (strlen_fn,
3932                                                 build_tree_list (NULL_TREE,
3933                                                                  dst)));
3934               /* Create (dst + strlen (dst)).  */
3935               newdst = fold (build2 (PLUS_EXPR, TREE_TYPE (dst), dst, newdst));
3936
3937               /* Prepend the new dst argument.  */
3938               arglist = tree_cons (NULL_TREE, newdst, arglist);
3939
3940               /* We don't want to get turned into a memcpy if the
3941                  target is const0_rtx, i.e. when the return value
3942                  isn't used.  That would produce pessimized code so
3943                  pass in a target of zero, it should never actually be
3944                  used.  If this was successful return the original
3945                  dst, not the result of mempcpy.  */
3946               if (expand_builtin_mempcpy (arglist, /*target=*/0, mode, /*endp=*/0))
3947                 return expand_expr (dst, target, mode, EXPAND_NORMAL);
3948               else
3949                 return 0;
3950             }
3951         }
3952
3953       return 0;
3954     }
3955 }
3956
3957 /* Expand expression EXP, which is a call to the strncat builtin.
3958    Return 0 if we failed the caller should emit a normal call,
3959    otherwise try to get the result in TARGET, if convenient.  */
3960
3961 static rtx
3962 expand_builtin_strncat (tree arglist, rtx target, enum machine_mode mode)
3963 {
3964   if (!validate_arglist (arglist,
3965                          POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
3966     return 0;
3967   else
3968     {
3969       tree dst = TREE_VALUE (arglist),
3970         src = TREE_VALUE (TREE_CHAIN (arglist)),
3971         len = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
3972       const char *p = c_getstr (src);
3973
3974       /* If the requested length is zero, or the src parameter string
3975           length is zero, return the dst parameter.  */
3976       if (integer_zerop (len) || (p && *p == '\0'))
3977         {
3978           /* Evaluate and ignore the src and len parameters in case
3979              they have side-effects.  */
3980           expand_expr (src, const0_rtx, VOIDmode, EXPAND_NORMAL);
3981           expand_expr (len, const0_rtx, VOIDmode, EXPAND_NORMAL);
3982           return expand_expr (dst, target, mode, EXPAND_NORMAL);
3983         }
3984
3985       /* If the requested len is greater than or equal to the string
3986          length, call strcat.  */
3987       if (TREE_CODE (len) == INTEGER_CST && p
3988           && compare_tree_int (len, strlen (p)) >= 0)
3989         {
3990           tree newarglist
3991             = tree_cons (NULL_TREE, dst, build_tree_list (NULL_TREE, src));
3992           tree fn = implicit_built_in_decls[BUILT_IN_STRCAT];
3993
3994           /* If the replacement _DECL isn't initialized, don't do the
3995              transformation.  */
3996           if (!fn)
3997             return 0;
3998
3999           return expand_expr (build_function_call_expr (fn, newarglist),
4000                               target, mode, EXPAND_NORMAL);
4001         }
4002       return 0;
4003     }
4004 }
4005
4006 /* Expand expression EXP, which is a call to the strspn builtin.
4007    Return 0 if we failed the caller should emit a normal call,
4008    otherwise try to get the result in TARGET, if convenient.  */
4009
4010 static rtx
4011 expand_builtin_strspn (tree arglist, rtx target, enum machine_mode mode)
4012 {
4013   if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
4014     return 0;
4015   else
4016     {
4017       tree s1 = TREE_VALUE (arglist), s2 = TREE_VALUE (TREE_CHAIN (arglist));
4018       const char *p1 = c_getstr (s1), *p2 = c_getstr (s2);
4019
4020       /* If both arguments are constants, evaluate at compile-time.  */
4021       if (p1 && p2)
4022         {
4023           const size_t r = strspn (p1, p2);
4024           return expand_expr (size_int (r), target, mode, EXPAND_NORMAL);
4025         }
4026
4027       /* If either argument is "", return 0.  */
4028       if ((p1 && *p1 == '\0') || (p2 && *p2 == '\0'))
4029         {
4030           /* Evaluate and ignore both arguments in case either one has
4031              side-effects.  */
4032           expand_expr (s1, const0_rtx, VOIDmode, EXPAND_NORMAL);
4033           expand_expr (s2, const0_rtx, VOIDmode, EXPAND_NORMAL);
4034           return const0_rtx;
4035         }
4036       return 0;
4037     }
4038 }
4039
4040 /* Expand expression EXP, which is a call to the strcspn builtin.
4041    Return 0 if we failed the caller should emit a normal call,
4042    otherwise try to get the result in TARGET, if convenient.  */
4043
4044 static rtx
4045 expand_builtin_strcspn (tree arglist, rtx target, enum machine_mode mode)
4046 {
4047   if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
4048     return 0;
4049   else
4050     {
4051       tree s1 = TREE_VALUE (arglist), s2 = TREE_VALUE (TREE_CHAIN (arglist));
4052       const char *p1 = c_getstr (s1), *p2 = c_getstr (s2);
4053
4054       /* If both arguments are constants, evaluate at compile-time.  */
4055       if (p1 && p2)
4056         {
4057           const size_t r = strcspn (p1, p2);
4058           return expand_expr (size_int (r), target, mode, EXPAND_NORMAL);
4059         }
4060
4061       /* If the first argument is "", return 0.  */
4062       if (p1 && *p1 == '\0')
4063         {
4064           /* Evaluate and ignore argument s2 in case it has
4065              side-effects.  */
4066           expand_expr (s2, const0_rtx, VOIDmode, EXPAND_NORMAL);
4067           return const0_rtx;
4068         }
4069
4070       /* If the second argument is "", return __builtin_strlen(s1).  */
4071       if (p2 && *p2 == '\0')
4072         {
4073           tree newarglist = build_tree_list (NULL_TREE, s1),
4074             fn = implicit_built_in_decls[BUILT_IN_STRLEN];
4075
4076           /* If the replacement _DECL isn't initialized, don't do the
4077              transformation.  */
4078           if (!fn)
4079             return 0;
4080
4081           return expand_expr (build_function_call_expr (fn, newarglist),
4082                               target, mode, EXPAND_NORMAL);
4083         }
4084       return 0;
4085     }
4086 }
4087
4088 /* Expand a call to __builtin_saveregs, generating the result in TARGET,
4089    if that's convenient.  */
4090
4091 rtx
4092 expand_builtin_saveregs (void)
4093 {
4094   rtx val, seq;
4095
4096   /* Don't do __builtin_saveregs more than once in a function.
4097      Save the result of the first call and reuse it.  */
4098   if (saveregs_value != 0)
4099     return saveregs_value;
4100
4101   /* When this function is called, it means that registers must be
4102      saved on entry to this function.  So we migrate the call to the
4103      first insn of this function.  */
4104
4105   start_sequence ();
4106
4107   /* Do whatever the machine needs done in this case.  */
4108   val = targetm.calls.expand_builtin_saveregs ();
4109
4110   seq = get_insns ();
4111   end_sequence ();
4112
4113   saveregs_value = val;
4114
4115   /* Put the insns after the NOTE that starts the function.  If this
4116      is inside a start_sequence, make the outer-level insn chain current, so
4117      the code is placed at the start of the function.  */
4118   push_topmost_sequence ();
4119   emit_insn_after (seq, entry_of_function ());
4120   pop_topmost_sequence ();
4121
4122   return val;
4123 }
4124
4125 /* __builtin_args_info (N) returns word N of the arg space info
4126    for the current function.  The number and meanings of words
4127    is controlled by the definition of CUMULATIVE_ARGS.  */
4128
4129 static rtx
4130 expand_builtin_args_info (tree arglist)
4131 {
4132   int nwords = sizeof (CUMULATIVE_ARGS) / sizeof (int);
4133   int *word_ptr = (int *) &current_function_args_info;
4134
4135   if (sizeof (CUMULATIVE_ARGS) % sizeof (int) != 0)
4136     abort ();
4137
4138   if (arglist != 0)
4139     {
4140       if (!host_integerp (TREE_VALUE (arglist), 0))
4141         error ("argument of `__builtin_args_info' must be constant");
4142       else
4143         {
4144           HOST_WIDE_INT wordnum = tree_low_cst (TREE_VALUE (arglist), 0);
4145
4146           if (wordnum < 0 || wordnum >= nwords)
4147             error ("argument of `__builtin_args_info' out of range");
4148           else
4149             return GEN_INT (word_ptr[wordnum]);
4150         }
4151     }
4152   else
4153     error ("missing argument in `__builtin_args_info'");
4154
4155   return const0_rtx;
4156 }
4157
4158 /* Expand ARGLIST, from a call to __builtin_next_arg.  */
4159
4160 static rtx
4161 expand_builtin_next_arg (tree arglist)
4162 {
4163   tree fntype = TREE_TYPE (current_function_decl);
4164
4165   if (TYPE_ARG_TYPES (fntype) == 0
4166       || (TREE_VALUE (tree_last (TYPE_ARG_TYPES (fntype)))
4167           == void_type_node))
4168     {
4169       error ("`va_start' used in function with fixed args");
4170       return const0_rtx;
4171     }
4172
4173   if (arglist)
4174     {
4175       tree last_parm = tree_last (DECL_ARGUMENTS (current_function_decl));
4176       tree arg = TREE_VALUE (arglist);
4177
4178       /* Strip off all nops for the sake of the comparison.  This
4179          is not quite the same as STRIP_NOPS.  It does more.
4180          We must also strip off INDIRECT_EXPR for C++ reference
4181          parameters.  */
4182       while (TREE_CODE (arg) == NOP_EXPR