OSDN Git Service

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