OSDN Git Service

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