Deleted Added
full compact
builtins.c (161660) builtins.c (169699)
1/* Expand builtin functions.
2 Copyright (C) 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
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.
3 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
4
5This file is part of GCC.
6
7GCC is free software; you can redistribute it and/or modify it under
8the terms of the GNU General Public License as published by the Free
9Software Foundation; either version 2, or (at your option) any later
10version.
11
12GCC is distributed in the hope that it will be useful, but WITHOUT ANY
13WARRANTY; without even the implied warranty of MERCHANTABILITY or
14FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15for more details.
16
17You should have received a copy of the GNU General Public License
18along with GCC; see the file COPYING. If not, write to the Free
4
5This file is part of GCC.
6
7GCC is free software; you can redistribute it and/or modify it under
8the terms of the GNU General Public License as published by the Free
9Software Foundation; either version 2, or (at your option) any later
10version.
11
12GCC is distributed in the hope that it will be useful, but WITHOUT ANY
13WARRANTY; without even the implied warranty of MERCHANTABILITY or
14FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15for more details.
16
17You should have received a copy of the GNU General Public License
18along with GCC; see the file COPYING. If not, write to the Free
19Software Foundation, 59 Temple Place - Suite 330, Boston, MA
2002111-1307, USA. */
19Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
2002110-1301, USA. */
21
22#include "config.h"
23#include "system.h"
24#include "coretypes.h"
25#include "tm.h"
26#include "machmode.h"
27#include "real.h"
28#include "rtl.h"
29#include "tree.h"
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"
30#include "flags.h"
31#include "regs.h"
32#include "hard-reg-set.h"
33#include "except.h"
34#include "function.h"
35#include "insn-config.h"
36#include "expr.h"
37#include "optabs.h"
38#include "libfuncs.h"
39#include "recog.h"
40#include "output.h"
41#include "typeclass.h"
42#include "toplev.h"
43#include "predict.h"
44#include "tm_p.h"
45#include "target.h"
46#include "langhooks.h"
31#include "flags.h"
32#include "regs.h"
33#include "hard-reg-set.h"
34#include "except.h"
35#include "function.h"
36#include "insn-config.h"
37#include "expr.h"
38#include "optabs.h"
39#include "libfuncs.h"
40#include "recog.h"
41#include "output.h"
42#include "typeclass.h"
43#include "toplev.h"
44#include "predict.h"
45#include "tm_p.h"
46#include "target.h"
47#include "langhooks.h"
48#include "basic-block.h"
49#include "tree-mudflap.h"
47
50
48#define CALLED_AS_BUILT_IN(NODE) \
49 (!strncmp (IDENTIFIER_POINTER (DECL_NAME (NODE)), "__builtin_", 10))
50
51/* Register mappings for target machines without register windows. */
52#ifndef INCOMING_REGNO
53#define INCOMING_REGNO(OUT) (OUT)
54#endif
55#ifndef OUTGOING_REGNO
56#define OUTGOING_REGNO(IN) (IN)
57#endif
58
59#ifndef PAD_VARARGS_DOWN
60#define PAD_VARARGS_DOWN BYTES_BIG_ENDIAN
61#endif
62
63/* Define the names of the builtin function types and codes. */
64const char *const built_in_class_names[4]
65 = {"NOT_BUILT_IN", "BUILT_IN_FRONTEND", "BUILT_IN_MD", "BUILT_IN_NORMAL"};
66
51#ifndef PAD_VARARGS_DOWN
52#define PAD_VARARGS_DOWN BYTES_BIG_ENDIAN
53#endif
54
55/* Define the names of the builtin function types and codes. */
56const char *const built_in_class_names[4]
57 = {"NOT_BUILT_IN", "BUILT_IN_FRONTEND", "BUILT_IN_MD", "BUILT_IN_NORMAL"};
58
67#define DEF_BUILTIN(X, N, C, T, LT, B, F, NA, AT, IM) #X,
68const char *const built_in_names[(int) END_BUILTINS] =
59#define DEF_BUILTIN(X, N, C, T, LT, B, F, NA, AT, IM, COND) #X,
60const char * built_in_names[(int) END_BUILTINS] =
69{
70#include "builtins.def"
71};
72#undef DEF_BUILTIN
73
74/* Setup an array of _DECL trees, make sure each element is
75 initialized to NULL_TREE. */
76tree built_in_decls[(int) END_BUILTINS];
77/* Declarations used when constructing the builtin implicitly in the compiler.
78 It may be NULL_TREE when this is invalid (for instance runtime is not
61{
62#include "builtins.def"
63};
64#undef DEF_BUILTIN
65
66/* Setup an array of _DECL trees, make sure each element is
67 initialized to NULL_TREE. */
68tree built_in_decls[(int) END_BUILTINS];
69/* Declarations used when constructing the builtin implicitly in the compiler.
70 It may be NULL_TREE when this is invalid (for instance runtime is not
79 required to implement the function call in all cases. */
71 required to implement the function call in all cases). */
80tree implicit_built_in_decls[(int) END_BUILTINS];
81
82static int get_pointer_alignment (tree, unsigned int);
72tree implicit_built_in_decls[(int) END_BUILTINS];
73
74static int get_pointer_alignment (tree, unsigned int);
83static tree c_strlen (tree, int);
84static const char *c_getstr (tree);
85static rtx c_readstr (const char *, enum machine_mode);
86static int target_char_cast (tree, char *);
75static const char *c_getstr (tree);
76static rtx c_readstr (const char *, enum machine_mode);
77static int target_char_cast (tree, char *);
87static rtx get_memory_rtx (tree);
88static tree build_string_literal (int, const char *);
78static rtx get_memory_rtx (tree, tree);
89static int apply_args_size (void);
90static int apply_result_size (void);
91#if defined (HAVE_untyped_call) || defined (HAVE_untyped_return)
92static rtx result_vector (int, rtx);
93#endif
79static int apply_args_size (void);
80static int apply_result_size (void);
81#if defined (HAVE_untyped_call) || defined (HAVE_untyped_return)
82static rtx result_vector (int, rtx);
83#endif
94static rtx expand_builtin_setjmp (tree, rtx);
84static void expand_builtin_update_setjmp_buf (rtx);
95static void expand_builtin_prefetch (tree);
96static rtx expand_builtin_apply_args (void);
97static rtx expand_builtin_apply_args_1 (void);
98static rtx expand_builtin_apply (rtx, rtx, rtx);
99static void expand_builtin_return (rtx);
100static enum type_class type_to_class (tree);
101static rtx expand_builtin_classify_type (tree);
102static void expand_errno_check (tree, rtx);
103static rtx expand_builtin_mathfn (tree, rtx, rtx);
104static rtx expand_builtin_mathfn_2 (tree, rtx, rtx);
85static void expand_builtin_prefetch (tree);
86static rtx expand_builtin_apply_args (void);
87static rtx expand_builtin_apply_args_1 (void);
88static rtx expand_builtin_apply (rtx, rtx, rtx);
89static void expand_builtin_return (rtx);
90static enum type_class type_to_class (tree);
91static rtx expand_builtin_classify_type (tree);
92static void expand_errno_check (tree, rtx);
93static rtx expand_builtin_mathfn (tree, rtx, rtx);
94static rtx expand_builtin_mathfn_2 (tree, rtx, rtx);
105static rtx expand_builtin_constant_p (tree, enum machine_mode);
95static rtx expand_builtin_mathfn_3 (tree, rtx, rtx);
96static rtx expand_builtin_sincos (tree);
97static rtx expand_builtin_int_roundingfn (tree, rtx, rtx);
106static rtx expand_builtin_args_info (tree);
98static rtx expand_builtin_args_info (tree);
107static rtx expand_builtin_next_arg (tree);
99static rtx expand_builtin_next_arg (void);
108static rtx expand_builtin_va_start (tree);
109static rtx expand_builtin_va_end (tree);
110static rtx expand_builtin_va_copy (tree);
111static rtx expand_builtin_memcmp (tree, tree, rtx, enum machine_mode);
112static rtx expand_builtin_strcmp (tree, rtx, enum machine_mode);
113static rtx expand_builtin_strncmp (tree, rtx, enum machine_mode);
114static rtx builtin_memcpy_read_str (void *, HOST_WIDE_INT, enum machine_mode);
100static rtx expand_builtin_va_start (tree);
101static rtx expand_builtin_va_end (tree);
102static rtx expand_builtin_va_copy (tree);
103static rtx expand_builtin_memcmp (tree, tree, rtx, enum machine_mode);
104static rtx expand_builtin_strcmp (tree, rtx, enum machine_mode);
105static rtx expand_builtin_strncmp (tree, rtx, enum machine_mode);
106static rtx builtin_memcpy_read_str (void *, HOST_WIDE_INT, enum machine_mode);
115static rtx expand_builtin_strcat (tree, rtx, enum machine_mode);
107static rtx expand_builtin_strcat (tree, tree, rtx, enum machine_mode);
116static rtx expand_builtin_strncat (tree, rtx, enum machine_mode);
117static rtx expand_builtin_strspn (tree, rtx, enum machine_mode);
118static rtx expand_builtin_strcspn (tree, rtx, enum machine_mode);
119static rtx expand_builtin_memcpy (tree, rtx, enum machine_mode);
108static rtx expand_builtin_strncat (tree, rtx, enum machine_mode);
109static rtx expand_builtin_strspn (tree, rtx, enum machine_mode);
110static rtx expand_builtin_strcspn (tree, rtx, enum machine_mode);
111static rtx expand_builtin_memcpy (tree, rtx, enum machine_mode);
120static rtx expand_builtin_mempcpy (tree, rtx, enum machine_mode, int);
121static rtx expand_builtin_memmove (tree, rtx, enum machine_mode);
112static rtx expand_builtin_mempcpy (tree, tree, rtx, enum machine_mode, int);
113static rtx expand_builtin_memmove (tree, tree, rtx, enum machine_mode, tree);
122static rtx expand_builtin_bcopy (tree);
114static rtx expand_builtin_bcopy (tree);
123static rtx expand_builtin_strcpy (tree, rtx, enum machine_mode);
115static rtx expand_builtin_strcpy (tree, tree, rtx, enum machine_mode);
124static rtx expand_builtin_stpcpy (tree, rtx, enum machine_mode);
125static rtx builtin_strncpy_read_str (void *, HOST_WIDE_INT, enum machine_mode);
126static rtx expand_builtin_strncpy (tree, rtx, enum machine_mode);
127static rtx builtin_memset_read_str (void *, HOST_WIDE_INT, enum machine_mode);
128static rtx builtin_memset_gen_str (void *, HOST_WIDE_INT, enum machine_mode);
116static rtx expand_builtin_stpcpy (tree, rtx, enum machine_mode);
117static rtx builtin_strncpy_read_str (void *, HOST_WIDE_INT, enum machine_mode);
118static rtx expand_builtin_strncpy (tree, rtx, enum machine_mode);
119static rtx builtin_memset_read_str (void *, HOST_WIDE_INT, enum machine_mode);
120static rtx builtin_memset_gen_str (void *, HOST_WIDE_INT, enum machine_mode);
129static rtx expand_builtin_memset (tree, rtx, enum machine_mode);
121static rtx expand_builtin_memset (tree, rtx, enum machine_mode, tree);
130static rtx expand_builtin_bzero (tree);
131static rtx expand_builtin_strlen (tree, rtx, enum machine_mode);
122static rtx expand_builtin_bzero (tree);
123static rtx expand_builtin_strlen (tree, rtx, enum machine_mode);
132static rtx expand_builtin_strstr (tree, rtx, enum machine_mode);
133static rtx expand_builtin_strpbrk (tree, rtx, enum machine_mode);
134static rtx expand_builtin_strchr (tree, rtx, enum machine_mode);
135static rtx expand_builtin_strrchr (tree, rtx, enum machine_mode);
124static rtx expand_builtin_strstr (tree, tree, rtx, enum machine_mode);
125static rtx expand_builtin_strpbrk (tree, tree, rtx, enum machine_mode);
126static rtx expand_builtin_strchr (tree, tree, rtx, enum machine_mode);
127static rtx expand_builtin_strrchr (tree, tree, rtx, enum machine_mode);
136static rtx expand_builtin_alloca (tree, rtx);
137static rtx expand_builtin_unop (enum machine_mode, tree, rtx, rtx, optab);
138static rtx expand_builtin_frame_address (tree, tree);
139static rtx expand_builtin_fputs (tree, rtx, bool);
140static rtx expand_builtin_printf (tree, rtx, enum machine_mode, bool);
141static rtx expand_builtin_fprintf (tree, rtx, enum machine_mode, bool);
142static rtx expand_builtin_sprintf (tree, rtx, enum machine_mode);
143static tree stabilize_va_list (tree, int);
144static rtx expand_builtin_expect (tree, rtx);
145static tree fold_builtin_constant_p (tree);
146static tree fold_builtin_classify_type (tree);
128static rtx expand_builtin_alloca (tree, rtx);
129static rtx expand_builtin_unop (enum machine_mode, tree, rtx, rtx, optab);
130static rtx expand_builtin_frame_address (tree, tree);
131static rtx expand_builtin_fputs (tree, rtx, bool);
132static rtx expand_builtin_printf (tree, rtx, enum machine_mode, bool);
133static rtx expand_builtin_fprintf (tree, rtx, enum machine_mode, bool);
134static rtx expand_builtin_sprintf (tree, rtx, enum machine_mode);
135static tree stabilize_va_list (tree, int);
136static rtx expand_builtin_expect (tree, rtx);
137static tree fold_builtin_constant_p (tree);
138static tree fold_builtin_classify_type (tree);
139static tree fold_builtin_strlen (tree);
147static tree fold_builtin_inf (tree, int);
148static tree fold_builtin_nan (tree, tree, int);
149static int validate_arglist (tree, ...);
150static bool integer_valued_real_p (tree);
140static tree fold_builtin_inf (tree, int);
141static tree fold_builtin_nan (tree, tree, int);
142static int validate_arglist (tree, ...);
143static bool integer_valued_real_p (tree);
151static tree fold_trunc_transparent_mathfn (tree);
144static tree fold_trunc_transparent_mathfn (tree, tree);
152static bool readonly_data_expr (tree);
153static rtx expand_builtin_fabs (tree, rtx, rtx);
145static bool readonly_data_expr (tree);
146static rtx expand_builtin_fabs (tree, rtx, rtx);
154static rtx expand_builtin_cabs (tree, rtx);
155static tree fold_builtin_cabs (tree, tree, tree);
156static tree fold_builtin_trunc (tree);
157static tree fold_builtin_floor (tree);
158static tree fold_builtin_ceil (tree);
159static tree fold_builtin_bitop (tree);
160static tree fold_builtin_memcpy (tree);
161static tree fold_builtin_mempcpy (tree);
162static tree fold_builtin_memmove (tree);
163static tree fold_builtin_strcpy (tree);
164static tree fold_builtin_strncpy (tree);
147static rtx expand_builtin_signbit (tree, rtx);
148static tree fold_builtin_sqrt (tree, tree);
149static tree fold_builtin_cbrt (tree, tree);
150static tree fold_builtin_pow (tree, tree, tree);
151static tree fold_builtin_powi (tree, tree, tree);
152static tree fold_builtin_sin (tree);
153static tree fold_builtin_cos (tree, tree, tree);
154static tree fold_builtin_tan (tree);
155static tree fold_builtin_atan (tree, tree);
156static tree fold_builtin_trunc (tree, tree);
157static tree fold_builtin_floor (tree, tree);
158static tree fold_builtin_ceil (tree, tree);
159static tree fold_builtin_round (tree, tree);
160static tree fold_builtin_int_roundingfn (tree, tree);
161static tree fold_builtin_bitop (tree, tree);
162static tree fold_builtin_memory_op (tree, tree, bool, int);
163static tree fold_builtin_strchr (tree, tree);
165static tree fold_builtin_memcmp (tree);
166static tree fold_builtin_strcmp (tree);
167static tree fold_builtin_strncmp (tree);
164static tree fold_builtin_memcmp (tree);
165static tree fold_builtin_strcmp (tree);
166static tree fold_builtin_strncmp (tree);
167static tree fold_builtin_signbit (tree, tree);
168static tree fold_builtin_copysign (tree, tree, tree);
169static tree fold_builtin_isascii (tree);
170static tree fold_builtin_toascii (tree);
171static tree fold_builtin_isdigit (tree);
172static tree fold_builtin_fabs (tree, tree);
173static tree fold_builtin_abs (tree, tree);
174static tree fold_builtin_unordered_cmp (tree, tree, enum tree_code,
175 enum tree_code);
176static tree fold_builtin_1 (tree, tree, bool);
168
177
178static tree fold_builtin_strpbrk (tree, tree);
179static tree fold_builtin_strstr (tree, tree);
180static tree fold_builtin_strrchr (tree, tree);
181static tree fold_builtin_strcat (tree);
182static tree fold_builtin_strncat (tree);
183static tree fold_builtin_strspn (tree);
184static tree fold_builtin_strcspn (tree);
185static tree fold_builtin_sprintf (tree, int);
186
187static rtx expand_builtin_object_size (tree);
188static rtx expand_builtin_memory_chk (tree, rtx, enum machine_mode,
189 enum built_in_function);
190static void maybe_emit_chk_warning (tree, enum built_in_function);
191static void maybe_emit_sprintf_chk_warning (tree, enum built_in_function);
192static tree fold_builtin_object_size (tree);
193static tree fold_builtin_strcat_chk (tree, tree);
194static tree fold_builtin_strncat_chk (tree, tree);
195static tree fold_builtin_sprintf_chk (tree, enum built_in_function);
196static tree fold_builtin_printf (tree, tree, bool, enum built_in_function);
197static tree fold_builtin_fprintf (tree, tree, bool, enum built_in_function);
198static bool init_target_chars (void);
199
200static unsigned HOST_WIDE_INT target_newline;
201static unsigned HOST_WIDE_INT target_percent;
202static unsigned HOST_WIDE_INT target_c;
203static unsigned HOST_WIDE_INT target_s;
204static char target_percent_c[3];
205static char target_percent_s[3];
206static char target_percent_s_newline[4];
207
208/* Return true if NODE should be considered for inline expansion regardless
209 of the optimization level. This means whenever a function is invoked with
210 its "internal" name, which normally contains the prefix "__builtin". */
211
212static bool called_as_built_in (tree node)
213{
214 const char *name = IDENTIFIER_POINTER (DECL_NAME (node));
215 if (strncmp (name, "__builtin_", 10) == 0)
216 return true;
217 if (strncmp (name, "__sync_", 7) == 0)
218 return true;
219 return false;
220}
221
169/* Return the alignment in bits of EXP, a pointer valued expression.
170 But don't return more than MAX_ALIGN no matter what.
171 The alignment returned is, by default, the alignment of the thing that
172 EXP points to. If it is not a POINTER_TYPE, 0 is returned.
173
174 Otherwise, look at the expression to see if we can do better, i.e., if the
175 expression is actually pointing at an object whose alignment is tighter. */
176
177static int
178get_pointer_alignment (tree exp, unsigned int max_align)
179{
180 unsigned int align, inner;
181
222/* Return the alignment in bits of EXP, a pointer valued expression.
223 But don't return more than MAX_ALIGN no matter what.
224 The alignment returned is, by default, the alignment of the thing that
225 EXP points to. If it is not a POINTER_TYPE, 0 is returned.
226
227 Otherwise, look at the expression to see if we can do better, i.e., if the
228 expression is actually pointing at an object whose alignment is tighter. */
229
230static int
231get_pointer_alignment (tree exp, unsigned int max_align)
232{
233 unsigned int align, inner;
234
182 if (TREE_CODE (TREE_TYPE (exp)) != POINTER_TYPE)
235 /* We rely on TER to compute accurate alignment information. */
236 if (!(optimize && flag_tree_ter))
183 return 0;
184
237 return 0;
238
239 if (!POINTER_TYPE_P (TREE_TYPE (exp)))
240 return 0;
241
185 align = TYPE_ALIGN (TREE_TYPE (TREE_TYPE (exp)));
186 align = MIN (align, max_align);
187
188 while (1)
189 {
190 switch (TREE_CODE (exp))
191 {
192 case NOP_EXPR:
193 case CONVERT_EXPR:
194 case NON_LVALUE_EXPR:
195 exp = TREE_OPERAND (exp, 0);
242 align = TYPE_ALIGN (TREE_TYPE (TREE_TYPE (exp)));
243 align = MIN (align, max_align);
244
245 while (1)
246 {
247 switch (TREE_CODE (exp))
248 {
249 case NOP_EXPR:
250 case CONVERT_EXPR:
251 case NON_LVALUE_EXPR:
252 exp = TREE_OPERAND (exp, 0);
196 if (TREE_CODE (TREE_TYPE (exp)) != POINTER_TYPE)
253 if (! POINTER_TYPE_P (TREE_TYPE (exp)))
197 return align;
198
199 inner = TYPE_ALIGN (TREE_TYPE (TREE_TYPE (exp)));
200 align = MIN (inner, max_align);
201 break;
202
203 case PLUS_EXPR:
204 /* If sum of pointer + int, restrict our maximum alignment to that

--- 8 unchanged lines hidden (view full) ---

213 max_align >>= 1;
214
215 exp = TREE_OPERAND (exp, 0);
216 break;
217
218 case ADDR_EXPR:
219 /* See what we are pointing at and look at its alignment. */
220 exp = TREE_OPERAND (exp, 0);
254 return align;
255
256 inner = TYPE_ALIGN (TREE_TYPE (TREE_TYPE (exp)));
257 align = MIN (inner, max_align);
258 break;
259
260 case PLUS_EXPR:
261 /* If sum of pointer + int, restrict our maximum alignment to that

--- 8 unchanged lines hidden (view full) ---

270 max_align >>= 1;
271
272 exp = TREE_OPERAND (exp, 0);
273 break;
274
275 case ADDR_EXPR:
276 /* See what we are pointing at and look at its alignment. */
277 exp = TREE_OPERAND (exp, 0);
278 inner = max_align;
279 if (handled_component_p (exp))
280 {
281 HOST_WIDE_INT bitsize, bitpos;
282 tree offset;
283 enum machine_mode mode;
284 int unsignedp, volatilep;
285
286 exp = get_inner_reference (exp, &bitsize, &bitpos, &offset,
287 &mode, &unsignedp, &volatilep, true);
288 if (bitpos)
289 inner = MIN (inner, (unsigned) (bitpos & -bitpos));
290 if (offset && TREE_CODE (offset) == PLUS_EXPR
291 && host_integerp (TREE_OPERAND (offset, 1), 1))
292 {
293 /* Any overflow in calculating offset_bits won't change
294 the alignment. */
295 unsigned offset_bits
296 = ((unsigned) tree_low_cst (TREE_OPERAND (offset, 1), 1)
297 * BITS_PER_UNIT);
298
299 if (offset_bits)
300 inner = MIN (inner, (offset_bits & -offset_bits));
301 offset = TREE_OPERAND (offset, 0);
302 }
303 if (offset && TREE_CODE (offset) == MULT_EXPR
304 && host_integerp (TREE_OPERAND (offset, 1), 1))
305 {
306 /* Any overflow in calculating offset_factor won't change
307 the alignment. */
308 unsigned offset_factor
309 = ((unsigned) tree_low_cst (TREE_OPERAND (offset, 1), 1)
310 * BITS_PER_UNIT);
311
312 if (offset_factor)
313 inner = MIN (inner, (offset_factor & -offset_factor));
314 }
315 else if (offset)
316 inner = MIN (inner, BITS_PER_UNIT);
317 }
221 if (TREE_CODE (exp) == FUNCTION_DECL)
222 align = FUNCTION_BOUNDARY;
223 else if (DECL_P (exp))
318 if (TREE_CODE (exp) == FUNCTION_DECL)
319 align = FUNCTION_BOUNDARY;
320 else if (DECL_P (exp))
224 align = DECL_ALIGN (exp);
321 align = MIN (inner, DECL_ALIGN (exp));
225#ifdef CONSTANT_ALIGNMENT
322#ifdef CONSTANT_ALIGNMENT
226 else if (TREE_CODE_CLASS (TREE_CODE (exp)) == 'c')
227 align = CONSTANT_ALIGNMENT (exp, align);
323 else if (CONSTANT_CLASS_P (exp))
324 align = MIN (inner, (unsigned)CONSTANT_ALIGNMENT (exp, align));
228#endif
325#endif
326 else if (TREE_CODE (exp) == VIEW_CONVERT_EXPR
327 || TREE_CODE (exp) == INDIRECT_REF)
328 align = MIN (TYPE_ALIGN (TREE_TYPE (exp)), inner);
329 else
330 align = MIN (align, inner);
229 return MIN (align, max_align);
230
231 default:
232 return align;
233 }
234 }
235}
236

--- 8 unchanged lines hidden (view full) ---

245 len = c_strlen (src, 1); if (len) expand_expr (len, ...); would not
246 evaluate the side-effects.
247
248 The value returned is of type `ssizetype'.
249
250 Unfortunately, string_constant can't access the values of const char
251 arrays with initializers, so neither can we do so here. */
252
331 return MIN (align, max_align);
332
333 default:
334 return align;
335 }
336 }
337}
338

--- 8 unchanged lines hidden (view full) ---

347 len = c_strlen (src, 1); if (len) expand_expr (len, ...); would not
348 evaluate the side-effects.
349
350 The value returned is of type `ssizetype'.
351
352 Unfortunately, string_constant can't access the values of const char
353 arrays with initializers, so neither can we do so here. */
354
253static tree
355tree
254c_strlen (tree src, int only_value)
255{
256 tree offset_node;
257 HOST_WIDE_INT offset;
258 int max;
259 const char *ptr;
260
261 STRIP_NOPS (src);
262 if (TREE_CODE (src) == COND_EXPR
263 && (only_value || !TREE_SIDE_EFFECTS (TREE_OPERAND (src, 0))))
264 {
265 tree len1, len2;
266
267 len1 = c_strlen (TREE_OPERAND (src, 1), only_value);
268 len2 = c_strlen (TREE_OPERAND (src, 2), only_value);
356c_strlen (tree src, int only_value)
357{
358 tree offset_node;
359 HOST_WIDE_INT offset;
360 int max;
361 const char *ptr;
362
363 STRIP_NOPS (src);
364 if (TREE_CODE (src) == COND_EXPR
365 && (only_value || !TREE_SIDE_EFFECTS (TREE_OPERAND (src, 0))))
366 {
367 tree len1, len2;
368
369 len1 = c_strlen (TREE_OPERAND (src, 1), only_value);
370 len2 = c_strlen (TREE_OPERAND (src, 2), only_value);
269 if (tree_int_cst_equal (len1, len2))
371 if (tree_int_cst_equal (len1, len2))
270 return len1;
271 }
272
273 if (TREE_CODE (src) == COMPOUND_EXPR
274 && (only_value || !TREE_SIDE_EFFECTS (TREE_OPERAND (src, 0))))
275 return c_strlen (TREE_OPERAND (src, 1), only_value);
276
277 src = string_constant (src, &offset_node);

--- 32 unchanged lines hidden (view full) ---

310 offset = -1;
311 else
312 offset = tree_low_cst (offset_node, 0);
313
314 /* If the offset is known to be out of bounds, warn, and call strlen at
315 runtime. */
316 if (offset < 0 || offset > max)
317 {
372 return len1;
373 }
374
375 if (TREE_CODE (src) == COMPOUND_EXPR
376 && (only_value || !TREE_SIDE_EFFECTS (TREE_OPERAND (src, 0))))
377 return c_strlen (TREE_OPERAND (src, 1), only_value);
378
379 src = string_constant (src, &offset_node);

--- 32 unchanged lines hidden (view full) ---

412 offset = -1;
413 else
414 offset = tree_low_cst (offset_node, 0);
415
416 /* If the offset is known to be out of bounds, warn, and call strlen at
417 runtime. */
418 if (offset < 0 || offset > max)
419 {
318 warning ("offset outside bounds of constant string");
420 warning (0, "offset outside bounds of constant string");
319 return 0;
320 }
321
322 /* Use strlen to search for the first zero byte. Since any strings
323 constructed with build_string will have nulls appended, we win even
324 if we get handed something like (char[4])"abcd".
325
326 Since OFFSET is our starting index into the string, no further

--- 27 unchanged lines hidden (view full) ---

354
355static rtx
356c_readstr (const char *str, enum machine_mode mode)
357{
358 HOST_WIDE_INT c[2];
359 HOST_WIDE_INT ch;
360 unsigned int i, j;
361
421 return 0;
422 }
423
424 /* Use strlen to search for the first zero byte. Since any strings
425 constructed with build_string will have nulls appended, we win even
426 if we get handed something like (char[4])"abcd".
427
428 Since OFFSET is our starting index into the string, no further

--- 27 unchanged lines hidden (view full) ---

456
457static rtx
458c_readstr (const char *str, enum machine_mode mode)
459{
460 HOST_WIDE_INT c[2];
461 HOST_WIDE_INT ch;
462 unsigned int i, j;
463
362 if (GET_MODE_CLASS (mode) != MODE_INT)
363 abort ();
464 gcc_assert (GET_MODE_CLASS (mode) == MODE_INT);
465
364 c[0] = 0;
365 c[1] = 0;
366 ch = 1;
367 for (i = 0; i < GET_MODE_SIZE (mode); i++)
368 {
369 j = i;
370 if (WORDS_BIG_ENDIAN)
371 j = GET_MODE_SIZE (mode) - i - 1;
372 if (BYTES_BIG_ENDIAN != WORDS_BIG_ENDIAN
373 && GET_MODE_SIZE (mode) > UNITS_PER_WORD)
374 j = j + UNITS_PER_WORD - 2 * (j % UNITS_PER_WORD) - 1;
375 j *= BITS_PER_UNIT;
466 c[0] = 0;
467 c[1] = 0;
468 ch = 1;
469 for (i = 0; i < GET_MODE_SIZE (mode); i++)
470 {
471 j = i;
472 if (WORDS_BIG_ENDIAN)
473 j = GET_MODE_SIZE (mode) - i - 1;
474 if (BYTES_BIG_ENDIAN != WORDS_BIG_ENDIAN
475 && GET_MODE_SIZE (mode) > UNITS_PER_WORD)
476 j = j + UNITS_PER_WORD - 2 * (j % UNITS_PER_WORD) - 1;
477 j *= BITS_PER_UNIT;
376 if (j > 2 * HOST_BITS_PER_WIDE_INT)
377 abort ();
478 gcc_assert (j <= 2 * HOST_BITS_PER_WIDE_INT);
479
378 if (ch)
379 ch = (unsigned char) str[i];
380 c[j / HOST_BITS_PER_WIDE_INT] |= ch << (j % HOST_BITS_PER_WIDE_INT);
381 }
382 return immed_double_const (c[0], c[1], mode);
383}
384
385/* Cast a target constant CST to target CHAR and if that value fits into
480 if (ch)
481 ch = (unsigned char) str[i];
482 c[j / HOST_BITS_PER_WIDE_INT] |= ch << (j % HOST_BITS_PER_WIDE_INT);
483 }
484 return immed_double_const (c[0], c[1], mode);
485}
486
487/* Cast a target constant CST to target CHAR and if that value fits into
386 host char type, return zero and put that value into variable pointed by
488 host char type, return zero and put that value into variable pointed to by
387 P. */
388
389static int
390target_char_cast (tree cst, char *p)
391{
392 unsigned HOST_WIDE_INT val, hostval;
393
394 if (!host_integerp (cst, 1)

--- 10 unchanged lines hidden (view full) ---

405
406 if (val != hostval)
407 return 1;
408
409 *p = hostval;
410 return 0;
411}
412
489 P. */
490
491static int
492target_char_cast (tree cst, char *p)
493{
494 unsigned HOST_WIDE_INT val, hostval;
495
496 if (!host_integerp (cst, 1)

--- 10 unchanged lines hidden (view full) ---

507
508 if (val != hostval)
509 return 1;
510
511 *p = hostval;
512 return 0;
513}
514
515/* Similar to save_expr, but assumes that arbitrary code is not executed
516 in between the multiple evaluations. In particular, we assume that a
517 non-addressable local variable will not be modified. */
518
519static tree
520builtin_save_expr (tree exp)
521{
522 if (TREE_ADDRESSABLE (exp) == 0
523 && (TREE_CODE (exp) == PARM_DECL
524 || (TREE_CODE (exp) == VAR_DECL && !TREE_STATIC (exp))))
525 return exp;
526
527 return save_expr (exp);
528}
529
413/* Given TEM, a pointer to a stack frame, follow the dynamic chain COUNT
414 times to get the address of either a higher stack frame, or a return
415 address located within it (depending on FNDECL_CODE). */
416
530/* Given TEM, a pointer to a stack frame, follow the dynamic chain COUNT
531 times to get the address of either a higher stack frame, or a return
532 address located within it (depending on FNDECL_CODE). */
533
417rtx
418expand_builtin_return_addr (enum built_in_function fndecl_code, int count,
419 rtx tem)
534static rtx
535expand_builtin_return_addr (enum built_in_function fndecl_code, int count)
420{
421 int i;
422
536{
537 int i;
538
539#ifdef INITIAL_FRAME_ADDRESS_RTX
540 rtx tem = INITIAL_FRAME_ADDRESS_RTX;
541#else
542 rtx tem;
543
544 /* For a zero count with __builtin_return_address, we don't care what
545 frame address we return, because target-specific definitions will
546 override us. Therefore frame pointer elimination is OK, and using
547 the soft frame pointer is OK.
548
549 For a non-zero count, or a zero count with __builtin_frame_address,
550 we require a stable offset from the current frame pointer to the
551 previous one, so we must use the hard frame pointer, and
552 we must disable frame pointer elimination. */
553 if (count == 0 && fndecl_code == BUILT_IN_RETURN_ADDRESS)
554 tem = frame_pointer_rtx;
555 else
556 {
557 tem = hard_frame_pointer_rtx;
558
559 /* Tell reload not to eliminate the frame pointer. */
560 current_function_accesses_prior_frames = 1;
561 }
562#endif
563
423 /* Some machines need special handling before we can access
564 /* Some machines need special handling before we can access
424 arbitrary frames. For example, on the sparc, we must first flush
565 arbitrary frames. For example, on the SPARC, we must first flush
425 all register windows to the stack. */
426#ifdef SETUP_FRAME_ADDRESSES
427 if (count > 0)
428 SETUP_FRAME_ADDRESSES ();
429#endif
430
566 all register windows to the stack. */
567#ifdef SETUP_FRAME_ADDRESSES
568 if (count > 0)
569 SETUP_FRAME_ADDRESSES ();
570#endif
571
431 /* On the sparc, the return address is not in the frame, it is in a
572 /* On the SPARC, the return address is not in the frame, it is in a
432 register. There is no way to access it off of the current frame
433 pointer, but it can be accessed off the previous frame pointer by
434 reading the value from the register window save area. */
435#ifdef RETURN_ADDR_IN_PREVIOUS_FRAME
436 if (fndecl_code == BUILT_IN_RETURN_ADDRESS)
437 count--;
438#endif
439
440 /* Scan back COUNT frames to the specified frame. */
441 for (i = 0; i < count; i++)
442 {
443 /* Assume the dynamic chain pointer is in the word that the
444 frame address points to, unless otherwise specified. */
445#ifdef DYNAMIC_CHAIN_ADDRESS
446 tem = DYNAMIC_CHAIN_ADDRESS (tem);
447#endif
448 tem = memory_address (Pmode, tem);
573 register. There is no way to access it off of the current frame
574 pointer, but it can be accessed off the previous frame pointer by
575 reading the value from the register window save area. */
576#ifdef RETURN_ADDR_IN_PREVIOUS_FRAME
577 if (fndecl_code == BUILT_IN_RETURN_ADDRESS)
578 count--;
579#endif
580
581 /* Scan back COUNT frames to the specified frame. */
582 for (i = 0; i < count; i++)
583 {
584 /* Assume the dynamic chain pointer is in the word that the
585 frame address points to, unless otherwise specified. */
586#ifdef DYNAMIC_CHAIN_ADDRESS
587 tem = DYNAMIC_CHAIN_ADDRESS (tem);
588#endif
589 tem = memory_address (Pmode, tem);
449 tem = gen_rtx_MEM (Pmode, tem);
450 set_mem_alias_set (tem, get_frame_alias_set ());
590 tem = gen_frame_mem (Pmode, tem);
451 tem = copy_to_reg (tem);
452 }
453
591 tem = copy_to_reg (tem);
592 }
593
454 /* For __builtin_frame_address, return what we've got. */
594 /* For __builtin_frame_address, return what we've got. But, on
595 the SPARC for example, we may have to add a bias. */
455 if (fndecl_code == BUILT_IN_FRAME_ADDRESS)
596 if (fndecl_code == BUILT_IN_FRAME_ADDRESS)
597#ifdef FRAME_ADDR_RTX
598 return FRAME_ADDR_RTX (tem);
599#else
456 return tem;
600 return tem;
601#endif
457
602
458 /* For __builtin_return_address, Get the return address from that
459 frame. */
603 /* For __builtin_return_address, get the return address from that frame. */
460#ifdef RETURN_ADDR_RTX
461 tem = RETURN_ADDR_RTX (count, tem);
462#else
463 tem = memory_address (Pmode,
464 plus_constant (tem, GET_MODE_SIZE (Pmode)));
604#ifdef RETURN_ADDR_RTX
605 tem = RETURN_ADDR_RTX (count, tem);
606#else
607 tem = memory_address (Pmode,
608 plus_constant (tem, GET_MODE_SIZE (Pmode)));
465 tem = gen_rtx_MEM (Pmode, tem);
466 set_mem_alias_set (tem, get_frame_alias_set ());
609 tem = gen_frame_mem (Pmode, tem);
467#endif
468 return tem;
469}
470
471/* Alias set used for setjmp buffer. */
472static HOST_WIDE_INT setjmp_alias_set = -1;
473
474/* Construct the leading half of a __builtin_setjmp call. Control will
610#endif
611 return tem;
612}
613
614/* Alias set used for setjmp buffer. */
615static HOST_WIDE_INT setjmp_alias_set = -1;
616
617/* Construct the leading half of a __builtin_setjmp call. Control will
475 return to RECEIVER_LABEL. This is used directly by sjlj exception
476 handling code. */
618 return to RECEIVER_LABEL. This is also called directly by the SJLJ
619 exception handling code. */
477
478void
479expand_builtin_setjmp_setup (rtx buf_addr, rtx receiver_label)
480{
481 enum machine_mode sa_mode = STACK_SAVEAREA_MODE (SAVE_NONLOCAL);
482 rtx stack_save;
483 rtx mem;
484
485 if (setjmp_alias_set == -1)
486 setjmp_alias_set = new_alias_set ();
487
488 buf_addr = convert_memory_address (Pmode, buf_addr);
489
490 buf_addr = force_reg (Pmode, force_operand (buf_addr, NULL_RTX));
491
620
621void
622expand_builtin_setjmp_setup (rtx buf_addr, rtx receiver_label)
623{
624 enum machine_mode sa_mode = STACK_SAVEAREA_MODE (SAVE_NONLOCAL);
625 rtx stack_save;
626 rtx mem;
627
628 if (setjmp_alias_set == -1)
629 setjmp_alias_set = new_alias_set ();
630
631 buf_addr = convert_memory_address (Pmode, buf_addr);
632
633 buf_addr = force_reg (Pmode, force_operand (buf_addr, NULL_RTX));
634
492 emit_queue ();
493
494 /* We store the frame pointer and the address of receiver_label in
495 the buffer and use the rest of it for the stack save area, which
496 is machine-dependent. */
497
635 /* We store the frame pointer and the address of receiver_label in
636 the buffer and use the rest of it for the stack save area, which
637 is machine-dependent. */
638
498#ifndef BUILTIN_SETJMP_FRAME_VALUE
499#define BUILTIN_SETJMP_FRAME_VALUE virtual_stack_vars_rtx
500#endif
501
502 mem = gen_rtx_MEM (Pmode, buf_addr);
503 set_mem_alias_set (mem, setjmp_alias_set);
639 mem = gen_rtx_MEM (Pmode, buf_addr);
640 set_mem_alias_set (mem, setjmp_alias_set);
504 emit_move_insn (mem, BUILTIN_SETJMP_FRAME_VALUE);
641 emit_move_insn (mem, targetm.builtin_setjmp_frame_value ());
505
506 mem = gen_rtx_MEM (Pmode, plus_constant (buf_addr, GET_MODE_SIZE (Pmode))),
507 set_mem_alias_set (mem, setjmp_alias_set);
508
509 emit_move_insn (validize_mem (mem),
510 force_reg (Pmode, gen_rtx_LABEL_REF (Pmode, receiver_label)));
511
512 stack_save = gen_rtx_MEM (sa_mode,

--- 12 unchanged lines hidden (view full) ---

525 need to go on during alloca. */
526 current_function_calls_setjmp = 1;
527
528 /* Set this so all the registers get saved in our frame; we need to be
529 able to copy the saved values for any registers from frames we unwind. */
530 current_function_has_nonlocal_label = 1;
531}
532
642
643 mem = gen_rtx_MEM (Pmode, plus_constant (buf_addr, GET_MODE_SIZE (Pmode))),
644 set_mem_alias_set (mem, setjmp_alias_set);
645
646 emit_move_insn (validize_mem (mem),
647 force_reg (Pmode, gen_rtx_LABEL_REF (Pmode, receiver_label)));
648
649 stack_save = gen_rtx_MEM (sa_mode,

--- 12 unchanged lines hidden (view full) ---

662 need to go on during alloca. */
663 current_function_calls_setjmp = 1;
664
665 /* Set this so all the registers get saved in our frame; we need to be
666 able to copy the saved values for any registers from frames we unwind. */
667 current_function_has_nonlocal_label = 1;
668}
669
533/* Construct the trailing part of a __builtin_setjmp call.
534 This is used directly by sjlj exception handling code. */
670/* Construct the trailing part of a __builtin_setjmp call. This is
671 also called directly by the SJLJ exception handling code. */
535
536void
537expand_builtin_setjmp_receiver (rtx receiver_label ATTRIBUTE_UNUSED)
538{
539 /* Clobber the FP when we get here, so we have to make sure it's
540 marked as used by this function. */
541 emit_insn (gen_rtx_USE (VOIDmode, hard_frame_pointer_rtx));
542
543 /* Mark the static chain as clobbered here so life information
544 doesn't get messed up for it. */
545 emit_insn (gen_rtx_CLOBBER (VOIDmode, static_chain_rtx));
546
547 /* Now put in the code to restore the frame pointer, and argument
672
673void
674expand_builtin_setjmp_receiver (rtx receiver_label ATTRIBUTE_UNUSED)
675{
676 /* Clobber the FP when we get here, so we have to make sure it's
677 marked as used by this function. */
678 emit_insn (gen_rtx_USE (VOIDmode, hard_frame_pointer_rtx));
679
680 /* Mark the static chain as clobbered here so life information
681 doesn't get messed up for it. */
682 emit_insn (gen_rtx_CLOBBER (VOIDmode, static_chain_rtx));
683
684 /* Now put in the code to restore the frame pointer, and argument
548 pointer, if needed. The code below is from expand_end_bindings
549 in stmt.c; see detailed documentation there. */
685 pointer, if needed. */
550#ifdef HAVE_nonlocal_goto
551 if (! HAVE_nonlocal_goto)
552#endif
686#ifdef HAVE_nonlocal_goto
687 if (! HAVE_nonlocal_goto)
688#endif
553 emit_move_insn (virtual_stack_vars_rtx, hard_frame_pointer_rtx);
689 {
690 emit_move_insn (virtual_stack_vars_rtx, hard_frame_pointer_rtx);
691 /* This might change the hard frame pointer in ways that aren't
692 apparent to early optimization passes, so force a clobber. */
693 emit_insn (gen_rtx_CLOBBER (VOIDmode, hard_frame_pointer_rtx));
694 }
554
555#if ARG_POINTER_REGNUM != HARD_FRAME_POINTER_REGNUM
556 if (fixed_regs[ARG_POINTER_REGNUM])
557 {
558#ifdef ELIMINABLE_REGS
559 size_t i;
560 static const struct elims {const int from, to;} elim_regs[] = ELIMINABLE_REGS;
561

--- 28 unchanged lines hidden (view full) ---

590 /* @@@ This is a kludge. Not all machine descriptions define a blockage
591 insn, but we must not allow the code we just generated to be reordered
592 by scheduling. Specifically, the update of the frame pointer must
593 happen immediately, not later. So emit an ASM_INPUT to act as blockage
594 insn. */
595 emit_insn (gen_rtx_ASM_INPUT (VOIDmode, ""));
596}
597
695
696#if ARG_POINTER_REGNUM != HARD_FRAME_POINTER_REGNUM
697 if (fixed_regs[ARG_POINTER_REGNUM])
698 {
699#ifdef ELIMINABLE_REGS
700 size_t i;
701 static const struct elims {const int from, to;} elim_regs[] = ELIMINABLE_REGS;
702

--- 28 unchanged lines hidden (view full) ---

731 /* @@@ This is a kludge. Not all machine descriptions define a blockage
732 insn, but we must not allow the code we just generated to be reordered
733 by scheduling. Specifically, the update of the frame pointer must
734 happen immediately, not later. So emit an ASM_INPUT to act as blockage
735 insn. */
736 emit_insn (gen_rtx_ASM_INPUT (VOIDmode, ""));
737}
738
598/* __builtin_setjmp is passed a pointer to an array of five words (not
599 all will be used on all machines). It operates similarly to the C
600 library function of the same name, but is more efficient. Much of
601 the code below (and for longjmp) is copied from the handling of
602 non-local gotos.
603
604 NOTE: This is intended for use by GNAT and the exception handling
605 scheme in the compiler and will only work in the method used by
606 them. */
607
608static rtx
609expand_builtin_setjmp (tree arglist, rtx target)
610{
611 rtx buf_addr, next_lab, cont_lab;
612
613 if (!validate_arglist (arglist, POINTER_TYPE, VOID_TYPE))
614 return NULL_RTX;
615
616 if (target == 0 || GET_CODE (target) != REG
617 || REGNO (target) < FIRST_PSEUDO_REGISTER)
618 target = gen_reg_rtx (TYPE_MODE (integer_type_node));
619
620 buf_addr = expand_expr (TREE_VALUE (arglist), NULL_RTX, VOIDmode, 0);
621
622 next_lab = gen_label_rtx ();
623 cont_lab = gen_label_rtx ();
624
625 expand_builtin_setjmp_setup (buf_addr, next_lab);
626
627 /* Set TARGET to zero and branch to the continue label. Use emit_jump to
628 ensure that pending stack adjustments are flushed. */
629 emit_move_insn (target, const0_rtx);
630 emit_jump (cont_lab);
631
632 emit_label (next_lab);
633
634 expand_builtin_setjmp_receiver (next_lab);
635
636 /* Set TARGET to one. */
637 emit_move_insn (target, const1_rtx);
638 emit_label (cont_lab);
639
640 /* Tell flow about the strange goings on. Putting `next_lab' on
641 `nonlocal_goto_handler_labels' to indicates that function
642 calls may traverse the arc back to this label. */
643
644 current_function_has_nonlocal_label = 1;
645 nonlocal_goto_handler_labels
646 = gen_rtx_EXPR_LIST (VOIDmode, next_lab, nonlocal_goto_handler_labels);
647
648 return target;
649}
650
651/* __builtin_longjmp is passed a pointer to an array of five words (not
652 all will be used on all machines). It operates similarly to the C
653 library function of the same name, but is more efficient. Much of
739/* __builtin_longjmp is passed a pointer to an array of five words (not
740 all will be used on all machines). It operates similarly to the C
741 library function of the same name, but is more efficient. Much of
654 the code below is copied from the handling of non-local gotos.
742 the code below is copied from the handling of non-local gotos. */
655
743
656 NOTE: This is intended for use by GNAT and the exception handling
657 scheme in the compiler and will only work in the method used by
658 them. */
659
660void
744static void
661expand_builtin_longjmp (rtx buf_addr, rtx value)
662{
663 rtx fp, lab, stack, insn, last;
664 enum machine_mode sa_mode = STACK_SAVEAREA_MODE (SAVE_NONLOCAL);
665
666 if (setjmp_alias_set == -1)
667 setjmp_alias_set = new_alias_set ();
668
669 buf_addr = convert_memory_address (Pmode, buf_addr);
670
671 buf_addr = force_reg (Pmode, buf_addr);
672
673 /* We used to store value in static_chain_rtx, but that fails if pointers
674 are smaller than integers. We instead require that the user must pass
675 a second argument of 1, because that is what builtin_setjmp will
676 return. This also makes EH slightly more efficient, since we are no
677 longer copying around a value that we don't care about. */
745expand_builtin_longjmp (rtx buf_addr, rtx value)
746{
747 rtx fp, lab, stack, insn, last;
748 enum machine_mode sa_mode = STACK_SAVEAREA_MODE (SAVE_NONLOCAL);
749
750 if (setjmp_alias_set == -1)
751 setjmp_alias_set = new_alias_set ();
752
753 buf_addr = convert_memory_address (Pmode, buf_addr);
754
755 buf_addr = force_reg (Pmode, buf_addr);
756
757 /* We used to store value in static_chain_rtx, but that fails if pointers
758 are smaller than integers. We instead require that the user must pass
759 a second argument of 1, because that is what builtin_setjmp will
760 return. This also makes EH slightly more efficient, since we are no
761 longer copying around a value that we don't care about. */
678 if (value != const1_rtx)
679 abort ();
762 gcc_assert (value == const1_rtx);
680
763
681 current_function_calls_longjmp = 1;
682
683 last = get_last_insn ();
684#ifdef HAVE_builtin_longjmp
685 if (HAVE_builtin_longjmp)
686 emit_insn (gen_builtin_longjmp (buf_addr));
687 else
688#endif
689 {
690 fp = gen_rtx_MEM (Pmode, buf_addr);
691 lab = gen_rtx_MEM (Pmode, plus_constant (buf_addr,
692 GET_MODE_SIZE (Pmode)));
693
694 stack = gen_rtx_MEM (sa_mode, plus_constant (buf_addr,
695 2 * GET_MODE_SIZE (Pmode)));
696 set_mem_alias_set (fp, setjmp_alias_set);
697 set_mem_alias_set (lab, setjmp_alias_set);
698 set_mem_alias_set (stack, setjmp_alias_set);
699
700 /* Pick up FP, label, and SP from the block and jump. This code is
701 from expand_goto in stmt.c; see there for detailed comments. */
764 last = get_last_insn ();
765#ifdef HAVE_builtin_longjmp
766 if (HAVE_builtin_longjmp)
767 emit_insn (gen_builtin_longjmp (buf_addr));
768 else
769#endif
770 {
771 fp = gen_rtx_MEM (Pmode, buf_addr);
772 lab = gen_rtx_MEM (Pmode, plus_constant (buf_addr,
773 GET_MODE_SIZE (Pmode)));
774
775 stack = gen_rtx_MEM (sa_mode, plus_constant (buf_addr,
776 2 * GET_MODE_SIZE (Pmode)));
777 set_mem_alias_set (fp, setjmp_alias_set);
778 set_mem_alias_set (lab, setjmp_alias_set);
779 set_mem_alias_set (stack, setjmp_alias_set);
780
781 /* Pick up FP, label, and SP from the block and jump. This code is
782 from expand_goto in stmt.c; see there for detailed comments. */
702#if HAVE_nonlocal_goto
783#ifdef HAVE_nonlocal_goto
703 if (HAVE_nonlocal_goto)
704 /* We have to pass a value to the nonlocal_goto pattern that will
705 get copied into the static_chain pointer, but it does not matter
706 what that value is, because builtin_setjmp does not use it. */
707 emit_insn (gen_nonlocal_goto (value, lab, stack, fp));
708 else
709#endif
710 {

--- 17 unchanged lines hidden (view full) ---

728
729 /* Search backwards and mark the jump insn as a non-local goto.
730 Note that this precludes the use of __builtin_longjmp to a
731 __builtin_setjmp target in the same function. However, we've
732 already cautioned the user that these functions are for
733 internal exception handling use only. */
734 for (insn = get_last_insn (); insn; insn = PREV_INSN (insn))
735 {
784 if (HAVE_nonlocal_goto)
785 /* We have to pass a value to the nonlocal_goto pattern that will
786 get copied into the static_chain pointer, but it does not matter
787 what that value is, because builtin_setjmp does not use it. */
788 emit_insn (gen_nonlocal_goto (value, lab, stack, fp));
789 else
790#endif
791 {

--- 17 unchanged lines hidden (view full) ---

809
810 /* Search backwards and mark the jump insn as a non-local goto.
811 Note that this precludes the use of __builtin_longjmp to a
812 __builtin_setjmp target in the same function. However, we've
813 already cautioned the user that these functions are for
814 internal exception handling use only. */
815 for (insn = get_last_insn (); insn; insn = PREV_INSN (insn))
816 {
736 if (insn == last)
737 abort ();
738 if (GET_CODE (insn) == JUMP_INSN)
817 gcc_assert (insn != last);
818
819 if (JUMP_P (insn))
739 {
740 REG_NOTES (insn) = alloc_EXPR_LIST (REG_NON_LOCAL_GOTO, const0_rtx,
741 REG_NOTES (insn));
742 break;
743 }
820 {
821 REG_NOTES (insn) = alloc_EXPR_LIST (REG_NON_LOCAL_GOTO, const0_rtx,
822 REG_NOTES (insn));
823 break;
824 }
744 else if (GET_CODE (insn) == CALL_INSN)
825 else if (CALL_P (insn))
745 break;
746 }
747}
748
826 break;
827 }
828}
829
830/* Expand a call to __builtin_nonlocal_goto. We're passed the target label
831 and the address of the save area. */
832
833static rtx
834expand_builtin_nonlocal_goto (tree arglist)
835{
836 tree t_label, t_save_area;
837 rtx r_label, r_save_area, r_fp, r_sp, insn;
838
839 if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
840 return NULL_RTX;
841
842 t_label = TREE_VALUE (arglist);
843 arglist = TREE_CHAIN (arglist);
844 t_save_area = TREE_VALUE (arglist);
845
846 r_label = expand_normal (t_label);
847 r_label = convert_memory_address (Pmode, r_label);
848 r_save_area = expand_normal (t_save_area);
849 r_save_area = convert_memory_address (Pmode, r_save_area);
850 r_fp = gen_rtx_MEM (Pmode, r_save_area);
851 r_sp = gen_rtx_MEM (STACK_SAVEAREA_MODE (SAVE_NONLOCAL),
852 plus_constant (r_save_area, GET_MODE_SIZE (Pmode)));
853
854 current_function_has_nonlocal_goto = 1;
855
856#ifdef HAVE_nonlocal_goto
857 /* ??? We no longer need to pass the static chain value, afaik. */
858 if (HAVE_nonlocal_goto)
859 emit_insn (gen_nonlocal_goto (const0_rtx, r_label, r_sp, r_fp));
860 else
861#endif
862 {
863 r_label = copy_to_reg (r_label);
864
865 emit_insn (gen_rtx_CLOBBER (VOIDmode,
866 gen_rtx_MEM (BLKmode,
867 gen_rtx_SCRATCH (VOIDmode))));
868
869 emit_insn (gen_rtx_CLOBBER (VOIDmode,
870 gen_rtx_MEM (BLKmode,
871 hard_frame_pointer_rtx)));
872
873 /* Restore frame pointer for containing function.
874 This sets the actual hard register used for the frame pointer
875 to the location of the function's incoming static chain info.
876 The non-local goto handler will then adjust it to contain the
877 proper value and reload the argument pointer, if needed. */
878 emit_move_insn (hard_frame_pointer_rtx, r_fp);
879 emit_stack_restore (SAVE_NONLOCAL, r_sp, NULL_RTX);
880
881 /* USE of hard_frame_pointer_rtx added for consistency;
882 not clear if really needed. */
883 emit_insn (gen_rtx_USE (VOIDmode, hard_frame_pointer_rtx));
884 emit_insn (gen_rtx_USE (VOIDmode, stack_pointer_rtx));
885 emit_indirect_jump (r_label);
886 }
887
888 /* Search backwards to the jump insn and mark it as a
889 non-local goto. */
890 for (insn = get_last_insn (); insn; insn = PREV_INSN (insn))
891 {
892 if (JUMP_P (insn))
893 {
894 REG_NOTES (insn) = alloc_EXPR_LIST (REG_NON_LOCAL_GOTO,
895 const0_rtx, REG_NOTES (insn));
896 break;
897 }
898 else if (CALL_P (insn))
899 break;
900 }
901
902 return const0_rtx;
903}
904
905/* __builtin_update_setjmp_buf is passed a pointer to an array of five words
906 (not all will be used on all machines) that was passed to __builtin_setjmp.
907 It updates the stack pointer in that block to correspond to the current
908 stack pointer. */
909
910static void
911expand_builtin_update_setjmp_buf (rtx buf_addr)
912{
913 enum machine_mode sa_mode = Pmode;
914 rtx stack_save;
915
916
917#ifdef HAVE_save_stack_nonlocal
918 if (HAVE_save_stack_nonlocal)
919 sa_mode = insn_data[(int) CODE_FOR_save_stack_nonlocal].operand[0].mode;
920#endif
921#ifdef STACK_SAVEAREA_MODE
922 sa_mode = STACK_SAVEAREA_MODE (SAVE_NONLOCAL);
923#endif
924
925 stack_save
926 = gen_rtx_MEM (sa_mode,
927 memory_address
928 (sa_mode,
929 plus_constant (buf_addr, 2 * GET_MODE_SIZE (Pmode))));
930
931#ifdef HAVE_setjmp
932 if (HAVE_setjmp)
933 emit_insn (gen_setjmp ());
934#endif
935
936 emit_stack_save (SAVE_NONLOCAL, &stack_save, NULL_RTX);
937}
938
749/* Expand a call to __builtin_prefetch. For a target that does not support
750 data prefetch, evaluate the memory address argument in case it has side
751 effects. */
752
753static void
754expand_builtin_prefetch (tree arglist)
755{
756 tree arg0, arg1, arg2;

--- 7 unchanged lines hidden (view full) ---

764 zero (read) and argument 2 (locality) defaults to 3 (high degree of
765 locality). */
766 if (TREE_CHAIN (arglist))
767 {
768 arg1 = TREE_VALUE (TREE_CHAIN (arglist));
769 if (TREE_CHAIN (TREE_CHAIN (arglist)))
770 arg2 = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
771 else
939/* Expand a call to __builtin_prefetch. For a target that does not support
940 data prefetch, evaluate the memory address argument in case it has side
941 effects. */
942
943static void
944expand_builtin_prefetch (tree arglist)
945{
946 tree arg0, arg1, arg2;

--- 7 unchanged lines hidden (view full) ---

954 zero (read) and argument 2 (locality) defaults to 3 (high degree of
955 locality). */
956 if (TREE_CHAIN (arglist))
957 {
958 arg1 = TREE_VALUE (TREE_CHAIN (arglist));
959 if (TREE_CHAIN (TREE_CHAIN (arglist)))
960 arg2 = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
961 else
772 arg2 = build_int_2 (3, 0);
962 arg2 = build_int_cst (NULL_TREE, 3);
773 }
774 else
775 {
776 arg1 = integer_zero_node;
963 }
964 else
965 {
966 arg1 = integer_zero_node;
777 arg2 = build_int_2 (3, 0);
967 arg2 = build_int_cst (NULL_TREE, 3);
778 }
779
780 /* Argument 0 is an address. */
781 op0 = expand_expr (arg0, NULL_RTX, Pmode, EXPAND_NORMAL);
782
783 /* Argument 1 (read/write flag) must be a compile-time constant int. */
784 if (TREE_CODE (arg1) != INTEGER_CST)
785 {
968 }
969
970 /* Argument 0 is an address. */
971 op0 = expand_expr (arg0, NULL_RTX, Pmode, EXPAND_NORMAL);
972
973 /* Argument 1 (read/write flag) must be a compile-time constant int. */
974 if (TREE_CODE (arg1) != INTEGER_CST)
975 {
786 error ("second arg to `__builtin_prefetch' must be a constant");
976 error ("second argument to %<__builtin_prefetch%> must be a constant");
787 arg1 = integer_zero_node;
788 }
977 arg1 = integer_zero_node;
978 }
789 op1 = expand_expr (arg1, NULL_RTX, VOIDmode, 0);
979 op1 = expand_normal (arg1);
790 /* Argument 1 must be either zero or one. */
791 if (INTVAL (op1) != 0 && INTVAL (op1) != 1)
792 {
980 /* Argument 1 must be either zero or one. */
981 if (INTVAL (op1) != 0 && INTVAL (op1) != 1)
982 {
793 warning ("invalid second arg to __builtin_prefetch; using zero");
983 warning (0, "invalid second argument to %<__builtin_prefetch%>;"
984 " using zero");
794 op1 = const0_rtx;
795 }
796
797 /* Argument 2 (locality) must be a compile-time constant int. */
798 if (TREE_CODE (arg2) != INTEGER_CST)
799 {
985 op1 = const0_rtx;
986 }
987
988 /* Argument 2 (locality) must be a compile-time constant int. */
989 if (TREE_CODE (arg2) != INTEGER_CST)
990 {
800 error ("third arg to `__builtin_prefetch' must be a constant");
991 error ("third argument to %<__builtin_prefetch%> must be a constant");
801 arg2 = integer_zero_node;
802 }
992 arg2 = integer_zero_node;
993 }
803 op2 = expand_expr (arg2, NULL_RTX, VOIDmode, 0);
994 op2 = expand_normal (arg2);
804 /* Argument 2 must be 0, 1, 2, or 3. */
805 if (INTVAL (op2) < 0 || INTVAL (op2) > 3)
806 {
995 /* Argument 2 must be 0, 1, 2, or 3. */
996 if (INTVAL (op2) < 0 || INTVAL (op2) > 3)
997 {
807 warning ("invalid third arg to __builtin_prefetch; using zero");
998 warning (0, "invalid third argument to %<__builtin_prefetch%>; using zero");
808 op2 = const0_rtx;
809 }
810
811#ifdef HAVE_prefetch
812 if (HAVE_prefetch)
813 {
814 if ((! (*insn_data[(int) CODE_FOR_prefetch].operand[0].predicate)
815 (op0,
816 insn_data[(int) CODE_FOR_prefetch].operand[0].mode))
817 || (GET_MODE (op0) != Pmode))
818 {
819 op0 = convert_memory_address (Pmode, op0);
820 op0 = force_reg (Pmode, op0);
821 }
822 emit_insn (gen_prefetch (op0, op1, op2));
823 }
999 op2 = const0_rtx;
1000 }
1001
1002#ifdef HAVE_prefetch
1003 if (HAVE_prefetch)
1004 {
1005 if ((! (*insn_data[(int) CODE_FOR_prefetch].operand[0].predicate)
1006 (op0,
1007 insn_data[(int) CODE_FOR_prefetch].operand[0].mode))
1008 || (GET_MODE (op0) != Pmode))
1009 {
1010 op0 = convert_memory_address (Pmode, op0);
1011 op0 = force_reg (Pmode, op0);
1012 }
1013 emit_insn (gen_prefetch (op0, op1, op2));
1014 }
824 else
825#endif
1015#endif
826 op0 = protect_from_queue (op0, 0);
1016
827 /* Don't do anything with direct references to volatile memory, but
828 generate code to handle other side effects. */
1017 /* Don't do anything with direct references to volatile memory, but
1018 generate code to handle other side effects. */
829 if (GET_CODE (op0) != MEM && side_effects_p (op0))
1019 if (!MEM_P (op0) && side_effects_p (op0))
830 emit_insn (op0);
831}
832
833/* Get a MEM rtx for expression EXP which is the address of an operand
1020 emit_insn (op0);
1021}
1022
1023/* Get a MEM rtx for expression EXP which is the address of an operand
834 to be used to be used in a string instruction (cmpstrsi, movstrsi, ..). */
1024 to be used in a string instruction (cmpstrsi, movmemsi, ..). LEN is
1025 the maximum length of the block of memory that might be accessed or
1026 NULL if unknown. */
835
836static rtx
1027
1028static rtx
837get_memory_rtx (tree exp)
1029get_memory_rtx (tree exp, tree len)
838{
1030{
839 rtx addr = expand_expr (exp, NULL_RTX, ptr_mode, EXPAND_SUM);
840 rtx mem;
1031 rtx addr = expand_expr (exp, NULL_RTX, ptr_mode, EXPAND_NORMAL);
1032 rtx mem = gen_rtx_MEM (BLKmode, memory_address (BLKmode, addr));
841
1033
842 addr = convert_memory_address (Pmode, addr);
843
844 mem = gen_rtx_MEM (BLKmode, memory_address (BLKmode, addr));
845
846 /* Get an expression we can use to find the attributes to assign to MEM.
847 If it is an ADDR_EXPR, use the operand. Otherwise, dereference it if
848 we can. First remove any nops. */
849 while ((TREE_CODE (exp) == NOP_EXPR || TREE_CODE (exp) == CONVERT_EXPR
850 || TREE_CODE (exp) == NON_LVALUE_EXPR)
851 && POINTER_TYPE_P (TREE_TYPE (TREE_OPERAND (exp, 0))))
852 exp = TREE_OPERAND (exp, 0);
853
854 if (TREE_CODE (exp) == ADDR_EXPR)
1034 /* Get an expression we can use to find the attributes to assign to MEM.
1035 If it is an ADDR_EXPR, use the operand. Otherwise, dereference it if
1036 we can. First remove any nops. */
1037 while ((TREE_CODE (exp) == NOP_EXPR || TREE_CODE (exp) == CONVERT_EXPR
1038 || TREE_CODE (exp) == NON_LVALUE_EXPR)
1039 && POINTER_TYPE_P (TREE_TYPE (TREE_OPERAND (exp, 0))))
1040 exp = TREE_OPERAND (exp, 0);
1041
1042 if (TREE_CODE (exp) == ADDR_EXPR)
855 {
856 exp = TREE_OPERAND (exp, 0);
857 set_mem_attributes (mem, exp, 0);
858 }
1043 exp = TREE_OPERAND (exp, 0);
859 else if (POINTER_TYPE_P (TREE_TYPE (exp)))
1044 else if (POINTER_TYPE_P (TREE_TYPE (exp)))
1045 exp = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (exp)), exp);
1046 else
1047 exp = NULL;
1048
1049 /* Honor attributes derived from exp, except for the alias set
1050 (as builtin stringops may alias with anything) and the size
1051 (as stringops may access multiple array elements). */
1052 if (exp)
860 {
1053 {
861 exp = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (exp)), exp);
862 /* memcpy, memset and other builtin stringops can alias with anything. */
1054 set_mem_attributes (mem, exp, 0);
1055
1056 /* Allow the string and memory builtins to overflow from one
1057 field into another, see http://gcc.gnu.org/PR23561.
1058 Thus avoid COMPONENT_REFs in MEM_EXPR unless we know the whole
1059 memory accessed by the string or memory builtin will fit
1060 within the field. */
1061 if (MEM_EXPR (mem) && TREE_CODE (MEM_EXPR (mem)) == COMPONENT_REF)
1062 {
1063 tree mem_expr = MEM_EXPR (mem);
1064 HOST_WIDE_INT offset = -1, length = -1;
1065 tree inner = exp;
1066
1067 while (TREE_CODE (inner) == ARRAY_REF
1068 || TREE_CODE (inner) == NOP_EXPR
1069 || TREE_CODE (inner) == CONVERT_EXPR
1070 || TREE_CODE (inner) == NON_LVALUE_EXPR
1071 || TREE_CODE (inner) == VIEW_CONVERT_EXPR
1072 || TREE_CODE (inner) == SAVE_EXPR)
1073 inner = TREE_OPERAND (inner, 0);
1074
1075 gcc_assert (TREE_CODE (inner) == COMPONENT_REF);
1076
1077 if (MEM_OFFSET (mem)
1078 && GET_CODE (MEM_OFFSET (mem)) == CONST_INT)
1079 offset = INTVAL (MEM_OFFSET (mem));
1080
1081 if (offset >= 0 && len && host_integerp (len, 0))
1082 length = tree_low_cst (len, 0);
1083
1084 while (TREE_CODE (inner) == COMPONENT_REF)
1085 {
1086 tree field = TREE_OPERAND (inner, 1);
1087 gcc_assert (! DECL_BIT_FIELD (field));
1088 gcc_assert (TREE_CODE (mem_expr) == COMPONENT_REF);
1089 gcc_assert (field == TREE_OPERAND (mem_expr, 1));
1090
1091 if (length >= 0
1092 && TYPE_SIZE_UNIT (TREE_TYPE (inner))
1093 && host_integerp (TYPE_SIZE_UNIT (TREE_TYPE (inner)), 0))
1094 {
1095 HOST_WIDE_INT size
1096 = tree_low_cst (TYPE_SIZE_UNIT (TREE_TYPE (inner)), 0);
1097 /* If we can prove the memory starting at XEXP (mem, 0)
1098 and ending at XEXP (mem, 0) + LENGTH will fit into
1099 this field, we can keep that COMPONENT_REF in MEM_EXPR. */
1100 if (offset <= size
1101 && length <= size
1102 && offset + length <= size)
1103 break;
1104 }
1105
1106 if (offset >= 0
1107 && host_integerp (DECL_FIELD_OFFSET (field), 0))
1108 offset += tree_low_cst (DECL_FIELD_OFFSET (field), 0)
1109 + tree_low_cst (DECL_FIELD_BIT_OFFSET (field), 1)
1110 / BITS_PER_UNIT;
1111 else
1112 {
1113 offset = -1;
1114 length = -1;
1115 }
1116
1117 mem_expr = TREE_OPERAND (mem_expr, 0);
1118 inner = TREE_OPERAND (inner, 0);
1119 }
1120
1121 if (mem_expr == NULL)
1122 offset = -1;
1123 if (mem_expr != MEM_EXPR (mem))
1124 {
1125 set_mem_expr (mem, mem_expr);
1126 set_mem_offset (mem, offset >= 0 ? GEN_INT (offset) : NULL_RTX);
1127 }
1128 }
863 set_mem_alias_set (mem, 0);
1129 set_mem_alias_set (mem, 0);
1130 set_mem_size (mem, NULL_RTX);
864 }
865
866 return mem;
867}
868
869/* Built-in functions to perform an untyped call and return. */
870
871/* For each register that may be used for calling a function, this

--- 11 unchanged lines hidden (view full) ---

883static enum machine_mode apply_result_mode[FIRST_PSEUDO_REGISTER];
884
885/* For each register that may be used for calling a function, this
886 gives the offset of that register into the block returned by
887 __builtin_apply_args. 0 indicates that the register is not
888 used for calling a function. */
889static int apply_args_reg_offset[FIRST_PSEUDO_REGISTER];
890
1131 }
1132
1133 return mem;
1134}
1135
1136/* Built-in functions to perform an untyped call and return. */
1137
1138/* For each register that may be used for calling a function, this

--- 11 unchanged lines hidden (view full) ---

1150static enum machine_mode apply_result_mode[FIRST_PSEUDO_REGISTER];
1151
1152/* For each register that may be used for calling a function, this
1153 gives the offset of that register into the block returned by
1154 __builtin_apply_args. 0 indicates that the register is not
1155 used for calling a function. */
1156static int apply_args_reg_offset[FIRST_PSEUDO_REGISTER];
1157
891/* Return the offset of register REGNO into the block returned by
892 __builtin_apply_args. This is not declared static, since it is
893 needed in objc-act.c. */
894
895int
896apply_args_register_offset (int regno)
897{
898 apply_args_size ();
899
900 /* Arguments are always put in outgoing registers (in the argument
901 block) if such make sense. */
902#ifdef OUTGOING_REGNO
903 regno = OUTGOING_REGNO (regno);
904#endif
905 return apply_args_reg_offset[regno];
906}
907
908/* Return the size required for the block returned by __builtin_apply_args,
909 and initialize apply_args_mode. */
910
911static int
912apply_args_size (void)
913{
914 static int size = -1;
915 int align;

--- 9 unchanged lines hidden (view full) ---

925 /* The second value is the structure value address unless this is
926 passed as an "invisible" first argument. */
927 if (targetm.calls.struct_value_rtx (cfun ? TREE_TYPE (cfun->decl) : 0, 0))
928 size += GET_MODE_SIZE (Pmode);
929
930 for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
931 if (FUNCTION_ARG_REGNO_P (regno))
932 {
1158/* Return the size required for the block returned by __builtin_apply_args,
1159 and initialize apply_args_mode. */
1160
1161static int
1162apply_args_size (void)
1163{
1164 static int size = -1;
1165 int align;

--- 9 unchanged lines hidden (view full) ---

1175 /* The second value is the structure value address unless this is
1176 passed as an "invisible" first argument. */
1177 if (targetm.calls.struct_value_rtx (cfun ? TREE_TYPE (cfun->decl) : 0, 0))
1178 size += GET_MODE_SIZE (Pmode);
1179
1180 for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
1181 if (FUNCTION_ARG_REGNO_P (regno))
1182 {
933 /* Search for the proper mode for copying this register's
934 value. I'm not sure this is right, but it works so far. */
935 enum machine_mode best_mode = VOIDmode;
1183 mode = reg_raw_mode[regno];
936
1184
937 for (mode = GET_CLASS_NARROWEST_MODE (MODE_INT);
938 mode != VOIDmode;
939 mode = GET_MODE_WIDER_MODE (mode))
940 if (HARD_REGNO_MODE_OK (regno, mode)
941 && HARD_REGNO_NREGS (regno, mode) == 1)
942 best_mode = mode;
1185 gcc_assert (mode != VOIDmode);
943
1186
944 if (best_mode == VOIDmode)
945 for (mode = GET_CLASS_NARROWEST_MODE (MODE_FLOAT);
946 mode != VOIDmode;
947 mode = GET_MODE_WIDER_MODE (mode))
948 if (HARD_REGNO_MODE_OK (regno, mode)
949 && have_insn_for (SET, mode))
950 best_mode = mode;
951
952 if (best_mode == VOIDmode)
953 for (mode = GET_CLASS_NARROWEST_MODE (MODE_VECTOR_FLOAT);
954 mode != VOIDmode;
955 mode = GET_MODE_WIDER_MODE (mode))
956 if (HARD_REGNO_MODE_OK (regno, mode)
957 && have_insn_for (SET, mode))
958 best_mode = mode;
959
960 if (best_mode == VOIDmode)
961 for (mode = GET_CLASS_NARROWEST_MODE (MODE_VECTOR_INT);
962 mode != VOIDmode;
963 mode = GET_MODE_WIDER_MODE (mode))
964 if (HARD_REGNO_MODE_OK (regno, mode)
965 && have_insn_for (SET, mode))
966 best_mode = mode;
967
968 mode = best_mode;
969 if (mode == VOIDmode)
970 abort ();
971
972 align = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT;
973 if (size % align != 0)
974 size = CEIL (size, align) * align;
975 apply_args_reg_offset[regno] = size;
976 size += GET_MODE_SIZE (mode);
977 apply_args_mode[regno] = mode;
978 }
979 else

--- 18 unchanged lines hidden (view full) ---

998 /* The values computed by this function never change. */
999 if (size < 0)
1000 {
1001 size = 0;
1002
1003 for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
1004 if (FUNCTION_VALUE_REGNO_P (regno))
1005 {
1187 align = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT;
1188 if (size % align != 0)
1189 size = CEIL (size, align) * align;
1190 apply_args_reg_offset[regno] = size;
1191 size += GET_MODE_SIZE (mode);
1192 apply_args_mode[regno] = mode;
1193 }
1194 else

--- 18 unchanged lines hidden (view full) ---

1213 /* The values computed by this function never change. */
1214 if (size < 0)
1215 {
1216 size = 0;
1217
1218 for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
1219 if (FUNCTION_VALUE_REGNO_P (regno))
1220 {
1006 /* Search for the proper mode for copying this register's
1007 value. I'm not sure this is right, but it works so far. */
1008 enum machine_mode best_mode = VOIDmode;
1221 mode = reg_raw_mode[regno];
1009
1222
1010 for (mode = GET_CLASS_NARROWEST_MODE (MODE_INT);
1011 mode != TImode;
1012 mode = GET_MODE_WIDER_MODE (mode))
1013 if (HARD_REGNO_MODE_OK (regno, mode))
1014 best_mode = mode;
1223 gcc_assert (mode != VOIDmode);
1015
1224
1016 if (best_mode == VOIDmode)
1017 for (mode = GET_CLASS_NARROWEST_MODE (MODE_FLOAT);
1018 mode != VOIDmode;
1019 mode = GET_MODE_WIDER_MODE (mode))
1020 if (HARD_REGNO_MODE_OK (regno, mode)
1021 && have_insn_for (SET, mode))
1022 best_mode = mode;
1023
1024 if (best_mode == VOIDmode)
1025 for (mode = GET_CLASS_NARROWEST_MODE (MODE_VECTOR_FLOAT);
1026 mode != VOIDmode;
1027 mode = GET_MODE_WIDER_MODE (mode))
1028 if (HARD_REGNO_MODE_OK (regno, mode)
1029 && have_insn_for (SET, mode))
1030 best_mode = mode;
1031
1032 if (best_mode == VOIDmode)
1033 for (mode = GET_CLASS_NARROWEST_MODE (MODE_VECTOR_INT);
1034 mode != VOIDmode;
1035 mode = GET_MODE_WIDER_MODE (mode))
1036 if (HARD_REGNO_MODE_OK (regno, mode)
1037 && have_insn_for (SET, mode))
1038 best_mode = mode;
1039
1040 mode = best_mode;
1041 if (mode == VOIDmode)
1042 abort ();
1043
1044 align = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT;
1045 if (size % align != 0)
1046 size = CEIL (size, align) * align;
1047 size += GET_MODE_SIZE (mode);
1048 apply_result_mode[regno] = mode;
1049 }
1050 else
1051 apply_result_mode[regno] = VOIDmode;

--- 78 unchanged lines hidden (view full) ---

1130 /* We need the pointer as the caller actually passed them to us, not
1131 as we might have pretended they were passed. Make sure it's a valid
1132 operand, as emit_move_insn isn't expected to handle a PLUS. */
1133 tem
1134 = force_operand (plus_constant (tem, current_function_pretend_args_size),
1135 NULL_RTX);
1136#endif
1137 emit_move_insn (adjust_address (registers, Pmode, 0), tem);
1225 align = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT;
1226 if (size % align != 0)
1227 size = CEIL (size, align) * align;
1228 size += GET_MODE_SIZE (mode);
1229 apply_result_mode[regno] = mode;
1230 }
1231 else
1232 apply_result_mode[regno] = VOIDmode;

--- 78 unchanged lines hidden (view full) ---

1311 /* We need the pointer as the caller actually passed them to us, not
1312 as we might have pretended they were passed. Make sure it's a valid
1313 operand, as emit_move_insn isn't expected to handle a PLUS. */
1314 tem
1315 = force_operand (plus_constant (tem, current_function_pretend_args_size),
1316 NULL_RTX);
1317#endif
1318 emit_move_insn (adjust_address (registers, Pmode, 0), tem);
1138
1319
1139 size = GET_MODE_SIZE (Pmode);
1140
1141 /* Save the structure value address unless this is passed as an
1142 "invisible" first argument. */
1143 if (struct_incoming_value)
1144 {
1145 emit_move_insn (adjust_address (registers, Pmode, size),
1146 copy_to_reg (struct_incoming_value));

--- 32 unchanged lines hidden (view full) ---

1179
1180 apply_args_value = temp;
1181
1182 /* Put the insns after the NOTE that starts the function.
1183 If this is inside a start_sequence, make the outer-level insn
1184 chain current, so the code is placed at the start of the
1185 function. */
1186 push_topmost_sequence ();
1320 size = GET_MODE_SIZE (Pmode);
1321
1322 /* Save the structure value address unless this is passed as an
1323 "invisible" first argument. */
1324 if (struct_incoming_value)
1325 {
1326 emit_move_insn (adjust_address (registers, Pmode, size),
1327 copy_to_reg (struct_incoming_value));

--- 32 unchanged lines hidden (view full) ---

1360
1361 apply_args_value = temp;
1362
1363 /* Put the insns after the NOTE that starts the function.
1364 If this is inside a start_sequence, make the outer-level insn
1365 chain current, so the code is placed at the start of the
1366 function. */
1367 push_topmost_sequence ();
1187 emit_insn_before (seq, NEXT_INSN (get_insns ()));
1368 emit_insn_before (seq, NEXT_INSN (entry_of_function ()));
1188 pop_topmost_sequence ();
1189 return temp;
1190 }
1191}
1192
1193/* Perform an untyped call and save the state required to perform an
1194 untyped return of whatever value was returned by the given function. */
1195

--- 15 unchanged lines hidden (view full) ---

1211 /* Fetch the arg pointer from the ARGUMENTS block. */
1212 incoming_args = gen_reg_rtx (Pmode);
1213 emit_move_insn (incoming_args, gen_rtx_MEM (Pmode, arguments));
1214#ifndef STACK_GROWS_DOWNWARD
1215 incoming_args = expand_simple_binop (Pmode, MINUS, incoming_args, argsize,
1216 incoming_args, 0, OPTAB_LIB_WIDEN);
1217#endif
1218
1369 pop_topmost_sequence ();
1370 return temp;
1371 }
1372}
1373
1374/* Perform an untyped call and save the state required to perform an
1375 untyped return of whatever value was returned by the given function. */
1376

--- 15 unchanged lines hidden (view full) ---

1392 /* Fetch the arg pointer from the ARGUMENTS block. */
1393 incoming_args = gen_reg_rtx (Pmode);
1394 emit_move_insn (incoming_args, gen_rtx_MEM (Pmode, arguments));
1395#ifndef STACK_GROWS_DOWNWARD
1396 incoming_args = expand_simple_binop (Pmode, MINUS, incoming_args, argsize,
1397 incoming_args, 0, OPTAB_LIB_WIDEN);
1398#endif
1399
1219 /* Perform postincrements before actually calling the function. */
1220 emit_queue ();
1221
1222 /* Push a new argument block and copy the arguments. Do not allow
1223 the (potential) memcpy call below to interfere with our stack
1224 manipulations. */
1225 do_pending_stack_adjust ();
1226 NO_DEFER_POP;
1227
1228 /* Save the stack with nonlocal if available. */
1229#ifdef HAVE_save_stack_nonlocal

--- 46 unchanged lines hidden (view full) ---

1276 /* Restore the structure value address unless this is passed as an
1277 "invisible" first argument. */
1278 size = GET_MODE_SIZE (Pmode);
1279 if (struct_value)
1280 {
1281 rtx value = gen_reg_rtx (Pmode);
1282 emit_move_insn (value, adjust_address (arguments, Pmode, size));
1283 emit_move_insn (struct_value, value);
1400 /* Push a new argument block and copy the arguments. Do not allow
1401 the (potential) memcpy call below to interfere with our stack
1402 manipulations. */
1403 do_pending_stack_adjust ();
1404 NO_DEFER_POP;
1405
1406 /* Save the stack with nonlocal if available. */
1407#ifdef HAVE_save_stack_nonlocal

--- 46 unchanged lines hidden (view full) ---

1454 /* Restore the structure value address unless this is passed as an
1455 "invisible" first argument. */
1456 size = GET_MODE_SIZE (Pmode);
1457 if (struct_value)
1458 {
1459 rtx value = gen_reg_rtx (Pmode);
1460 emit_move_insn (value, adjust_address (arguments, Pmode, size));
1461 emit_move_insn (struct_value, value);
1284 if (GET_CODE (struct_value) == REG)
1462 if (REG_P (struct_value))
1285 use_reg (&call_fusage, struct_value);
1286 size += GET_MODE_SIZE (Pmode);
1287 }
1288
1289 /* All arguments and registers used for the call are set up by now! */
1463 use_reg (&call_fusage, struct_value);
1464 size += GET_MODE_SIZE (Pmode);
1465 }
1466
1467 /* All arguments and registers used for the call are set up by now! */
1290 function = prepare_call_address (function, NULL_TREE, &call_fusage, 0, 0);
1468 function = prepare_call_address (function, NULL, &call_fusage, 0, 0);
1291
1292 /* Ensure address is valid. SYMBOL_REF is already valid, so no need,
1293 and we don't want to load it into a register as an optimization,
1294 because prepare_call_address already did it if it should be done. */
1295 if (GET_CODE (function) != SYMBOL_REF)
1296 function = memory_address (FUNCTION_MODE, function);
1297
1298 /* Generate the actual call instruction and save the return value. */

--- 10 unchanged lines hidden (view full) ---

1309
1310 /* Locate the unique return register. It is not possible to
1311 express a call that sets more than one return register using
1312 call_value; use untyped_call for that. In fact, untyped_call
1313 only needs to save the return registers in the given block. */
1314 for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
1315 if ((mode = apply_result_mode[regno]) != VOIDmode)
1316 {
1469
1470 /* Ensure address is valid. SYMBOL_REF is already valid, so no need,
1471 and we don't want to load it into a register as an optimization,
1472 because prepare_call_address already did it if it should be done. */
1473 if (GET_CODE (function) != SYMBOL_REF)
1474 function = memory_address (FUNCTION_MODE, function);
1475
1476 /* Generate the actual call instruction and save the return value. */

--- 10 unchanged lines hidden (view full) ---

1487
1488 /* Locate the unique return register. It is not possible to
1489 express a call that sets more than one return register using
1490 call_value; use untyped_call for that. In fact, untyped_call
1491 only needs to save the return registers in the given block. */
1492 for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
1493 if ((mode = apply_result_mode[regno]) != VOIDmode)
1494 {
1317 if (valreg)
1318 abort (); /* HAVE_untyped_call required. */
1495 gcc_assert (!valreg); /* HAVE_untyped_call required. */
1496
1319 valreg = gen_rtx_REG (mode, regno);
1320 }
1321
1322 emit_call_insn (GEN_CALL_VALUE (valreg,
1323 gen_rtx_MEM (FUNCTION_MODE, function),
1324 const0_rtx, NULL_RTX, const0_rtx));
1325
1326 emit_move_insn (adjust_address (result, GET_MODE (valreg), 0), valreg);
1327 }
1328 else
1329#endif
1497 valreg = gen_rtx_REG (mode, regno);
1498 }
1499
1500 emit_call_insn (GEN_CALL_VALUE (valreg,
1501 gen_rtx_MEM (FUNCTION_MODE, function),
1502 const0_rtx, NULL_RTX, const0_rtx));
1503
1504 emit_move_insn (adjust_address (result, GET_MODE (valreg), 0), valreg);
1505 }
1506 else
1507#endif
1330 abort ();
1508 gcc_unreachable ();
1331
1332 /* Find the CALL insn we just emitted, and attach the register usage
1333 information. */
1334 call_insn = last_call_insn ();
1335 add_function_usage_to (call_insn, call_fusage);
1336
1337 /* Restore the stack. */
1338#ifdef HAVE_save_stack_nonlocal

--- 64 unchanged lines hidden (view full) ---

1403
1404static enum type_class
1405type_to_class (tree type)
1406{
1407 switch (TREE_CODE (type))
1408 {
1409 case VOID_TYPE: return void_type_class;
1410 case INTEGER_TYPE: return integer_type_class;
1509
1510 /* Find the CALL insn we just emitted, and attach the register usage
1511 information. */
1512 call_insn = last_call_insn ();
1513 add_function_usage_to (call_insn, call_fusage);
1514
1515 /* Restore the stack. */
1516#ifdef HAVE_save_stack_nonlocal

--- 64 unchanged lines hidden (view full) ---

1581
1582static enum type_class
1583type_to_class (tree type)
1584{
1585 switch (TREE_CODE (type))
1586 {
1587 case VOID_TYPE: return void_type_class;
1588 case INTEGER_TYPE: return integer_type_class;
1411 case CHAR_TYPE: return char_type_class;
1412 case ENUMERAL_TYPE: return enumeral_type_class;
1413 case BOOLEAN_TYPE: return boolean_type_class;
1414 case POINTER_TYPE: return pointer_type_class;
1415 case REFERENCE_TYPE: return reference_type_class;
1416 case OFFSET_TYPE: return offset_type_class;
1417 case REAL_TYPE: return real_type_class;
1418 case COMPLEX_TYPE: return complex_type_class;
1419 case FUNCTION_TYPE: return function_type_class;
1420 case METHOD_TYPE: return method_type_class;
1421 case RECORD_TYPE: return record_type_class;
1422 case UNION_TYPE:
1423 case QUAL_UNION_TYPE: return union_type_class;
1424 case ARRAY_TYPE: return (TYPE_STRING_FLAG (type)
1425 ? string_type_class : array_type_class);
1589 case ENUMERAL_TYPE: return enumeral_type_class;
1590 case BOOLEAN_TYPE: return boolean_type_class;
1591 case POINTER_TYPE: return pointer_type_class;
1592 case REFERENCE_TYPE: return reference_type_class;
1593 case OFFSET_TYPE: return offset_type_class;
1594 case REAL_TYPE: return real_type_class;
1595 case COMPLEX_TYPE: return complex_type_class;
1596 case FUNCTION_TYPE: return function_type_class;
1597 case METHOD_TYPE: return method_type_class;
1598 case RECORD_TYPE: return record_type_class;
1599 case UNION_TYPE:
1600 case QUAL_UNION_TYPE: return union_type_class;
1601 case ARRAY_TYPE: return (TYPE_STRING_FLAG (type)
1602 ? string_type_class : array_type_class);
1426 case SET_TYPE: return set_type_class;
1427 case FILE_TYPE: return file_type_class;
1428 case LANG_TYPE: return lang_type_class;
1429 default: return no_type_class;
1430 }
1431}
1432
1433/* Expand a call to __builtin_classify_type with arguments found in
1434 ARGLIST. */
1435
1436static rtx
1437expand_builtin_classify_type (tree arglist)
1438{
1439 if (arglist != 0)
1440 return GEN_INT (type_to_class (TREE_TYPE (TREE_VALUE (arglist))));
1441 return GEN_INT (no_type_class);
1442}
1443
1603 case LANG_TYPE: return lang_type_class;
1604 default: return no_type_class;
1605 }
1606}
1607
1608/* Expand a call to __builtin_classify_type with arguments found in
1609 ARGLIST. */
1610
1611static rtx
1612expand_builtin_classify_type (tree arglist)
1613{
1614 if (arglist != 0)
1615 return GEN_INT (type_to_class (TREE_TYPE (TREE_VALUE (arglist))));
1616 return GEN_INT (no_type_class);
1617}
1618
1444/* Expand expression EXP, which is a call to __builtin_constant_p. */
1445
1446static rtx
1447expand_builtin_constant_p (tree arglist, enum machine_mode target_mode)
1448{
1449 rtx tmp;
1450
1451 if (arglist == 0)
1452 return const0_rtx;
1453 arglist = TREE_VALUE (arglist);
1454
1455 /* We have taken care of the easy cases during constant folding. This
1456 case is not obvious, so emit (constant_p_rtx (ARGLIST)) and let CSE
1457 get a chance to see if it can deduce whether ARGLIST is constant.
1458 If CSE isn't going to run, of course, don't bother waiting. */
1459
1460 if (cse_not_expected)
1461 return const0_rtx;
1462
1463 current_function_calls_constant_p = 1;
1464
1465 tmp = expand_expr (arglist, NULL_RTX, VOIDmode, 0);
1466 tmp = gen_rtx_CONSTANT_P_RTX (target_mode, tmp);
1467 return tmp;
1468}
1469
1470/* This helper macro, meant to be used in mathfn_built_in below,
1471 determines which among a set of three builtin math functions is
1472 appropriate for a given type mode. The `F' and `L' cases are
1473 automatically generated from the `double' case. */
1474#define CASE_MATHFN(BUILT_IN_MATHFN) \
1475 case BUILT_IN_MATHFN: case BUILT_IN_MATHFN##F: case BUILT_IN_MATHFN##L: \
1476 fcode = BUILT_IN_MATHFN; fcodef = BUILT_IN_MATHFN##F ; \
1477 fcodel = BUILT_IN_MATHFN##L ; break;
1478
1479/* Return mathematic function equivalent to FN but operating directly
1480 on TYPE, if available. If we can't do the conversion, return zero. */
1481tree
1482mathfn_built_in (tree type, enum built_in_function fn)
1483{
1619/* This helper macro, meant to be used in mathfn_built_in below,
1620 determines which among a set of three builtin math functions is
1621 appropriate for a given type mode. The `F' and `L' cases are
1622 automatically generated from the `double' case. */
1623#define CASE_MATHFN(BUILT_IN_MATHFN) \
1624 case BUILT_IN_MATHFN: case BUILT_IN_MATHFN##F: case BUILT_IN_MATHFN##L: \
1625 fcode = BUILT_IN_MATHFN; fcodef = BUILT_IN_MATHFN##F ; \
1626 fcodel = BUILT_IN_MATHFN##L ; break;
1627
1628/* Return mathematic function equivalent to FN but operating directly
1629 on TYPE, if available. If we can't do the conversion, return zero. */
1630tree
1631mathfn_built_in (tree type, enum built_in_function fn)
1632{
1484 const enum machine_mode type_mode = TYPE_MODE (type);
1485 enum built_in_function fcode, fcodef, fcodel;
1486
1487 switch (fn)
1488 {
1489 CASE_MATHFN (BUILT_IN_ACOS)
1490 CASE_MATHFN (BUILT_IN_ACOSH)
1491 CASE_MATHFN (BUILT_IN_ASIN)
1492 CASE_MATHFN (BUILT_IN_ASINH)

--- 23 unchanged lines hidden (view full) ---

1516 CASE_MATHFN (BUILT_IN_GAMMA)
1517 CASE_MATHFN (BUILT_IN_HUGE_VAL)
1518 CASE_MATHFN (BUILT_IN_HYPOT)
1519 CASE_MATHFN (BUILT_IN_ILOGB)
1520 CASE_MATHFN (BUILT_IN_INF)
1521 CASE_MATHFN (BUILT_IN_J0)
1522 CASE_MATHFN (BUILT_IN_J1)
1523 CASE_MATHFN (BUILT_IN_JN)
1633 enum built_in_function fcode, fcodef, fcodel;
1634
1635 switch (fn)
1636 {
1637 CASE_MATHFN (BUILT_IN_ACOS)
1638 CASE_MATHFN (BUILT_IN_ACOSH)
1639 CASE_MATHFN (BUILT_IN_ASIN)
1640 CASE_MATHFN (BUILT_IN_ASINH)

--- 23 unchanged lines hidden (view full) ---

1664 CASE_MATHFN (BUILT_IN_GAMMA)
1665 CASE_MATHFN (BUILT_IN_HUGE_VAL)
1666 CASE_MATHFN (BUILT_IN_HYPOT)
1667 CASE_MATHFN (BUILT_IN_ILOGB)
1668 CASE_MATHFN (BUILT_IN_INF)
1669 CASE_MATHFN (BUILT_IN_J0)
1670 CASE_MATHFN (BUILT_IN_J1)
1671 CASE_MATHFN (BUILT_IN_JN)
1672 CASE_MATHFN (BUILT_IN_LCEIL)
1524 CASE_MATHFN (BUILT_IN_LDEXP)
1673 CASE_MATHFN (BUILT_IN_LDEXP)
1674 CASE_MATHFN (BUILT_IN_LFLOOR)
1525 CASE_MATHFN (BUILT_IN_LGAMMA)
1675 CASE_MATHFN (BUILT_IN_LGAMMA)
1676 CASE_MATHFN (BUILT_IN_LLCEIL)
1677 CASE_MATHFN (BUILT_IN_LLFLOOR)
1526 CASE_MATHFN (BUILT_IN_LLRINT)
1527 CASE_MATHFN (BUILT_IN_LLROUND)
1528 CASE_MATHFN (BUILT_IN_LOG)
1529 CASE_MATHFN (BUILT_IN_LOG10)
1530 CASE_MATHFN (BUILT_IN_LOG1P)
1531 CASE_MATHFN (BUILT_IN_LOG2)
1532 CASE_MATHFN (BUILT_IN_LOGB)
1533 CASE_MATHFN (BUILT_IN_LRINT)
1534 CASE_MATHFN (BUILT_IN_LROUND)
1535 CASE_MATHFN (BUILT_IN_MODF)
1536 CASE_MATHFN (BUILT_IN_NAN)
1537 CASE_MATHFN (BUILT_IN_NANS)
1538 CASE_MATHFN (BUILT_IN_NEARBYINT)
1539 CASE_MATHFN (BUILT_IN_NEXTAFTER)
1540 CASE_MATHFN (BUILT_IN_NEXTTOWARD)
1541 CASE_MATHFN (BUILT_IN_POW)
1678 CASE_MATHFN (BUILT_IN_LLRINT)
1679 CASE_MATHFN (BUILT_IN_LLROUND)
1680 CASE_MATHFN (BUILT_IN_LOG)
1681 CASE_MATHFN (BUILT_IN_LOG10)
1682 CASE_MATHFN (BUILT_IN_LOG1P)
1683 CASE_MATHFN (BUILT_IN_LOG2)
1684 CASE_MATHFN (BUILT_IN_LOGB)
1685 CASE_MATHFN (BUILT_IN_LRINT)
1686 CASE_MATHFN (BUILT_IN_LROUND)
1687 CASE_MATHFN (BUILT_IN_MODF)
1688 CASE_MATHFN (BUILT_IN_NAN)
1689 CASE_MATHFN (BUILT_IN_NANS)
1690 CASE_MATHFN (BUILT_IN_NEARBYINT)
1691 CASE_MATHFN (BUILT_IN_NEXTAFTER)
1692 CASE_MATHFN (BUILT_IN_NEXTTOWARD)
1693 CASE_MATHFN (BUILT_IN_POW)
1694 CASE_MATHFN (BUILT_IN_POWI)
1542 CASE_MATHFN (BUILT_IN_POW10)
1543 CASE_MATHFN (BUILT_IN_REMAINDER)
1544 CASE_MATHFN (BUILT_IN_REMQUO)
1545 CASE_MATHFN (BUILT_IN_RINT)
1546 CASE_MATHFN (BUILT_IN_ROUND)
1547 CASE_MATHFN (BUILT_IN_SCALB)
1548 CASE_MATHFN (BUILT_IN_SCALBLN)
1549 CASE_MATHFN (BUILT_IN_SCALBN)

--- 9 unchanged lines hidden (view full) ---

1559 CASE_MATHFN (BUILT_IN_Y0)
1560 CASE_MATHFN (BUILT_IN_Y1)
1561 CASE_MATHFN (BUILT_IN_YN)
1562
1563 default:
1564 return 0;
1565 }
1566
1695 CASE_MATHFN (BUILT_IN_POW10)
1696 CASE_MATHFN (BUILT_IN_REMAINDER)
1697 CASE_MATHFN (BUILT_IN_REMQUO)
1698 CASE_MATHFN (BUILT_IN_RINT)
1699 CASE_MATHFN (BUILT_IN_ROUND)
1700 CASE_MATHFN (BUILT_IN_SCALB)
1701 CASE_MATHFN (BUILT_IN_SCALBLN)
1702 CASE_MATHFN (BUILT_IN_SCALBN)

--- 9 unchanged lines hidden (view full) ---

1712 CASE_MATHFN (BUILT_IN_Y0)
1713 CASE_MATHFN (BUILT_IN_Y1)
1714 CASE_MATHFN (BUILT_IN_YN)
1715
1716 default:
1717 return 0;
1718 }
1719
1567 if (type_mode == TYPE_MODE (double_type_node))
1720 if (TYPE_MAIN_VARIANT (type) == double_type_node)
1568 return implicit_built_in_decls[fcode];
1721 return implicit_built_in_decls[fcode];
1569 else if (type_mode == TYPE_MODE (float_type_node))
1722 else if (TYPE_MAIN_VARIANT (type) == float_type_node)
1570 return implicit_built_in_decls[fcodef];
1723 return implicit_built_in_decls[fcodef];
1571 else if (type_mode == TYPE_MODE (long_double_type_node))
1724 else if (TYPE_MAIN_VARIANT (type) == long_double_type_node)
1572 return implicit_built_in_decls[fcodel];
1573 else
1574 return 0;
1575}
1576
1577/* If errno must be maintained, expand the RTL to check if the result,
1578 TARGET, of a built-in function call, EXP, is NaN, and if so set
1579 errno to EDOM. */

--- 28 unchanged lines hidden (view full) ---

1608 Pop the arguments right away in case the call gets deleted. */
1609 NO_DEFER_POP;
1610 expand_call (exp, target, 0);
1611 OK_DEFER_POP;
1612 emit_label (lab);
1613}
1614
1615
1725 return implicit_built_in_decls[fcodel];
1726 else
1727 return 0;
1728}
1729
1730/* If errno must be maintained, expand the RTL to check if the result,
1731 TARGET, of a built-in function call, EXP, is NaN, and if so set
1732 errno to EDOM. */

--- 28 unchanged lines hidden (view full) ---

1761 Pop the arguments right away in case the call gets deleted. */
1762 NO_DEFER_POP;
1763 expand_call (exp, target, 0);
1764 OK_DEFER_POP;
1765 emit_label (lab);
1766}
1767
1768
1616/* Expand a call to one of the builtin math functions (sin, cos, or sqrt).
1769/* Expand a call to one of the builtin math functions (sqrt, exp, or log).
1617 Return 0 if a normal call should be emitted rather than expanding the
1618 function in-line. EXP is the expression that is a call to the builtin
1619 function; if convenient, the result should be placed in TARGET.
1620 SUBTARGET may be used as the target for computing one of EXP's operands. */
1621
1622static rtx
1623expand_builtin_mathfn (tree exp, rtx target, rtx subtarget)
1624{

--- 7 unchanged lines hidden (view full) ---

1632
1633 if (!validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
1634 return 0;
1635
1636 arg = TREE_VALUE (arglist);
1637
1638 switch (DECL_FUNCTION_CODE (fndecl))
1639 {
1770 Return 0 if a normal call should be emitted rather than expanding the
1771 function in-line. EXP is the expression that is a call to the builtin
1772 function; if convenient, the result should be placed in TARGET.
1773 SUBTARGET may be used as the target for computing one of EXP's operands. */
1774
1775static rtx
1776expand_builtin_mathfn (tree exp, rtx target, rtx subtarget)
1777{

--- 7 unchanged lines hidden (view full) ---

1785
1786 if (!validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
1787 return 0;
1788
1789 arg = TREE_VALUE (arglist);
1790
1791 switch (DECL_FUNCTION_CODE (fndecl))
1792 {
1640 case BUILT_IN_SIN:
1641 case BUILT_IN_SINF:
1642 case BUILT_IN_SINL:
1643 builtin_optab = sin_optab; break;
1644 case BUILT_IN_COS:
1645 case BUILT_IN_COSF:
1646 case BUILT_IN_COSL:
1647 builtin_optab = cos_optab; break;
1648 case BUILT_IN_SQRT:
1649 case BUILT_IN_SQRTF:
1650 case BUILT_IN_SQRTL:
1793 CASE_FLT_FN (BUILT_IN_SQRT):
1651 errno_set = ! tree_expr_nonnegative_p (arg);
1652 builtin_optab = sqrt_optab;
1653 break;
1794 errno_set = ! tree_expr_nonnegative_p (arg);
1795 builtin_optab = sqrt_optab;
1796 break;
1654 case BUILT_IN_EXP:
1655 case BUILT_IN_EXPF:
1656 case BUILT_IN_EXPL:
1797 CASE_FLT_FN (BUILT_IN_EXP):
1657 errno_set = true; builtin_optab = exp_optab; break;
1798 errno_set = true; builtin_optab = exp_optab; break;
1658 case BUILT_IN_LOG:
1659 case BUILT_IN_LOGF:
1660 case BUILT_IN_LOGL:
1799 CASE_FLT_FN (BUILT_IN_EXP10):
1800 CASE_FLT_FN (BUILT_IN_POW10):
1801 errno_set = true; builtin_optab = exp10_optab; break;
1802 CASE_FLT_FN (BUILT_IN_EXP2):
1803 errno_set = true; builtin_optab = exp2_optab; break;
1804 CASE_FLT_FN (BUILT_IN_EXPM1):
1805 errno_set = true; builtin_optab = expm1_optab; break;
1806 CASE_FLT_FN (BUILT_IN_LOGB):
1807 errno_set = true; builtin_optab = logb_optab; break;
1808 CASE_FLT_FN (BUILT_IN_ILOGB):
1809 errno_set = true; builtin_optab = ilogb_optab; break;
1810 CASE_FLT_FN (BUILT_IN_LOG):
1661 errno_set = true; builtin_optab = log_optab; break;
1811 errno_set = true; builtin_optab = log_optab; break;
1662 case BUILT_IN_TAN:
1663 case BUILT_IN_TANF:
1664 case BUILT_IN_TANL:
1812 CASE_FLT_FN (BUILT_IN_LOG10):
1813 errno_set = true; builtin_optab = log10_optab; break;
1814 CASE_FLT_FN (BUILT_IN_LOG2):
1815 errno_set = true; builtin_optab = log2_optab; break;
1816 CASE_FLT_FN (BUILT_IN_LOG1P):
1817 errno_set = true; builtin_optab = log1p_optab; break;
1818 CASE_FLT_FN (BUILT_IN_ASIN):
1819 builtin_optab = asin_optab; break;
1820 CASE_FLT_FN (BUILT_IN_ACOS):
1821 builtin_optab = acos_optab; break;
1822 CASE_FLT_FN (BUILT_IN_TAN):
1665 builtin_optab = tan_optab; break;
1823 builtin_optab = tan_optab; break;
1666 case BUILT_IN_ATAN:
1667 case BUILT_IN_ATANF:
1668 case BUILT_IN_ATANL:
1824 CASE_FLT_FN (BUILT_IN_ATAN):
1669 builtin_optab = atan_optab; break;
1825 builtin_optab = atan_optab; break;
1670 case BUILT_IN_FLOOR:
1671 case BUILT_IN_FLOORF:
1672 case BUILT_IN_FLOORL:
1826 CASE_FLT_FN (BUILT_IN_FLOOR):
1673 builtin_optab = floor_optab; break;
1827 builtin_optab = floor_optab; break;
1674 case BUILT_IN_CEIL:
1675 case BUILT_IN_CEILF:
1676 case BUILT_IN_CEILL:
1828 CASE_FLT_FN (BUILT_IN_CEIL):
1677 builtin_optab = ceil_optab; break;
1829 builtin_optab = ceil_optab; break;
1678 case BUILT_IN_TRUNC:
1679 case BUILT_IN_TRUNCF:
1680 case BUILT_IN_TRUNCL:
1830 CASE_FLT_FN (BUILT_IN_TRUNC):
1681 builtin_optab = btrunc_optab; break;
1831 builtin_optab = btrunc_optab; break;
1682 case BUILT_IN_ROUND:
1683 case BUILT_IN_ROUNDF:
1684 case BUILT_IN_ROUNDL:
1832 CASE_FLT_FN (BUILT_IN_ROUND):
1685 builtin_optab = round_optab; break;
1833 builtin_optab = round_optab; break;
1686 case BUILT_IN_NEARBYINT:
1687 case BUILT_IN_NEARBYINTF:
1688 case BUILT_IN_NEARBYINTL:
1834 CASE_FLT_FN (BUILT_IN_NEARBYINT):
1689 builtin_optab = nearbyint_optab; break;
1835 builtin_optab = nearbyint_optab; break;
1836 CASE_FLT_FN (BUILT_IN_RINT):
1837 builtin_optab = rint_optab; break;
1838 CASE_FLT_FN (BUILT_IN_LRINT):
1839 CASE_FLT_FN (BUILT_IN_LLRINT):
1840 builtin_optab = lrint_optab; break;
1690 default:
1841 default:
1691 abort ();
1842 gcc_unreachable ();
1692 }
1693
1694 /* Make a suitable register to place result in. */
1695 mode = TYPE_MODE (TREE_TYPE (exp));
1696
1697 if (! flag_errno_math || ! HONOR_NANS (mode))
1698 errno_set = false;
1699
1700 /* Before working hard, check whether the instruction is available. */
1701 if (builtin_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing)
1702 {
1703 target = gen_reg_rtx (mode);
1704
1705 /* Wrap the computation of the argument in a SAVE_EXPR, as we may
1706 need to expand the argument again. This way, we will not perform
1707 side-effects more the once. */
1843 }
1844
1845 /* Make a suitable register to place result in. */
1846 mode = TYPE_MODE (TREE_TYPE (exp));
1847
1848 if (! flag_errno_math || ! HONOR_NANS (mode))
1849 errno_set = false;
1850
1851 /* Before working hard, check whether the instruction is available. */
1852 if (builtin_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing)
1853 {
1854 target = gen_reg_rtx (mode);
1855
1856 /* Wrap the computation of the argument in a SAVE_EXPR, as we may
1857 need to expand the argument again. This way, we will not perform
1858 side-effects more the once. */
1708 narg = save_expr (arg);
1859 narg = builtin_save_expr (arg);
1709 if (narg != arg)
1710 {
1711 arg = narg;
1712 arglist = build_tree_list (NULL_TREE, arg);
1713 exp = build_function_call_expr (fndecl, arglist);
1714 }
1715
1716 op0 = expand_expr (arg, subtarget, VOIDmode, 0);
1717
1860 if (narg != arg)
1861 {
1862 arg = narg;
1863 arglist = build_tree_list (NULL_TREE, arg);
1864 exp = build_function_call_expr (fndecl, arglist);
1865 }
1866
1867 op0 = expand_expr (arg, subtarget, VOIDmode, 0);
1868
1718 emit_queue ();
1719 start_sequence ();
1720
1721 /* Compute into TARGET.
1722 Set TARGET to wherever the result comes back. */
1723 target = expand_unop (mode, builtin_optab, op0, target, 0);
1724
1725 if (target != 0)
1726 {

--- 37 unchanged lines hidden (view full) ---

1764 && GET_CODE (note) == EXPR_LIST
1765 && GET_CODE (XEXP (note, 0)) == EXPR_LIST
1766 && XEXP (XEXP (note, 0), 1) != NULL_RTX
1767 && XEXP (XEXP (XEXP (note, 0), 1), 1) == NULL_RTX)
1768 {
1769 rtx operand = XEXP (XEXP (XEXP (note, 0), 1), 0);
1770 /* Check operand is a register with expected mode. */
1771 if (operand
1869 start_sequence ();
1870
1871 /* Compute into TARGET.
1872 Set TARGET to wherever the result comes back. */
1873 target = expand_unop (mode, builtin_optab, op0, target, 0);
1874
1875 if (target != 0)
1876 {

--- 37 unchanged lines hidden (view full) ---

1914 && GET_CODE (note) == EXPR_LIST
1915 && GET_CODE (XEXP (note, 0)) == EXPR_LIST
1916 && XEXP (XEXP (note, 0), 1) != NULL_RTX
1917 && XEXP (XEXP (XEXP (note, 0), 1), 1) == NULL_RTX)
1918 {
1919 rtx operand = XEXP (XEXP (XEXP (note, 0), 1), 0);
1920 /* Check operand is a register with expected mode. */
1921 if (operand
1772 && GET_CODE (operand) == REG
1922 && REG_P (operand)
1773 && GET_MODE (operand) == mode)
1774 {
1775 /* Replace the REG_EQUAL note with a SQRT rtx. */
1776 rtx equiv = gen_rtx_SQRT (mode, operand);
1777 set_unique_reg_note (last, REG_EQUAL, equiv);
1778 }
1779 }
1780 break;

--- 12 unchanged lines hidden (view full) ---

1793 SUBTARGET may be used as the target for computing one of EXP's
1794 operands. */
1795
1796static rtx
1797expand_builtin_mathfn_2 (tree exp, rtx target, rtx subtarget)
1798{
1799 optab builtin_optab;
1800 rtx op0, op1, insns;
1923 && GET_MODE (operand) == mode)
1924 {
1925 /* Replace the REG_EQUAL note with a SQRT rtx. */
1926 rtx equiv = gen_rtx_SQRT (mode, operand);
1927 set_unique_reg_note (last, REG_EQUAL, equiv);
1928 }
1929 }
1930 break;

--- 12 unchanged lines hidden (view full) ---

1943 SUBTARGET may be used as the target for computing one of EXP's
1944 operands. */
1945
1946static rtx
1947expand_builtin_mathfn_2 (tree exp, rtx target, rtx subtarget)
1948{
1949 optab builtin_optab;
1950 rtx op0, op1, insns;
1951 int op1_type = REAL_TYPE;
1801 tree fndecl = get_callee_fndecl (exp);
1802 tree arglist = TREE_OPERAND (exp, 1);
1803 tree arg0, arg1, temp, narg;
1804 enum machine_mode mode;
1805 bool errno_set = true;
1806 bool stable = true;
1807
1952 tree fndecl = get_callee_fndecl (exp);
1953 tree arglist = TREE_OPERAND (exp, 1);
1954 tree arg0, arg1, temp, narg;
1955 enum machine_mode mode;
1956 bool errno_set = true;
1957 bool stable = true;
1958
1808 if (!validate_arglist (arglist, REAL_TYPE, REAL_TYPE, VOID_TYPE))
1959 if ((DECL_FUNCTION_CODE (fndecl) == BUILT_IN_LDEXP)
1960 || (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_LDEXPF)
1961 || (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_LDEXPL))
1962 op1_type = INTEGER_TYPE;
1963
1964 if (!validate_arglist (arglist, REAL_TYPE, op1_type, VOID_TYPE))
1809 return 0;
1810
1811 arg0 = TREE_VALUE (arglist);
1812 arg1 = TREE_VALUE (TREE_CHAIN (arglist));
1813
1814 switch (DECL_FUNCTION_CODE (fndecl))
1815 {
1965 return 0;
1966
1967 arg0 = TREE_VALUE (arglist);
1968 arg1 = TREE_VALUE (TREE_CHAIN (arglist));
1969
1970 switch (DECL_FUNCTION_CODE (fndecl))
1971 {
1816 case BUILT_IN_POW:
1817 case BUILT_IN_POWF:
1818 case BUILT_IN_POWL:
1972 CASE_FLT_FN (BUILT_IN_POW):
1819 builtin_optab = pow_optab; break;
1973 builtin_optab = pow_optab; break;
1820 case BUILT_IN_ATAN2:
1821 case BUILT_IN_ATAN2F:
1822 case BUILT_IN_ATAN2L:
1974 CASE_FLT_FN (BUILT_IN_ATAN2):
1823 builtin_optab = atan2_optab; break;
1975 builtin_optab = atan2_optab; break;
1976 CASE_FLT_FN (BUILT_IN_LDEXP):
1977 builtin_optab = ldexp_optab; break;
1978 CASE_FLT_FN (BUILT_IN_FMOD):
1979 builtin_optab = fmod_optab; break;
1980 CASE_FLT_FN (BUILT_IN_DREM):
1981 builtin_optab = drem_optab; break;
1824 default:
1982 default:
1825 abort ();
1983 gcc_unreachable ();
1826 }
1827
1828 /* Make a suitable register to place result in. */
1829 mode = TYPE_MODE (TREE_TYPE (exp));
1830
1831 /* Before working hard, check whether the instruction is available. */
1832 if (builtin_optab->handlers[(int) mode].insn_code == CODE_FOR_nothing)
1833 return 0;
1834
1835 target = gen_reg_rtx (mode);
1836
1837 if (! flag_errno_math || ! HONOR_NANS (mode))
1838 errno_set = false;
1839
1984 }
1985
1986 /* Make a suitable register to place result in. */
1987 mode = TYPE_MODE (TREE_TYPE (exp));
1988
1989 /* Before working hard, check whether the instruction is available. */
1990 if (builtin_optab->handlers[(int) mode].insn_code == CODE_FOR_nothing)
1991 return 0;
1992
1993 target = gen_reg_rtx (mode);
1994
1995 if (! flag_errno_math || ! HONOR_NANS (mode))
1996 errno_set = false;
1997
1840 /* Alway stabilize the argument list. */
1841 narg = save_expr (arg1);
1998 /* Always stabilize the argument list. */
1999 narg = builtin_save_expr (arg1);
1842 if (narg != arg1)
1843 {
1844 arg1 = narg;
1845 temp = build_tree_list (NULL_TREE, narg);
1846 stable = false;
1847 }
1848 else
1849 temp = TREE_CHAIN (arglist);
1850
2000 if (narg != arg1)
2001 {
2002 arg1 = narg;
2003 temp = build_tree_list (NULL_TREE, narg);
2004 stable = false;
2005 }
2006 else
2007 temp = TREE_CHAIN (arglist);
2008
1851 narg = save_expr (arg0);
2009 narg = builtin_save_expr (arg0);
1852 if (narg != arg0)
1853 {
1854 arg0 = narg;
1855 arglist = tree_cons (NULL_TREE, narg, temp);
1856 stable = false;
1857 }
1858 else if (! stable)
1859 arglist = tree_cons (NULL_TREE, arg0, temp);
1860
1861 if (! stable)
1862 exp = build_function_call_expr (fndecl, arglist);
1863
2010 if (narg != arg0)
2011 {
2012 arg0 = narg;
2013 arglist = tree_cons (NULL_TREE, narg, temp);
2014 stable = false;
2015 }
2016 else if (! stable)
2017 arglist = tree_cons (NULL_TREE, arg0, temp);
2018
2019 if (! stable)
2020 exp = build_function_call_expr (fndecl, arglist);
2021
1864 op0 = expand_expr (arg0, subtarget, VOIDmode, 0);
1865 op1 = expand_expr (arg1, 0, VOIDmode, 0);
2022 op0 = expand_expr (arg0, subtarget, VOIDmode, EXPAND_NORMAL);
2023 op1 = expand_normal (arg1);
1866
2024
1867 emit_queue ();
1868 start_sequence ();
1869
1870 /* Compute into TARGET.
1871 Set TARGET to wherever the result comes back. */
1872 target = expand_binop (mode, builtin_optab, op0, op1,
1873 target, 0, OPTAB_DIRECT);
1874
1875 /* If we were unable to expand via the builtin, stop the sequence

--- 11 unchanged lines hidden (view full) ---

1887 /* Output the entire sequence. */
1888 insns = get_insns ();
1889 end_sequence ();
1890 emit_insn (insns);
1891
1892 return target;
1893}
1894
2025 start_sequence ();
2026
2027 /* Compute into TARGET.
2028 Set TARGET to wherever the result comes back. */
2029 target = expand_binop (mode, builtin_optab, op0, op1,
2030 target, 0, OPTAB_DIRECT);
2031
2032 /* If we were unable to expand via the builtin, stop the sequence

--- 11 unchanged lines hidden (view full) ---

2044 /* Output the entire sequence. */
2045 insns = get_insns ();
2046 end_sequence ();
2047 emit_insn (insns);
2048
2049 return target;
2050}
2051
2052/* Expand a call to the builtin sin and cos math functions.
2053 Return 0 if a normal call should be emitted rather than expanding the
2054 function in-line. EXP is the expression that is a call to the builtin
2055 function; if convenient, the result should be placed in TARGET.
2056 SUBTARGET may be used as the target for computing one of EXP's
2057 operands. */
2058
2059static rtx
2060expand_builtin_mathfn_3 (tree exp, rtx target, rtx subtarget)
2061{
2062 optab builtin_optab;
2063 rtx op0, insns;
2064 tree fndecl = get_callee_fndecl (exp);
2065 tree arglist = TREE_OPERAND (exp, 1);
2066 enum machine_mode mode;
2067 tree arg, narg;
2068
2069 if (!validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
2070 return 0;
2071
2072 arg = TREE_VALUE (arglist);
2073
2074 switch (DECL_FUNCTION_CODE (fndecl))
2075 {
2076 CASE_FLT_FN (BUILT_IN_SIN):
2077 CASE_FLT_FN (BUILT_IN_COS):
2078 builtin_optab = sincos_optab; break;
2079 default:
2080 gcc_unreachable ();
2081 }
2082
2083 /* Make a suitable register to place result in. */
2084 mode = TYPE_MODE (TREE_TYPE (exp));
2085
2086 /* Check if sincos insn is available, otherwise fallback
2087 to sin or cos insn. */
2088 if (builtin_optab->handlers[(int) mode].insn_code == CODE_FOR_nothing) {
2089 switch (DECL_FUNCTION_CODE (fndecl))
2090 {
2091 CASE_FLT_FN (BUILT_IN_SIN):
2092 builtin_optab = sin_optab; break;
2093 CASE_FLT_FN (BUILT_IN_COS):
2094 builtin_optab = cos_optab; break;
2095 default:
2096 gcc_unreachable ();
2097 }
2098 }
2099
2100 /* Before working hard, check whether the instruction is available. */
2101 if (builtin_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing)
2102 {
2103 target = gen_reg_rtx (mode);
2104
2105 /* Wrap the computation of the argument in a SAVE_EXPR, as we may
2106 need to expand the argument again. This way, we will not perform
2107 side-effects more the once. */
2108 narg = save_expr (arg);
2109 if (narg != arg)
2110 {
2111 arg = narg;
2112 arglist = build_tree_list (NULL_TREE, arg);
2113 exp = build_function_call_expr (fndecl, arglist);
2114 }
2115
2116 op0 = expand_expr (arg, subtarget, VOIDmode, 0);
2117
2118 start_sequence ();
2119
2120 /* Compute into TARGET.
2121 Set TARGET to wherever the result comes back. */
2122 if (builtin_optab == sincos_optab)
2123 {
2124 int result;
2125
2126 switch (DECL_FUNCTION_CODE (fndecl))
2127 {
2128 CASE_FLT_FN (BUILT_IN_SIN):
2129 result = expand_twoval_unop (builtin_optab, op0, 0, target, 0);
2130 break;
2131 CASE_FLT_FN (BUILT_IN_COS):
2132 result = expand_twoval_unop (builtin_optab, op0, target, 0, 0);
2133 break;
2134 default:
2135 gcc_unreachable ();
2136 }
2137 gcc_assert (result);
2138 }
2139 else
2140 {
2141 target = expand_unop (mode, builtin_optab, op0, target, 0);
2142 }
2143
2144 if (target != 0)
2145 {
2146 /* Output the entire sequence. */
2147 insns = get_insns ();
2148 end_sequence ();
2149 emit_insn (insns);
2150 return target;
2151 }
2152
2153 /* If we were unable to expand via the builtin, stop the sequence
2154 (without outputting the insns) and call to the library function
2155 with the stabilized argument list. */
2156 end_sequence ();
2157 }
2158
2159 target = expand_call (exp, target, target == const0_rtx);
2160
2161 return target;
2162}
2163
2164/* Expand a call to the builtin sincos math function.
2165 Return 0 if a normal call should be emitted rather than expanding the
2166 function in-line. EXP is the expression that is a call to the builtin
2167 function. */
2168
2169static rtx
2170expand_builtin_sincos (tree exp)
2171{
2172 rtx op0, op1, op2, target1, target2;
2173 tree arglist = TREE_OPERAND (exp, 1);
2174 enum machine_mode mode;
2175 tree arg, sinp, cosp;
2176 int result;
2177
2178 if (!validate_arglist (arglist, REAL_TYPE,
2179 POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
2180 return 0;
2181
2182 arg = TREE_VALUE (arglist);
2183 sinp = TREE_VALUE (TREE_CHAIN (arglist));
2184 cosp = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
2185
2186 /* Make a suitable register to place result in. */
2187 mode = TYPE_MODE (TREE_TYPE (arg));
2188
2189 /* Check if sincos insn is available, otherwise emit the call. */
2190 if (sincos_optab->handlers[(int) mode].insn_code == CODE_FOR_nothing)
2191 return NULL_RTX;
2192
2193 target1 = gen_reg_rtx (mode);
2194 target2 = gen_reg_rtx (mode);
2195
2196 op0 = expand_normal (arg);
2197 op1 = expand_normal (build_fold_indirect_ref (sinp));
2198 op2 = expand_normal (build_fold_indirect_ref (cosp));
2199
2200 /* Compute into target1 and target2.
2201 Set TARGET to wherever the result comes back. */
2202 result = expand_twoval_unop (sincos_optab, op0, target2, target1, 0);
2203 gcc_assert (result);
2204
2205 /* Move target1 and target2 to the memory locations indicated
2206 by op1 and op2. */
2207 emit_move_insn (op1, target1);
2208 emit_move_insn (op2, target2);
2209
2210 return const0_rtx;
2211}
2212
2213/* Expand a call to one of the builtin rounding functions (lfloor).
2214 If expanding via optab fails, lower expression to (int)(floor(x)).
2215 EXP is the expression that is a call to the builtin function;
2216 if convenient, the result should be placed in TARGET. SUBTARGET may
2217 be used as the target for computing one of EXP's operands. */
2218
2219static rtx
2220expand_builtin_int_roundingfn (tree exp, rtx target, rtx subtarget)
2221{
2222 optab builtin_optab;
2223 rtx op0, insns, tmp;
2224 tree fndecl = get_callee_fndecl (exp);
2225 tree arglist = TREE_OPERAND (exp, 1);
2226 enum built_in_function fallback_fn;
2227 tree fallback_fndecl;
2228 enum machine_mode mode;
2229 tree arg, narg;
2230
2231 if (!validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
2232 gcc_unreachable ();
2233
2234 arg = TREE_VALUE (arglist);
2235
2236 switch (DECL_FUNCTION_CODE (fndecl))
2237 {
2238 CASE_FLT_FN (BUILT_IN_LCEIL):
2239 CASE_FLT_FN (BUILT_IN_LLCEIL):
2240 builtin_optab = lceil_optab;
2241 fallback_fn = BUILT_IN_CEIL;
2242 break;
2243
2244 CASE_FLT_FN (BUILT_IN_LFLOOR):
2245 CASE_FLT_FN (BUILT_IN_LLFLOOR):
2246 builtin_optab = lfloor_optab;
2247 fallback_fn = BUILT_IN_FLOOR;
2248 break;
2249
2250 default:
2251 gcc_unreachable ();
2252 }
2253
2254 /* Make a suitable register to place result in. */
2255 mode = TYPE_MODE (TREE_TYPE (exp));
2256
2257 /* Before working hard, check whether the instruction is available. */
2258 if (builtin_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing)
2259 {
2260 target = gen_reg_rtx (mode);
2261
2262 /* Wrap the computation of the argument in a SAVE_EXPR, as we may
2263 need to expand the argument again. This way, we will not perform
2264 side-effects more the once. */
2265 narg = builtin_save_expr (arg);
2266 if (narg != arg)
2267 {
2268 arg = narg;
2269 arglist = build_tree_list (NULL_TREE, arg);
2270 exp = build_function_call_expr (fndecl, arglist);
2271 }
2272
2273 op0 = expand_expr (arg, subtarget, VOIDmode, 0);
2274
2275 start_sequence ();
2276
2277 /* Compute into TARGET.
2278 Set TARGET to wherever the result comes back. */
2279 target = expand_unop (mode, builtin_optab, op0, target, 0);
2280
2281 if (target != 0)
2282 {
2283 /* Output the entire sequence. */
2284 insns = get_insns ();
2285 end_sequence ();
2286 emit_insn (insns);
2287 return target;
2288 }
2289
2290 /* If we were unable to expand via the builtin, stop the sequence
2291 (without outputting the insns). */
2292 end_sequence ();
2293 }
2294
2295 /* Fall back to floating point rounding optab. */
2296 fallback_fndecl = mathfn_built_in (TREE_TYPE (arg), fallback_fn);
2297 /* We shouldn't get here on targets without TARGET_C99_FUNCTIONS.
2298 ??? Perhaps convert (int)floorf(x) into (int)floor((double)x). */
2299 gcc_assert (fallback_fndecl != NULL_TREE);
2300 exp = build_function_call_expr (fallback_fndecl, arglist);
2301
2302 tmp = expand_normal (exp);
2303
2304 /* Truncate the result of floating point optab to integer
2305 via expand_fix (). */
2306 target = gen_reg_rtx (mode);
2307 expand_fix (target, tmp, 0);
2308
2309 return target;
2310}
2311
1895/* To evaluate powi(x,n), the floating point value x raised to the
1896 constant integer exponent n, we use a hybrid algorithm that
1897 combines the "window method" with look-up tables. For an
1898 introduction to exponentiation algorithms and "addition chains",
1899 see section 4.6.3, "Evaluation of Powers" of Donald E. Knuth,
1900 "Seminumerical Algorithms", Vol. 2, "The Art of Computer Programming",
1901 3rd Edition, 1998, and Daniel M. Gordon, "A Survey of Fast Exponentiation
1902 Methods", Journal of Algorithms, Vol. 27, pp. 129-146, 1998. */
1903
1904/* Provide a default value for POWI_MAX_MULTS, the maximum number of
1905 multiplications to inline before calling the system library's pow
1906 function. powi(x,n) requires at worst 2*bits(n)-2 multiplications,
1907 so this default never requires calling pow, powf or powl. */
2312/* To evaluate powi(x,n), the floating point value x raised to the
2313 constant integer exponent n, we use a hybrid algorithm that
2314 combines the "window method" with look-up tables. For an
2315 introduction to exponentiation algorithms and "addition chains",
2316 see section 4.6.3, "Evaluation of Powers" of Donald E. Knuth,
2317 "Seminumerical Algorithms", Vol. 2, "The Art of Computer Programming",
2318 3rd Edition, 1998, and Daniel M. Gordon, "A Survey of Fast Exponentiation
2319 Methods", Journal of Algorithms, Vol. 27, pp. 129-146, 1998. */
2320
2321/* Provide a default value for POWI_MAX_MULTS, the maximum number of
2322 multiplications to inline before calling the system library's pow
2323 function. powi(x,n) requires at worst 2*bits(n)-2 multiplications,
2324 so this default never requires calling pow, powf or powl. */
1908
2325
1909#ifndef POWI_MAX_MULTS
1910#define POWI_MAX_MULTS (2*HOST_BITS_PER_WIDE_INT-2)
1911#endif
1912
1913/* The size of the "optimal power tree" lookup table. All
1914 exponents less than this value are simply looked up in the
1915 powi_table below. This threshold is also used to size the
1916 cache of pseudo registers that hold intermediate results. */

--- 100 unchanged lines hidden (view full) ---

2017 val >>= POWI_WINDOW_SIZE;
2018 }
2019 else
2020 {
2021 val >>= 1;
2022 result++;
2023 }
2024 }
2326#ifndef POWI_MAX_MULTS
2327#define POWI_MAX_MULTS (2*HOST_BITS_PER_WIDE_INT-2)
2328#endif
2329
2330/* The size of the "optimal power tree" lookup table. All
2331 exponents less than this value are simply looked up in the
2332 powi_table below. This threshold is also used to size the
2333 cache of pseudo registers that hold intermediate results. */

--- 100 unchanged lines hidden (view full) ---

2434 val >>= POWI_WINDOW_SIZE;
2435 }
2436 else
2437 {
2438 val >>= 1;
2439 result++;
2440 }
2441 }
2025
2442
2026 return result + powi_lookup_cost (val, cache);
2027}
2028
2029/* Recursive subroutine of expand_powi. This function takes the array,
2030 CACHE, of already calculated exponents and an exponent N and returns
2031 an RTX that corresponds to CACHE[1]**N, as calculated in mode MODE. */
2032
2033static rtx
2034expand_powi_1 (enum machine_mode mode, unsigned HOST_WIDE_INT n, rtx *cache)
2035{
2036 unsigned HOST_WIDE_INT digit;
2037 rtx target, result;
2038 rtx op0, op1;
2039
2040 if (n < POWI_TABLE_SIZE)
2041 {
2042 if (cache[n])
2443 return result + powi_lookup_cost (val, cache);
2444}
2445
2446/* Recursive subroutine of expand_powi. This function takes the array,
2447 CACHE, of already calculated exponents and an exponent N and returns
2448 an RTX that corresponds to CACHE[1]**N, as calculated in mode MODE. */
2449
2450static rtx
2451expand_powi_1 (enum machine_mode mode, unsigned HOST_WIDE_INT n, rtx *cache)
2452{
2453 unsigned HOST_WIDE_INT digit;
2454 rtx target, result;
2455 rtx op0, op1;
2456
2457 if (n < POWI_TABLE_SIZE)
2458 {
2459 if (cache[n])
2043 return cache[n];
2460 return cache[n];
2044
2045 target = gen_reg_rtx (mode);
2046 cache[n] = target;
2047
2048 op0 = expand_powi_1 (mode, n - powi_table[n], cache);
2049 op1 = expand_powi_1 (mode, powi_table[n], cache);
2050 }
2051 else if (n & 1)

--- 14 unchanged lines hidden (view full) ---

2066 if (result != target)
2067 emit_move_insn (target, result);
2068 return target;
2069}
2070
2071/* Expand the RTL to evaluate powi(x,n) in mode MODE. X is the
2072 floating point operand in mode MODE, and N is the exponent. This
2073 function needs to be kept in sync with powi_cost above. */
2461
2462 target = gen_reg_rtx (mode);
2463 cache[n] = target;
2464
2465 op0 = expand_powi_1 (mode, n - powi_table[n], cache);
2466 op1 = expand_powi_1 (mode, powi_table[n], cache);
2467 }
2468 else if (n & 1)

--- 14 unchanged lines hidden (view full) ---

2483 if (result != target)
2484 emit_move_insn (target, result);
2485 return target;
2486}
2487
2488/* Expand the RTL to evaluate powi(x,n) in mode MODE. X is the
2489 floating point operand in mode MODE, and N is the exponent. This
2490 function needs to be kept in sync with powi_cost above. */
2074
2491
2075static rtx
2076expand_powi (rtx x, enum machine_mode mode, HOST_WIDE_INT n)
2077{
2078 unsigned HOST_WIDE_INT val;
2079 rtx cache[POWI_TABLE_SIZE];
2080 rtx result;
2081
2082 if (n == 0)

--- 53 unchanged lines hidden (view full) ---

2136 {
2137 enum machine_mode mode = TYPE_MODE (TREE_TYPE (exp));
2138 rtx op = expand_expr (arg0, subtarget, VOIDmode, 0);
2139 op = force_reg (mode, op);
2140 return expand_powi (op, mode, n);
2141 }
2142 }
2143 }
2492static rtx
2493expand_powi (rtx x, enum machine_mode mode, HOST_WIDE_INT n)
2494{
2495 unsigned HOST_WIDE_INT val;
2496 rtx cache[POWI_TABLE_SIZE];
2497 rtx result;
2498
2499 if (n == 0)

--- 53 unchanged lines hidden (view full) ---

2553 {
2554 enum machine_mode mode = TYPE_MODE (TREE_TYPE (exp));
2555 rtx op = expand_expr (arg0, subtarget, VOIDmode, 0);
2556 op = force_reg (mode, op);
2557 return expand_powi (op, mode, n);
2558 }
2559 }
2560 }
2144 return expand_builtin_mathfn_2 (exp, target, NULL_RTX);
2561
2562 if (! flag_unsafe_math_optimizations)
2563 return NULL_RTX;
2564 return expand_builtin_mathfn_2 (exp, target, subtarget);
2145}
2146
2565}
2566
2567/* Expand a call to the powi built-in mathematical function. Return 0 if
2568 a normal call should be emitted rather than expanding the function
2569 in-line. EXP is the expression that is a call to the builtin
2570 function; if convenient, the result should be placed in TARGET. */
2571
2572static rtx
2573expand_builtin_powi (tree exp, rtx target, rtx subtarget)
2574{
2575 tree arglist = TREE_OPERAND (exp, 1);
2576 tree arg0, arg1;
2577 rtx op0, op1;
2578 enum machine_mode mode;
2579 enum machine_mode mode2;
2580
2581 if (! validate_arglist (arglist, REAL_TYPE, INTEGER_TYPE, VOID_TYPE))
2582 return 0;
2583
2584 arg0 = TREE_VALUE (arglist);
2585 arg1 = TREE_VALUE (TREE_CHAIN (arglist));
2586 mode = TYPE_MODE (TREE_TYPE (exp));
2587
2588 /* Handle constant power. */
2589
2590 if (TREE_CODE (arg1) == INTEGER_CST
2591 && ! TREE_CONSTANT_OVERFLOW (arg1))
2592 {
2593 HOST_WIDE_INT n = TREE_INT_CST_LOW (arg1);
2594
2595 /* If the exponent is -1, 0, 1 or 2, then expand_powi is exact.
2596 Otherwise, check the number of multiplications required. */
2597 if ((TREE_INT_CST_HIGH (arg1) == 0
2598 || TREE_INT_CST_HIGH (arg1) == -1)
2599 && ((n >= -1 && n <= 2)
2600 || (! optimize_size
2601 && powi_cost (n) <= POWI_MAX_MULTS)))
2602 {
2603 op0 = expand_expr (arg0, subtarget, VOIDmode, 0);
2604 op0 = force_reg (mode, op0);
2605 return expand_powi (op0, mode, n);
2606 }
2607 }
2608
2609 /* Emit a libcall to libgcc. */
2610
2611 /* Mode of the 2nd argument must match that of an int. */
2612 mode2 = mode_for_size (INT_TYPE_SIZE, MODE_INT, 0);
2613
2614 if (target == NULL_RTX)
2615 target = gen_reg_rtx (mode);
2616
2617 op0 = expand_expr (arg0, subtarget, mode, 0);
2618 if (GET_MODE (op0) != mode)
2619 op0 = convert_to_mode (mode, op0, 0);
2620 op1 = expand_expr (arg1, 0, mode2, 0);
2621 if (GET_MODE (op1) != mode2)
2622 op1 = convert_to_mode (mode2, op1, 0);
2623
2624 target = emit_library_call_value (powi_optab->handlers[(int) mode].libfunc,
2625 target, LCT_CONST_MAKE_BLOCK, mode, 2,
2626 op0, mode, op1, mode2);
2627
2628 return target;
2629}
2630
2147/* Expand expression EXP which is a call to the strlen builtin. Return 0
2148 if we failed the caller should emit a normal call, otherwise
2149 try to get the result in TARGET, if convenient. */
2150
2151static rtx
2152expand_builtin_strlen (tree arglist, rtx target,
2153 enum machine_mode target_mode)
2154{

--- 41 unchanged lines hidden (view full) ---

2196 insn_mode = GET_MODE_WIDER_MODE (insn_mode);
2197 }
2198 if (insn_mode == VOIDmode)
2199 return 0;
2200
2201 /* Make a place to write the result of the instruction. */
2202 result = target;
2203 if (! (result != 0
2631/* Expand expression EXP which is a call to the strlen builtin. Return 0
2632 if we failed the caller should emit a normal call, otherwise
2633 try to get the result in TARGET, if convenient. */
2634
2635static rtx
2636expand_builtin_strlen (tree arglist, rtx target,
2637 enum machine_mode target_mode)
2638{

--- 41 unchanged lines hidden (view full) ---

2680 insn_mode = GET_MODE_WIDER_MODE (insn_mode);
2681 }
2682 if (insn_mode == VOIDmode)
2683 return 0;
2684
2685 /* Make a place to write the result of the instruction. */
2686 result = target;
2687 if (! (result != 0
2204 && GET_CODE (result) == REG
2688 && REG_P (result)
2205 && GET_MODE (result) == insn_mode
2206 && REGNO (result) >= FIRST_PSEUDO_REGISTER))
2207 result = gen_reg_rtx (insn_mode);
2208
2209 /* Make a place to hold the source address. We will not expand
2210 the actual source until we are sure that the expansion will
2211 not fail -- there are trees that cannot be expanded twice. */
2212 src_reg = gen_reg_rtx (Pmode);

--- 11 unchanged lines hidden (view full) ---

2224 pat = GEN_FCN (icode) (result, gen_rtx_MEM (BLKmode, src_reg),
2225 char_rtx, GEN_INT (align));
2226 if (! pat)
2227 return 0;
2228 emit_insn (pat);
2229
2230 /* Now that we are assured of success, expand the source. */
2231 start_sequence ();
2689 && GET_MODE (result) == insn_mode
2690 && REGNO (result) >= FIRST_PSEUDO_REGISTER))
2691 result = gen_reg_rtx (insn_mode);
2692
2693 /* Make a place to hold the source address. We will not expand
2694 the actual source until we are sure that the expansion will
2695 not fail -- there are trees that cannot be expanded twice. */
2696 src_reg = gen_reg_rtx (Pmode);

--- 11 unchanged lines hidden (view full) ---

2708 pat = GEN_FCN (icode) (result, gen_rtx_MEM (BLKmode, src_reg),
2709 char_rtx, GEN_INT (align));
2710 if (! pat)
2711 return 0;
2712 emit_insn (pat);
2713
2714 /* Now that we are assured of success, expand the source. */
2715 start_sequence ();
2232 pat = memory_address (BLKmode,
2233 expand_expr (src, src_reg, ptr_mode, EXPAND_SUM));
2716 pat = expand_expr (src, src_reg, ptr_mode, EXPAND_NORMAL);
2234 if (pat != src_reg)
2235 emit_move_insn (src_reg, pat);
2236 pat = get_insns ();
2237 end_sequence ();
2238
2239 if (before_strlen)
2240 emit_insn_after (pat, before_strlen);
2241 else

--- 11 unchanged lines hidden (view full) ---

2253 }
2254}
2255
2256/* Expand a call to the strstr builtin. Return 0 if we failed the
2257 caller should emit a normal call, otherwise try to get the result
2258 in TARGET, if convenient (and in mode MODE if that's convenient). */
2259
2260static rtx
2717 if (pat != src_reg)
2718 emit_move_insn (src_reg, pat);
2719 pat = get_insns ();
2720 end_sequence ();
2721
2722 if (before_strlen)
2723 emit_insn_after (pat, before_strlen);
2724 else

--- 11 unchanged lines hidden (view full) ---

2736 }
2737}
2738
2739/* Expand a call to the strstr builtin. Return 0 if we failed the
2740 caller should emit a normal call, otherwise try to get the result
2741 in TARGET, if convenient (and in mode MODE if that's convenient). */
2742
2743static rtx
2261expand_builtin_strstr (tree arglist, rtx target, enum machine_mode mode)
2744expand_builtin_strstr (tree arglist, tree type, rtx target, enum machine_mode mode)
2262{
2745{
2263 if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
2264 return 0;
2265 else
2746 if (validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
2266 {
2747 {
2267 tree s1 = TREE_VALUE (arglist), s2 = TREE_VALUE (TREE_CHAIN (arglist));
2268 tree fn;
2269 const char *p1, *p2;
2270
2271 p2 = c_getstr (s2);
2272 if (p2 == NULL)
2273 return 0;
2274
2275 p1 = c_getstr (s1);
2276 if (p1 != NULL)
2277 {
2278 const char *r = strstr (p1, p2);
2279
2280 if (r == NULL)
2281 return const0_rtx;
2282
2283 /* Return an offset into the constant string argument. */
2284 return expand_expr (fold (build (PLUS_EXPR, TREE_TYPE (s1),
2285 s1, convert (TREE_TYPE (s1),
2286 ssize_int (r - p1)))),
2287 target, mode, EXPAND_NORMAL);
2288 }
2289
2290 if (p2[0] == '\0')
2291 return expand_expr (s1, target, mode, EXPAND_NORMAL);
2292
2293 if (p2[1] != '\0')
2294 return 0;
2295
2296 fn = implicit_built_in_decls[BUILT_IN_STRCHR];
2297 if (!fn)
2298 return 0;
2299
2300 /* New argument list transforming strstr(s1, s2) to
2301 strchr(s1, s2[0]). */
2302 arglist =
2303 build_tree_list (NULL_TREE, build_int_2 (p2[0], 0));
2304 arglist = tree_cons (NULL_TREE, s1, arglist);
2305 return expand_expr (build_function_call_expr (fn, arglist),
2306 target, mode, EXPAND_NORMAL);
2748 tree result = fold_builtin_strstr (arglist, type);
2749 if (result)
2750 return expand_expr (result, target, mode, EXPAND_NORMAL);
2307 }
2751 }
2752 return 0;
2308}
2309
2310/* Expand a call to the strchr builtin. Return 0 if we failed the
2311 caller should emit a normal call, otherwise try to get the result
2312 in TARGET, if convenient (and in mode MODE if that's convenient). */
2313
2314static rtx
2753}
2754
2755/* Expand a call to the strchr builtin. Return 0 if we failed the
2756 caller should emit a normal call, otherwise try to get the result
2757 in TARGET, if convenient (and in mode MODE if that's convenient). */
2758
2759static rtx
2315expand_builtin_strchr (tree arglist, rtx target, enum machine_mode mode)
2760expand_builtin_strchr (tree arglist, tree type, rtx target, enum machine_mode mode)
2316{
2761{
2317 if (!validate_arglist (arglist, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
2318 return 0;
2319 else
2762 if (validate_arglist (arglist, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
2320 {
2763 {
2321 tree s1 = TREE_VALUE (arglist), s2 = TREE_VALUE (TREE_CHAIN (arglist));
2322 const char *p1;
2764 tree result = fold_builtin_strchr (arglist, type);
2765 if (result)
2766 return expand_expr (result, target, mode, EXPAND_NORMAL);
2323
2767
2324 if (TREE_CODE (s2) != INTEGER_CST)
2325 return 0;
2326
2327 p1 = c_getstr (s1);
2328 if (p1 != NULL)
2329 {
2330 char c;
2331 const char *r;
2332
2333 if (target_char_cast (s2, &c))
2334 return 0;
2335
2336 r = strchr (p1, c);
2337
2338 if (r == NULL)
2339 return const0_rtx;
2340
2341 /* Return an offset into the constant string argument. */
2342 return expand_expr (fold (build (PLUS_EXPR, TREE_TYPE (s1),
2343 s1, convert (TREE_TYPE (s1),
2344 ssize_int (r - p1)))),
2345 target, mode, EXPAND_NORMAL);
2346 }
2347
2348 /* FIXME: Should use here strchrM optab so that ports can optimize
2349 this. */
2350 return 0;
2768 /* FIXME: Should use strchrM optab so that ports can optimize this. */
2351 }
2769 }
2770 return 0;
2352}
2353
2354/* Expand a call to the strrchr builtin. Return 0 if we failed the
2355 caller should emit a normal call, otherwise try to get the result
2356 in TARGET, if convenient (and in mode MODE if that's convenient). */
2357
2358static rtx
2771}
2772
2773/* Expand a call to the strrchr builtin. Return 0 if we failed the
2774 caller should emit a normal call, otherwise try to get the result
2775 in TARGET, if convenient (and in mode MODE if that's convenient). */
2776
2777static rtx
2359expand_builtin_strrchr (tree arglist, rtx target, enum machine_mode mode)
2778expand_builtin_strrchr (tree arglist, tree type, rtx target, enum machine_mode mode)
2360{
2779{
2361 if (!validate_arglist (arglist, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
2362 return 0;
2363 else
2780 if (validate_arglist (arglist, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
2364 {
2781 {
2365 tree s1 = TREE_VALUE (arglist), s2 = TREE_VALUE (TREE_CHAIN (arglist));
2366 tree fn;
2367 const char *p1;
2368
2369 if (TREE_CODE (s2) != INTEGER_CST)
2370 return 0;
2371
2372 p1 = c_getstr (s1);
2373 if (p1 != NULL)
2374 {
2375 char c;
2376 const char *r;
2377
2378 if (target_char_cast (s2, &c))
2379 return 0;
2380
2381 r = strrchr (p1, c);
2382
2383 if (r == NULL)
2384 return const0_rtx;
2385
2386 /* Return an offset into the constant string argument. */
2387 return expand_expr (fold (build (PLUS_EXPR, TREE_TYPE (s1),
2388 s1, convert (TREE_TYPE (s1),
2389 ssize_int (r - p1)))),
2390 target, mode, EXPAND_NORMAL);
2391 }
2392
2393 if (! integer_zerop (s2))
2394 return 0;
2395
2396 fn = implicit_built_in_decls[BUILT_IN_STRCHR];
2397 if (!fn)
2398 return 0;
2399
2400 /* Transform strrchr(s1, '\0') to strchr(s1, '\0'). */
2401 return expand_expr (build_function_call_expr (fn, arglist),
2402 target, mode, EXPAND_NORMAL);
2782 tree result = fold_builtin_strrchr (arglist, type);
2783 if (result)
2784 return expand_expr (result, target, mode, EXPAND_NORMAL);
2403 }
2785 }
2786 return 0;
2404}
2405
2406/* Expand a call to the strpbrk builtin. Return 0 if we failed the
2407 caller should emit a normal call, otherwise try to get the result
2408 in TARGET, if convenient (and in mode MODE if that's convenient). */
2409
2410static rtx
2787}
2788
2789/* Expand a call to the strpbrk builtin. Return 0 if we failed the
2790 caller should emit a normal call, otherwise try to get the result
2791 in TARGET, if convenient (and in mode MODE if that's convenient). */
2792
2793static rtx
2411expand_builtin_strpbrk (tree arglist, rtx target, enum machine_mode mode)
2794expand_builtin_strpbrk (tree arglist, tree type, rtx target, enum machine_mode mode)
2412{
2795{
2413 if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
2414 return 0;
2415 else
2796 if (validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
2416 {
2797 {
2417 tree s1 = TREE_VALUE (arglist), s2 = TREE_VALUE (TREE_CHAIN (arglist));
2418 tree fn;
2419 const char *p1, *p2;
2420
2421 p2 = c_getstr (s2);
2422 if (p2 == NULL)
2423 return 0;
2424
2425 p1 = c_getstr (s1);
2426 if (p1 != NULL)
2427 {
2428 const char *r = strpbrk (p1, p2);
2429
2430 if (r == NULL)
2431 return const0_rtx;
2432
2433 /* Return an offset into the constant string argument. */
2434 return expand_expr (fold (build (PLUS_EXPR, TREE_TYPE (s1),
2435 s1, convert (TREE_TYPE (s1),
2436 ssize_int (r - p1)))),
2437 target, mode, EXPAND_NORMAL);
2438 }
2439
2440 if (p2[0] == '\0')
2441 {
2442 /* strpbrk(x, "") == NULL.
2443 Evaluate and ignore the arguments in case they had
2444 side-effects. */
2445 expand_expr (s1, const0_rtx, VOIDmode, EXPAND_NORMAL);
2446 return const0_rtx;
2447 }
2448
2449 if (p2[1] != '\0')
2450 return 0; /* Really call strpbrk. */
2451
2452 fn = implicit_built_in_decls[BUILT_IN_STRCHR];
2453 if (!fn)
2454 return 0;
2455
2456 /* New argument list transforming strpbrk(s1, s2) to
2457 strchr(s1, s2[0]). */
2458 arglist =
2459 build_tree_list (NULL_TREE, build_int_2 (p2[0], 0));
2460 arglist = tree_cons (NULL_TREE, s1, arglist);
2461 return expand_expr (build_function_call_expr (fn, arglist),
2462 target, mode, EXPAND_NORMAL);
2798 tree result = fold_builtin_strpbrk (arglist, type);
2799 if (result)
2800 return expand_expr (result, target, mode, EXPAND_NORMAL);
2463 }
2801 }
2802 return 0;
2464}
2465
2466/* Callback routine for store_by_pieces. Read GET_MODE_BITSIZE (MODE)
2467 bytes from constant string DATA + OFFSET and return it as target
2468 constant. */
2469
2470static rtx
2471builtin_memcpy_read_str (void *data, HOST_WIDE_INT offset,
2472 enum machine_mode mode)
2473{
2474 const char *str = (const char *) data;
2475
2803}
2804
2805/* Callback routine for store_by_pieces. Read GET_MODE_BITSIZE (MODE)
2806 bytes from constant string DATA + OFFSET and return it as target
2807 constant. */
2808
2809static rtx
2810builtin_memcpy_read_str (void *data, HOST_WIDE_INT offset,
2811 enum machine_mode mode)
2812{
2813 const char *str = (const char *) data;
2814
2476 if (offset < 0
2477 || ((unsigned HOST_WIDE_INT) offset + GET_MODE_SIZE (mode)
2478 > strlen (str) + 1))
2479 abort (); /* Attempt to read past the end of constant string. */
2815 gcc_assert (offset >= 0
2816 && ((unsigned HOST_WIDE_INT) offset + GET_MODE_SIZE (mode)
2817 <= strlen (str) + 1));
2480
2481 return c_readstr (str + offset, mode);
2482}
2483
2484/* Expand a call to the memcpy builtin, with arguments in ARGLIST.
2485 Return 0 if we failed, the caller should emit a normal call,
2486 otherwise try to get the result in TARGET, if convenient (and in
2487 mode MODE if that's convenient). */
2488static rtx
2818
2819 return c_readstr (str + offset, mode);
2820}
2821
2822/* Expand a call to the memcpy builtin, with arguments in ARGLIST.
2823 Return 0 if we failed, the caller should emit a normal call,
2824 otherwise try to get the result in TARGET, if convenient (and in
2825 mode MODE if that's convenient). */
2826static rtx
2489expand_builtin_memcpy (tree arglist, rtx target, enum machine_mode mode)
2827expand_builtin_memcpy (tree exp, rtx target, enum machine_mode mode)
2490{
2828{
2829 tree fndecl = get_callee_fndecl (exp);
2830 tree arglist = TREE_OPERAND (exp, 1);
2491 if (!validate_arglist (arglist,
2492 POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
2493 return 0;
2494 else
2495 {
2496 tree dest = TREE_VALUE (arglist);
2497 tree src = TREE_VALUE (TREE_CHAIN (arglist));
2498 tree len = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
2499 const char *src_str;
2500 unsigned int src_align = get_pointer_alignment (src, BIGGEST_ALIGNMENT);
2501 unsigned int dest_align
2502 = get_pointer_alignment (dest, BIGGEST_ALIGNMENT);
2503 rtx dest_mem, src_mem, dest_addr, len_rtx;
2831 if (!validate_arglist (arglist,
2832 POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
2833 return 0;
2834 else
2835 {
2836 tree dest = TREE_VALUE (arglist);
2837 tree src = TREE_VALUE (TREE_CHAIN (arglist));
2838 tree len = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
2839 const char *src_str;
2840 unsigned int src_align = get_pointer_alignment (src, BIGGEST_ALIGNMENT);
2841 unsigned int dest_align
2842 = get_pointer_alignment (dest, BIGGEST_ALIGNMENT);
2843 rtx dest_mem, src_mem, dest_addr, len_rtx;
2844 tree result = fold_builtin_memory_op (arglist, TREE_TYPE (TREE_TYPE (fndecl)),
2845 false, /*endp=*/0);
2504
2846
2847 if (result)
2848 {
2849 while (TREE_CODE (result) == COMPOUND_EXPR)
2850 {
2851 expand_expr (TREE_OPERAND (result, 0), const0_rtx, VOIDmode,
2852 EXPAND_NORMAL);
2853 result = TREE_OPERAND (result, 1);
2854 }
2855 return expand_expr (result, target, mode, EXPAND_NORMAL);
2856 }
2857
2505 /* If DEST is not a pointer type, call the normal function. */
2506 if (dest_align == 0)
2507 return 0;
2508
2858 /* If DEST is not a pointer type, call the normal function. */
2859 if (dest_align == 0)
2860 return 0;
2861
2509 /* If the LEN parameter is zero, return DEST. */
2510 if (integer_zerop (len))
2511 {
2512 /* Evaluate and ignore SRC in case it has side-effects. */
2513 expand_expr (src, const0_rtx, VOIDmode, EXPAND_NORMAL);
2514 return expand_expr (dest, target, mode, EXPAND_NORMAL);
2515 }
2516
2517 /* If SRC and DEST are the same (and not volatile), return DEST. */
2518 if (operand_equal_p (src, dest, 0))
2519 {
2520 /* Evaluate and ignore LEN in case it has side-effects. */
2521 expand_expr (len, const0_rtx, VOIDmode, EXPAND_NORMAL);
2522 return expand_expr (dest, target, mode, EXPAND_NORMAL);
2523 }
2524
2525 /* If either SRC is not a pointer type, don't do this
2862 /* If either SRC is not a pointer type, don't do this
2526 operation in-line. */
2863 operation in-line. */
2527 if (src_align == 0)
2528 return 0;
2529
2864 if (src_align == 0)
2865 return 0;
2866
2530 dest_mem = get_memory_rtx (dest);
2867 dest_mem = get_memory_rtx (dest, len);
2531 set_mem_align (dest_mem, dest_align);
2868 set_mem_align (dest_mem, dest_align);
2532 len_rtx = expand_expr (len, NULL_RTX, VOIDmode, 0);
2869 len_rtx = expand_normal (len);
2533 src_str = c_getstr (src);
2534
2535 /* If SRC is a string constant and block move would be done
2536 by pieces, we can avoid loading the string from memory
2537 and only stored the computed constants. */
2538 if (src_str
2539 && GET_CODE (len_rtx) == CONST_INT
2540 && (unsigned HOST_WIDE_INT) INTVAL (len_rtx) <= strlen (src_str) + 1
2541 && can_store_by_pieces (INTVAL (len_rtx), builtin_memcpy_read_str,
2542 (void *) src_str, dest_align))
2543 {
2544 dest_mem = store_by_pieces (dest_mem, INTVAL (len_rtx),
2545 builtin_memcpy_read_str,
2546 (void *) src_str, dest_align, 0);
2547 dest_mem = force_operand (XEXP (dest_mem, 0), NULL_RTX);
2548 dest_mem = convert_memory_address (ptr_mode, dest_mem);
2549 return dest_mem;
2550 }
2551
2870 src_str = c_getstr (src);
2871
2872 /* If SRC is a string constant and block move would be done
2873 by pieces, we can avoid loading the string from memory
2874 and only stored the computed constants. */
2875 if (src_str
2876 && GET_CODE (len_rtx) == CONST_INT
2877 && (unsigned HOST_WIDE_INT) INTVAL (len_rtx) <= strlen (src_str) + 1
2878 && can_store_by_pieces (INTVAL (len_rtx), builtin_memcpy_read_str,
2879 (void *) src_str, dest_align))
2880 {
2881 dest_mem = store_by_pieces (dest_mem, INTVAL (len_rtx),
2882 builtin_memcpy_read_str,
2883 (void *) src_str, dest_align, 0);
2884 dest_mem = force_operand (XEXP (dest_mem, 0), NULL_RTX);
2885 dest_mem = convert_memory_address (ptr_mode, dest_mem);
2886 return dest_mem;
2887 }
2888
2552 src_mem = get_memory_rtx (src);
2889 src_mem = get_memory_rtx (src, len);
2553 set_mem_align (src_mem, src_align);
2554
2555 /* Copy word part most expediently. */
2556 dest_addr = emit_block_move (dest_mem, src_mem, len_rtx,
2890 set_mem_align (src_mem, src_align);
2891
2892 /* Copy word part most expediently. */
2893 dest_addr = emit_block_move (dest_mem, src_mem, len_rtx,
2557 BLOCK_OP_NORMAL);
2894 CALL_EXPR_TAILCALL (exp)
2895 ? BLOCK_OP_TAILCALL : BLOCK_OP_NORMAL);
2558
2559 if (dest_addr == 0)
2560 {
2561 dest_addr = force_operand (XEXP (dest_mem, 0), NULL_RTX);
2562 dest_addr = convert_memory_address (ptr_mode, dest_addr);
2563 }
2564 return dest_addr;
2565 }
2566}
2567
2568/* Expand a call to the mempcpy builtin, with arguments in ARGLIST.
2896
2897 if (dest_addr == 0)
2898 {
2899 dest_addr = force_operand (XEXP (dest_mem, 0), NULL_RTX);
2900 dest_addr = convert_memory_address (ptr_mode, dest_addr);
2901 }
2902 return dest_addr;
2903 }
2904}
2905
2906/* Expand a call to the mempcpy builtin, with arguments in ARGLIST.
2569 Return 0 if we failed the caller should emit a normal call,
2907 Return 0 if we failed; the caller should emit a normal call,
2570 otherwise try to get the result in TARGET, if convenient (and in
2571 mode MODE if that's convenient). If ENDP is 0 return the
2572 destination pointer, if ENDP is 1 return the end pointer ala
2573 mempcpy, and if ENDP is 2 return the end pointer minus one ala
2574 stpcpy. */
2575
2576static rtx
2908 otherwise try to get the result in TARGET, if convenient (and in
2909 mode MODE if that's convenient). If ENDP is 0 return the
2910 destination pointer, if ENDP is 1 return the end pointer ala
2911 mempcpy, and if ENDP is 2 return the end pointer minus one ala
2912 stpcpy. */
2913
2914static rtx
2577expand_builtin_mempcpy (tree arglist, rtx target, enum machine_mode mode,
2915expand_builtin_mempcpy (tree arglist, tree type, rtx target, enum machine_mode mode,
2578 int endp)
2579{
2580 if (!validate_arglist (arglist,
2581 POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
2582 return 0;
2583 /* If return value is ignored, transform mempcpy into memcpy. */
2584 else if (target == const0_rtx)
2585 {

--- 10 unchanged lines hidden (view full) ---

2596 tree dest = TREE_VALUE (arglist);
2597 tree src = TREE_VALUE (TREE_CHAIN (arglist));
2598 tree len = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
2599 const char *src_str;
2600 unsigned int src_align = get_pointer_alignment (src, BIGGEST_ALIGNMENT);
2601 unsigned int dest_align
2602 = get_pointer_alignment (dest, BIGGEST_ALIGNMENT);
2603 rtx dest_mem, src_mem, len_rtx;
2916 int endp)
2917{
2918 if (!validate_arglist (arglist,
2919 POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
2920 return 0;
2921 /* If return value is ignored, transform mempcpy into memcpy. */
2922 else if (target == const0_rtx)
2923 {

--- 10 unchanged lines hidden (view full) ---

2934 tree dest = TREE_VALUE (arglist);
2935 tree src = TREE_VALUE (TREE_CHAIN (arglist));
2936 tree len = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
2937 const char *src_str;
2938 unsigned int src_align = get_pointer_alignment (src, BIGGEST_ALIGNMENT);
2939 unsigned int dest_align
2940 = get_pointer_alignment (dest, BIGGEST_ALIGNMENT);
2941 rtx dest_mem, src_mem, len_rtx;
2942 tree result = fold_builtin_memory_op (arglist, type, false, endp);
2604
2943
2605 /* If DEST is not a pointer type, call the normal function. */
2606 if (dest_align == 0)
2607 return 0;
2608
2609 /* If SRC and DEST are the same (and not volatile), do nothing. */
2610 if (operand_equal_p (src, dest, 0))
2944 if (result)
2611 {
2945 {
2612 tree expr;
2613
2614 if (endp == 0)
2946 while (TREE_CODE (result) == COMPOUND_EXPR)
2615 {
2947 {
2616 /* Evaluate and ignore LEN in case it has side-effects. */
2617 expand_expr (len, const0_rtx, VOIDmode, EXPAND_NORMAL);
2618 return expand_expr (dest, target, mode, EXPAND_NORMAL);
2948 expand_expr (TREE_OPERAND (result, 0), const0_rtx, VOIDmode,
2949 EXPAND_NORMAL);
2950 result = TREE_OPERAND (result, 1);
2619 }
2951 }
2620
2621 if (endp == 2)
2622 len = fold (build (MINUS_EXPR, TREE_TYPE (len), dest,
2623 integer_one_node));
2624 len = convert (TREE_TYPE (dest), len);
2625 expr = fold (build (PLUS_EXPR, TREE_TYPE (dest), dest, len));
2626 return expand_expr (expr, target, mode, EXPAND_NORMAL);
2952 return expand_expr (result, target, mode, EXPAND_NORMAL);
2627 }
2628
2953 }
2954
2955 /* If either SRC or DEST is not a pointer type, don't do this
2956 operation in-line. */
2957 if (dest_align == 0 || src_align == 0)
2958 return 0;
2959
2629 /* If LEN is not constant, call the normal function. */
2630 if (! host_integerp (len, 1))
2631 return 0;
2960 /* If LEN is not constant, call the normal function. */
2961 if (! host_integerp (len, 1))
2962 return 0;
2632
2633 /* If the LEN parameter is zero, return DEST. */
2634 if (tree_low_cst (len, 1) == 0)
2635 {
2636 /* Evaluate and ignore SRC in case it has side-effects. */
2637 expand_expr (src, const0_rtx, VOIDmode, EXPAND_NORMAL);
2638 return expand_expr (dest, target, mode, EXPAND_NORMAL);
2639 }
2640
2963
2641 /* If either SRC is not a pointer type, don't do this
2642 operation in-line. */
2643 if (src_align == 0)
2644 return 0;
2645
2646 len_rtx = expand_expr (len, NULL_RTX, VOIDmode, 0);
2964 len_rtx = expand_normal (len);
2647 src_str = c_getstr (src);
2648
2649 /* If SRC is a string constant and block move would be done
2650 by pieces, we can avoid loading the string from memory
2651 and only stored the computed constants. */
2652 if (src_str
2653 && GET_CODE (len_rtx) == CONST_INT
2654 && (unsigned HOST_WIDE_INT) INTVAL (len_rtx) <= strlen (src_str) + 1
2655 && can_store_by_pieces (INTVAL (len_rtx), builtin_memcpy_read_str,
2656 (void *) src_str, dest_align))
2657 {
2965 src_str = c_getstr (src);
2966
2967 /* If SRC is a string constant and block move would be done
2968 by pieces, we can avoid loading the string from memory
2969 and only stored the computed constants. */
2970 if (src_str
2971 && GET_CODE (len_rtx) == CONST_INT
2972 && (unsigned HOST_WIDE_INT) INTVAL (len_rtx) <= strlen (src_str) + 1
2973 && can_store_by_pieces (INTVAL (len_rtx), builtin_memcpy_read_str,
2974 (void *) src_str, dest_align))
2975 {
2658 dest_mem = get_memory_rtx (dest);
2976 dest_mem = get_memory_rtx (dest, len);
2659 set_mem_align (dest_mem, dest_align);
2660 dest_mem = store_by_pieces (dest_mem, INTVAL (len_rtx),
2661 builtin_memcpy_read_str,
2662 (void *) src_str, dest_align, endp);
2663 dest_mem = force_operand (XEXP (dest_mem, 0), NULL_RTX);
2664 dest_mem = convert_memory_address (ptr_mode, dest_mem);
2665 return dest_mem;
2666 }
2667
2668 if (GET_CODE (len_rtx) == CONST_INT
2669 && can_move_by_pieces (INTVAL (len_rtx),
2670 MIN (dest_align, src_align)))
2671 {
2977 set_mem_align (dest_mem, dest_align);
2978 dest_mem = store_by_pieces (dest_mem, INTVAL (len_rtx),
2979 builtin_memcpy_read_str,
2980 (void *) src_str, dest_align, endp);
2981 dest_mem = force_operand (XEXP (dest_mem, 0), NULL_RTX);
2982 dest_mem = convert_memory_address (ptr_mode, dest_mem);
2983 return dest_mem;
2984 }
2985
2986 if (GET_CODE (len_rtx) == CONST_INT
2987 && can_move_by_pieces (INTVAL (len_rtx),
2988 MIN (dest_align, src_align)))
2989 {
2672 dest_mem = get_memory_rtx (dest);
2990 dest_mem = get_memory_rtx (dest, len);
2673 set_mem_align (dest_mem, dest_align);
2991 set_mem_align (dest_mem, dest_align);
2674 src_mem = get_memory_rtx (src);
2992 src_mem = get_memory_rtx (src, len);
2675 set_mem_align (src_mem, src_align);
2676 dest_mem = move_by_pieces (dest_mem, src_mem, INTVAL (len_rtx),
2677 MIN (dest_align, src_align), endp);
2678 dest_mem = force_operand (XEXP (dest_mem, 0), NULL_RTX);
2679 dest_mem = convert_memory_address (ptr_mode, dest_mem);
2680 return dest_mem;
2681 }
2682
2683 return 0;
2684 }
2685}
2686
2687/* Expand expression EXP, which is a call to the memmove builtin. Return 0
2993 set_mem_align (src_mem, src_align);
2994 dest_mem = move_by_pieces (dest_mem, src_mem, INTVAL (len_rtx),
2995 MIN (dest_align, src_align), endp);
2996 dest_mem = force_operand (XEXP (dest_mem, 0), NULL_RTX);
2997 dest_mem = convert_memory_address (ptr_mode, dest_mem);
2998 return dest_mem;
2999 }
3000
3001 return 0;
3002 }
3003}
3004
3005/* Expand expression EXP, which is a call to the memmove builtin. Return 0
2688 if we failed the caller should emit a normal call. */
3006 if we failed; the caller should emit a normal call. */
2689
2690static rtx
3007
3008static rtx
2691expand_builtin_memmove (tree arglist, rtx target, enum machine_mode mode)
3009expand_builtin_memmove (tree arglist, tree type, rtx target,
3010 enum machine_mode mode, tree orig_exp)
2692{
2693 if (!validate_arglist (arglist,
2694 POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
2695 return 0;
2696 else
2697 {
2698 tree dest = TREE_VALUE (arglist);
2699 tree src = TREE_VALUE (TREE_CHAIN (arglist));
2700 tree len = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
2701
2702 unsigned int src_align = get_pointer_alignment (src, BIGGEST_ALIGNMENT);
2703 unsigned int dest_align
2704 = get_pointer_alignment (dest, BIGGEST_ALIGNMENT);
3011{
3012 if (!validate_arglist (arglist,
3013 POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
3014 return 0;
3015 else
3016 {
3017 tree dest = TREE_VALUE (arglist);
3018 tree src = TREE_VALUE (TREE_CHAIN (arglist));
3019 tree len = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
3020
3021 unsigned int src_align = get_pointer_alignment (src, BIGGEST_ALIGNMENT);
3022 unsigned int dest_align
3023 = get_pointer_alignment (dest, BIGGEST_ALIGNMENT);
3024 tree result = fold_builtin_memory_op (arglist, type, false, /*endp=*/3);
2705
3025
3026 if (result)
3027 {
3028 while (TREE_CODE (result) == COMPOUND_EXPR)
3029 {
3030 expand_expr (TREE_OPERAND (result, 0), const0_rtx, VOIDmode,
3031 EXPAND_NORMAL);
3032 result = TREE_OPERAND (result, 1);
3033 }
3034 return expand_expr (result, target, mode, EXPAND_NORMAL);
3035 }
3036
2706 /* If DEST is not a pointer type, call the normal function. */
2707 if (dest_align == 0)
2708 return 0;
2709
3037 /* If DEST is not a pointer type, call the normal function. */
3038 if (dest_align == 0)
3039 return 0;
3040
2710 /* If the LEN parameter is zero, return DEST. */
2711 if (integer_zerop (len))
2712 {
2713 /* Evaluate and ignore SRC in case it has side-effects. */
2714 expand_expr (src, const0_rtx, VOIDmode, EXPAND_NORMAL);
2715 return expand_expr (dest, target, mode, EXPAND_NORMAL);
2716 }
2717
2718 /* If SRC and DEST are the same (and not volatile), return DEST. */
2719 if (operand_equal_p (src, dest, 0))
2720 {
2721 /* Evaluate and ignore LEN in case it has side-effects. */
2722 expand_expr (len, const0_rtx, VOIDmode, EXPAND_NORMAL);
2723 return expand_expr (dest, target, mode, EXPAND_NORMAL);
2724 }
2725
2726 /* If either SRC is not a pointer type, don't do this
3041 /* If either SRC is not a pointer type, don't do this
2727 operation in-line. */
3042 operation in-line. */
2728 if (src_align == 0)
2729 return 0;
2730
2731 /* If src is categorized for a readonly section we can use
2732 normal memcpy. */
2733 if (readonly_data_expr (src))
3043 if (src_align == 0)
3044 return 0;
3045
3046 /* If src is categorized for a readonly section we can use
3047 normal memcpy. */
3048 if (readonly_data_expr (src))
2734 {
2735 tree const fn = implicit_built_in_decls[BUILT_IN_MEMCPY];
3049 {
3050 tree fn = implicit_built_in_decls[BUILT_IN_MEMCPY];
2736 if (!fn)
2737 return 0;
3051 if (!fn)
3052 return 0;
2738 return expand_expr (build_function_call_expr (fn, arglist),
2739 target, mode, EXPAND_NORMAL);
3053 fn = build_function_call_expr (fn, arglist);
3054 if (TREE_CODE (fn) == CALL_EXPR)
3055 CALL_EXPR_TAILCALL (fn) = CALL_EXPR_TAILCALL (orig_exp);
3056 return expand_expr (fn, target, mode, EXPAND_NORMAL);
2740 }
2741
3057 }
3058
3059 /* If length is 1 and we can expand memcpy call inline,
3060 it is ok to use memcpy as well. */
3061 if (integer_onep (len))
3062 {
3063 rtx ret = expand_builtin_mempcpy (arglist, type, target, mode,
3064 /*endp=*/0);
3065 if (ret)
3066 return ret;
3067 }
3068
2742 /* Otherwise, call the normal function. */
2743 return 0;
2744 }
2745}
2746
2747/* Expand expression EXP, which is a call to the bcopy builtin. Return 0
2748 if we failed the caller should emit a normal call. */
2749
2750static rtx
3069 /* Otherwise, call the normal function. */
3070 return 0;
3071 }
3072}
3073
3074/* Expand expression EXP, which is a call to the bcopy builtin. Return 0
3075 if we failed the caller should emit a normal call. */
3076
3077static rtx
2751expand_builtin_bcopy (tree arglist)
3078expand_builtin_bcopy (tree exp)
2752{
3079{
3080 tree arglist = TREE_OPERAND (exp, 1);
3081 tree type = TREE_TYPE (exp);
2753 tree src, dest, size, newarglist;
2754
2755 if (!validate_arglist (arglist,
2756 POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
2757 return NULL_RTX;
2758
2759 src = TREE_VALUE (arglist);
2760 dest = TREE_VALUE (TREE_CHAIN (arglist));
2761 size = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
2762
2763 /* New argument list transforming bcopy(ptr x, ptr y, int z) to
2764 memmove(ptr y, ptr x, size_t z). This is done this way
2765 so that if it isn't expanded inline, we fallback to
2766 calling bcopy instead of memmove. */
2767
3082 tree src, dest, size, newarglist;
3083
3084 if (!validate_arglist (arglist,
3085 POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
3086 return NULL_RTX;
3087
3088 src = TREE_VALUE (arglist);
3089 dest = TREE_VALUE (TREE_CHAIN (arglist));
3090 size = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
3091
3092 /* New argument list transforming bcopy(ptr x, ptr y, int z) to
3093 memmove(ptr y, ptr x, size_t z). This is done this way
3094 so that if it isn't expanded inline, we fallback to
3095 calling bcopy instead of memmove. */
3096
2768 newarglist = build_tree_list (NULL_TREE, convert (sizetype, size));
3097 newarglist = build_tree_list (NULL_TREE, fold_convert (sizetype, size));
2769 newarglist = tree_cons (NULL_TREE, src, newarglist);
2770 newarglist = tree_cons (NULL_TREE, dest, newarglist);
2771
3098 newarglist = tree_cons (NULL_TREE, src, newarglist);
3099 newarglist = tree_cons (NULL_TREE, dest, newarglist);
3100
2772 return expand_builtin_memmove (newarglist, const0_rtx, VOIDmode);
3101 return expand_builtin_memmove (newarglist, type, const0_rtx, VOIDmode, exp);
2773}
2774
3102}
3103
2775/* Expand expression EXP, which is a call to the strcpy builtin. Return 0
2776 if we failed the caller should emit a normal call, otherwise try to get
2777 the result in TARGET, if convenient (and in mode MODE if that's
2778 convenient). */
3104#ifndef HAVE_movstr
3105# define HAVE_movstr 0
3106# define CODE_FOR_movstr CODE_FOR_nothing
3107#endif
2779
3108
3109/* Expand into a movstr instruction, if one is available. Return 0 if
3110 we failed, the caller should emit a normal call, otherwise try to
3111 get the result in TARGET, if convenient. If ENDP is 0 return the
3112 destination pointer, if ENDP is 1 return the end pointer ala
3113 mempcpy, and if ENDP is 2 return the end pointer minus one ala
3114 stpcpy. */
3115
2780static rtx
3116static rtx
2781expand_builtin_strcpy (tree arglist, rtx target, enum machine_mode mode)
3117expand_movstr (tree dest, tree src, rtx target, int endp)
2782{
3118{
2783 tree fn, len, src, dst;
3119 rtx end;
3120 rtx dest_mem;
3121 rtx src_mem;
3122 rtx insn;
3123 const struct insn_data * data;
2784
3124
2785 if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
3125 if (!HAVE_movstr)
2786 return 0;
2787
3126 return 0;
3127
2788 src = TREE_VALUE (TREE_CHAIN (arglist));
2789 dst = TREE_VALUE (arglist);
3128 dest_mem = get_memory_rtx (dest, NULL);
3129 src_mem = get_memory_rtx (src, NULL);
3130 if (!endp)
3131 {
3132 target = force_reg (Pmode, XEXP (dest_mem, 0));
3133 dest_mem = replace_equiv_address (dest_mem, target);
3134 end = gen_reg_rtx (Pmode);
3135 }
3136 else
3137 {
3138 if (target == 0 || target == const0_rtx)
3139 {
3140 end = gen_reg_rtx (Pmode);
3141 if (target == 0)
3142 target = end;
3143 }
3144 else
3145 end = target;
3146 }
2790
3147
2791 /* If SRC and DST are equal (and not volatile), return DST. */
2792 if (operand_equal_p (src, dst, 0))
2793 return expand_expr (dst, target, mode, EXPAND_NORMAL);
3148 data = insn_data + CODE_FOR_movstr;
2794
3149
2795 fn = implicit_built_in_decls[BUILT_IN_MEMCPY];
2796 if (!fn)
2797 return 0;
3150 if (data->operand[0].mode != VOIDmode)
3151 end = gen_lowpart (data->operand[0].mode, end);
2798
3152
2799 len = c_strlen (src, 1);
2800 if (len == 0 || TREE_SIDE_EFFECTS (len))
2801 return 0;
3153 insn = data->genfun (end, dest_mem, src_mem);
2802
3154
2803 len = size_binop (PLUS_EXPR, len, ssize_int (1));
2804 arglist = build_tree_list (NULL_TREE, len);
2805 arglist = tree_cons (NULL_TREE, src, arglist);
2806 arglist = tree_cons (NULL_TREE, dst, arglist);
2807 return expand_expr (build_function_call_expr (fn, arglist),
2808 target, mode, EXPAND_NORMAL);
3155 gcc_assert (insn);
3156
3157 emit_insn (insn);
3158
3159 /* movstr is supposed to set end to the address of the NUL
3160 terminator. If the caller requested a mempcpy-like return value,
3161 adjust it. */
3162 if (endp == 1 && target != const0_rtx)
3163 {
3164 rtx tem = plus_constant (gen_lowpart (GET_MODE (target), end), 1);
3165 emit_move_insn (target, force_operand (tem, NULL_RTX));
3166 }
3167
3168 return target;
2809}
2810
3169}
3170
3171/* Expand expression EXP, which is a call to the strcpy builtin. Return 0
3172 if we failed the caller should emit a normal call, otherwise try to get
3173 the result in TARGET, if convenient (and in mode MODE if that's
3174 convenient). */
3175
3176static rtx
3177expand_builtin_strcpy (tree fndecl, tree arglist, rtx target, enum machine_mode mode)
3178{
3179 if (validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
3180 {
3181 tree result = fold_builtin_strcpy (fndecl, arglist, 0);
3182 if (result)
3183 {
3184 while (TREE_CODE (result) == COMPOUND_EXPR)
3185 {
3186 expand_expr (TREE_OPERAND (result, 0), const0_rtx, VOIDmode,
3187 EXPAND_NORMAL);
3188 result = TREE_OPERAND (result, 1);
3189 }
3190 return expand_expr (result, target, mode, EXPAND_NORMAL);
3191 }
3192
3193 return expand_movstr (TREE_VALUE (arglist),
3194 TREE_VALUE (TREE_CHAIN (arglist)),
3195 target, /*endp=*/0);
3196 }
3197 return 0;
3198}
3199
2811/* Expand a call to the stpcpy builtin, with arguments in ARGLIST.
2812 Return 0 if we failed the caller should emit a normal call,
2813 otherwise try to get the result in TARGET, if convenient (and in
2814 mode MODE if that's convenient). */
2815
2816static rtx
3200/* Expand a call to the stpcpy builtin, with arguments in ARGLIST.
3201 Return 0 if we failed the caller should emit a normal call,
3202 otherwise try to get the result in TARGET, if convenient (and in
3203 mode MODE if that's convenient). */
3204
3205static rtx
2817expand_builtin_stpcpy (tree arglist, rtx target, enum machine_mode mode)
3206expand_builtin_stpcpy (tree exp, rtx target, enum machine_mode mode)
2818{
3207{
3208 tree arglist = TREE_OPERAND (exp, 1);
3209 /* If return value is ignored, transform stpcpy into strcpy. */
3210 if (target == const0_rtx)
3211 {
3212 tree fn = implicit_built_in_decls[BUILT_IN_STRCPY];
3213 if (!fn)
3214 return 0;
3215
3216 return expand_expr (build_function_call_expr (fn, arglist),
3217 target, mode, EXPAND_NORMAL);
3218 }
3219
2819 if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
2820 return 0;
2821 else
2822 {
3220 if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
3221 return 0;
3222 else
3223 {
2823 tree dst, src, len;
3224 tree dst, src, len, lenp1;
3225 tree narglist;
3226 rtx ret;
2824
3227
2825 /* If return value is ignored, transform stpcpy into strcpy. */
2826 if (target == const0_rtx)
2827 {
2828 tree fn = implicit_built_in_decls[BUILT_IN_STRCPY];
2829 if (!fn)
2830 return 0;
2831
2832 return expand_expr (build_function_call_expr (fn, arglist),
2833 target, mode, EXPAND_NORMAL);
2834 }
2835
2836 /* Ensure we get an actual string whose length can be evaluated at
3228 /* Ensure we get an actual string whose length can be evaluated at
2837 compile-time, not an expression containing a string. This is
2838 because the latter will potentially produce pessimized code
2839 when used to produce the return value. */
3229 compile-time, not an expression containing a string. This is
3230 because the latter will potentially produce pessimized code
3231 when used to produce the return value. */
2840 src = TREE_VALUE (TREE_CHAIN (arglist));
2841 if (! c_getstr (src) || ! (len = c_strlen (src, 0)))
3232 src = TREE_VALUE (TREE_CHAIN (arglist));
3233 if (! c_getstr (src) || ! (len = c_strlen (src, 0)))
2842 return 0;
3234 return expand_movstr (TREE_VALUE (arglist),
3235 TREE_VALUE (TREE_CHAIN (arglist)),
3236 target, /*endp=*/2);
2843
2844 dst = TREE_VALUE (arglist);
3237
3238 dst = TREE_VALUE (arglist);
2845 len = fold (size_binop (PLUS_EXPR, len, ssize_int (1)));
2846 arglist = build_tree_list (NULL_TREE, len);
2847 arglist = tree_cons (NULL_TREE, src, arglist);
2848 arglist = tree_cons (NULL_TREE, dst, arglist);
2849 return expand_builtin_mempcpy (arglist, target, mode, /*endp=*/2);
3239 lenp1 = size_binop (PLUS_EXPR, len, ssize_int (1));
3240 narglist = build_tree_list (NULL_TREE, lenp1);
3241 narglist = tree_cons (NULL_TREE, src, narglist);
3242 narglist = tree_cons (NULL_TREE, dst, narglist);
3243 ret = expand_builtin_mempcpy (narglist, TREE_TYPE (exp),
3244 target, mode, /*endp=*/2);
3245
3246 if (ret)
3247 return ret;
3248
3249 if (TREE_CODE (len) == INTEGER_CST)
3250 {
3251 rtx len_rtx = expand_normal (len);
3252
3253 if (GET_CODE (len_rtx) == CONST_INT)
3254 {
3255 ret = expand_builtin_strcpy (get_callee_fndecl (exp),
3256 arglist, target, mode);
3257
3258 if (ret)
3259 {
3260 if (! target)
3261 {
3262 if (mode != VOIDmode)
3263 target = gen_reg_rtx (mode);
3264 else
3265 target = gen_reg_rtx (GET_MODE (ret));
3266 }
3267 if (GET_MODE (target) != GET_MODE (ret))
3268 ret = gen_lowpart (GET_MODE (target), ret);
3269
3270 ret = plus_constant (ret, INTVAL (len_rtx));
3271 ret = emit_move_insn (target, force_operand (ret, NULL_RTX));
3272 gcc_assert (ret);
3273
3274 return target;
3275 }
3276 }
3277 }
3278
3279 return expand_movstr (TREE_VALUE (arglist),
3280 TREE_VALUE (TREE_CHAIN (arglist)),
3281 target, /*endp=*/2);
2850 }
2851}
2852
2853/* Callback routine for store_by_pieces. Read GET_MODE_BITSIZE (MODE)
2854 bytes from constant string DATA + OFFSET and return it as target
2855 constant. */
2856
2857static rtx

--- 7 unchanged lines hidden (view full) ---

2865
2866 return c_readstr (str + offset, mode);
2867}
2868
2869/* Expand expression EXP, which is a call to the strncpy builtin. Return 0
2870 if we failed the caller should emit a normal call. */
2871
2872static rtx
3282 }
3283}
3284
3285/* Callback routine for store_by_pieces. Read GET_MODE_BITSIZE (MODE)
3286 bytes from constant string DATA + OFFSET and return it as target
3287 constant. */
3288
3289static rtx

--- 7 unchanged lines hidden (view full) ---

3297
3298 return c_readstr (str + offset, mode);
3299}
3300
3301/* Expand expression EXP, which is a call to the strncpy builtin. Return 0
3302 if we failed the caller should emit a normal call. */
3303
3304static rtx
2873expand_builtin_strncpy (tree arglist, rtx target, enum machine_mode mode)
3305expand_builtin_strncpy (tree exp, rtx target, enum machine_mode mode)
2874{
3306{
2875 if (!validate_arglist (arglist,
2876 POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
2877 return 0;
2878 else
3307 tree fndecl = get_callee_fndecl (exp);
3308 tree arglist = TREE_OPERAND (exp, 1);
3309 if (validate_arglist (arglist,
3310 POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
2879 {
2880 tree slen = c_strlen (TREE_VALUE (TREE_CHAIN (arglist)), 1);
2881 tree len = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
3311 {
3312 tree slen = c_strlen (TREE_VALUE (TREE_CHAIN (arglist)), 1);
3313 tree len = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
2882 tree fn;
3314 tree result = fold_builtin_strncpy (fndecl, arglist, slen);
2883
3315
2884 /* We must be passed a constant len parameter. */
2885 if (TREE_CODE (len) != INTEGER_CST)
2886 return 0;
2887
2888 /* If the len parameter is zero, return the dst parameter. */
2889 if (integer_zerop (len))
3316 if (result)
2890 {
3317 {
2891 /* Evaluate and ignore the src argument in case it has
2892 side-effects. */
2893 expand_expr (TREE_VALUE (TREE_CHAIN (arglist)), const0_rtx,
2894 VOIDmode, EXPAND_NORMAL);
2895 /* Return the dst parameter. */
2896 return expand_expr (TREE_VALUE (arglist), target, mode,
2897 EXPAND_NORMAL);
3318 while (TREE_CODE (result) == COMPOUND_EXPR)
3319 {
3320 expand_expr (TREE_OPERAND (result, 0), const0_rtx, VOIDmode,
3321 EXPAND_NORMAL);
3322 result = TREE_OPERAND (result, 1);
3323 }
3324 return expand_expr (result, target, mode, EXPAND_NORMAL);
2898 }
2899
3325 }
3326
2900 /* Now, we must be passed a constant src ptr parameter. */
2901 if (slen == 0 || TREE_CODE (slen) != INTEGER_CST)
3327 /* We must be passed a constant len and src parameter. */
3328 if (!host_integerp (len, 1) || !slen || !host_integerp (slen, 1))
2902 return 0;
2903
2904 slen = size_binop (PLUS_EXPR, slen, ssize_int (1));
2905
2906 /* We're required to pad with trailing zeros if the requested
3329 return 0;
3330
3331 slen = size_binop (PLUS_EXPR, slen, ssize_int (1));
3332
3333 /* We're required to pad with trailing zeros if the requested
2907 len is greater than strlen(s2)+1. In that case try to
3334 len is greater than strlen(s2)+1. In that case try to
2908 use store_by_pieces, if it fails, punt. */
2909 if (tree_int_cst_lt (slen, len))
2910 {
2911 tree dest = TREE_VALUE (arglist);
2912 unsigned int dest_align
2913 = get_pointer_alignment (dest, BIGGEST_ALIGNMENT);
2914 const char *p = c_getstr (TREE_VALUE (TREE_CHAIN (arglist)));
2915 rtx dest_mem;
2916
2917 if (!p || dest_align == 0 || !host_integerp (len, 1)
2918 || !can_store_by_pieces (tree_low_cst (len, 1),
2919 builtin_strncpy_read_str,
2920 (void *) p, dest_align))
2921 return 0;
2922
3335 use store_by_pieces, if it fails, punt. */
3336 if (tree_int_cst_lt (slen, len))
3337 {
3338 tree dest = TREE_VALUE (arglist);
3339 unsigned int dest_align
3340 = get_pointer_alignment (dest, BIGGEST_ALIGNMENT);
3341 const char *p = c_getstr (TREE_VALUE (TREE_CHAIN (arglist)));
3342 rtx dest_mem;
3343
3344 if (!p || dest_align == 0 || !host_integerp (len, 1)
3345 || !can_store_by_pieces (tree_low_cst (len, 1),
3346 builtin_strncpy_read_str,
3347 (void *) p, dest_align))
3348 return 0;
3349
2923 dest_mem = get_memory_rtx (dest);
3350 dest_mem = get_memory_rtx (dest, len);
2924 store_by_pieces (dest_mem, tree_low_cst (len, 1),
2925 builtin_strncpy_read_str,
2926 (void *) p, dest_align, 0);
2927 dest_mem = force_operand (XEXP (dest_mem, 0), NULL_RTX);
2928 dest_mem = convert_memory_address (ptr_mode, dest_mem);
2929 return dest_mem;
2930 }
3351 store_by_pieces (dest_mem, tree_low_cst (len, 1),
3352 builtin_strncpy_read_str,
3353 (void *) p, dest_align, 0);
3354 dest_mem = force_operand (XEXP (dest_mem, 0), NULL_RTX);
3355 dest_mem = convert_memory_address (ptr_mode, dest_mem);
3356 return dest_mem;
3357 }
2931
2932 /* OK transform into builtin memcpy. */
2933 fn = implicit_built_in_decls[BUILT_IN_MEMCPY];
2934 if (!fn)
2935 return 0;
2936 return expand_expr (build_function_call_expr (fn, arglist),
2937 target, mode, EXPAND_NORMAL);
2938 }
3358 }
3359 return 0;
2939}
2940
2941/* Callback routine for store_by_pieces. Read GET_MODE_BITSIZE (MODE)
2942 bytes from constant string DATA + OFFSET and return it as target
2943 constant. */
2944
2945static rtx
2946builtin_memset_read_str (void *data, HOST_WIDE_INT offset ATTRIBUTE_UNUSED,

--- 34 unchanged lines hidden (view full) ---

2981}
2982
2983/* Expand expression EXP, which is a call to the memset builtin. Return 0
2984 if we failed the caller should emit a normal call, otherwise try to get
2985 the result in TARGET, if convenient (and in mode MODE if that's
2986 convenient). */
2987
2988static rtx
3360}
3361
3362/* Callback routine for store_by_pieces. Read GET_MODE_BITSIZE (MODE)
3363 bytes from constant string DATA + OFFSET and return it as target
3364 constant. */
3365
3366static rtx
3367builtin_memset_read_str (void *data, HOST_WIDE_INT offset ATTRIBUTE_UNUSED,

--- 34 unchanged lines hidden (view full) ---

3402}
3403
3404/* Expand expression EXP, which is a call to the memset builtin. Return 0
3405 if we failed the caller should emit a normal call, otherwise try to get
3406 the result in TARGET, if convenient (and in mode MODE if that's
3407 convenient). */
3408
3409static rtx
2989expand_builtin_memset (tree arglist, rtx target, enum machine_mode mode)
3410expand_builtin_memset (tree arglist, rtx target, enum machine_mode mode,
3411 tree orig_exp)
2990{
2991 if (!validate_arglist (arglist,
2992 POINTER_TYPE, INTEGER_TYPE, INTEGER_TYPE, VOID_TYPE))
2993 return 0;
2994 else
2995 {
2996 tree dest = TREE_VALUE (arglist);
2997 tree val = TREE_VALUE (TREE_CHAIN (arglist));
2998 tree len = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
3412{
3413 if (!validate_arglist (arglist,
3414 POINTER_TYPE, INTEGER_TYPE, INTEGER_TYPE, VOID_TYPE))
3415 return 0;
3416 else
3417 {
3418 tree dest = TREE_VALUE (arglist);
3419 tree val = TREE_VALUE (TREE_CHAIN (arglist));
3420 tree len = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
3421 tree fndecl, fn;
3422 enum built_in_function fcode;
2999 char c;
3423 char c;
3000
3001 unsigned int dest_align
3002 = get_pointer_alignment (dest, BIGGEST_ALIGNMENT);
3424 unsigned int dest_align;
3003 rtx dest_mem, dest_addr, len_rtx;
3004
3425 rtx dest_mem, dest_addr, len_rtx;
3426
3427 dest_align = get_pointer_alignment (dest, BIGGEST_ALIGNMENT);
3428
3005 /* If DEST is not a pointer type, don't do this
3006 operation in-line. */
3007 if (dest_align == 0)
3008 return 0;
3009
3010 /* If the LEN parameter is zero, return DEST. */
3011 if (integer_zerop (len))
3012 {
3013 /* Evaluate and ignore VAL in case it has side-effects. */
3014 expand_expr (val, const0_rtx, VOIDmode, EXPAND_NORMAL);
3015 return expand_expr (dest, target, mode, EXPAND_NORMAL);
3016 }
3017
3429 /* If DEST is not a pointer type, don't do this
3430 operation in-line. */
3431 if (dest_align == 0)
3432 return 0;
3433
3434 /* If the LEN parameter is zero, return DEST. */
3435 if (integer_zerop (len))
3436 {
3437 /* Evaluate and ignore VAL in case it has side-effects. */
3438 expand_expr (val, const0_rtx, VOIDmode, EXPAND_NORMAL);
3439 return expand_expr (dest, target, mode, EXPAND_NORMAL);
3440 }
3441
3442 /* Stabilize the arguments in case we fail. */
3443 dest = builtin_save_expr (dest);
3444 val = builtin_save_expr (val);
3445 len = builtin_save_expr (len);
3446
3447 len_rtx = expand_normal (len);
3448 dest_mem = get_memory_rtx (dest, len);
3449
3018 if (TREE_CODE (val) != INTEGER_CST)
3019 {
3020 rtx val_rtx;
3021
3450 if (TREE_CODE (val) != INTEGER_CST)
3451 {
3452 rtx val_rtx;
3453
3022 if (!host_integerp (len, 1))
3023 return 0;
3454 val_rtx = expand_normal (val);
3455 val_rtx = convert_to_mode (TYPE_MODE (unsigned_char_type_node),
3456 val_rtx, 0);
3024
3457
3025 if (optimize_size && tree_low_cst (len, 1) > 1)
3026 return 0;
3027
3028 /* Assume that we can memset by pieces if we can store the
3029 * the coefficients by pieces (in the required modes).
3030 * We can't pass builtin_memset_gen_str as that emits RTL. */
3031 c = 1;
3458 /* Assume that we can memset by pieces if we can store the
3459 * the coefficients by pieces (in the required modes).
3460 * We can't pass builtin_memset_gen_str as that emits RTL. */
3461 c = 1;
3032 if (!can_store_by_pieces (tree_low_cst (len, 1),
3033 builtin_memset_read_str,
3034 &c, dest_align))
3035 return 0;
3462 if (host_integerp (len, 1)
3463 && !(optimize_size && tree_low_cst (len, 1) > 1)
3464 && can_store_by_pieces (tree_low_cst (len, 1),
3465 builtin_memset_read_str, &c, dest_align))
3466 {
3467 val_rtx = force_reg (TYPE_MODE (unsigned_char_type_node),
3468 val_rtx);
3469 store_by_pieces (dest_mem, tree_low_cst (len, 1),
3470 builtin_memset_gen_str, val_rtx, dest_align, 0);
3471 }
3472 else if (!set_storage_via_setmem (dest_mem, len_rtx, val_rtx,
3473 dest_align))
3474 goto do_libcall;
3036
3475
3037 val = fold (build1 (CONVERT_EXPR, unsigned_char_type_node, val));
3038 val_rtx = expand_expr (val, NULL_RTX, VOIDmode, 0);
3039 val_rtx = force_reg (TYPE_MODE (unsigned_char_type_node),
3040 val_rtx);
3041 dest_mem = get_memory_rtx (dest);
3042 store_by_pieces (dest_mem, tree_low_cst (len, 1),
3043 builtin_memset_gen_str,
3044 val_rtx, dest_align, 0);
3045 dest_mem = force_operand (XEXP (dest_mem, 0), NULL_RTX);
3046 dest_mem = convert_memory_address (ptr_mode, dest_mem);
3047 return dest_mem;
3048 }
3049
3050 if (target_char_cast (val, &c))
3476 dest_mem = force_operand (XEXP (dest_mem, 0), NULL_RTX);
3477 dest_mem = convert_memory_address (ptr_mode, dest_mem);
3478 return dest_mem;
3479 }
3480
3481 if (target_char_cast (val, &c))
3051 return 0;
3482 goto do_libcall;
3052
3053 if (c)
3054 {
3483
3484 if (c)
3485 {
3055 if (!host_integerp (len, 1))
3056 return 0;
3057 if (!can_store_by_pieces (tree_low_cst (len, 1),
3058 builtin_memset_read_str, &c,
3059 dest_align))
3060 return 0;
3486 if (host_integerp (len, 1)
3487 && !(optimize_size && tree_low_cst (len, 1) > 1)
3488 && can_store_by_pieces (tree_low_cst (len, 1),
3489 builtin_memset_read_str, &c, dest_align))
3490 store_by_pieces (dest_mem, tree_low_cst (len, 1),
3491 builtin_memset_read_str, &c, dest_align, 0);
3492 else if (!set_storage_via_setmem (dest_mem, len_rtx, GEN_INT (c),
3493 dest_align))
3494 goto do_libcall;
3061
3495
3062 dest_mem = get_memory_rtx (dest);
3063 store_by_pieces (dest_mem, tree_low_cst (len, 1),
3064 builtin_memset_read_str,
3065 &c, dest_align, 0);
3066 dest_mem = force_operand (XEXP (dest_mem, 0), NULL_RTX);
3067 dest_mem = convert_memory_address (ptr_mode, dest_mem);
3068 return dest_mem;
3069 }
3070
3496 dest_mem = force_operand (XEXP (dest_mem, 0), NULL_RTX);
3497 dest_mem = convert_memory_address (ptr_mode, dest_mem);
3498 return dest_mem;
3499 }
3500
3071 len_rtx = expand_expr (len, NULL_RTX, VOIDmode, 0);
3072
3073 dest_mem = get_memory_rtx (dest);
3074 set_mem_align (dest_mem, dest_align);
3501 set_mem_align (dest_mem, dest_align);
3075 dest_addr = clear_storage (dest_mem, len_rtx);
3502 dest_addr = clear_storage (dest_mem, len_rtx,
3503 CALL_EXPR_TAILCALL (orig_exp)
3504 ? BLOCK_OP_TAILCALL : BLOCK_OP_NORMAL);
3076
3077 if (dest_addr == 0)
3078 {
3079 dest_addr = force_operand (XEXP (dest_mem, 0), NULL_RTX);
3080 dest_addr = convert_memory_address (ptr_mode, dest_addr);
3081 }
3082
3083 return dest_addr;
3505
3506 if (dest_addr == 0)
3507 {
3508 dest_addr = force_operand (XEXP (dest_mem, 0), NULL_RTX);
3509 dest_addr = convert_memory_address (ptr_mode, dest_addr);
3510 }
3511
3512 return dest_addr;
3513
3514 do_libcall:
3515 fndecl = get_callee_fndecl (orig_exp);
3516 fcode = DECL_FUNCTION_CODE (fndecl);
3517 gcc_assert (fcode == BUILT_IN_MEMSET || fcode == BUILT_IN_BZERO);
3518 arglist = build_tree_list (NULL_TREE, len);
3519 if (fcode == BUILT_IN_MEMSET)
3520 arglist = tree_cons (NULL_TREE, val, arglist);
3521 arglist = tree_cons (NULL_TREE, dest, arglist);
3522 fn = build_function_call_expr (fndecl, arglist);
3523 if (TREE_CODE (fn) == CALL_EXPR)
3524 CALL_EXPR_TAILCALL (fn) = CALL_EXPR_TAILCALL (orig_exp);
3525 return expand_call (fn, target, target == const0_rtx);
3084 }
3085}
3086
3087/* Expand expression EXP, which is a call to the bzero builtin. Return 0
3088 if we failed the caller should emit a normal call. */
3089
3090static rtx
3526 }
3527}
3528
3529/* Expand expression EXP, which is a call to the bzero builtin. Return 0
3530 if we failed the caller should emit a normal call. */
3531
3532static rtx
3091expand_builtin_bzero (tree arglist)
3533expand_builtin_bzero (tree exp)
3092{
3534{
3535 tree arglist = TREE_OPERAND (exp, 1);
3093 tree dest, size, newarglist;
3094
3095 if (!validate_arglist (arglist, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
3096 return NULL_RTX;
3097
3098 dest = TREE_VALUE (arglist);
3099 size = TREE_VALUE (TREE_CHAIN (arglist));
3100
3101 /* New argument list transforming bzero(ptr x, int y) to
3102 memset(ptr x, int 0, size_t y). This is done this way
3103 so that if it isn't expanded inline, we fallback to
3104 calling bzero instead of memset. */
3105
3536 tree dest, size, newarglist;
3537
3538 if (!validate_arglist (arglist, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
3539 return NULL_RTX;
3540
3541 dest = TREE_VALUE (arglist);
3542 size = TREE_VALUE (TREE_CHAIN (arglist));
3543
3544 /* New argument list transforming bzero(ptr x, int y) to
3545 memset(ptr x, int 0, size_t y). This is done this way
3546 so that if it isn't expanded inline, we fallback to
3547 calling bzero instead of memset. */
3548
3106 newarglist = build_tree_list (NULL_TREE, convert (sizetype, size));
3549 newarglist = build_tree_list (NULL_TREE, fold_convert (sizetype, size));
3107 newarglist = tree_cons (NULL_TREE, integer_zero_node, newarglist);
3108 newarglist = tree_cons (NULL_TREE, dest, newarglist);
3109
3550 newarglist = tree_cons (NULL_TREE, integer_zero_node, newarglist);
3551 newarglist = tree_cons (NULL_TREE, dest, newarglist);
3552
3110 return expand_builtin_memset (newarglist, const0_rtx, VOIDmode);
3553 return expand_builtin_memset (newarglist, const0_rtx, VOIDmode, exp);
3111}
3112
3113/* Expand expression EXP, which is a call to the memcmp built-in function.
3114 ARGLIST is the argument list for this call. Return 0 if we failed and the
3115 caller should emit a normal call, otherwise try to get the result in
3116 TARGET, if convenient (and in mode MODE, if that's convenient). */
3117
3118static rtx
3119expand_builtin_memcmp (tree exp ATTRIBUTE_UNUSED, tree arglist, rtx target,
3120 enum machine_mode mode)
3121{
3554}
3555
3556/* Expand expression EXP, which is a call to the memcmp built-in function.
3557 ARGLIST is the argument list for this call. Return 0 if we failed and the
3558 caller should emit a normal call, otherwise try to get the result in
3559 TARGET, if convenient (and in mode MODE, if that's convenient). */
3560
3561static rtx
3562expand_builtin_memcmp (tree exp ATTRIBUTE_UNUSED, tree arglist, rtx target,
3563 enum machine_mode mode)
3564{
3122 tree arg1, arg2, len;
3123 const char *p1, *p2;
3124
3125 if (!validate_arglist (arglist,
3126 POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
3127 return 0;
3565 if (!validate_arglist (arglist,
3566 POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
3567 return 0;
3128
3129 arg1 = TREE_VALUE (arglist);
3130 arg2 = TREE_VALUE (TREE_CHAIN (arglist));
3131 len = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
3132
3133 /* If the len parameter is zero, return zero. */
3134 if (integer_zerop (len))
3568 else
3135 {
3569 {
3136 /* Evaluate and ignore arg1 and arg2 in case they have
3137 side-effects. */
3138 expand_expr (arg1, const0_rtx, VOIDmode, EXPAND_NORMAL);
3139 expand_expr (arg2, const0_rtx, VOIDmode, EXPAND_NORMAL);
3140 return const0_rtx;
3570 tree result = fold_builtin_memcmp (arglist);
3571 if (result)
3572 return expand_expr (result, target, mode, EXPAND_NORMAL);
3141 }
3142
3573 }
3574
3143 /* If both arguments are equal (and not volatile), return zero. */
3144 if (operand_equal_p (arg1, arg2, 0))
3145 {
3146 /* Evaluate and ignore len in case it has side-effects. */
3147 expand_expr (len, const0_rtx, VOIDmode, EXPAND_NORMAL);
3148 return const0_rtx;
3149 }
3150
3151 p1 = c_getstr (arg1);
3152 p2 = c_getstr (arg2);
3153
3154 /* If all arguments are constant, and the value of len is not greater
3155 than the lengths of arg1 and arg2, evaluate at compile-time. */
3156 if (host_integerp (len, 1) && p1 && p2
3157 && compare_tree_int (len, strlen (p1) + 1) <= 0
3158 && compare_tree_int (len, strlen (p2) + 1) <= 0)
3159 {
3160 const int r = memcmp (p1, p2, tree_low_cst (len, 1));
3161
3162 return (r < 0 ? constm1_rtx : (r > 0 ? const1_rtx : const0_rtx));
3163 }
3164
3165 /* If len parameter is one, return an expression corresponding to
3166 (*(const unsigned char*)arg1 - (const unsigned char*)arg2). */
3167 if (integer_onep (len))
3168 {
3169 tree cst_uchar_node = build_type_variant (unsigned_char_type_node, 1, 0);
3170 tree cst_uchar_ptr_node = build_pointer_type (cst_uchar_node);
3171 tree ind1 =
3172 fold (build1 (CONVERT_EXPR, integer_type_node,
3173 build1 (INDIRECT_REF, cst_uchar_node,
3174 build1 (NOP_EXPR, cst_uchar_ptr_node, arg1))));
3175 tree ind2 =
3176 fold (build1 (CONVERT_EXPR, integer_type_node,
3177 build1 (INDIRECT_REF, cst_uchar_node,
3178 build1 (NOP_EXPR, cst_uchar_ptr_node, arg2))));
3179 tree result = fold (build (MINUS_EXPR, integer_type_node, ind1, ind2));
3180 return expand_expr (result, target, mode, EXPAND_NORMAL);
3181 }
3182
3183#if defined HAVE_cmpmemsi || defined HAVE_cmpstrsi
3575#if defined HAVE_cmpmemsi || defined HAVE_cmpstrnsi
3184 {
3576 {
3577 tree arg1 = TREE_VALUE (arglist);
3578 tree arg2 = TREE_VALUE (TREE_CHAIN (arglist));
3579 tree len = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
3185 rtx arg1_rtx, arg2_rtx, arg3_rtx;
3186 rtx result;
3187 rtx insn;
3188
3189 int arg1_align
3190 = get_pointer_alignment (arg1, BIGGEST_ALIGNMENT) / BITS_PER_UNIT;
3191 int arg2_align
3192 = get_pointer_alignment (arg2, BIGGEST_ALIGNMENT) / BITS_PER_UNIT;
3193 enum machine_mode insn_mode;
3194
3195#ifdef HAVE_cmpmemsi
3196 if (HAVE_cmpmemsi)
3197 insn_mode = insn_data[(int) CODE_FOR_cmpmemsi].operand[0].mode;
3198 else
3199#endif
3580 rtx arg1_rtx, arg2_rtx, arg3_rtx;
3581 rtx result;
3582 rtx insn;
3583
3584 int arg1_align
3585 = get_pointer_alignment (arg1, BIGGEST_ALIGNMENT) / BITS_PER_UNIT;
3586 int arg2_align
3587 = get_pointer_alignment (arg2, BIGGEST_ALIGNMENT) / BITS_PER_UNIT;
3588 enum machine_mode insn_mode;
3589
3590#ifdef HAVE_cmpmemsi
3591 if (HAVE_cmpmemsi)
3592 insn_mode = insn_data[(int) CODE_FOR_cmpmemsi].operand[0].mode;
3593 else
3594#endif
3200#ifdef HAVE_cmpstrsi
3201 if (HAVE_cmpstrsi)
3202 insn_mode = insn_data[(int) CODE_FOR_cmpstrsi].operand[0].mode;
3595#ifdef HAVE_cmpstrnsi
3596 if (HAVE_cmpstrnsi)
3597 insn_mode = insn_data[(int) CODE_FOR_cmpstrnsi].operand[0].mode;
3203 else
3204#endif
3598 else
3599#endif
3205 return 0;
3600 return 0;
3206
3207 /* If we don't have POINTER_TYPE, call the function. */
3208 if (arg1_align == 0 || arg2_align == 0)
3209 return 0;
3210
3211 /* Make a place to write the result of the instruction. */
3212 result = target;
3213 if (! (result != 0
3601
3602 /* If we don't have POINTER_TYPE, call the function. */
3603 if (arg1_align == 0 || arg2_align == 0)
3604 return 0;
3605
3606 /* Make a place to write the result of the instruction. */
3607 result = target;
3608 if (! (result != 0
3214 && GET_CODE (result) == REG && GET_MODE (result) == insn_mode
3609 && REG_P (result) && GET_MODE (result) == insn_mode
3215 && REGNO (result) >= FIRST_PSEUDO_REGISTER))
3216 result = gen_reg_rtx (insn_mode);
3217
3610 && REGNO (result) >= FIRST_PSEUDO_REGISTER))
3611 result = gen_reg_rtx (insn_mode);
3612
3218 arg1_rtx = get_memory_rtx (arg1);
3219 arg2_rtx = get_memory_rtx (arg2);
3220 arg3_rtx = expand_expr (len, NULL_RTX, VOIDmode, 0);
3613 arg1_rtx = get_memory_rtx (arg1, len);
3614 arg2_rtx = get_memory_rtx (arg2, len);
3615 arg3_rtx = expand_normal (len);
3616
3617 /* Set MEM_SIZE as appropriate. */
3618 if (GET_CODE (arg3_rtx) == CONST_INT)
3619 {
3620 set_mem_size (arg1_rtx, arg3_rtx);
3621 set_mem_size (arg2_rtx, arg3_rtx);
3622 }
3623
3221#ifdef HAVE_cmpmemsi
3222 if (HAVE_cmpmemsi)
3223 insn = gen_cmpmemsi (result, arg1_rtx, arg2_rtx, arg3_rtx,
3224 GEN_INT (MIN (arg1_align, arg2_align)));
3225 else
3226#endif
3624#ifdef HAVE_cmpmemsi
3625 if (HAVE_cmpmemsi)
3626 insn = gen_cmpmemsi (result, arg1_rtx, arg2_rtx, arg3_rtx,
3627 GEN_INT (MIN (arg1_align, arg2_align)));
3628 else
3629#endif
3227#ifdef HAVE_cmpstrsi
3228 if (HAVE_cmpstrsi)
3229 insn = gen_cmpstrsi (result, arg1_rtx, arg2_rtx, arg3_rtx,
3230 GEN_INT (MIN (arg1_align, arg2_align)));
3630#ifdef HAVE_cmpstrnsi
3631 if (HAVE_cmpstrnsi)
3632 insn = gen_cmpstrnsi (result, arg1_rtx, arg2_rtx, arg3_rtx,
3633 GEN_INT (MIN (arg1_align, arg2_align)));
3231 else
3232#endif
3634 else
3635#endif
3233 abort ();
3636 gcc_unreachable ();
3234
3235 if (insn)
3236 emit_insn (insn);
3237 else
3238 emit_library_call_value (memcmp_libfunc, result, LCT_PURE_MAKE_BLOCK,
3239 TYPE_MODE (integer_type_node), 3,
3240 XEXP (arg1_rtx, 0), Pmode,
3241 XEXP (arg2_rtx, 0), Pmode,
3242 convert_to_mode (TYPE_MODE (sizetype), arg3_rtx,
3637
3638 if (insn)
3639 emit_insn (insn);
3640 else
3641 emit_library_call_value (memcmp_libfunc, result, LCT_PURE_MAKE_BLOCK,
3642 TYPE_MODE (integer_type_node), 3,
3643 XEXP (arg1_rtx, 0), Pmode,
3644 XEXP (arg2_rtx, 0), Pmode,
3645 convert_to_mode (TYPE_MODE (sizetype), arg3_rtx,
3243 TREE_UNSIGNED (sizetype)),
3646 TYPE_UNSIGNED (sizetype)),
3244 TYPE_MODE (sizetype));
3245
3246 /* Return the value in the proper mode for this function. */
3247 mode = TYPE_MODE (TREE_TYPE (exp));
3248 if (GET_MODE (result) == mode)
3249 return result;
3250 else if (target != 0)
3251 {

--- 11 unchanged lines hidden (view full) ---

3263/* Expand expression EXP, which is a call to the strcmp builtin. Return 0
3264 if we failed the caller should emit a normal call, otherwise try to get
3265 the result in TARGET, if convenient. */
3266
3267static rtx
3268expand_builtin_strcmp (tree exp, rtx target, enum machine_mode mode)
3269{
3270 tree arglist = TREE_OPERAND (exp, 1);
3647 TYPE_MODE (sizetype));
3648
3649 /* Return the value in the proper mode for this function. */
3650 mode = TYPE_MODE (TREE_TYPE (exp));
3651 if (GET_MODE (result) == mode)
3652 return result;
3653 else if (target != 0)
3654 {

--- 11 unchanged lines hidden (view full) ---

3666/* Expand expression EXP, which is a call to the strcmp builtin. Return 0
3667 if we failed the caller should emit a normal call, otherwise try to get
3668 the result in TARGET, if convenient. */
3669
3670static rtx
3671expand_builtin_strcmp (tree exp, rtx target, enum machine_mode mode)
3672{
3673 tree arglist = TREE_OPERAND (exp, 1);
3271 tree arg1, arg2;
3272 const char *p1, *p2;
3273
3274 if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
3275 return 0;
3674
3675 if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
3676 return 0;
3677 else
3678 {
3679 tree result = fold_builtin_strcmp (arglist);
3680 if (result)
3681 return expand_expr (result, target, mode, EXPAND_NORMAL);
3682 }
3276
3683
3277 arg1 = TREE_VALUE (arglist);
3278 arg2 = TREE_VALUE (TREE_CHAIN (arglist));
3684#if defined HAVE_cmpstrsi || defined HAVE_cmpstrnsi
3685 if (cmpstr_optab[SImode] != CODE_FOR_nothing
3686 || cmpstrn_optab[SImode] != CODE_FOR_nothing)
3687 {
3688 rtx arg1_rtx, arg2_rtx;
3689 rtx result, insn = NULL_RTX;
3690 tree fndecl, fn;
3279
3691
3280 /* If both arguments are equal (and not volatile), return zero. */
3281 if (operand_equal_p (arg1, arg2, 0))
3282 return const0_rtx;
3692 tree arg1 = TREE_VALUE (arglist);
3693 tree arg2 = TREE_VALUE (TREE_CHAIN (arglist));
3694 int arg1_align
3695 = get_pointer_alignment (arg1, BIGGEST_ALIGNMENT) / BITS_PER_UNIT;
3696 int arg2_align
3697 = get_pointer_alignment (arg2, BIGGEST_ALIGNMENT) / BITS_PER_UNIT;
3283
3698
3284 p1 = c_getstr (arg1);
3285 p2 = c_getstr (arg2);
3699 /* If we don't have POINTER_TYPE, call the function. */
3700 if (arg1_align == 0 || arg2_align == 0)
3701 return 0;
3286
3702
3287 if (p1 && p2)
3288 {
3289 const int i = strcmp (p1, p2);
3290 return (i < 0 ? constm1_rtx : (i > 0 ? const1_rtx : const0_rtx));
3291 }
3703 /* Stabilize the arguments in case gen_cmpstr(n)si fail. */
3704 arg1 = builtin_save_expr (arg1);
3705 arg2 = builtin_save_expr (arg2);
3292
3706
3293 /* If either arg is "", return an expression corresponding to
3294 (*(const unsigned char*)arg1 - (const unsigned char*)arg2). */
3295 if ((p1 && *p1 == '\0') || (p2 && *p2 == '\0'))
3296 {
3297 tree cst_uchar_node = build_type_variant (unsigned_char_type_node, 1, 0);
3298 tree cst_uchar_ptr_node = build_pointer_type (cst_uchar_node);
3299 tree ind1 =
3300 fold (build1 (CONVERT_EXPR, integer_type_node,
3301 build1 (INDIRECT_REF, cst_uchar_node,
3302 build1 (NOP_EXPR, cst_uchar_ptr_node, arg1))));
3303 tree ind2 =
3304 fold (build1 (CONVERT_EXPR, integer_type_node,
3305 build1 (INDIRECT_REF, cst_uchar_node,
3306 build1 (NOP_EXPR, cst_uchar_ptr_node, arg2))));
3307 tree result = fold (build (MINUS_EXPR, integer_type_node, ind1, ind2));
3308 return expand_expr (result, target, mode, EXPAND_NORMAL);
3309 }
3707 arg1_rtx = get_memory_rtx (arg1, NULL);
3708 arg2_rtx = get_memory_rtx (arg2, NULL);
3310
3311#ifdef HAVE_cmpstrsi
3709
3710#ifdef HAVE_cmpstrsi
3312 if (HAVE_cmpstrsi)
3313 {
3314 tree len, len1, len2;
3315 rtx arg1_rtx, arg2_rtx, arg3_rtx;
3316 rtx result, insn;
3317 tree fndecl;
3711 /* Try to call cmpstrsi. */
3712 if (HAVE_cmpstrsi)
3713 {
3714 enum machine_mode insn_mode
3715 = insn_data[(int) CODE_FOR_cmpstrsi].operand[0].mode;
3318
3716
3319 int arg1_align
3320 = get_pointer_alignment (arg1, BIGGEST_ALIGNMENT) / BITS_PER_UNIT;
3321 int arg2_align
3322 = get_pointer_alignment (arg2, BIGGEST_ALIGNMENT) / BITS_PER_UNIT;
3323 enum machine_mode insn_mode
3324 = insn_data[(int) CODE_FOR_cmpstrsi].operand[0].mode;
3717 /* Make a place to write the result of the instruction. */
3718 result = target;
3719 if (! (result != 0
3720 && REG_P (result) && GET_MODE (result) == insn_mode
3721 && REGNO (result) >= FIRST_PSEUDO_REGISTER))
3722 result = gen_reg_rtx (insn_mode);
3325
3723
3326 len1 = c_strlen (arg1, 1);
3327 len2 = c_strlen (arg2, 1);
3724 insn = gen_cmpstrsi (result, arg1_rtx, arg2_rtx,
3725 GEN_INT (MIN (arg1_align, arg2_align)));
3726 }
3727#endif
3728#ifdef HAVE_cmpstrnsi
3729 /* Try to determine at least one length and call cmpstrnsi. */
3730 if (!insn && HAVE_cmpstrnsi)
3731 {
3732 tree len;
3733 rtx arg3_rtx;
3328
3734
3329 if (len1)
3330 len1 = size_binop (PLUS_EXPR, ssize_int (1), len1);
3331 if (len2)
3332 len2 = size_binop (PLUS_EXPR, ssize_int (1), len2);
3735 enum machine_mode insn_mode
3736 = insn_data[(int) CODE_FOR_cmpstrnsi].operand[0].mode;
3737 tree len1 = c_strlen (arg1, 1);
3738 tree len2 = c_strlen (arg2, 1);
3333
3739
3334 /* If we don't have a constant length for the first, use the length
3335 of the second, if we know it. We don't require a constant for
3336 this case; some cost analysis could be done if both are available
3337 but neither is constant. For now, assume they're equally cheap,
3338 unless one has side effects. If both strings have constant lengths,
3339 use the smaller. */
3740 if (len1)
3741 len1 = size_binop (PLUS_EXPR, ssize_int (1), len1);
3742 if (len2)
3743 len2 = size_binop (PLUS_EXPR, ssize_int (1), len2);
3340
3744
3341 if (!len1)
3342 len = len2;
3343 else if (!len2)
3344 len = len1;
3345 else if (TREE_SIDE_EFFECTS (len1))
3346 len = len2;
3347 else if (TREE_SIDE_EFFECTS (len2))
3348 len = len1;
3349 else if (TREE_CODE (len1) != INTEGER_CST)
3350 len = len2;
3351 else if (TREE_CODE (len2) != INTEGER_CST)
3352 len = len1;
3353 else if (tree_int_cst_lt (len1, len2))
3354 len = len1;
3355 else
3356 len = len2;
3745 /* If we don't have a constant length for the first, use the length
3746 of the second, if we know it. We don't require a constant for
3747 this case; some cost analysis could be done if both are available
3748 but neither is constant. For now, assume they're equally cheap,
3749 unless one has side effects. If both strings have constant lengths,
3750 use the smaller. */
3357
3751
3358 /* If both arguments have side effects, we cannot optimize. */
3359 if (!len || TREE_SIDE_EFFECTS (len))
3360 return 0;
3752 if (!len1)
3753 len = len2;
3754 else if (!len2)
3755 len = len1;
3756 else if (TREE_SIDE_EFFECTS (len1))
3757 len = len2;
3758 else if (TREE_SIDE_EFFECTS (len2))
3759 len = len1;
3760 else if (TREE_CODE (len1) != INTEGER_CST)
3761 len = len2;
3762 else if (TREE_CODE (len2) != INTEGER_CST)
3763 len = len1;
3764 else if (tree_int_cst_lt (len1, len2))
3765 len = len1;
3766 else
3767 len = len2;
3361
3768
3362 /* If we don't have POINTER_TYPE, call the function. */
3363 if (arg1_align == 0 || arg2_align == 0)
3364 return 0;
3769 /* If both arguments have side effects, we cannot optimize. */
3770 if (!len || TREE_SIDE_EFFECTS (len))
3771 goto do_libcall;
3365
3772
3366 /* Make a place to write the result of the instruction. */
3367 result = target;
3368 if (! (result != 0
3369 && GET_CODE (result) == REG && GET_MODE (result) == insn_mode
3370 && REGNO (result) >= FIRST_PSEUDO_REGISTER))
3371 result = gen_reg_rtx (insn_mode);
3773 arg3_rtx = expand_normal (len);
3372
3774
3373 /* Stabilize the arguments in case gen_cmpstrsi fails. */
3374 arg1 = save_expr (arg1);
3375 arg2 = save_expr (arg2);
3775 /* Make a place to write the result of the instruction. */
3776 result = target;
3777 if (! (result != 0
3778 && REG_P (result) && GET_MODE (result) == insn_mode
3779 && REGNO (result) >= FIRST_PSEUDO_REGISTER))
3780 result = gen_reg_rtx (insn_mode);
3376
3781
3377 arg1_rtx = get_memory_rtx (arg1);
3378 arg2_rtx = get_memory_rtx (arg2);
3379 arg3_rtx = expand_expr (len, NULL_RTX, VOIDmode, 0);
3380 insn = gen_cmpstrsi (result, arg1_rtx, arg2_rtx, arg3_rtx,
3381 GEN_INT (MIN (arg1_align, arg2_align)));
3382 if (insn)
3383 {
3384 emit_insn (insn);
3782 insn = gen_cmpstrnsi (result, arg1_rtx, arg2_rtx, arg3_rtx,
3783 GEN_INT (MIN (arg1_align, arg2_align)));
3784 }
3785#endif
3385
3786
3386 /* Return the value in the proper mode for this function. */
3387 mode = TYPE_MODE (TREE_TYPE (exp));
3388 if (GET_MODE (result) == mode)
3389 return result;
3390 if (target == 0)
3391 return convert_to_mode (mode, result, 0);
3392 convert_move (target, result, 0);
3393 return target;
3394 }
3787 if (insn)
3788 {
3789 emit_insn (insn);
3395
3790
3396 /* Expand the library call ourselves using a stabilized argument
3397 list to avoid re-evaluating the function's arguments twice. */
3398 arglist = build_tree_list (NULL_TREE, arg2);
3399 arglist = tree_cons (NULL_TREE, arg1, arglist);
3400 fndecl = get_callee_fndecl (exp);
3401 exp = build_function_call_expr (fndecl, arglist);
3402 return expand_call (exp, target, target == const0_rtx);
3403 }
3791 /* Return the value in the proper mode for this function. */
3792 mode = TYPE_MODE (TREE_TYPE (exp));
3793 if (GET_MODE (result) == mode)
3794 return result;
3795 if (target == 0)
3796 return convert_to_mode (mode, result, 0);
3797 convert_move (target, result, 0);
3798 return target;
3799 }
3800
3801 /* Expand the library call ourselves using a stabilized argument
3802 list to avoid re-evaluating the function's arguments twice. */
3803#ifdef HAVE_cmpstrnsi
3804 do_libcall:
3404#endif
3805#endif
3806 arglist = build_tree_list (NULL_TREE, arg2);
3807 arglist = tree_cons (NULL_TREE, arg1, arglist);
3808 fndecl = get_callee_fndecl (exp);
3809 fn = build_function_call_expr (fndecl, arglist);
3810 if (TREE_CODE (fn) == CALL_EXPR)
3811 CALL_EXPR_TAILCALL (fn) = CALL_EXPR_TAILCALL (exp);
3812 return expand_call (fn, target, target == const0_rtx);
3813 }
3814#endif
3405 return 0;
3406}
3407
3408/* Expand expression EXP, which is a call to the strncmp builtin. Return 0
3409 if we failed the caller should emit a normal call, otherwise try to get
3410 the result in TARGET, if convenient. */
3411
3412static rtx
3413expand_builtin_strncmp (tree exp, rtx target, enum machine_mode mode)
3414{
3415 tree arglist = TREE_OPERAND (exp, 1);
3815 return 0;
3816}
3817
3818/* Expand expression EXP, which is a call to the strncmp builtin. Return 0
3819 if we failed the caller should emit a normal call, otherwise try to get
3820 the result in TARGET, if convenient. */
3821
3822static rtx
3823expand_builtin_strncmp (tree exp, rtx target, enum machine_mode mode)
3824{
3825 tree arglist = TREE_OPERAND (exp, 1);
3416 tree arg1, arg2, arg3;
3417 const char *p1, *p2;
3418
3419 if (!validate_arglist (arglist,
3420 POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
3421 return 0;
3826
3827 if (!validate_arglist (arglist,
3828 POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
3829 return 0;
3422
3423 arg1 = TREE_VALUE (arglist);
3424 arg2 = TREE_VALUE (TREE_CHAIN (arglist));
3425 arg3 = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
3426
3427 /* If the len parameter is zero, return zero. */
3428 if (integer_zerop (arg3))
3830 else
3429 {
3831 {
3430 /* Evaluate and ignore arg1 and arg2 in case they have
3431 side-effects. */
3432 expand_expr (arg1, const0_rtx, VOIDmode, EXPAND_NORMAL);
3433 expand_expr (arg2, const0_rtx, VOIDmode, EXPAND_NORMAL);
3434 return const0_rtx;
3832 tree result = fold_builtin_strncmp (arglist);
3833 if (result)
3834 return expand_expr (result, target, mode, EXPAND_NORMAL);
3435 }
3436
3835 }
3836
3437 /* If arg1 and arg2 are equal (and not volatile), return zero. */
3438 if (operand_equal_p (arg1, arg2, 0))
3439 {
3440 /* Evaluate and ignore arg3 in case it has side-effects. */
3441 expand_expr (arg3, const0_rtx, VOIDmode, EXPAND_NORMAL);
3442 return const0_rtx;
3443 }
3444
3445 p1 = c_getstr (arg1);
3446 p2 = c_getstr (arg2);
3447
3448 /* If all arguments are constant, evaluate at compile-time. */
3449 if (host_integerp (arg3, 1) && p1 && p2)
3450 {
3451 const int r = strncmp (p1, p2, tree_low_cst (arg3, 1));
3452 return (r < 0 ? constm1_rtx : (r > 0 ? const1_rtx : const0_rtx));
3453 }
3454
3455 /* If len == 1 or (either string parameter is "" and (len >= 1)),
3456 return (*(const u_char*)arg1 - *(const u_char*)arg2). */
3457 if (host_integerp (arg3, 1)
3458 && (tree_low_cst (arg3, 1) == 1
3459 || (tree_low_cst (arg3, 1) > 1
3460 && ((p1 && *p1 == '\0') || (p2 && *p2 == '\0')))))
3461 {
3462 tree cst_uchar_node = build_type_variant (unsigned_char_type_node, 1, 0);
3463 tree cst_uchar_ptr_node = build_pointer_type (cst_uchar_node);
3464 tree ind1 =
3465 fold (build1 (CONVERT_EXPR, integer_type_node,
3466 build1 (INDIRECT_REF, cst_uchar_node,
3467 build1 (NOP_EXPR, cst_uchar_ptr_node, arg1))));
3468 tree ind2 =
3469 fold (build1 (CONVERT_EXPR, integer_type_node,
3470 build1 (INDIRECT_REF, cst_uchar_node,
3471 build1 (NOP_EXPR, cst_uchar_ptr_node, arg2))));
3472 tree result = fold (build (MINUS_EXPR, integer_type_node, ind1, ind2));
3473 return expand_expr (result, target, mode, EXPAND_NORMAL);
3474 }
3475
3476 /* If c_strlen can determine an expression for one of the string
3837 /* If c_strlen can determine an expression for one of the string
3477 lengths, and it doesn't have side effects, then emit cmpstrsi
3838 lengths, and it doesn't have side effects, then emit cmpstrnsi
3478 using length MIN(strlen(string)+1, arg3). */
3839 using length MIN(strlen(string)+1, arg3). */
3479#ifdef HAVE_cmpstrsi
3480 if (HAVE_cmpstrsi)
3840#ifdef HAVE_cmpstrnsi
3841 if (HAVE_cmpstrnsi)
3481 {
3842 {
3843 tree arg1 = TREE_VALUE (arglist);
3844 tree arg2 = TREE_VALUE (TREE_CHAIN (arglist));
3845 tree arg3 = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
3482 tree len, len1, len2;
3483 rtx arg1_rtx, arg2_rtx, arg3_rtx;
3484 rtx result, insn;
3846 tree len, len1, len2;
3847 rtx arg1_rtx, arg2_rtx, arg3_rtx;
3848 rtx result, insn;
3485 tree fndecl;
3849 tree fndecl, fn;
3486
3487 int arg1_align
3488 = get_pointer_alignment (arg1, BIGGEST_ALIGNMENT) / BITS_PER_UNIT;
3489 int arg2_align
3490 = get_pointer_alignment (arg2, BIGGEST_ALIGNMENT) / BITS_PER_UNIT;
3491 enum machine_mode insn_mode
3850
3851 int arg1_align
3852 = get_pointer_alignment (arg1, BIGGEST_ALIGNMENT) / BITS_PER_UNIT;
3853 int arg2_align
3854 = get_pointer_alignment (arg2, BIGGEST_ALIGNMENT) / BITS_PER_UNIT;
3855 enum machine_mode insn_mode
3492 = insn_data[(int) CODE_FOR_cmpstrsi].operand[0].mode;
3856 = insn_data[(int) CODE_FOR_cmpstrnsi].operand[0].mode;
3493
3494 len1 = c_strlen (arg1, 1);
3495 len2 = c_strlen (arg2, 1);
3496
3497 if (len1)
3498 len1 = size_binop (PLUS_EXPR, ssize_int (1), len1);
3499 if (len2)
3500 len2 = size_binop (PLUS_EXPR, ssize_int (1), len2);

--- 22 unchanged lines hidden (view full) ---

3523 else
3524 len = len2;
3525
3526 /* If both arguments have side effects, we cannot optimize. */
3527 if (!len || TREE_SIDE_EFFECTS (len))
3528 return 0;
3529
3530 /* The actual new length parameter is MIN(len,arg3). */
3857
3858 len1 = c_strlen (arg1, 1);
3859 len2 = c_strlen (arg2, 1);
3860
3861 if (len1)
3862 len1 = size_binop (PLUS_EXPR, ssize_int (1), len1);
3863 if (len2)
3864 len2 = size_binop (PLUS_EXPR, ssize_int (1), len2);

--- 22 unchanged lines hidden (view full) ---

3887 else
3888 len = len2;
3889
3890 /* If both arguments have side effects, we cannot optimize. */
3891 if (!len || TREE_SIDE_EFFECTS (len))
3892 return 0;
3893
3894 /* The actual new length parameter is MIN(len,arg3). */
3531 len = fold (build (MIN_EXPR, TREE_TYPE (len), len, arg3));
3895 len = fold_build2 (MIN_EXPR, TREE_TYPE (len), len,
3896 fold_convert (TREE_TYPE (len), arg3));
3532
3533 /* If we don't have POINTER_TYPE, call the function. */
3534 if (arg1_align == 0 || arg2_align == 0)
3535 return 0;
3536
3537 /* Make a place to write the result of the instruction. */
3538 result = target;
3539 if (! (result != 0
3897
3898 /* If we don't have POINTER_TYPE, call the function. */
3899 if (arg1_align == 0 || arg2_align == 0)
3900 return 0;
3901
3902 /* Make a place to write the result of the instruction. */
3903 result = target;
3904 if (! (result != 0
3540 && GET_CODE (result) == REG && GET_MODE (result) == insn_mode
3905 && REG_P (result) && GET_MODE (result) == insn_mode
3541 && REGNO (result) >= FIRST_PSEUDO_REGISTER))
3542 result = gen_reg_rtx (insn_mode);
3543
3906 && REGNO (result) >= FIRST_PSEUDO_REGISTER))
3907 result = gen_reg_rtx (insn_mode);
3908
3544 /* Stabilize the arguments in case gen_cmpstrsi fails. */
3545 arg1 = save_expr (arg1);
3546 arg2 = save_expr (arg2);
3547 len = save_expr (len);
3909 /* Stabilize the arguments in case gen_cmpstrnsi fails. */
3910 arg1 = builtin_save_expr (arg1);
3911 arg2 = builtin_save_expr (arg2);
3912 len = builtin_save_expr (len);
3548
3913
3549 arg1_rtx = get_memory_rtx (arg1);
3550 arg2_rtx = get_memory_rtx (arg2);
3551 arg3_rtx = expand_expr (len, NULL_RTX, VOIDmode, 0);
3552 insn = gen_cmpstrsi (result, arg1_rtx, arg2_rtx, arg3_rtx,
3553 GEN_INT (MIN (arg1_align, arg2_align)));
3914 arg1_rtx = get_memory_rtx (arg1, len);
3915 arg2_rtx = get_memory_rtx (arg2, len);
3916 arg3_rtx = expand_normal (len);
3917 insn = gen_cmpstrnsi (result, arg1_rtx, arg2_rtx, arg3_rtx,
3918 GEN_INT (MIN (arg1_align, arg2_align)));
3554 if (insn)
3555 {
3556 emit_insn (insn);
3557
3558 /* Return the value in the proper mode for this function. */
3559 mode = TYPE_MODE (TREE_TYPE (exp));
3560 if (GET_MODE (result) == mode)
3561 return result;

--- 4 unchanged lines hidden (view full) ---

3566 }
3567
3568 /* Expand the library call ourselves using a stabilized argument
3569 list to avoid re-evaluating the function's arguments twice. */
3570 arglist = build_tree_list (NULL_TREE, len);
3571 arglist = tree_cons (NULL_TREE, arg2, arglist);
3572 arglist = tree_cons (NULL_TREE, arg1, arglist);
3573 fndecl = get_callee_fndecl (exp);
3919 if (insn)
3920 {
3921 emit_insn (insn);
3922
3923 /* Return the value in the proper mode for this function. */
3924 mode = TYPE_MODE (TREE_TYPE (exp));
3925 if (GET_MODE (result) == mode)
3926 return result;

--- 4 unchanged lines hidden (view full) ---

3931 }
3932
3933 /* Expand the library call ourselves using a stabilized argument
3934 list to avoid re-evaluating the function's arguments twice. */
3935 arglist = build_tree_list (NULL_TREE, len);
3936 arglist = tree_cons (NULL_TREE, arg2, arglist);
3937 arglist = tree_cons (NULL_TREE, arg1, arglist);
3938 fndecl = get_callee_fndecl (exp);
3574 exp = build_function_call_expr (fndecl, arglist);
3575 return expand_call (exp, target, target == const0_rtx);
3939 fn = build_function_call_expr (fndecl, arglist);
3940 if (TREE_CODE (fn) == CALL_EXPR)
3941 CALL_EXPR_TAILCALL (fn) = CALL_EXPR_TAILCALL (exp);
3942 return expand_call (fn, target, target == const0_rtx);
3576 }
3577#endif
3578 return 0;
3579}
3580
3581/* Expand expression EXP, which is a call to the strcat builtin.
3582 Return 0 if we failed the caller should emit a normal call,
3583 otherwise try to get the result in TARGET, if convenient. */
3584
3585static rtx
3943 }
3944#endif
3945 return 0;
3946}
3947
3948/* Expand expression EXP, which is a call to the strcat builtin.
3949 Return 0 if we failed the caller should emit a normal call,
3950 otherwise try to get the result in TARGET, if convenient. */
3951
3952static rtx
3586expand_builtin_strcat (tree arglist, rtx target, enum machine_mode mode)
3953expand_builtin_strcat (tree fndecl, tree arglist, rtx target, enum machine_mode mode)
3587{
3588 if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
3589 return 0;
3590 else
3591 {
3592 tree dst = TREE_VALUE (arglist),
3954{
3955 if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
3956 return 0;
3957 else
3958 {
3959 tree dst = TREE_VALUE (arglist),
3593 src = TREE_VALUE (TREE_CHAIN (arglist));
3960 src = TREE_VALUE (TREE_CHAIN (arglist));
3594 const char *p = c_getstr (src);
3595
3961 const char *p = c_getstr (src);
3962
3596 if (p)
3963 /* If the string length is zero, return the dst parameter. */
3964 if (p && *p == '\0')
3965 return expand_expr (dst, target, mode, EXPAND_NORMAL);
3966
3967 if (!optimize_size)
3597 {
3968 {
3598 /* If the string length is zero, return the dst parameter. */
3599 if (*p == '\0')
3600 return expand_expr (dst, target, mode, EXPAND_NORMAL);
3601 else if (!optimize_size)
3602 {
3603 /* Otherwise if !optimize_size, see if we can store by
3604 pieces into (dst + strlen(dst)). */
3605 tree newdst, arglist,
3606 strlen_fn = implicit_built_in_decls[BUILT_IN_STRLEN];
3607
3608 /* This is the length argument. */
3609 arglist = build_tree_list (NULL_TREE,
3610 fold (size_binop (PLUS_EXPR,
3611 c_strlen (src, 0),
3612 ssize_int (1))));
3613 /* Prepend src argument. */
3614 arglist = tree_cons (NULL_TREE, src, arglist);
3615
3616 /* We're going to use dst more than once. */
3617 dst = save_expr (dst);
3969 /* See if we can store by pieces into (dst + strlen(dst)). */
3970 tree newsrc, newdst,
3971 strlen_fn = implicit_built_in_decls[BUILT_IN_STRLEN];
3972 rtx insns;
3618
3973
3619 /* Create strlen (dst). */
3620 newdst =
3621 fold (build_function_call_expr (strlen_fn,
3622 build_tree_list (NULL_TREE,
3623 dst)));
3624 /* Create (dst + strlen (dst)). */
3625 newdst = fold (build (PLUS_EXPR, TREE_TYPE (dst), dst, newdst));
3974 /* Stabilize the argument list. */
3975 newsrc = builtin_save_expr (src);
3976 if (newsrc != src)
3977 arglist = build_tree_list (NULL_TREE, newsrc);
3978 else
3979 arglist = TREE_CHAIN (arglist); /* Reusing arglist if safe. */
3626
3980
3627 /* Prepend the new dst argument. */
3628 arglist = tree_cons (NULL_TREE, newdst, arglist);
3629
3630 /* We don't want to get turned into a memcpy if the
3631 target is const0_rtx, i.e. when the return value
3632 isn't used. That would produce pessimized code so
3633 pass in a target of zero, it should never actually be
3634 used. If this was successful return the original
3635 dst, not the result of mempcpy. */
3636 if (expand_builtin_mempcpy (arglist, /*target=*/0, mode, /*endp=*/0))
3637 return expand_expr (dst, target, mode, EXPAND_NORMAL);
3638 else
3639 return 0;
3981 dst = builtin_save_expr (dst);
3982
3983 start_sequence ();
3984
3985 /* Create strlen (dst). */
3986 newdst =
3987 build_function_call_expr (strlen_fn,
3988 build_tree_list (NULL_TREE, dst));
3989 /* Create (dst + (cast) strlen (dst)). */
3990 newdst = fold_convert (TREE_TYPE (dst), newdst);
3991 newdst = fold_build2 (PLUS_EXPR, TREE_TYPE (dst), dst, newdst);
3992
3993 newdst = builtin_save_expr (newdst);
3994 arglist = tree_cons (NULL_TREE, newdst, arglist);
3995
3996 if (!expand_builtin_strcpy (fndecl, arglist, target, mode))
3997 {
3998 end_sequence (); /* Stop sequence. */
3999 return 0;
3640 }
4000 }
4001
4002 /* Output the entire sequence. */
4003 insns = get_insns ();
4004 end_sequence ();
4005 emit_insn (insns);
4006
4007 return expand_expr (dst, target, mode, EXPAND_NORMAL);
3641 }
3642
3643 return 0;
3644 }
3645}
3646
3647/* Expand expression EXP, which is a call to the strncat builtin.
3648 Return 0 if we failed the caller should emit a normal call,
3649 otherwise try to get the result in TARGET, if convenient. */
3650
3651static rtx
3652expand_builtin_strncat (tree arglist, rtx target, enum machine_mode mode)
3653{
4008 }
4009
4010 return 0;
4011 }
4012}
4013
4014/* Expand expression EXP, which is a call to the strncat builtin.
4015 Return 0 if we failed the caller should emit a normal call,
4016 otherwise try to get the result in TARGET, if convenient. */
4017
4018static rtx
4019expand_builtin_strncat (tree arglist, rtx target, enum machine_mode mode)
4020{
3654 if (!validate_arglist (arglist,
3655 POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
3656 return 0;
3657 else
4021 if (validate_arglist (arglist,
4022 POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
3658 {
4023 {
3659 tree dst = TREE_VALUE (arglist),
3660 src = TREE_VALUE (TREE_CHAIN (arglist)),
3661 len = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
3662 const char *p = c_getstr (src);
3663
3664 /* If the requested length is zero, or the src parameter string
3665 length is zero, return the dst parameter. */
3666 if (integer_zerop (len) || (p && *p == '\0'))
3667 {
3668 /* Evaluate and ignore the src and len parameters in case
3669 they have side-effects. */
3670 expand_expr (src, const0_rtx, VOIDmode, EXPAND_NORMAL);
3671 expand_expr (len, const0_rtx, VOIDmode, EXPAND_NORMAL);
3672 return expand_expr (dst, target, mode, EXPAND_NORMAL);
3673 }
3674
3675 /* If the requested len is greater than or equal to the string
3676 length, call strcat. */
3677 if (TREE_CODE (len) == INTEGER_CST && p
3678 && compare_tree_int (len, strlen (p)) >= 0)
3679 {
3680 tree newarglist
3681 = tree_cons (NULL_TREE, dst, build_tree_list (NULL_TREE, src));
3682 tree fn = implicit_built_in_decls[BUILT_IN_STRCAT];
3683
3684 /* If the replacement _DECL isn't initialized, don't do the
3685 transformation. */
3686 if (!fn)
3687 return 0;
3688
3689 return expand_expr (build_function_call_expr (fn, newarglist),
3690 target, mode, EXPAND_NORMAL);
3691 }
3692 return 0;
4024 tree result = fold_builtin_strncat (arglist);
4025 if (result)
4026 return expand_expr (result, target, mode, EXPAND_NORMAL);
3693 }
4027 }
4028 return 0;
3694}
3695
3696/* Expand expression EXP, which is a call to the strspn builtin.
3697 Return 0 if we failed the caller should emit a normal call,
3698 otherwise try to get the result in TARGET, if convenient. */
3699
3700static rtx
3701expand_builtin_strspn (tree arglist, rtx target, enum machine_mode mode)
3702{
4029}
4030
4031/* Expand expression EXP, which is a call to the strspn builtin.
4032 Return 0 if we failed the caller should emit a normal call,
4033 otherwise try to get the result in TARGET, if convenient. */
4034
4035static rtx
4036expand_builtin_strspn (tree arglist, rtx target, enum machine_mode mode)
4037{
3703 if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
3704 return 0;
3705 else
4038 if (validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
3706 {
4039 {
3707 tree s1 = TREE_VALUE (arglist), s2 = TREE_VALUE (TREE_CHAIN (arglist));
3708 const char *p1 = c_getstr (s1), *p2 = c_getstr (s2);
3709
3710 /* If both arguments are constants, evaluate at compile-time. */
3711 if (p1 && p2)
3712 {
3713 const size_t r = strspn (p1, p2);
3714 return expand_expr (size_int (r), target, mode, EXPAND_NORMAL);
3715 }
3716
3717 /* If either argument is "", return 0. */
3718 if ((p1 && *p1 == '\0') || (p2 && *p2 == '\0'))
3719 {
3720 /* Evaluate and ignore both arguments in case either one has
3721 side-effects. */
3722 expand_expr (s1, const0_rtx, VOIDmode, EXPAND_NORMAL);
3723 expand_expr (s2, const0_rtx, VOIDmode, EXPAND_NORMAL);
3724 return const0_rtx;
3725 }
3726 return 0;
4040 tree result = fold_builtin_strspn (arglist);
4041 if (result)
4042 return expand_expr (result, target, mode, EXPAND_NORMAL);
3727 }
4043 }
4044 return 0;
3728}
3729
3730/* Expand expression EXP, which is a call to the strcspn builtin.
3731 Return 0 if we failed the caller should emit a normal call,
3732 otherwise try to get the result in TARGET, if convenient. */
3733
3734static rtx
3735expand_builtin_strcspn (tree arglist, rtx target, enum machine_mode mode)
3736{
4045}
4046
4047/* Expand expression EXP, which is a call to the strcspn builtin.
4048 Return 0 if we failed the caller should emit a normal call,
4049 otherwise try to get the result in TARGET, if convenient. */
4050
4051static rtx
4052expand_builtin_strcspn (tree arglist, rtx target, enum machine_mode mode)
4053{
3737 if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
3738 return 0;
3739 else
4054 if (validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
3740 {
4055 {
3741 tree s1 = TREE_VALUE (arglist), s2 = TREE_VALUE (TREE_CHAIN (arglist));
3742 const char *p1 = c_getstr (s1), *p2 = c_getstr (s2);
3743
3744 /* If both arguments are constants, evaluate at compile-time. */
3745 if (p1 && p2)
3746 {
3747 const size_t r = strcspn (p1, p2);
3748 return expand_expr (size_int (r), target, mode, EXPAND_NORMAL);
3749 }
3750
3751 /* If the first argument is "", return 0. */
3752 if (p1 && *p1 == '\0')
3753 {
3754 /* Evaluate and ignore argument s2 in case it has
3755 side-effects. */
3756 expand_expr (s2, const0_rtx, VOIDmode, EXPAND_NORMAL);
3757 return const0_rtx;
3758 }
3759
3760 /* If the second argument is "", return __builtin_strlen(s1). */
3761 if (p2 && *p2 == '\0')
3762 {
3763 tree newarglist = build_tree_list (NULL_TREE, s1),
3764 fn = implicit_built_in_decls[BUILT_IN_STRLEN];
3765
3766 /* If the replacement _DECL isn't initialized, don't do the
3767 transformation. */
3768 if (!fn)
3769 return 0;
3770
3771 return expand_expr (build_function_call_expr (fn, newarglist),
3772 target, mode, EXPAND_NORMAL);
3773 }
3774 return 0;
4056 tree result = fold_builtin_strcspn (arglist);
4057 if (result)
4058 return expand_expr (result, target, mode, EXPAND_NORMAL);
3775 }
4059 }
4060 return 0;
3776}
3777
3778/* Expand a call to __builtin_saveregs, generating the result in TARGET,
3779 if that's convenient. */
3780
3781rtx
3782expand_builtin_saveregs (void)
3783{

--- 17 unchanged lines hidden (view full) ---

3801 end_sequence ();
3802
3803 saveregs_value = val;
3804
3805 /* Put the insns after the NOTE that starts the function. If this
3806 is inside a start_sequence, make the outer-level insn chain current, so
3807 the code is placed at the start of the function. */
3808 push_topmost_sequence ();
4061}
4062
4063/* Expand a call to __builtin_saveregs, generating the result in TARGET,
4064 if that's convenient. */
4065
4066rtx
4067expand_builtin_saveregs (void)
4068{

--- 17 unchanged lines hidden (view full) ---

4086 end_sequence ();
4087
4088 saveregs_value = val;
4089
4090 /* Put the insns after the NOTE that starts the function. If this
4091 is inside a start_sequence, make the outer-level insn chain current, so
4092 the code is placed at the start of the function. */
4093 push_topmost_sequence ();
3809 emit_insn_after (seq, get_insns ());
4094 emit_insn_after (seq, entry_of_function ());
3810 pop_topmost_sequence ();
3811
3812 return val;
3813}
3814
3815/* __builtin_args_info (N) returns word N of the arg space info
3816 for the current function. The number and meanings of words
3817 is controlled by the definition of CUMULATIVE_ARGS. */
3818
3819static rtx
3820expand_builtin_args_info (tree arglist)
3821{
3822 int nwords = sizeof (CUMULATIVE_ARGS) / sizeof (int);
3823 int *word_ptr = (int *) &current_function_args_info;
3824
4095 pop_topmost_sequence ();
4096
4097 return val;
4098}
4099
4100/* __builtin_args_info (N) returns word N of the arg space info
4101 for the current function. The number and meanings of words
4102 is controlled by the definition of CUMULATIVE_ARGS. */
4103
4104static rtx
4105expand_builtin_args_info (tree arglist)
4106{
4107 int nwords = sizeof (CUMULATIVE_ARGS) / sizeof (int);
4108 int *word_ptr = (int *) &current_function_args_info;
4109
3825 if (sizeof (CUMULATIVE_ARGS) % sizeof (int) != 0)
3826 abort ();
4110 gcc_assert (sizeof (CUMULATIVE_ARGS) % sizeof (int) == 0);
3827
3828 if (arglist != 0)
3829 {
3830 if (!host_integerp (TREE_VALUE (arglist), 0))
4111
4112 if (arglist != 0)
4113 {
4114 if (!host_integerp (TREE_VALUE (arglist), 0))
3831 error ("argument of `__builtin_args_info' must be constant");
4115 error ("argument of %<__builtin_args_info%> must be constant");
3832 else
3833 {
3834 HOST_WIDE_INT wordnum = tree_low_cst (TREE_VALUE (arglist), 0);
3835
3836 if (wordnum < 0 || wordnum >= nwords)
4116 else
4117 {
4118 HOST_WIDE_INT wordnum = tree_low_cst (TREE_VALUE (arglist), 0);
4119
4120 if (wordnum < 0 || wordnum >= nwords)
3837 error ("argument of `__builtin_args_info' out of range");
4121 error ("argument of %<__builtin_args_info%> out of range");
3838 else
3839 return GEN_INT (word_ptr[wordnum]);
3840 }
3841 }
3842 else
4122 else
4123 return GEN_INT (word_ptr[wordnum]);
4124 }
4125 }
4126 else
3843 error ("missing argument in `__builtin_args_info'");
4127 error ("missing argument in %<__builtin_args_info%>");
3844
3845 return const0_rtx;
3846}
3847
4128
4129 return const0_rtx;
4130}
4131
3848/* Expand ARGLIST, from a call to __builtin_next_arg. */
4132/* Expand a call to __builtin_next_arg. */
3849
3850static rtx
4133
4134static rtx
3851expand_builtin_next_arg (tree arglist)
4135expand_builtin_next_arg (void)
3852{
4136{
3853 tree fntype = TREE_TYPE (current_function_decl);
3854
3855 if (TYPE_ARG_TYPES (fntype) == 0
3856 || (TREE_VALUE (tree_last (TYPE_ARG_TYPES (fntype)))
3857 == void_type_node))
3858 {
3859 error ("`va_start' used in function with fixed args");
3860 return const0_rtx;
3861 }
3862
3863 if (arglist)
3864 {
3865 tree last_parm = tree_last (DECL_ARGUMENTS (current_function_decl));
3866 tree arg = TREE_VALUE (arglist);
3867
3868 /* Strip off all nops for the sake of the comparison. This
3869 is not quite the same as STRIP_NOPS. It does more.
3870 We must also strip off INDIRECT_EXPR for C++ reference
3871 parameters. */
3872 while (TREE_CODE (arg) == NOP_EXPR
3873 || TREE_CODE (arg) == CONVERT_EXPR
3874 || TREE_CODE (arg) == NON_LVALUE_EXPR
3875 || TREE_CODE (arg) == INDIRECT_REF)
3876 arg = TREE_OPERAND (arg, 0);
3877 if (arg != last_parm)
3878 warning ("second parameter of `va_start' not last named argument");
3879 }
3880 else
3881 /* Evidently an out of date version of <stdarg.h>; can't validate
3882 va_start's second argument, but can still work as intended. */
3883 warning ("`__builtin_next_arg' called without an argument");
3884
4137 /* Checking arguments is already done in fold_builtin_next_arg
4138 that must be called before this function. */
3885 return expand_binop (Pmode, add_optab,
3886 current_function_internal_arg_pointer,
3887 current_function_arg_offset_rtx,
3888 NULL_RTX, 0, OPTAB_LIB_WIDEN);
3889}
3890
3891/* Make it easier for the backends by protecting the valist argument
3892 from multiple evaluations. */

--- 8 unchanged lines hidden (view full) ---

3901
3902 /* For this case, the backends will be expecting a pointer to
3903 TREE_TYPE (va_list_type_node), but it's possible we've
3904 actually been given an array (an actual va_list_type_node).
3905 So fix it. */
3906 if (TREE_CODE (TREE_TYPE (valist)) == ARRAY_TYPE)
3907 {
3908 tree p1 = build_pointer_type (TREE_TYPE (va_list_type_node));
4139 return expand_binop (Pmode, add_optab,
4140 current_function_internal_arg_pointer,
4141 current_function_arg_offset_rtx,
4142 NULL_RTX, 0, OPTAB_LIB_WIDEN);
4143}
4144
4145/* Make it easier for the backends by protecting the valist argument
4146 from multiple evaluations. */

--- 8 unchanged lines hidden (view full) ---

4155
4156 /* For this case, the backends will be expecting a pointer to
4157 TREE_TYPE (va_list_type_node), but it's possible we've
4158 actually been given an array (an actual va_list_type_node).
4159 So fix it. */
4160 if (TREE_CODE (TREE_TYPE (valist)) == ARRAY_TYPE)
4161 {
4162 tree p1 = build_pointer_type (TREE_TYPE (va_list_type_node));
3909 tree p2 = build_pointer_type (va_list_type_node);
3910
3911 valist = build1 (ADDR_EXPR, p2, valist);
3912 valist = fold (build1 (NOP_EXPR, p1, valist));
4163 valist = build_fold_addr_expr_with_type (valist, p1);
3913 }
3914 }
3915 else
3916 {
3917 tree pt;
3918
3919 if (! needs_lvalue)
3920 {
3921 if (! TREE_SIDE_EFFECTS (valist))
3922 return valist;
3923
3924 pt = build_pointer_type (va_list_type_node);
4164 }
4165 }
4166 else
4167 {
4168 tree pt;
4169
4170 if (! needs_lvalue)
4171 {
4172 if (! TREE_SIDE_EFFECTS (valist))
4173 return valist;
4174
4175 pt = build_pointer_type (va_list_type_node);
3925 valist = fold (build1 (ADDR_EXPR, pt, valist));
4176 valist = fold_build1 (ADDR_EXPR, pt, valist);
3926 TREE_SIDE_EFFECTS (valist) = 1;
3927 }
3928
3929 if (TREE_SIDE_EFFECTS (valist))
3930 valist = save_expr (valist);
4177 TREE_SIDE_EFFECTS (valist) = 1;
4178 }
4179
4180 if (TREE_SIDE_EFFECTS (valist))
4181 valist = save_expr (valist);
3931 valist = fold (build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (valist)),
3932 valist));
4182 valist = build_fold_indirect_ref (valist);
3933 }
3934
3935 return valist;
3936}
3937
3938/* The "standard" definition of va_list is void*. */
3939
3940tree

--- 5 unchanged lines hidden (view full) ---

3946/* The "standard" implementation of va_start: just assign `nextarg' to
3947 the variable. */
3948
3949void
3950std_expand_builtin_va_start (tree valist, rtx nextarg)
3951{
3952 tree t;
3953
4183 }
4184
4185 return valist;
4186}
4187
4188/* The "standard" definition of va_list is void*. */
4189
4190tree

--- 5 unchanged lines hidden (view full) ---

4196/* The "standard" implementation of va_start: just assign `nextarg' to
4197 the variable. */
4198
4199void
4200std_expand_builtin_va_start (tree valist, rtx nextarg)
4201{
4202 tree t;
4203
3954 t = build (MODIFY_EXPR, TREE_TYPE (valist), valist,
3955 make_tree (ptr_type_node, nextarg));
4204 t = build2 (MODIFY_EXPR, TREE_TYPE (valist), valist,
4205 make_tree (ptr_type_node, nextarg));
3956 TREE_SIDE_EFFECTS (t) = 1;
3957
3958 expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
3959}
3960
3961/* Expand ARGLIST, from a call to __builtin_va_start. */
3962
3963static rtx
3964expand_builtin_va_start (tree arglist)
3965{
3966 rtx nextarg;
3967 tree chain, valist;
3968
3969 chain = TREE_CHAIN (arglist);
3970
4206 TREE_SIDE_EFFECTS (t) = 1;
4207
4208 expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
4209}
4210
4211/* Expand ARGLIST, from a call to __builtin_va_start. */
4212
4213static rtx
4214expand_builtin_va_start (tree arglist)
4215{
4216 rtx nextarg;
4217 tree chain, valist;
4218
4219 chain = TREE_CHAIN (arglist);
4220
3971 if (TREE_CHAIN (chain))
3972 error ("too many arguments to function `va_start'");
4221 if (!chain)
4222 {
4223 error ("too few arguments to function %<va_start%>");
4224 return const0_rtx;
4225 }
3973
4226
3974 nextarg = expand_builtin_next_arg (chain);
4227 if (fold_builtin_next_arg (chain))
4228 return const0_rtx;
4229
4230 nextarg = expand_builtin_next_arg ();
3975 valist = stabilize_va_list (TREE_VALUE (arglist), 1);
3976
3977#ifdef EXPAND_BUILTIN_VA_START
3978 EXPAND_BUILTIN_VA_START (valist, nextarg);
3979#else
3980 std_expand_builtin_va_start (valist, nextarg);
3981#endif
3982
3983 return const0_rtx;
3984}
3985
3986/* The "standard" implementation of va_arg: read the value from the
3987 current (padded) address and increment by the (padded) size. */
3988
4231 valist = stabilize_va_list (TREE_VALUE (arglist), 1);
4232
4233#ifdef EXPAND_BUILTIN_VA_START
4234 EXPAND_BUILTIN_VA_START (valist, nextarg);
4235#else
4236 std_expand_builtin_va_start (valist, nextarg);
4237#endif
4238
4239 return const0_rtx;
4240}
4241
4242/* The "standard" implementation of va_arg: read the value from the
4243 current (padded) address and increment by the (padded) size. */
4244
3989rtx
3990std_expand_builtin_va_arg (tree valist, tree type)
4245tree
4246std_gimplify_va_arg_expr (tree valist, tree type, tree *pre_p, tree *post_p)
3991{
4247{
3992 tree addr_tree, t, type_size = NULL;
3993 tree align, alignm1;
3994 tree rounded_size;
3995 rtx addr;
3996 HOST_WIDE_INT boundary;
4248 tree addr, t, type_size, rounded_size, valist_tmp;
4249 unsigned HOST_WIDE_INT align, boundary;
4250 bool indirect;
3997
4251
3998 /* Compute the rounded size of the type. */
3999 align = size_int (PARM_BOUNDARY / BITS_PER_UNIT);
4000 alignm1 = size_int (PARM_BOUNDARY / BITS_PER_UNIT - 1);
4001 boundary = FUNCTION_ARG_BOUNDARY (TYPE_MODE (type), type);
4252#ifdef ARGS_GROW_DOWNWARD
4253 /* All of the alignment and movement below is for args-grow-up machines.
4254 As of 2004, there are only 3 ARGS_GROW_DOWNWARD targets, and they all
4255 implement their own specialized gimplify_va_arg_expr routines. */
4256 gcc_unreachable ();
4257#endif
4002
4258
4259 indirect = pass_by_reference (NULL, TYPE_MODE (type), type, false);
4260 if (indirect)
4261 type = build_pointer_type (type);
4262
4263 align = PARM_BOUNDARY / BITS_PER_UNIT;
4264 boundary = FUNCTION_ARG_BOUNDARY (TYPE_MODE (type), type) / BITS_PER_UNIT;
4265
4266 /* Hoist the valist value into a temporary for the moment. */
4267 valist_tmp = get_initialized_tmp_var (valist, pre_p, NULL);
4268
4003 /* va_list pointer is aligned to PARM_BOUNDARY. If argument actually
4004 requires greater alignment, we must perform dynamic alignment. */
4269 /* va_list pointer is aligned to PARM_BOUNDARY. If argument actually
4270 requires greater alignment, we must perform dynamic alignment. */
4005
4006 if (boundary > PARM_BOUNDARY)
4271 if (boundary > align
4272 && !integer_zerop (TYPE_SIZE (type)))
4007 {
4273 {
4008 if (!PAD_VARARGS_DOWN)
4009 {
4010 t = build (MODIFY_EXPR, TREE_TYPE (valist), valist,
4011 build (PLUS_EXPR, TREE_TYPE (valist), valist,
4012 build_int_2 (boundary / BITS_PER_UNIT - 1, 0)));
4013 TREE_SIDE_EFFECTS (t) = 1;
4014 expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
4015 }
4016 t = build (MODIFY_EXPR, TREE_TYPE (valist), valist,
4017 build (BIT_AND_EXPR, TREE_TYPE (valist), valist,
4018 build_int_2 (~(boundary / BITS_PER_UNIT - 1), -1)));
4019 TREE_SIDE_EFFECTS (t) = 1;
4020 expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
4274 t = fold_convert (TREE_TYPE (valist), size_int (boundary - 1));
4275 t = build2 (MODIFY_EXPR, TREE_TYPE (valist), valist_tmp,
4276 build2 (PLUS_EXPR, TREE_TYPE (valist), valist_tmp, t));
4277 gimplify_and_add (t, pre_p);
4278
4279 t = fold_convert (TREE_TYPE (valist), size_int (-boundary));
4280 t = build2 (MODIFY_EXPR, TREE_TYPE (valist), valist_tmp,
4281 build2 (BIT_AND_EXPR, TREE_TYPE (valist), valist_tmp, t));
4282 gimplify_and_add (t, pre_p);
4021 }
4283 }
4022 if (type == error_mark_node
4023 || (type_size = TYPE_SIZE_UNIT (TYPE_MAIN_VARIANT (type))) == NULL
4024 || TREE_OVERFLOW (type_size))
4025 rounded_size = size_zero_node;
4026 else
4284 else
4027 rounded_size = fold (build (MULT_EXPR, sizetype,
4028 fold (build (TRUNC_DIV_EXPR, sizetype,
4029 fold (build (PLUS_EXPR, sizetype,
4030 type_size, alignm1)),
4031 align)),
4032 align));
4285 boundary = align;
4033
4286
4034 /* Get AP. */
4035 addr_tree = valist;
4036 if (PAD_VARARGS_DOWN && ! integer_zerop (rounded_size))
4287 /* If the actual alignment is less than the alignment of the type,
4288 adjust the type accordingly so that we don't assume strict alignment
4289 when deferencing the pointer. */
4290 boundary *= BITS_PER_UNIT;
4291 if (boundary < TYPE_ALIGN (type))
4037 {
4292 {
4038 /* Small args are padded downward. */
4039 addr_tree = fold (build (PLUS_EXPR, TREE_TYPE (addr_tree), addr_tree,
4040 fold (build (COND_EXPR, sizetype,
4041 fold (build (GT_EXPR, sizetype,
4042 rounded_size,
4043 align)),
4044 size_zero_node,
4045 fold (build (MINUS_EXPR, sizetype,
4046 rounded_size,
4047 type_size))))));
4293 type = build_variant_type_copy (type);
4294 TYPE_ALIGN (type) = boundary;
4048 }
4049
4295 }
4296
4050 addr = expand_expr (addr_tree, NULL_RTX, Pmode, EXPAND_NORMAL);
4051 addr = copy_to_reg (addr);
4297 /* Compute the rounded size of the type. */
4298 type_size = size_in_bytes (type);
4299 rounded_size = round_up (type_size, align);
4052
4300
4053 /* Compute new value for AP. */
4054 if (! integer_zerop (rounded_size))
4301 /* Reduce rounded_size so it's sharable with the postqueue. */
4302 gimplify_expr (&rounded_size, pre_p, post_p, is_gimple_val, fb_rvalue);
4303
4304 /* Get AP. */
4305 addr = valist_tmp;
4306 if (PAD_VARARGS_DOWN && !integer_zerop (rounded_size))
4055 {
4307 {
4056 t = build (MODIFY_EXPR, TREE_TYPE (valist), valist,
4057 build (PLUS_EXPR, TREE_TYPE (valist), valist,
4058 rounded_size));
4059 TREE_SIDE_EFFECTS (t) = 1;
4060 expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
4308 /* Small args are padded downward. */
4309 t = fold_build2 (GT_EXPR, sizetype, rounded_size, size_int (align));
4310 t = fold_build3 (COND_EXPR, sizetype, t, size_zero_node,
4311 size_binop (MINUS_EXPR, rounded_size, type_size));
4312 t = fold_convert (TREE_TYPE (addr), t);
4313 addr = fold_build2 (PLUS_EXPR, TREE_TYPE (addr), addr, t);
4061 }
4062
4314 }
4315
4316 /* Compute new value for AP. */
4317 t = fold_convert (TREE_TYPE (valist), rounded_size);
4318 t = build2 (PLUS_EXPR, TREE_TYPE (valist), valist_tmp, t);
4319 t = build2 (MODIFY_EXPR, TREE_TYPE (valist), valist, t);
4320 gimplify_and_add (t, pre_p);
4321
4322 addr = fold_convert (build_pointer_type (type), addr);
4323
4324 if (indirect)
4325 addr = build_va_arg_indirect_ref (addr);
4326
4327 return build_va_arg_indirect_ref (addr);
4328}
4329
4330/* Build an indirect-ref expression over the given TREE, which represents a
4331 piece of a va_arg() expansion. */
4332tree
4333build_va_arg_indirect_ref (tree addr)
4334{
4335 addr = build_fold_indirect_ref (addr);
4336
4337 if (flag_mudflap) /* Don't instrument va_arg INDIRECT_REF. */
4338 mf_mark (addr);
4339
4063 return addr;
4064}
4065
4340 return addr;
4341}
4342
4066/* Expand __builtin_va_arg, which is not really a builtin function, but
4067 a very special sort of operator. */
4343/* Return a dummy expression of type TYPE in order to keep going after an
4344 error. */
4068
4345
4069rtx
4070expand_builtin_va_arg (tree valist, tree type)
4346static tree
4347dummy_object (tree type)
4071{
4348{
4072 rtx addr, result;
4349 tree t = build_int_cst (build_pointer_type (type), 0);
4350 return build1 (INDIRECT_REF, type, t);
4351}
4352
4353/* Gimplify __builtin_va_arg, aka VA_ARG_EXPR, which is not really a
4354 builtin function, but a very special sort of operator. */
4355
4356enum gimplify_status
4357gimplify_va_arg_expr (tree *expr_p, tree *pre_p, tree *post_p)
4358{
4073 tree promoted_type, want_va_type, have_va_type;
4359 tree promoted_type, want_va_type, have_va_type;
4360 tree valist = TREE_OPERAND (*expr_p, 0);
4361 tree type = TREE_TYPE (*expr_p);
4362 tree t;
4074
4075 /* Verify that valist is of the proper type. */
4363
4364 /* Verify that valist is of the proper type. */
4076
4077 want_va_type = va_list_type_node;
4078 have_va_type = TREE_TYPE (valist);
4365 want_va_type = va_list_type_node;
4366 have_va_type = TREE_TYPE (valist);
4367
4368 if (have_va_type == error_mark_node)
4369 return GS_ERROR;
4370
4079 if (TREE_CODE (want_va_type) == ARRAY_TYPE)
4080 {
4081 /* If va_list is an array type, the argument may have decayed
4082 to a pointer type, e.g. by being passed to another function.
4371 if (TREE_CODE (want_va_type) == ARRAY_TYPE)
4372 {
4373 /* If va_list is an array type, the argument may have decayed
4374 to a pointer type, e.g. by being passed to another function.
4083 In that case, unwrap both types so that we can compare the
4375 In that case, unwrap both types so that we can compare the
4084 underlying records. */
4085 if (TREE_CODE (have_va_type) == ARRAY_TYPE
4376 underlying records. */
4377 if (TREE_CODE (have_va_type) == ARRAY_TYPE
4086 || TREE_CODE (have_va_type) == POINTER_TYPE)
4378 || POINTER_TYPE_P (have_va_type))
4087 {
4088 want_va_type = TREE_TYPE (want_va_type);
4089 have_va_type = TREE_TYPE (have_va_type);
4090 }
4091 }
4379 {
4380 want_va_type = TREE_TYPE (want_va_type);
4381 have_va_type = TREE_TYPE (have_va_type);
4382 }
4383 }
4384
4092 if (TYPE_MAIN_VARIANT (want_va_type) != TYPE_MAIN_VARIANT (have_va_type))
4093 {
4385 if (TYPE_MAIN_VARIANT (want_va_type) != TYPE_MAIN_VARIANT (have_va_type))
4386 {
4094 error ("first argument to `va_arg' not of type `va_list'");
4095 addr = const0_rtx;
4387 error ("first argument to %<va_arg%> not of type %<va_list%>");
4388 return GS_ERROR;
4096 }
4097
4098 /* Generate a diagnostic for requesting data of a type that cannot
4099 be passed through `...' due to type promotion at the call site. */
4389 }
4390
4391 /* Generate a diagnostic for requesting data of a type that cannot
4392 be passed through `...' due to type promotion at the call site. */
4100 else if ((promoted_type = (*lang_hooks.types.type_promotes_to) (type))
4393 else if ((promoted_type = lang_hooks.types.type_promotes_to (type))
4101 != type)
4102 {
4394 != type)
4395 {
4103 const char *name = "<anonymous type>", *pname = 0;
4104 static bool gave_help;
4105
4396 static bool gave_help;
4397
4106 if (TYPE_NAME (type))
4107 {
4108 if (TREE_CODE (TYPE_NAME (type)) == IDENTIFIER_NODE)
4109 name = IDENTIFIER_POINTER (TYPE_NAME (type));
4110 else if (TREE_CODE (TYPE_NAME (type)) == TYPE_DECL
4111 && DECL_NAME (TYPE_NAME (type)))
4112 name = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (type)));
4113 }
4114 if (TYPE_NAME (promoted_type))
4115 {
4116 if (TREE_CODE (TYPE_NAME (promoted_type)) == IDENTIFIER_NODE)
4117 pname = IDENTIFIER_POINTER (TYPE_NAME (promoted_type));
4118 else if (TREE_CODE (TYPE_NAME (promoted_type)) == TYPE_DECL
4119 && DECL_NAME (TYPE_NAME (promoted_type)))
4120 pname = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (promoted_type)));
4121 }
4122
4123 /* Unfortunately, this is merely undefined, rather than a constraint
4124 violation, so we cannot make this an error. If this call is never
4125 executed, the program is still strictly conforming. */
4398 /* Unfortunately, this is merely undefined, rather than a constraint
4399 violation, so we cannot make this an error. If this call is never
4400 executed, the program is still strictly conforming. */
4126 warning ("`%s' is promoted to `%s' when passed through `...'",
4127 name, pname);
4401 warning (0, "%qT is promoted to %qT when passed through %<...%>",
4402 type, promoted_type);
4128 if (! gave_help)
4129 {
4130 gave_help = true;
4403 if (! gave_help)
4404 {
4405 gave_help = true;
4131 warning ("(so you should pass `%s' not `%s' to `va_arg')",
4132 pname, name);
4406 warning (0, "(so you should pass %qT not %qT to %<va_arg%>)",
4407 promoted_type, type);
4133 }
4134
4135 /* We can, however, treat "undefined" any way we please.
4136 Call abort to encourage the user to fix the program. */
4137 inform ("if this code is reached, the program will abort");
4408 }
4409
4410 /* We can, however, treat "undefined" any way we please.
4411 Call abort to encourage the user to fix the program. */
4412 inform ("if this code is reached, the program will abort");
4138 expand_builtin_trap ();
4413 t = build_function_call_expr (implicit_built_in_decls[BUILT_IN_TRAP],
4414 NULL);
4415 append_to_statement_list (t, pre_p);
4139
4140 /* This is dead code, but go ahead and finish so that the
4141 mode of the result comes out right. */
4416
4417 /* This is dead code, but go ahead and finish so that the
4418 mode of the result comes out right. */
4142 addr = const0_rtx;
4419 *expr_p = dummy_object (type);
4420 return GS_ALL_DONE;
4143 }
4144 else
4145 {
4146 /* Make it easier for the backends by protecting the valist argument
4421 }
4422 else
4423 {
4424 /* Make it easier for the backends by protecting the valist argument
4147 from multiple evaluations. */
4148 valist = stabilize_va_list (valist, 0);
4425 from multiple evaluations. */
4426 if (TREE_CODE (va_list_type_node) == ARRAY_TYPE)
4427 {
4428 /* For this case, the backends will be expecting a pointer to
4429 TREE_TYPE (va_list_type_node), but it's possible we've
4430 actually been given an array (an actual va_list_type_node).
4431 So fix it. */
4432 if (TREE_CODE (TREE_TYPE (valist)) == ARRAY_TYPE)
4433 {
4434 tree p1 = build_pointer_type (TREE_TYPE (va_list_type_node));
4435 valist = build_fold_addr_expr_with_type (valist, p1);
4436 }
4437 gimplify_expr (&valist, pre_p, post_p, is_gimple_val, fb_rvalue);
4438 }
4439 else
4440 gimplify_expr (&valist, pre_p, post_p, is_gimple_min_lval, fb_lvalue);
4149
4441
4150#ifdef EXPAND_BUILTIN_VA_ARG
4151 addr = EXPAND_BUILTIN_VA_ARG (valist, type);
4152#else
4153 addr = std_expand_builtin_va_arg (valist, type);
4154#endif
4155 }
4442 if (!targetm.gimplify_va_arg_expr)
4443 /* FIXME:Once most targets are converted we should merely
4444 assert this is non-null. */
4445 return GS_ALL_DONE;
4156
4446
4157 addr = convert_memory_address (Pmode, addr);
4158
4159 result = gen_rtx_MEM (TYPE_MODE (type), addr);
4160 set_mem_alias_set (result, get_varargs_alias_set ());
4161
4162 return result;
4447 *expr_p = targetm.gimplify_va_arg_expr (valist, type, pre_p, post_p);
4448 return GS_OK;
4449 }
4163}
4164
4165/* Expand ARGLIST, from a call to __builtin_va_end. */
4166
4167static rtx
4168expand_builtin_va_end (tree arglist)
4169{
4170 tree valist = TREE_VALUE (arglist);

--- 18 unchanged lines hidden (view full) ---

4189 dst = TREE_VALUE (arglist);
4190 src = TREE_VALUE (TREE_CHAIN (arglist));
4191
4192 dst = stabilize_va_list (dst, 1);
4193 src = stabilize_va_list (src, 0);
4194
4195 if (TREE_CODE (va_list_type_node) != ARRAY_TYPE)
4196 {
4450}
4451
4452/* Expand ARGLIST, from a call to __builtin_va_end. */
4453
4454static rtx
4455expand_builtin_va_end (tree arglist)
4456{
4457 tree valist = TREE_VALUE (arglist);

--- 18 unchanged lines hidden (view full) ---

4476 dst = TREE_VALUE (arglist);
4477 src = TREE_VALUE (TREE_CHAIN (arglist));
4478
4479 dst = stabilize_va_list (dst, 1);
4480 src = stabilize_va_list (src, 0);
4481
4482 if (TREE_CODE (va_list_type_node) != ARRAY_TYPE)
4483 {
4197 t = build (MODIFY_EXPR, va_list_type_node, dst, src);
4484 t = build2 (MODIFY_EXPR, va_list_type_node, dst, src);
4198 TREE_SIDE_EFFECTS (t) = 1;
4199 expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
4200 }
4201 else
4202 {
4203 rtx dstb, srcb, size;
4204
4205 /* Evaluate to pointers. */

--- 30 unchanged lines hidden (view full) ---

4236 It counts the number of frames to scan up the stack.
4237 The value is the return address saved in that frame. */
4238 if (arglist == 0)
4239 /* Warning about missing arg was already issued. */
4240 return const0_rtx;
4241 else if (! host_integerp (TREE_VALUE (arglist), 1))
4242 {
4243 if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_FRAME_ADDRESS)
4485 TREE_SIDE_EFFECTS (t) = 1;
4486 expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
4487 }
4488 else
4489 {
4490 rtx dstb, srcb, size;
4491
4492 /* Evaluate to pointers. */

--- 30 unchanged lines hidden (view full) ---

4523 It counts the number of frames to scan up the stack.
4524 The value is the return address saved in that frame. */
4525 if (arglist == 0)
4526 /* Warning about missing arg was already issued. */
4527 return const0_rtx;
4528 else if (! host_integerp (TREE_VALUE (arglist), 1))
4529 {
4530 if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_FRAME_ADDRESS)
4244 error ("invalid arg to `__builtin_frame_address'");
4531 error ("invalid argument to %<__builtin_frame_address%>");
4245 else
4532 else
4246 error ("invalid arg to `__builtin_return_address'");
4533 error ("invalid argument to %<__builtin_return_address%>");
4247 return const0_rtx;
4248 }
4249 else
4250 {
4251 rtx tem
4252 = expand_builtin_return_addr (DECL_FUNCTION_CODE (fndecl),
4534 return const0_rtx;
4535 }
4536 else
4537 {
4538 rtx tem
4539 = expand_builtin_return_addr (DECL_FUNCTION_CODE (fndecl),
4253 tree_low_cst (TREE_VALUE (arglist), 1),
4254 hard_frame_pointer_rtx);
4540 tree_low_cst (TREE_VALUE (arglist), 1));
4255
4256 /* Some ports cannot access arbitrary stack frames. */
4257 if (tem == NULL)
4258 {
4259 if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_FRAME_ADDRESS)
4541
4542 /* Some ports cannot access arbitrary stack frames. */
4543 if (tem == NULL)
4544 {
4545 if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_FRAME_ADDRESS)
4260 warning ("unsupported arg to `__builtin_frame_address'");
4546 warning (0, "unsupported argument to %<__builtin_frame_address%>");
4261 else
4547 else
4262 warning ("unsupported arg to `__builtin_return_address'");
4548 warning (0, "unsupported argument to %<__builtin_return_address%>");
4263 return const0_rtx;
4264 }
4265
4266 /* For __builtin_frame_address, return what we've got. */
4267 if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_FRAME_ADDRESS)
4268 return tem;
4269
4549 return const0_rtx;
4550 }
4551
4552 /* For __builtin_frame_address, return what we've got. */
4553 if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_FRAME_ADDRESS)
4554 return tem;
4555
4270 if (GET_CODE (tem) != REG
4556 if (!REG_P (tem)
4271 && ! CONSTANT_P (tem))
4272 tem = copy_to_mode_reg (Pmode, tem);
4273 return tem;
4274 }
4275}
4276
4277/* Expand a call to the alloca builtin, with arguments ARGLIST. Return 0 if
4278 we failed and the caller should emit a normal call, otherwise try to get
4279 the result in TARGET, if convenient. */
4280
4281static rtx
4282expand_builtin_alloca (tree arglist, rtx target)
4283{
4284 rtx op0;
4285 rtx result;
4286
4557 && ! CONSTANT_P (tem))
4558 tem = copy_to_mode_reg (Pmode, tem);
4559 return tem;
4560 }
4561}
4562
4563/* Expand a call to the alloca builtin, with arguments ARGLIST. Return 0 if
4564 we failed and the caller should emit a normal call, otherwise try to get
4565 the result in TARGET, if convenient. */
4566
4567static rtx
4568expand_builtin_alloca (tree arglist, rtx target)
4569{
4570 rtx op0;
4571 rtx result;
4572
4573 /* In -fmudflap-instrumented code, alloca() and __builtin_alloca()
4574 should always expand to function calls. These can be intercepted
4575 in libmudflap. */
4576 if (flag_mudflap)
4577 return 0;
4578
4287 if (!validate_arglist (arglist, INTEGER_TYPE, VOID_TYPE))
4288 return 0;
4289
4290 /* Compute the argument. */
4579 if (!validate_arglist (arglist, INTEGER_TYPE, VOID_TYPE))
4580 return 0;
4581
4582 /* Compute the argument. */
4291 op0 = expand_expr (TREE_VALUE (arglist), NULL_RTX, VOIDmode, 0);
4583 op0 = expand_normal (TREE_VALUE (arglist));
4292
4293 /* Allocate the desired space. */
4294 result = allocate_dynamic_stack_space (op0, target, BITS_PER_UNIT);
4295 result = convert_memory_address (ptr_mode, result);
4296
4297 return result;
4298}
4299

--- 11 unchanged lines hidden (view full) ---

4311 return 0;
4312
4313 /* Compute the argument. */
4314 op0 = expand_expr (TREE_VALUE (arglist), subtarget, VOIDmode, 0);
4315 /* Compute op, into TARGET if possible.
4316 Set TARGET to wherever the result comes back. */
4317 target = expand_unop (TYPE_MODE (TREE_TYPE (TREE_VALUE (arglist))),
4318 op_optab, op0, target, 1);
4584
4585 /* Allocate the desired space. */
4586 result = allocate_dynamic_stack_space (op0, target, BITS_PER_UNIT);
4587 result = convert_memory_address (ptr_mode, result);
4588
4589 return result;
4590}
4591

--- 11 unchanged lines hidden (view full) ---

4603 return 0;
4604
4605 /* Compute the argument. */
4606 op0 = expand_expr (TREE_VALUE (arglist), subtarget, VOIDmode, 0);
4607 /* Compute op, into TARGET if possible.
4608 Set TARGET to wherever the result comes back. */
4609 target = expand_unop (TYPE_MODE (TREE_TYPE (TREE_VALUE (arglist))),
4610 op_optab, op0, target, 1);
4319 if (target == 0)
4320 abort ();
4611 gcc_assert (target);
4321
4322 return convert_to_mode (target_mode, target, 0);
4323}
4324
4325/* If the string passed to fputs is a constant and is one character
4326 long, we attempt to transform this call into __builtin_fputc(). */
4327
4328static rtx
4329expand_builtin_fputs (tree arglist, rtx target, bool unlocked)
4330{
4612
4613 return convert_to_mode (target_mode, target, 0);
4614}
4615
4616/* If the string passed to fputs is a constant and is one character
4617 long, we attempt to transform this call into __builtin_fputc(). */
4618
4619static rtx
4620expand_builtin_fputs (tree arglist, rtx target, bool unlocked)
4621{
4331 tree len, fn;
4332 /* If we're using an unlocked function, assume the other unlocked
4333 functions exist explicitly. */
4334 tree const fn_fputc = unlocked ? built_in_decls[BUILT_IN_FPUTC_UNLOCKED]
4335 : implicit_built_in_decls[BUILT_IN_FPUTC];
4336 tree const fn_fwrite = unlocked ? built_in_decls[BUILT_IN_FWRITE_UNLOCKED]
4337 : implicit_built_in_decls[BUILT_IN_FWRITE];
4338
4339 /* If the return value is used, don't do the transformation. */
4340 if (target != const0_rtx)
4341 return 0;
4342
4343 /* Verify the arguments in the original call. */
4622 /* Verify the arguments in the original call. */
4344 if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
4345 return 0;
4346
4347 /* Get the length of the string passed to fputs. If the length
4348 can't be determined, punt. */
4349 if (!(len = c_strlen (TREE_VALUE (arglist), 1))
4350 || TREE_CODE (len) != INTEGER_CST)
4351 return 0;
4352
4353 switch (compare_tree_int (len, 1))
4623 if (validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
4354 {
4624 {
4355 case -1: /* length is 0, delete the call entirely . */
4356 {
4357 /* Evaluate and ignore the argument in case it has
4358 side-effects. */
4359 expand_expr (TREE_VALUE (TREE_CHAIN (arglist)), const0_rtx,
4360 VOIDmode, EXPAND_NORMAL);
4361 return const0_rtx;
4362 }
4363 case 0: /* length is 1, call fputc. */
4364 {
4365 const char *p = c_getstr (TREE_VALUE (arglist));
4366
4367 if (p != NULL)
4368 {
4369 /* New argument list transforming fputs(string, stream) to
4370 fputc(string[0], stream). */
4371 arglist =
4372 build_tree_list (NULL_TREE, TREE_VALUE (TREE_CHAIN (arglist)));
4373 arglist =
4374 tree_cons (NULL_TREE, build_int_2 (p[0], 0), arglist);
4375 fn = fn_fputc;
4376 break;
4377 }
4378 }
4379 /* Fall through. */
4380 case 1: /* length is greater than 1, call fwrite. */
4381 {
4382 tree string_arg;
4383
4384 /* If optimizing for size keep fputs. */
4385 if (optimize_size)
4386 return 0;
4387 string_arg = TREE_VALUE (arglist);
4388 /* New argument list transforming fputs(string, stream) to
4389 fwrite(string, 1, len, stream). */
4390 arglist = build_tree_list (NULL_TREE, TREE_VALUE (TREE_CHAIN (arglist)));
4391 arglist = tree_cons (NULL_TREE, len, arglist);
4392 arglist = tree_cons (NULL_TREE, size_one_node, arglist);
4393 arglist = tree_cons (NULL_TREE, string_arg, arglist);
4394 fn = fn_fwrite;
4395 break;
4396 }
4397 default:
4398 abort ();
4625 tree result = fold_builtin_fputs (arglist, (target == const0_rtx),
4626 unlocked, NULL_TREE);
4627 if (result)
4628 return expand_expr (result, target, VOIDmode, EXPAND_NORMAL);
4399 }
4629 }
4400
4401 /* If the replacement _DECL isn't initialized, don't do the
4402 transformation. */
4403 if (!fn)
4404 return 0;
4405
4406 return expand_expr (build_function_call_expr (fn, arglist),
4407 const0_rtx, VOIDmode, EXPAND_NORMAL);
4630 return 0;
4408}
4409
4410/* Expand a call to __builtin_expect. We return our argument and emit a
4411 NOTE_INSN_EXPECTED_VALUE note. This is the expansion of __builtin_expect in
4412 a non-jump context. */
4413
4414static rtx
4415expand_builtin_expect (tree arglist, rtx target)

--- 4 unchanged lines hidden (view full) ---

4420 if (arglist == NULL_TREE
4421 || TREE_CHAIN (arglist) == NULL_TREE)
4422 return const0_rtx;
4423 exp = TREE_VALUE (arglist);
4424 c = TREE_VALUE (TREE_CHAIN (arglist));
4425
4426 if (TREE_CODE (c) != INTEGER_CST)
4427 {
4631}
4632
4633/* Expand a call to __builtin_expect. We return our argument and emit a
4634 NOTE_INSN_EXPECTED_VALUE note. This is the expansion of __builtin_expect in
4635 a non-jump context. */
4636
4637static rtx
4638expand_builtin_expect (tree arglist, rtx target)

--- 4 unchanged lines hidden (view full) ---

4643 if (arglist == NULL_TREE
4644 || TREE_CHAIN (arglist) == NULL_TREE)
4645 return const0_rtx;
4646 exp = TREE_VALUE (arglist);
4647 c = TREE_VALUE (TREE_CHAIN (arglist));
4648
4649 if (TREE_CODE (c) != INTEGER_CST)
4650 {
4428 error ("second arg to `__builtin_expect' must be a constant");
4651 error ("second argument to %<__builtin_expect%> must be a constant");
4429 c = integer_zero_node;
4430 }
4431
4432 target = expand_expr (exp, target, VOIDmode, EXPAND_NORMAL);
4433
4434 /* Don't bother with expected value notes for integral constants. */
4435 if (flag_guess_branch_prob && GET_CODE (target) != CONST_INT)
4436 {

--- 34 unchanged lines hidden (view full) ---

4471 rtx insn, drop_through_label, temp;
4472
4473 /* Expand the jump insns. */
4474 start_sequence ();
4475 do_jump (arg0, if_false_label, if_true_label);
4476 ret = get_insns ();
4477
4478 drop_through_label = get_last_insn ();
4652 c = integer_zero_node;
4653 }
4654
4655 target = expand_expr (exp, target, VOIDmode, EXPAND_NORMAL);
4656
4657 /* Don't bother with expected value notes for integral constants. */
4658 if (flag_guess_branch_prob && GET_CODE (target) != CONST_INT)
4659 {

--- 34 unchanged lines hidden (view full) ---

4694 rtx insn, drop_through_label, temp;
4695
4696 /* Expand the jump insns. */
4697 start_sequence ();
4698 do_jump (arg0, if_false_label, if_true_label);
4699 ret = get_insns ();
4700
4701 drop_through_label = get_last_insn ();
4479 if (drop_through_label && GET_CODE (drop_through_label) == NOTE)
4702 if (drop_through_label && NOTE_P (drop_through_label))
4480 drop_through_label = prev_nonnote_insn (drop_through_label);
4703 drop_through_label = prev_nonnote_insn (drop_through_label);
4481 if (drop_through_label && GET_CODE (drop_through_label) != CODE_LABEL)
4704 if (drop_through_label && !LABEL_P (drop_through_label))
4482 drop_through_label = NULL_RTX;
4483 end_sequence ();
4484
4485 if (! if_true_label)
4486 if_true_label = drop_through_label;
4487 if (! if_false_label)
4488 if_false_label = drop_through_label;
4489
4490 /* Go through and add the expect's to each of the conditional jumps. */
4491 insn = ret;
4492 while (insn != NULL_RTX)
4493 {
4494 rtx next = NEXT_INSN (insn);
4495
4705 drop_through_label = NULL_RTX;
4706 end_sequence ();
4707
4708 if (! if_true_label)
4709 if_true_label = drop_through_label;
4710 if (! if_false_label)
4711 if_false_label = drop_through_label;
4712
4713 /* Go through and add the expect's to each of the conditional jumps. */
4714 insn = ret;
4715 while (insn != NULL_RTX)
4716 {
4717 rtx next = NEXT_INSN (insn);
4718
4496 if (GET_CODE (insn) == JUMP_INSN && any_condjump_p (insn))
4719 if (JUMP_P (insn) && any_condjump_p (insn))
4497 {
4498 rtx ifelse = SET_SRC (pc_set (insn));
4499 rtx then_dest = XEXP (ifelse, 1);
4500 rtx else_dest = XEXP (ifelse, 2);
4501 int taken = -1;
4502
4503 /* First check if we recognize any of the labels. */
4504 if (GET_CODE (then_dest) == LABEL_REF

--- 6 unchanged lines hidden (view full) ---

4511 && XEXP (else_dest, 0) == if_false_label)
4512 taken = 1;
4513 else if (GET_CODE (else_dest) == LABEL_REF
4514 && XEXP (else_dest, 0) == if_true_label)
4515 taken = 0;
4516 /* Otherwise check where we drop through. */
4517 else if (else_dest == pc_rtx)
4518 {
4720 {
4721 rtx ifelse = SET_SRC (pc_set (insn));
4722 rtx then_dest = XEXP (ifelse, 1);
4723 rtx else_dest = XEXP (ifelse, 2);
4724 int taken = -1;
4725
4726 /* First check if we recognize any of the labels. */
4727 if (GET_CODE (then_dest) == LABEL_REF

--- 6 unchanged lines hidden (view full) ---

4734 && XEXP (else_dest, 0) == if_false_label)
4735 taken = 1;
4736 else if (GET_CODE (else_dest) == LABEL_REF
4737 && XEXP (else_dest, 0) == if_true_label)
4738 taken = 0;
4739 /* Otherwise check where we drop through. */
4740 else if (else_dest == pc_rtx)
4741 {
4519 if (next && GET_CODE (next) == NOTE)
4742 if (next && NOTE_P (next))
4520 next = next_nonnote_insn (next);
4521
4743 next = next_nonnote_insn (next);
4744
4522 if (next && GET_CODE (next) == JUMP_INSN
4745 if (next && JUMP_P (next)
4523 && any_uncondjump_p (next))
4524 temp = XEXP (SET_SRC (pc_set (next)), 0);
4525 else
4526 temp = next;
4527
4528 /* TEMP is either a CODE_LABEL, NULL_RTX or something
4529 else that can't possibly match either target label. */
4530 if (temp == if_false_label)
4531 taken = 1;
4532 else if (temp == if_true_label)
4533 taken = 0;
4534 }
4535 else if (then_dest == pc_rtx)
4536 {
4746 && any_uncondjump_p (next))
4747 temp = XEXP (SET_SRC (pc_set (next)), 0);
4748 else
4749 temp = next;
4750
4751 /* TEMP is either a CODE_LABEL, NULL_RTX or something
4752 else that can't possibly match either target label. */
4753 if (temp == if_false_label)
4754 taken = 1;
4755 else if (temp == if_true_label)
4756 taken = 0;
4757 }
4758 else if (then_dest == pc_rtx)
4759 {
4537 if (next && GET_CODE (next) == NOTE)
4760 if (next && NOTE_P (next))
4538 next = next_nonnote_insn (next);
4539
4761 next = next_nonnote_insn (next);
4762
4540 if (next && GET_CODE (next) == JUMP_INSN
4763 if (next && JUMP_P (next)
4541 && any_uncondjump_p (next))
4542 temp = XEXP (SET_SRC (pc_set (next)), 0);
4543 else
4544 temp = next;
4545
4546 if (temp == if_false_label)
4547 taken = 0;
4548 else if (temp == if_true_label)
4549 taken = 1;
4550 }
4551
4552 if (taken != -1)
4553 {
4554 /* If the test is expected to fail, reverse the
4555 probabilities. */
4556 if (integer_zerop (arg1))
4557 taken = 1 - taken;
4764 && any_uncondjump_p (next))
4765 temp = XEXP (SET_SRC (pc_set (next)), 0);
4766 else
4767 temp = next;
4768
4769 if (temp == if_false_label)
4770 taken = 0;
4771 else if (temp == if_true_label)
4772 taken = 1;
4773 }
4774
4775 if (taken != -1)
4776 {
4777 /* If the test is expected to fail, reverse the
4778 probabilities. */
4779 if (integer_zerop (arg1))
4780 taken = 1 - taken;
4558 predict_insn_def (insn, PRED_BUILTIN_EXPECT, taken);
4781 predict_insn_def (insn, PRED_BUILTIN_EXPECT, taken);
4559 }
4560 }
4561
4562 insn = next;
4563 }
4564 }
4565
4566 return ret;

--- 28 unchanged lines hidden (view full) ---

4595 return 0;
4596
4597 arg = TREE_VALUE (arglist);
4598 mode = TYPE_MODE (TREE_TYPE (arg));
4599 op0 = expand_expr (arg, subtarget, VOIDmode, 0);
4600 return expand_abs (mode, op0, target, 0, safe_from_p (target, arg, 1));
4601}
4602
4782 }
4783 }
4784
4785 insn = next;
4786 }
4787 }
4788
4789 return ret;

--- 28 unchanged lines hidden (view full) ---

4818 return 0;
4819
4820 arg = TREE_VALUE (arglist);
4821 mode = TYPE_MODE (TREE_TYPE (arg));
4822 op0 = expand_expr (arg, subtarget, VOIDmode, 0);
4823 return expand_abs (mode, op0, target, 0, safe_from_p (target, arg, 1));
4824}
4825
4603/* Expand a call to cabs, cabsf or cabsl with arguments ARGLIST.
4604 Return 0 if a normal call should be emitted rather than expanding
4605 the function inline. If convenient, the result should be placed
4606 in target. */
4826/* Expand a call to copysign, copysignf, or copysignl with arguments ARGLIST.
4827 Return NULL is a normal call should be emitted rather than expanding the
4828 function inline. If convenient, the result should be placed in TARGET.
4829 SUBTARGET may be used as the target for computing the operand. */
4607
4608static rtx
4830
4831static rtx
4609expand_builtin_cabs (tree arglist, rtx target)
4832expand_builtin_copysign (tree arglist, rtx target, rtx subtarget)
4610{
4833{
4611 enum machine_mode mode;
4834 rtx op0, op1;
4612 tree arg;
4835 tree arg;
4613 rtx op0;
4614
4836
4615 if (arglist == 0 || TREE_CHAIN (arglist))
4837 if (!validate_arglist (arglist, REAL_TYPE, REAL_TYPE, VOID_TYPE))
4616 return 0;
4838 return 0;
4839
4617 arg = TREE_VALUE (arglist);
4840 arg = TREE_VALUE (arglist);
4618 if (TREE_CODE (TREE_TYPE (arg)) != COMPLEX_TYPE
4619 || TREE_CODE (TREE_TYPE (TREE_TYPE (arg))) != REAL_TYPE)
4620 return 0;
4841 op0 = expand_expr (arg, subtarget, VOIDmode, EXPAND_NORMAL);
4621
4842
4622 mode = TYPE_MODE (TREE_TYPE (arg));
4623 op0 = expand_expr (arg, NULL_RTX, VOIDmode, 0);
4624 return expand_complex_abs (mode, op0, target, 0);
4843 arg = TREE_VALUE (TREE_CHAIN (arglist));
4844 op1 = expand_normal (arg);
4845
4846 return expand_copysign (op0, op1, target);
4625}
4626
4627/* Create a new constant string literal and return a char* pointer to it.
4628 The STRING_CST value is the LEN characters at STR. */
4847}
4848
4849/* Create a new constant string literal and return a char* pointer to it.
4850 The STRING_CST value is the LEN characters at STR. */
4629static tree
4851tree
4630build_string_literal (int len, const char *str)
4631{
4632 tree t, elem, index, type;
4633
4634 t = build_string (len, str);
4635 elem = build_type_variant (char_type_node, 1, 0);
4852build_string_literal (int len, const char *str)
4853{
4854 tree t, elem, index, type;
4855
4856 t = build_string (len, str);
4857 elem = build_type_variant (char_type_node, 1, 0);
4636 index = build_index_type (build_int_2 (len - 1, 0));
4858 index = build_index_type (build_int_cst (NULL_TREE, len - 1));
4637 type = build_array_type (elem, index);
4638 TREE_TYPE (t) = type;
4639 TREE_CONSTANT (t) = 1;
4859 type = build_array_type (elem, index);
4860 TREE_TYPE (t) = type;
4861 TREE_CONSTANT (t) = 1;
4862 TREE_INVARIANT (t) = 1;
4640 TREE_READONLY (t) = 1;
4641 TREE_STATIC (t) = 1;
4642
4643 type = build_pointer_type (type);
4644 t = build1 (ADDR_EXPR, type, t);
4645
4646 type = build_pointer_type (elem);
4647 t = build1 (NOP_EXPR, type, t);
4648 return t;
4649}
4650
4863 TREE_READONLY (t) = 1;
4864 TREE_STATIC (t) = 1;
4865
4866 type = build_pointer_type (type);
4867 t = build1 (ADDR_EXPR, type, t);
4868
4869 type = build_pointer_type (elem);
4870 t = build1 (NOP_EXPR, type, t);
4871 return t;
4872}
4873
4651/* Expand a call to printf or printf_unlocked with argument list ARGLIST.
4874/* Expand EXP, a call to printf or printf_unlocked.
4652 Return 0 if a normal call should be emitted rather than transforming
4653 the function inline. If convenient, the result should be placed in
4875 Return 0 if a normal call should be emitted rather than transforming
4876 the function inline. If convenient, the result should be placed in
4654 TARGET with mode MODE. UNLOCKED indicates this is a printf_unlocked
4877 TARGET with mode MODE. UNLOCKED indicates this is a printf_unlocked
4655 call. */
4656static rtx
4878 call. */
4879static rtx
4657expand_builtin_printf (tree arglist, rtx target, enum machine_mode mode,
4880expand_builtin_printf (tree exp, rtx target, enum machine_mode mode,
4658 bool unlocked)
4659{
4881 bool unlocked)
4882{
4883 tree arglist = TREE_OPERAND (exp, 1);
4660 /* If we're using an unlocked function, assume the other unlocked
4661 functions exist explicitly. */
4662 tree const fn_putchar = unlocked ? built_in_decls[BUILT_IN_PUTCHAR_UNLOCKED]
4663 : implicit_built_in_decls[BUILT_IN_PUTCHAR];
4664 tree const fn_puts = unlocked ? built_in_decls[BUILT_IN_PUTS_UNLOCKED]
4665 : implicit_built_in_decls[BUILT_IN_PUTS];
4666 const char *fmt_str;
4667 tree fn, fmt, arg;
4668
4669 /* If the return value is used, don't do the transformation. */
4670 if (target != const0_rtx)
4671 return 0;
4672
4673 /* Verify the required arguments in the original call. */
4674 if (! arglist)
4675 return 0;
4676 fmt = TREE_VALUE (arglist);
4884 /* If we're using an unlocked function, assume the other unlocked
4885 functions exist explicitly. */
4886 tree const fn_putchar = unlocked ? built_in_decls[BUILT_IN_PUTCHAR_UNLOCKED]
4887 : implicit_built_in_decls[BUILT_IN_PUTCHAR];
4888 tree const fn_puts = unlocked ? built_in_decls[BUILT_IN_PUTS_UNLOCKED]
4889 : implicit_built_in_decls[BUILT_IN_PUTS];
4890 const char *fmt_str;
4891 tree fn, fmt, arg;
4892
4893 /* If the return value is used, don't do the transformation. */
4894 if (target != const0_rtx)
4895 return 0;
4896
4897 /* Verify the required arguments in the original call. */
4898 if (! arglist)
4899 return 0;
4900 fmt = TREE_VALUE (arglist);
4677 if (TREE_CODE (TREE_TYPE (fmt)) != POINTER_TYPE)
4901 if (! POINTER_TYPE_P (TREE_TYPE (fmt)))
4678 return 0;
4679 arglist = TREE_CHAIN (arglist);
4680
4681 /* Check whether the format is a literal string constant. */
4682 fmt_str = c_getstr (fmt);
4683 if (fmt_str == NULL)
4684 return 0;
4685
4902 return 0;
4903 arglist = TREE_CHAIN (arglist);
4904
4905 /* Check whether the format is a literal string constant. */
4906 fmt_str = c_getstr (fmt);
4907 if (fmt_str == NULL)
4908 return 0;
4909
4910 if (!init_target_chars())
4911 return 0;
4912
4686 /* If the format specifier was "%s\n", call __builtin_puts(arg). */
4913 /* If the format specifier was "%s\n", call __builtin_puts(arg). */
4687 if (strcmp (fmt_str, "%s\n") == 0)
4914 if (strcmp (fmt_str, target_percent_s_newline) == 0)
4688 {
4689 if (! arglist
4915 {
4916 if (! arglist
4690 || TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))) != POINTER_TYPE
4917 || ! POINTER_TYPE_P (TREE_TYPE (TREE_VALUE (arglist)))
4691 || TREE_CHAIN (arglist))
4692 return 0;
4693 fn = fn_puts;
4694 }
4695 /* If the format specifier was "%c", call __builtin_putchar(arg). */
4918 || TREE_CHAIN (arglist))
4919 return 0;
4920 fn = fn_puts;
4921 }
4922 /* If the format specifier was "%c", call __builtin_putchar(arg). */
4696 else if (strcmp (fmt_str, "%c") == 0)
4923 else if (strcmp (fmt_str, target_percent_c) == 0)
4697 {
4698 if (! arglist
4699 || TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))) != INTEGER_TYPE
4700 || TREE_CHAIN (arglist))
4701 return 0;
4702 fn = fn_putchar;
4703 }
4704 else
4705 {
4706 /* We can't handle anything else with % args or %% ... yet. */
4924 {
4925 if (! arglist
4926 || TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))) != INTEGER_TYPE
4927 || TREE_CHAIN (arglist))
4928 return 0;
4929 fn = fn_putchar;
4930 }
4931 else
4932 {
4933 /* We can't handle anything else with % args or %% ... yet. */
4707 if (strchr (fmt_str, '%'))
4708 return 0;
4934 if (strchr (fmt_str, target_percent))
4935 return 0;
4709
4710 if (arglist)
4711 return 0;
4712
4713 /* If the format specifier was "", printf does nothing. */
4714 if (fmt_str[0] == '\0')
4715 return const0_rtx;
4716 /* If the format specifier has length of 1, call putchar. */
4717 if (fmt_str[1] == '\0')
4718 {
4719 /* Given printf("c"), (where c is any one character,)
4720 convert "c"[0] to an int and pass that to the replacement
4721 function. */
4936
4937 if (arglist)
4938 return 0;
4939
4940 /* If the format specifier was "", printf does nothing. */
4941 if (fmt_str[0] == '\0')
4942 return const0_rtx;
4943 /* If the format specifier has length of 1, call putchar. */
4944 if (fmt_str[1] == '\0')
4945 {
4946 /* Given printf("c"), (where c is any one character,)
4947 convert "c"[0] to an int and pass that to the replacement
4948 function. */
4722 arg = build_int_2 (fmt_str[0], 0);
4949 arg = build_int_cst (NULL_TREE, fmt_str[0]);
4723 arglist = build_tree_list (NULL_TREE, arg);
4724 fn = fn_putchar;
4725 }
4726 else
4727 {
4728 /* If the format specifier was "string\n", call puts("string"). */
4729 size_t len = strlen (fmt_str);
4950 arglist = build_tree_list (NULL_TREE, arg);
4951 fn = fn_putchar;
4952 }
4953 else
4954 {
4955 /* If the format specifier was "string\n", call puts("string"). */
4956 size_t len = strlen (fmt_str);
4730 if (fmt_str[len - 1] == '\n')
4957 if ((unsigned char)fmt_str[len - 1] == target_newline)
4731 {
4732 /* Create a NUL-terminated string that's one char shorter
4733 than the original, stripping off the trailing '\n'. */
4958 {
4959 /* Create a NUL-terminated string that's one char shorter
4960 than the original, stripping off the trailing '\n'. */
4734 char *newstr = (char *) alloca (len);
4961 char *newstr = alloca (len);
4735 memcpy (newstr, fmt_str, len - 1);
4736 newstr[len - 1] = 0;
4737
4738 arg = build_string_literal (len, newstr);
4739 arglist = build_tree_list (NULL_TREE, arg);
4740 fn = fn_puts;
4741 }
4742 else
4743 /* We'd like to arrange to call fputs(string,stdout) here,
4744 but we need stdout and don't have a way to get it yet. */
4745 return 0;
4746 }
4747 }
4748
4749 if (!fn)
4750 return 0;
4962 memcpy (newstr, fmt_str, len - 1);
4963 newstr[len - 1] = 0;
4964
4965 arg = build_string_literal (len, newstr);
4966 arglist = build_tree_list (NULL_TREE, arg);
4967 fn = fn_puts;
4968 }
4969 else
4970 /* We'd like to arrange to call fputs(string,stdout) here,
4971 but we need stdout and don't have a way to get it yet. */
4972 return 0;
4973 }
4974 }
4975
4976 if (!fn)
4977 return 0;
4751 return expand_expr (build_function_call_expr (fn, arglist),
4752 target, mode, EXPAND_NORMAL);
4978 fn = build_function_call_expr (fn, arglist);
4979 if (TREE_CODE (fn) == CALL_EXPR)
4980 CALL_EXPR_TAILCALL (fn) = CALL_EXPR_TAILCALL (exp);
4981 return expand_expr (fn, target, mode, EXPAND_NORMAL);
4753}
4754
4982}
4983
4755/* Expand a call to fprintf or fprintf_unlocked with argument list ARGLIST.
4984/* Expand EXP, a call to fprintf or fprintf_unlocked.
4756 Return 0 if a normal call should be emitted rather than transforming
4757 the function inline. If convenient, the result should be placed in
4985 Return 0 if a normal call should be emitted rather than transforming
4986 the function inline. If convenient, the result should be placed in
4758 TARGET with mode MODE. UNLOCKED indicates this is a fprintf_unlocked
4987 TARGET with mode MODE. UNLOCKED indicates this is a fprintf_unlocked
4759 call. */
4760static rtx
4988 call. */
4989static rtx
4761expand_builtin_fprintf (tree arglist, rtx target, enum machine_mode mode,
4762 bool unlocked)
4990expand_builtin_fprintf (tree exp, rtx target, enum machine_mode mode,
4991 bool unlocked)
4763{
4992{
4993 tree arglist = TREE_OPERAND (exp, 1);
4764 /* If we're using an unlocked function, assume the other unlocked
4765 functions exist explicitly. */
4766 tree const fn_fputc = unlocked ? built_in_decls[BUILT_IN_FPUTC_UNLOCKED]
4767 : implicit_built_in_decls[BUILT_IN_FPUTC];
4768 tree const fn_fputs = unlocked ? built_in_decls[BUILT_IN_FPUTS_UNLOCKED]
4769 : implicit_built_in_decls[BUILT_IN_FPUTS];
4770 const char *fmt_str;
4771 tree fn, fmt, fp, arg;
4772
4773 /* If the return value is used, don't do the transformation. */
4774 if (target != const0_rtx)
4775 return 0;
4776
4777 /* Verify the required arguments in the original call. */
4778 if (! arglist)
4779 return 0;
4780 fp = TREE_VALUE (arglist);
4994 /* If we're using an unlocked function, assume the other unlocked
4995 functions exist explicitly. */
4996 tree const fn_fputc = unlocked ? built_in_decls[BUILT_IN_FPUTC_UNLOCKED]
4997 : implicit_built_in_decls[BUILT_IN_FPUTC];
4998 tree const fn_fputs = unlocked ? built_in_decls[BUILT_IN_FPUTS_UNLOCKED]
4999 : implicit_built_in_decls[BUILT_IN_FPUTS];
5000 const char *fmt_str;
5001 tree fn, fmt, fp, arg;
5002
5003 /* If the return value is used, don't do the transformation. */
5004 if (target != const0_rtx)
5005 return 0;
5006
5007 /* Verify the required arguments in the original call. */
5008 if (! arglist)
5009 return 0;
5010 fp = TREE_VALUE (arglist);
4781 if (TREE_CODE (TREE_TYPE (fp)) != POINTER_TYPE)
5011 if (! POINTER_TYPE_P (TREE_TYPE (fp)))
4782 return 0;
4783 arglist = TREE_CHAIN (arglist);
4784 if (! arglist)
4785 return 0;
4786 fmt = TREE_VALUE (arglist);
5012 return 0;
5013 arglist = TREE_CHAIN (arglist);
5014 if (! arglist)
5015 return 0;
5016 fmt = TREE_VALUE (arglist);
4787 if (TREE_CODE (TREE_TYPE (fmt)) != POINTER_TYPE)
5017 if (! POINTER_TYPE_P (TREE_TYPE (fmt)))
4788 return 0;
4789 arglist = TREE_CHAIN (arglist);
4790
4791 /* Check whether the format is a literal string constant. */
4792 fmt_str = c_getstr (fmt);
4793 if (fmt_str == NULL)
4794 return 0;
4795
5018 return 0;
5019 arglist = TREE_CHAIN (arglist);
5020
5021 /* Check whether the format is a literal string constant. */
5022 fmt_str = c_getstr (fmt);
5023 if (fmt_str == NULL)
5024 return 0;
5025
5026 if (!init_target_chars())
5027 return 0;
5028
4796 /* If the format specifier was "%s", call __builtin_fputs(arg,fp). */
5029 /* If the format specifier was "%s", call __builtin_fputs(arg,fp). */
4797 if (strcmp (fmt_str, "%s") == 0)
5030 if (strcmp (fmt_str, target_percent_s) == 0)
4798 {
4799 if (! arglist
5031 {
5032 if (! arglist
4800 || TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))) != POINTER_TYPE
5033 || ! POINTER_TYPE_P (TREE_TYPE (TREE_VALUE (arglist)))
4801 || TREE_CHAIN (arglist))
4802 return 0;
4803 arg = TREE_VALUE (arglist);
4804 arglist = build_tree_list (NULL_TREE, fp);
4805 arglist = tree_cons (NULL_TREE, arg, arglist);
4806 fn = fn_fputs;
4807 }
4808 /* If the format specifier was "%c", call __builtin_fputc(arg,fp). */
5034 || TREE_CHAIN (arglist))
5035 return 0;
5036 arg = TREE_VALUE (arglist);
5037 arglist = build_tree_list (NULL_TREE, fp);
5038 arglist = tree_cons (NULL_TREE, arg, arglist);
5039 fn = fn_fputs;
5040 }
5041 /* If the format specifier was "%c", call __builtin_fputc(arg,fp). */
4809 else if (strcmp (fmt_str, "%c") == 0)
5042 else if (strcmp (fmt_str, target_percent_c) == 0)
4810 {
4811 if (! arglist
4812 || TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))) != INTEGER_TYPE
4813 || TREE_CHAIN (arglist))
4814 return 0;
4815 arg = TREE_VALUE (arglist);
4816 arglist = build_tree_list (NULL_TREE, fp);
4817 arglist = tree_cons (NULL_TREE, arg, arglist);
4818 fn = fn_fputc;
4819 }
4820 else
4821 {
4822 /* We can't handle anything else with % args or %% ... yet. */
5043 {
5044 if (! arglist
5045 || TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))) != INTEGER_TYPE
5046 || TREE_CHAIN (arglist))
5047 return 0;
5048 arg = TREE_VALUE (arglist);
5049 arglist = build_tree_list (NULL_TREE, fp);
5050 arglist = tree_cons (NULL_TREE, arg, arglist);
5051 fn = fn_fputc;
5052 }
5053 else
5054 {
5055 /* We can't handle anything else with % args or %% ... yet. */
4823 if (strchr (fmt_str, '%'))
4824 return 0;
5056 if (strchr (fmt_str, target_percent))
5057 return 0;
4825
4826 if (arglist)
4827 return 0;
4828
4829 /* If the format specifier was "", fprintf does nothing. */
4830 if (fmt_str[0] == '\0')
4831 {
4832 /* Evaluate and ignore FILE* argument for side-effects. */

--- 6 unchanged lines hidden (view full) ---

4839 builtin will take care of special cases like length == 1. */
4840 arglist = build_tree_list (NULL_TREE, fp);
4841 arglist = tree_cons (NULL_TREE, fmt, arglist);
4842 fn = fn_fputs;
4843 }
4844
4845 if (!fn)
4846 return 0;
5058
5059 if (arglist)
5060 return 0;
5061
5062 /* If the format specifier was "", fprintf does nothing. */
5063 if (fmt_str[0] == '\0')
5064 {
5065 /* Evaluate and ignore FILE* argument for side-effects. */

--- 6 unchanged lines hidden (view full) ---

5072 builtin will take care of special cases like length == 1. */
5073 arglist = build_tree_list (NULL_TREE, fp);
5074 arglist = tree_cons (NULL_TREE, fmt, arglist);
5075 fn = fn_fputs;
5076 }
5077
5078 if (!fn)
5079 return 0;
4847 return expand_expr (build_function_call_expr (fn, arglist),
4848 target, mode, EXPAND_NORMAL);
5080 fn = build_function_call_expr (fn, arglist);
5081 if (TREE_CODE (fn) == CALL_EXPR)
5082 CALL_EXPR_TAILCALL (fn) = CALL_EXPR_TAILCALL (exp);
5083 return expand_expr (fn, target, mode, EXPAND_NORMAL);
4849}
4850
4851/* Expand a call to sprintf with argument list ARGLIST. Return 0 if
4852 a normal call should be emitted rather than expanding the function
4853 inline. If convenient, the result should be placed in TARGET with
4854 mode MODE. */
4855
4856static rtx
4857expand_builtin_sprintf (tree arglist, rtx target, enum machine_mode mode)
4858{
4859 tree orig_arglist, dest, fmt;
4860 const char *fmt_str;
4861
4862 orig_arglist = arglist;
4863
4864 /* Verify the required arguments in the original call. */
4865 if (! arglist)
4866 return 0;
4867 dest = TREE_VALUE (arglist);
5084}
5085
5086/* Expand a call to sprintf with argument list ARGLIST. Return 0 if
5087 a normal call should be emitted rather than expanding the function
5088 inline. If convenient, the result should be placed in TARGET with
5089 mode MODE. */
5090
5091static rtx
5092expand_builtin_sprintf (tree arglist, rtx target, enum machine_mode mode)
5093{
5094 tree orig_arglist, dest, fmt;
5095 const char *fmt_str;
5096
5097 orig_arglist = arglist;
5098
5099 /* Verify the required arguments in the original call. */
5100 if (! arglist)
5101 return 0;
5102 dest = TREE_VALUE (arglist);
4868 if (TREE_CODE (TREE_TYPE (dest)) != POINTER_TYPE)
5103 if (! POINTER_TYPE_P (TREE_TYPE (dest)))
4869 return 0;
4870 arglist = TREE_CHAIN (arglist);
4871 if (! arglist)
4872 return 0;
4873 fmt = TREE_VALUE (arglist);
5104 return 0;
5105 arglist = TREE_CHAIN (arglist);
5106 if (! arglist)
5107 return 0;
5108 fmt = TREE_VALUE (arglist);
4874 if (TREE_CODE (TREE_TYPE (fmt)) != POINTER_TYPE)
5109 if (! POINTER_TYPE_P (TREE_TYPE (fmt)))
4875 return 0;
4876 arglist = TREE_CHAIN (arglist);
4877
4878 /* Check whether the format is a literal string constant. */
4879 fmt_str = c_getstr (fmt);
4880 if (fmt_str == NULL)
4881 return 0;
4882
5110 return 0;
5111 arglist = TREE_CHAIN (arglist);
5112
5113 /* Check whether the format is a literal string constant. */
5114 fmt_str = c_getstr (fmt);
5115 if (fmt_str == NULL)
5116 return 0;
5117
5118 if (!init_target_chars())
5119 return 0;
5120
4883 /* If the format doesn't contain % args or %%, use strcpy. */
5121 /* If the format doesn't contain % args or %%, use strcpy. */
4884 if (strchr (fmt_str, '%') == 0)
5122 if (strchr (fmt_str, target_percent) == 0)
4885 {
4886 tree fn = implicit_built_in_decls[BUILT_IN_STRCPY];
4887 tree exp;
4888
4889 if (arglist || ! fn)
4890 return 0;
4891 expand_expr (build_function_call_expr (fn, orig_arglist),
4892 const0_rtx, VOIDmode, EXPAND_NORMAL);
4893 if (target == const0_rtx)
4894 return const0_rtx;
5123 {
5124 tree fn = implicit_built_in_decls[BUILT_IN_STRCPY];
5125 tree exp;
5126
5127 if (arglist || ! fn)
5128 return 0;
5129 expand_expr (build_function_call_expr (fn, orig_arglist),
5130 const0_rtx, VOIDmode, EXPAND_NORMAL);
5131 if (target == const0_rtx)
5132 return const0_rtx;
4895 exp = build_int_2 (strlen (fmt_str), 0);
4896 exp = fold (build1 (NOP_EXPR, integer_type_node, exp));
5133 exp = build_int_cst (NULL_TREE, strlen (fmt_str));
4897 return expand_expr (exp, target, mode, EXPAND_NORMAL);
4898 }
4899 /* If the format is "%s", use strcpy if the result isn't used. */
5134 return expand_expr (exp, target, mode, EXPAND_NORMAL);
5135 }
5136 /* If the format is "%s", use strcpy if the result isn't used. */
4900 else if (strcmp (fmt_str, "%s") == 0)
5137 else if (strcmp (fmt_str, target_percent_s) == 0)
4901 {
4902 tree fn, arg, len;
4903 fn = implicit_built_in_decls[BUILT_IN_STRCPY];
4904
4905 if (! fn)
4906 return 0;
4907
4908 if (! arglist || TREE_CHAIN (arglist))
4909 return 0;
4910 arg = TREE_VALUE (arglist);
5138 {
5139 tree fn, arg, len;
5140 fn = implicit_built_in_decls[BUILT_IN_STRCPY];
5141
5142 if (! fn)
5143 return 0;
5144
5145 if (! arglist || TREE_CHAIN (arglist))
5146 return 0;
5147 arg = TREE_VALUE (arglist);
4911 if (TREE_CODE (TREE_TYPE (arg)) != POINTER_TYPE)
5148 if (! POINTER_TYPE_P (TREE_TYPE (arg)))
4912 return 0;
4913
4914 if (target != const0_rtx)
4915 {
4916 len = c_strlen (arg, 1);
4917 if (! len || TREE_CODE (len) != INTEGER_CST)
4918 return 0;
4919 }

--- 7 unchanged lines hidden (view full) ---

4927
4928 if (target == const0_rtx)
4929 return const0_rtx;
4930 return expand_expr (len, target, mode, EXPAND_NORMAL);
4931 }
4932
4933 return 0;
4934}
5149 return 0;
5150
5151 if (target != const0_rtx)
5152 {
5153 len = c_strlen (arg, 1);
5154 if (! len || TREE_CODE (len) != INTEGER_CST)
5155 return 0;
5156 }

--- 7 unchanged lines hidden (view full) ---

5164
5165 if (target == const0_rtx)
5166 return const0_rtx;
5167 return expand_expr (len, target, mode, EXPAND_NORMAL);
5168 }
5169
5170 return 0;
5171}
5172
5173/* Expand a call to either the entry or exit function profiler. */
5174
5175static rtx
5176expand_builtin_profile_func (bool exitp)
5177{
5178 rtx this, which;
5179
5180 this = DECL_RTL (current_function_decl);
5181 gcc_assert (MEM_P (this));
5182 this = XEXP (this, 0);
5183
5184 if (exitp)
5185 which = profile_function_exit_libfunc;
5186 else
5187 which = profile_function_entry_libfunc;
5188
5189 emit_library_call (which, LCT_NORMAL, VOIDmode, 2, this, Pmode,
5190 expand_builtin_return_addr (BUILT_IN_RETURN_ADDRESS,
5191 0),
5192 Pmode);
5193
5194 return const0_rtx;
5195}
5196
5197/* Given a trampoline address, make sure it satisfies TRAMPOLINE_ALIGNMENT. */
5198
5199static rtx
5200round_trampoline_addr (rtx tramp)
5201{
5202 rtx temp, addend, mask;
5203
5204 /* If we don't need too much alignment, we'll have been guaranteed
5205 proper alignment by get_trampoline_type. */
5206 if (TRAMPOLINE_ALIGNMENT <= STACK_BOUNDARY)
5207 return tramp;
5208
5209 /* Round address up to desired boundary. */
5210 temp = gen_reg_rtx (Pmode);
5211 addend = GEN_INT (TRAMPOLINE_ALIGNMENT / BITS_PER_UNIT - 1);
5212 mask = GEN_INT (-TRAMPOLINE_ALIGNMENT / BITS_PER_UNIT);
5213
5214 temp = expand_simple_binop (Pmode, PLUS, tramp, addend,
5215 temp, 0, OPTAB_LIB_WIDEN);
5216 tramp = expand_simple_binop (Pmode, AND, temp, mask,
5217 temp, 0, OPTAB_LIB_WIDEN);
5218
5219 return tramp;
5220}
5221
5222static rtx
5223expand_builtin_init_trampoline (tree arglist)
5224{
5225 tree t_tramp, t_func, t_chain;
5226 rtx r_tramp, r_func, r_chain;
5227#ifdef TRAMPOLINE_TEMPLATE
5228 rtx blktramp;
5229#endif
5230
5231 if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE,
5232 POINTER_TYPE, VOID_TYPE))
5233 return NULL_RTX;
5234
5235 t_tramp = TREE_VALUE (arglist);
5236 arglist = TREE_CHAIN (arglist);
5237 t_func = TREE_VALUE (arglist);
5238 arglist = TREE_CHAIN (arglist);
5239 t_chain = TREE_VALUE (arglist);
5240
5241 r_tramp = expand_normal (t_tramp);
5242 r_func = expand_normal (t_func);
5243 r_chain = expand_normal (t_chain);
5244
5245 /* Generate insns to initialize the trampoline. */
5246 r_tramp = round_trampoline_addr (r_tramp);
5247#ifdef TRAMPOLINE_TEMPLATE
5248 blktramp = gen_rtx_MEM (BLKmode, r_tramp);
5249 set_mem_align (blktramp, TRAMPOLINE_ALIGNMENT);
5250 emit_block_move (blktramp, assemble_trampoline_template (),
5251 GEN_INT (TRAMPOLINE_SIZE), BLOCK_OP_NORMAL);
5252#endif
5253 trampolines_created = 1;
5254 INITIALIZE_TRAMPOLINE (r_tramp, r_func, r_chain);
5255
5256 return const0_rtx;
5257}
5258
5259static rtx
5260expand_builtin_adjust_trampoline (tree arglist)
5261{
5262 rtx tramp;
5263
5264 if (!validate_arglist (arglist, POINTER_TYPE, VOID_TYPE))
5265 return NULL_RTX;
5266
5267 tramp = expand_normal (TREE_VALUE (arglist));
5268 tramp = round_trampoline_addr (tramp);
5269#ifdef TRAMPOLINE_ADJUST_ADDRESS
5270 TRAMPOLINE_ADJUST_ADDRESS (tramp);
5271#endif
5272
5273 return tramp;
5274}
5275
5276/* Expand a call to the built-in signbit, signbitf or signbitl function.
5277 Return NULL_RTX if a normal call should be emitted rather than expanding
5278 the function in-line. EXP is the expression that is a call to the builtin
5279 function; if convenient, the result should be placed in TARGET. */
5280
5281static rtx
5282expand_builtin_signbit (tree exp, rtx target)
5283{
5284 const struct real_format *fmt;
5285 enum machine_mode fmode, imode, rmode;
5286 HOST_WIDE_INT hi, lo;
5287 tree arg, arglist;
5288 int word, bitpos;
5289 rtx temp;
5290
5291 arglist = TREE_OPERAND (exp, 1);
5292 if (!validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
5293 return 0;
5294
5295 arg = TREE_VALUE (arglist);
5296 fmode = TYPE_MODE (TREE_TYPE (arg));
5297 rmode = TYPE_MODE (TREE_TYPE (exp));
5298 fmt = REAL_MODE_FORMAT (fmode);
5299
5300 /* For floating point formats without a sign bit, implement signbit
5301 as "ARG < 0.0". */
5302 bitpos = fmt->signbit_ro;
5303 if (bitpos < 0)
5304 {
5305 /* But we can't do this if the format supports signed zero. */
5306 if (fmt->has_signed_zero && HONOR_SIGNED_ZEROS (fmode))
5307 return 0;
5308
5309 arg = fold_build2 (LT_EXPR, TREE_TYPE (exp), arg,
5310 build_real (TREE_TYPE (arg), dconst0));
5311 return expand_expr (arg, target, VOIDmode, EXPAND_NORMAL);
5312 }
5313
5314 temp = expand_normal (arg);
5315 if (GET_MODE_SIZE (fmode) <= UNITS_PER_WORD)
5316 {
5317 imode = int_mode_for_mode (fmode);
5318 if (imode == BLKmode)
5319 return 0;
5320 temp = gen_lowpart (imode, temp);
5321 }
5322 else
5323 {
5324 imode = word_mode;
5325 /* Handle targets with different FP word orders. */
5326 if (FLOAT_WORDS_BIG_ENDIAN)
5327 word = (GET_MODE_BITSIZE (fmode) - bitpos) / BITS_PER_WORD;
5328 else
5329 word = bitpos / BITS_PER_WORD;
5330 temp = operand_subword_force (temp, word, fmode);
5331 bitpos = bitpos % BITS_PER_WORD;
5332 }
5333
5334 /* Force the intermediate word_mode (or narrower) result into a
5335 register. This avoids attempting to create paradoxical SUBREGs
5336 of floating point modes below. */
5337 temp = force_reg (imode, temp);
5338
5339 /* If the bitpos is within the "result mode" lowpart, the operation
5340 can be implement with a single bitwise AND. Otherwise, we need
5341 a right shift and an AND. */
5342
5343 if (bitpos < GET_MODE_BITSIZE (rmode))
5344 {
5345 if (bitpos < HOST_BITS_PER_WIDE_INT)
5346 {
5347 hi = 0;
5348 lo = (HOST_WIDE_INT) 1 << bitpos;
5349 }
5350 else
5351 {
5352 hi = (HOST_WIDE_INT) 1 << (bitpos - HOST_BITS_PER_WIDE_INT);
5353 lo = 0;
5354 }
5355
5356 if (imode != rmode)
5357 temp = gen_lowpart (rmode, temp);
5358 temp = expand_binop (rmode, and_optab, temp,
5359 immed_double_const (lo, hi, rmode),
5360 NULL_RTX, 1, OPTAB_LIB_WIDEN);
5361 }
5362 else
5363 {
5364 /* Perform a logical right shift to place the signbit in the least
5365 significant bit, then truncate the result to the desired mode
5366 and mask just this bit. */
5367 temp = expand_shift (RSHIFT_EXPR, imode, temp,
5368 build_int_cst (NULL_TREE, bitpos), NULL_RTX, 1);
5369 temp = gen_lowpart (rmode, temp);
5370 temp = expand_binop (rmode, and_optab, temp, const1_rtx,
5371 NULL_RTX, 1, OPTAB_LIB_WIDEN);
5372 }
5373
5374 return temp;
5375}
5376
5377/* Expand fork or exec calls. TARGET is the desired target of the
5378 call. ARGLIST is the list of arguments of the call. FN is the
5379 identificator of the actual function. IGNORE is nonzero if the
5380 value is to be ignored. */
5381
5382static rtx
5383expand_builtin_fork_or_exec (tree fn, tree arglist, rtx target, int ignore)
5384{
5385 tree id, decl;
5386 tree call;
5387
5388 /* If we are not profiling, just call the function. */
5389 if (!profile_arc_flag)
5390 return NULL_RTX;
5391
5392 /* Otherwise call the wrapper. This should be equivalent for the rest of
5393 compiler, so the code does not diverge, and the wrapper may run the
5394 code necessary for keeping the profiling sane. */
5395
5396 switch (DECL_FUNCTION_CODE (fn))
5397 {
5398 case BUILT_IN_FORK:
5399 id = get_identifier ("__gcov_fork");
5400 break;
5401
5402 case BUILT_IN_EXECL:
5403 id = get_identifier ("__gcov_execl");
5404 break;
5405
5406 case BUILT_IN_EXECV:
5407 id = get_identifier ("__gcov_execv");
5408 break;
5409
5410 case BUILT_IN_EXECLP:
5411 id = get_identifier ("__gcov_execlp");
5412 break;
5413
5414 case BUILT_IN_EXECLE:
5415 id = get_identifier ("__gcov_execle");
5416 break;
5417
5418 case BUILT_IN_EXECVP:
5419 id = get_identifier ("__gcov_execvp");
5420 break;
5421
5422 case BUILT_IN_EXECVE:
5423 id = get_identifier ("__gcov_execve");
5424 break;
5425
5426 default:
5427 gcc_unreachable ();
5428 }
5429
5430 decl = build_decl (FUNCTION_DECL, id, TREE_TYPE (fn));
5431 DECL_EXTERNAL (decl) = 1;
5432 TREE_PUBLIC (decl) = 1;
5433 DECL_ARTIFICIAL (decl) = 1;
5434 TREE_NOTHROW (decl) = 1;
5435 DECL_VISIBILITY (decl) = VISIBILITY_DEFAULT;
5436 DECL_VISIBILITY_SPECIFIED (decl) = 1;
5437 call = build_function_call_expr (decl, arglist);
5438
5439 return expand_call (call, target, ignore);
5440}
5441
4935
5442
5443/* Reconstitute a mode for a __sync intrinsic operation. Since the type of
5444 the pointer in these functions is void*, the tree optimizers may remove
5445 casts. The mode computed in expand_builtin isn't reliable either, due
5446 to __sync_bool_compare_and_swap.
5447
5448 FCODE_DIFF should be fcode - base, where base is the FOO_1 code for the
5449 group of builtins. This gives us log2 of the mode size. */
5450
5451static inline enum machine_mode
5452get_builtin_sync_mode (int fcode_diff)
5453{
5454 /* The size is not negotiable, so ask not to get BLKmode in return
5455 if the target indicates that a smaller size would be better. */
5456 return mode_for_size (BITS_PER_UNIT << fcode_diff, MODE_INT, 0);
5457}
5458
5459/* Expand the memory expression LOC and return the appropriate memory operand
5460 for the builtin_sync operations. */
5461
5462static rtx
5463get_builtin_sync_mem (tree loc, enum machine_mode mode)
5464{
5465 rtx addr, mem;
5466
5467 addr = expand_expr (loc, NULL, Pmode, EXPAND_SUM);
5468
5469 /* Note that we explicitly do not want any alias information for this
5470 memory, so that we kill all other live memories. Otherwise we don't
5471 satisfy the full barrier semantics of the intrinsic. */
5472 mem = validize_mem (gen_rtx_MEM (mode, addr));
5473
5474 set_mem_align (mem, get_pointer_alignment (loc, BIGGEST_ALIGNMENT));
5475 set_mem_alias_set (mem, ALIAS_SET_MEMORY_BARRIER);
5476 MEM_VOLATILE_P (mem) = 1;
5477
5478 return mem;
5479}
5480
5481/* Expand the __sync_xxx_and_fetch and __sync_fetch_and_xxx intrinsics.
5482 ARGLIST is the operands list to the function. CODE is the rtx code
5483 that corresponds to the arithmetic or logical operation from the name;
5484 an exception here is that NOT actually means NAND. TARGET is an optional
5485 place for us to store the results; AFTER is true if this is the
5486 fetch_and_xxx form. IGNORE is true if we don't actually care about
5487 the result of the operation at all. */
5488
5489static rtx
5490expand_builtin_sync_operation (enum machine_mode mode, tree arglist,
5491 enum rtx_code code, bool after,
5492 rtx target, bool ignore)
5493{
5494 rtx val, mem;
5495 enum machine_mode old_mode;
5496
5497 /* Expand the operands. */
5498 mem = get_builtin_sync_mem (TREE_VALUE (arglist), mode);
5499
5500 arglist = TREE_CHAIN (arglist);
5501 val = expand_expr (TREE_VALUE (arglist), NULL, mode, EXPAND_NORMAL);
5502 /* If VAL is promoted to a wider mode, convert it back to MODE. Take care
5503 of CONST_INTs, where we know the old_mode only from the call argument. */
5504 old_mode = GET_MODE (val);
5505 if (old_mode == VOIDmode)
5506 old_mode = TYPE_MODE (TREE_TYPE (TREE_VALUE (arglist)));
5507 val = convert_modes (mode, old_mode, val, 1);
5508
5509 if (ignore)
5510 return expand_sync_operation (mem, val, code);
5511 else
5512 return expand_sync_fetch_operation (mem, val, code, after, target);
5513}
5514
5515/* Expand the __sync_val_compare_and_swap and __sync_bool_compare_and_swap
5516 intrinsics. ARGLIST is the operands list to the function. IS_BOOL is
5517 true if this is the boolean form. TARGET is a place for us to store the
5518 results; this is NOT optional if IS_BOOL is true. */
5519
5520static rtx
5521expand_builtin_compare_and_swap (enum machine_mode mode, tree arglist,
5522 bool is_bool, rtx target)
5523{
5524 rtx old_val, new_val, mem;
5525 enum machine_mode old_mode;
5526
5527 /* Expand the operands. */
5528 mem = get_builtin_sync_mem (TREE_VALUE (arglist), mode);
5529
5530 arglist = TREE_CHAIN (arglist);
5531 old_val = expand_expr (TREE_VALUE (arglist), NULL, mode, EXPAND_NORMAL);
5532 /* If VAL is promoted to a wider mode, convert it back to MODE. Take care
5533 of CONST_INTs, where we know the old_mode only from the call argument. */
5534 old_mode = GET_MODE (old_val);
5535 if (old_mode == VOIDmode)
5536 old_mode = TYPE_MODE (TREE_TYPE (TREE_VALUE (arglist)));
5537 old_val = convert_modes (mode, old_mode, old_val, 1);
5538
5539 arglist = TREE_CHAIN (arglist);
5540 new_val = expand_expr (TREE_VALUE (arglist), NULL, mode, EXPAND_NORMAL);
5541 /* If VAL is promoted to a wider mode, convert it back to MODE. Take care
5542 of CONST_INTs, where we know the old_mode only from the call argument. */
5543 old_mode = GET_MODE (new_val);
5544 if (old_mode == VOIDmode)
5545 old_mode = TYPE_MODE (TREE_TYPE (TREE_VALUE (arglist)));
5546 new_val = convert_modes (mode, old_mode, new_val, 1);
5547
5548 if (is_bool)
5549 return expand_bool_compare_and_swap (mem, old_val, new_val, target);
5550 else
5551 return expand_val_compare_and_swap (mem, old_val, new_val, target);
5552}
5553
5554/* Expand the __sync_lock_test_and_set intrinsic. Note that the most
5555 general form is actually an atomic exchange, and some targets only
5556 support a reduced form with the second argument being a constant 1.
5557 ARGLIST is the operands list to the function; TARGET is an optional
5558 place for us to store the results. */
5559
5560static rtx
5561expand_builtin_lock_test_and_set (enum machine_mode mode, tree arglist,
5562 rtx target)
5563{
5564 rtx val, mem;
5565 enum machine_mode old_mode;
5566
5567 /* Expand the operands. */
5568 mem = get_builtin_sync_mem (TREE_VALUE (arglist), mode);
5569
5570 arglist = TREE_CHAIN (arglist);
5571 val = expand_expr (TREE_VALUE (arglist), NULL, mode, EXPAND_NORMAL);
5572 /* If VAL is promoted to a wider mode, convert it back to MODE. Take care
5573 of CONST_INTs, where we know the old_mode only from the call argument. */
5574 old_mode = GET_MODE (val);
5575 if (old_mode == VOIDmode)
5576 old_mode = TYPE_MODE (TREE_TYPE (TREE_VALUE (arglist)));
5577 val = convert_modes (mode, old_mode, val, 1);
5578
5579 return expand_sync_lock_test_and_set (mem, val, target);
5580}
5581
5582/* Expand the __sync_synchronize intrinsic. */
5583
5584static void
5585expand_builtin_synchronize (void)
5586{
5587 tree x;
5588
5589#ifdef HAVE_memory_barrier
5590 if (HAVE_memory_barrier)
5591 {
5592 emit_insn (gen_memory_barrier ());
5593 return;
5594 }
5595#endif
5596
5597 /* If no explicit memory barrier instruction is available, create an
5598 empty asm stmt with a memory clobber. */
5599 x = build4 (ASM_EXPR, void_type_node, build_string (0, ""), NULL, NULL,
5600 tree_cons (NULL, build_string (6, "memory"), NULL));
5601 ASM_VOLATILE_P (x) = 1;
5602 expand_asm_expr (x);
5603}
5604
5605/* Expand the __sync_lock_release intrinsic. ARGLIST is the operands list
5606 to the function. */
5607
5608static void
5609expand_builtin_lock_release (enum machine_mode mode, tree arglist)
5610{
5611 enum insn_code icode;
5612 rtx mem, insn;
5613 rtx val = const0_rtx;
5614
5615 /* Expand the operands. */
5616 mem = get_builtin_sync_mem (TREE_VALUE (arglist), mode);
5617
5618 /* If there is an explicit operation in the md file, use it. */
5619 icode = sync_lock_release[mode];
5620 if (icode != CODE_FOR_nothing)
5621 {
5622 if (!insn_data[icode].operand[1].predicate (val, mode))
5623 val = force_reg (mode, val);
5624
5625 insn = GEN_FCN (icode) (mem, val);
5626 if (insn)
5627 {
5628 emit_insn (insn);
5629 return;
5630 }
5631 }
5632
5633 /* Otherwise we can implement this operation by emitting a barrier
5634 followed by a store of zero. */
5635 expand_builtin_synchronize ();
5636 emit_move_insn (mem, val);
5637}
5638
4936/* Expand an expression EXP that calls a built-in function,
4937 with result going to TARGET if that's convenient
4938 (and in mode MODE if that's convenient).
4939 SUBTARGET may be used as the target for computing one of EXP's operands.
4940 IGNORE is nonzero if the value is to be ignored. */
4941
4942rtx
4943expand_builtin (tree exp, rtx target, rtx subtarget, enum machine_mode mode,
4944 int ignore)
4945{
4946 tree fndecl = get_callee_fndecl (exp);
4947 tree arglist = TREE_OPERAND (exp, 1);
4948 enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
4949 enum machine_mode target_mode = TYPE_MODE (TREE_TYPE (exp));
4950
5639/* Expand an expression EXP that calls a built-in function,
5640 with result going to TARGET if that's convenient
5641 (and in mode MODE if that's convenient).
5642 SUBTARGET may be used as the target for computing one of EXP's operands.
5643 IGNORE is nonzero if the value is to be ignored. */
5644
5645rtx
5646expand_builtin (tree exp, rtx target, rtx subtarget, enum machine_mode mode,
5647 int ignore)
5648{
5649 tree fndecl = get_callee_fndecl (exp);
5650 tree arglist = TREE_OPERAND (exp, 1);
5651 enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
5652 enum machine_mode target_mode = TYPE_MODE (TREE_TYPE (exp));
5653
4951 /* Perform postincrements before expanding builtin functions. */
4952 emit_queue ();
4953
4954 if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_MD)
5654 if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_MD)
4955 return (*targetm.expand_builtin) (exp, target, subtarget, mode, ignore);
5655 return targetm.expand_builtin (exp, target, subtarget, mode, ignore);
4956
4957 /* When not optimizing, generate calls to library functions for a certain
4958 set of builtins. */
4959 if (!optimize
5656
5657 /* When not optimizing, generate calls to library functions for a certain
5658 set of builtins. */
5659 if (!optimize
4960 && !CALLED_AS_BUILT_IN (fndecl)
5660 && !called_as_built_in (fndecl)
4961 && DECL_ASSEMBLER_NAME_SET_P (fndecl)
4962 && fcode != BUILT_IN_ALLOCA)
4963 return expand_call (exp, target, ignore);
4964
4965 /* The built-in function expanders test for target == const0_rtx
4966 to determine whether the function's result will be ignored. */
4967 if (ignore)
4968 target = const0_rtx;

--- 20 unchanged lines hidden (view full) ---

4989 expand_expr (TREE_VALUE (arg), const0_rtx,
4990 VOIDmode, EXPAND_NORMAL);
4991 return const0_rtx;
4992 }
4993 }
4994
4995 switch (fcode)
4996 {
5661 && DECL_ASSEMBLER_NAME_SET_P (fndecl)
5662 && fcode != BUILT_IN_ALLOCA)
5663 return expand_call (exp, target, ignore);
5664
5665 /* The built-in function expanders test for target == const0_rtx
5666 to determine whether the function's result will be ignored. */
5667 if (ignore)
5668 target = const0_rtx;

--- 20 unchanged lines hidden (view full) ---

5689 expand_expr (TREE_VALUE (arg), const0_rtx,
5690 VOIDmode, EXPAND_NORMAL);
5691 return const0_rtx;
5692 }
5693 }
5694
5695 switch (fcode)
5696 {
4997 case BUILT_IN_ABS:
4998 case BUILT_IN_LABS:
4999 case BUILT_IN_LLABS:
5000 case BUILT_IN_IMAXABS:
5001 /* build_function_call changes these into ABS_EXPR. */
5002 abort ();
5003
5004 case BUILT_IN_FABS:
5005 case BUILT_IN_FABSF:
5006 case BUILT_IN_FABSL:
5697 CASE_FLT_FN (BUILT_IN_FABS):
5007 target = expand_builtin_fabs (arglist, target, subtarget);
5008 if (target)
5698 target = expand_builtin_fabs (arglist, target, subtarget);
5699 if (target)
5009 return target;
5700 return target;
5010 break;
5011
5701 break;
5702
5012 case BUILT_IN_CABS:
5013 case BUILT_IN_CABSF:
5014 case BUILT_IN_CABSL:
5015 if (flag_unsafe_math_optimizations)
5016 {
5017 target = expand_builtin_cabs (arglist, target);
5018 if (target)
5019 return target;
5020 }
5703 CASE_FLT_FN (BUILT_IN_COPYSIGN):
5704 target = expand_builtin_copysign (arglist, target, subtarget);
5705 if (target)
5706 return target;
5021 break;
5022
5707 break;
5708
5023 case BUILT_IN_CONJ:
5024 case BUILT_IN_CONJF:
5025 case BUILT_IN_CONJL:
5026 case BUILT_IN_CREAL:
5027 case BUILT_IN_CREALF:
5028 case BUILT_IN_CREALL:
5029 case BUILT_IN_CIMAG:
5030 case BUILT_IN_CIMAGF:
5031 case BUILT_IN_CIMAGL:
5032 /* expand_tree_builtin changes these into CONJ_EXPR, REALPART_EXPR
5033 and IMAGPART_EXPR. */
5034 abort ();
5709 /* Just do a normal library call if we were unable to fold
5710 the values. */
5711 CASE_FLT_FN (BUILT_IN_CABS):
5712 break;
5035
5713
5036 case BUILT_IN_SIN:
5037 case BUILT_IN_SINF:
5038 case BUILT_IN_SINL:
5039 case BUILT_IN_COS:
5040 case BUILT_IN_COSF:
5041 case BUILT_IN_COSL:
5042 case BUILT_IN_EXP:
5043 case BUILT_IN_EXPF:
5044 case BUILT_IN_EXPL:
5045 case BUILT_IN_LOG:
5046 case BUILT_IN_LOGF:
5047 case BUILT_IN_LOGL:
5048 case BUILT_IN_TAN:
5049 case BUILT_IN_TANF:
5050 case BUILT_IN_TANL:
5051 case BUILT_IN_ATAN:
5052 case BUILT_IN_ATANF:
5053 case BUILT_IN_ATANL:
5714 CASE_FLT_FN (BUILT_IN_EXP):
5715 CASE_FLT_FN (BUILT_IN_EXP10):
5716 CASE_FLT_FN (BUILT_IN_POW10):
5717 CASE_FLT_FN (BUILT_IN_EXP2):
5718 CASE_FLT_FN (BUILT_IN_EXPM1):
5719 CASE_FLT_FN (BUILT_IN_LOGB):
5720 CASE_FLT_FN (BUILT_IN_ILOGB):
5721 CASE_FLT_FN (BUILT_IN_LOG):
5722 CASE_FLT_FN (BUILT_IN_LOG10):
5723 CASE_FLT_FN (BUILT_IN_LOG2):
5724 CASE_FLT_FN (BUILT_IN_LOG1P):
5725 CASE_FLT_FN (BUILT_IN_TAN):
5726 CASE_FLT_FN (BUILT_IN_ASIN):
5727 CASE_FLT_FN (BUILT_IN_ACOS):
5728 CASE_FLT_FN (BUILT_IN_ATAN):
5054 /* Treat these like sqrt only if unsafe math optimizations are allowed,
5055 because of possible accuracy problems. */
5056 if (! flag_unsafe_math_optimizations)
5057 break;
5729 /* Treat these like sqrt only if unsafe math optimizations are allowed,
5730 because of possible accuracy problems. */
5731 if (! flag_unsafe_math_optimizations)
5732 break;
5058 case BUILT_IN_SQRT:
5059 case BUILT_IN_SQRTF:
5060 case BUILT_IN_SQRTL:
5061 case BUILT_IN_FLOOR:
5062 case BUILT_IN_FLOORF:
5063 case BUILT_IN_FLOORL:
5064 case BUILT_IN_CEIL:
5065 case BUILT_IN_CEILF:
5066 case BUILT_IN_CEILL:
5067 case BUILT_IN_TRUNC:
5068 case BUILT_IN_TRUNCF:
5069 case BUILT_IN_TRUNCL:
5070 case BUILT_IN_ROUND:
5071 case BUILT_IN_ROUNDF:
5072 case BUILT_IN_ROUNDL:
5073 case BUILT_IN_NEARBYINT:
5074 case BUILT_IN_NEARBYINTF:
5075 case BUILT_IN_NEARBYINTL:
5733 CASE_FLT_FN (BUILT_IN_SQRT):
5734 CASE_FLT_FN (BUILT_IN_FLOOR):
5735 CASE_FLT_FN (BUILT_IN_CEIL):
5736 CASE_FLT_FN (BUILT_IN_TRUNC):
5737 CASE_FLT_FN (BUILT_IN_ROUND):
5738 CASE_FLT_FN (BUILT_IN_NEARBYINT):
5739 CASE_FLT_FN (BUILT_IN_RINT):
5740 CASE_FLT_FN (BUILT_IN_LRINT):
5741 CASE_FLT_FN (BUILT_IN_LLRINT):
5076 target = expand_builtin_mathfn (exp, target, subtarget);
5077 if (target)
5078 return target;
5079 break;
5080
5742 target = expand_builtin_mathfn (exp, target, subtarget);
5743 if (target)
5744 return target;
5745 break;
5746
5081 case BUILT_IN_POW:
5082 case BUILT_IN_POWF:
5083 case BUILT_IN_POWL:
5084 if (! flag_unsafe_math_optimizations)
5085 break;
5747 CASE_FLT_FN (BUILT_IN_LCEIL):
5748 CASE_FLT_FN (BUILT_IN_LLCEIL):
5749 CASE_FLT_FN (BUILT_IN_LFLOOR):
5750 CASE_FLT_FN (BUILT_IN_LLFLOOR):
5751 target = expand_builtin_int_roundingfn (exp, target, subtarget);
5752 if (target)
5753 return target;
5754 break;
5755
5756 CASE_FLT_FN (BUILT_IN_POW):
5086 target = expand_builtin_pow (exp, target, subtarget);
5087 if (target)
5088 return target;
5089 break;
5090
5757 target = expand_builtin_pow (exp, target, subtarget);
5758 if (target)
5759 return target;
5760 break;
5761
5091 case BUILT_IN_ATAN2:
5092 case BUILT_IN_ATAN2F:
5093 case BUILT_IN_ATAN2L:
5762 CASE_FLT_FN (BUILT_IN_POWI):
5763 target = expand_builtin_powi (exp, target, subtarget);
5764 if (target)
5765 return target;
5766 break;
5767
5768 CASE_FLT_FN (BUILT_IN_ATAN2):
5769 CASE_FLT_FN (BUILT_IN_LDEXP):
5770 CASE_FLT_FN (BUILT_IN_FMOD):
5771 CASE_FLT_FN (BUILT_IN_DREM):
5094 if (! flag_unsafe_math_optimizations)
5095 break;
5096 target = expand_builtin_mathfn_2 (exp, target, subtarget);
5097 if (target)
5098 return target;
5099 break;
5100
5772 if (! flag_unsafe_math_optimizations)
5773 break;
5774 target = expand_builtin_mathfn_2 (exp, target, subtarget);
5775 if (target)
5776 return target;
5777 break;
5778
5779 CASE_FLT_FN (BUILT_IN_SIN):
5780 CASE_FLT_FN (BUILT_IN_COS):
5781 if (! flag_unsafe_math_optimizations)
5782 break;
5783 target = expand_builtin_mathfn_3 (exp, target, subtarget);
5784 if (target)
5785 return target;
5786 break;
5787
5788 CASE_FLT_FN (BUILT_IN_SINCOS):
5789 if (! flag_unsafe_math_optimizations)
5790 break;
5791 target = expand_builtin_sincos (exp);
5792 if (target)
5793 return target;
5794 break;
5795
5101 case BUILT_IN_APPLY_ARGS:
5102 return expand_builtin_apply_args ();
5103
5104 /* __builtin_apply (FUNCTION, ARGUMENTS, ARGSIZE) invokes
5105 FUNCTION with a copy of the parameters described by
5106 ARGUMENTS, and ARGSIZE. It returns a block of memory
5107 allocated on the stack into which is stored all the registers
5108 that might possibly be used for returning the result of a

--- 10 unchanged lines hidden (view full) ---

5119 return const0_rtx;
5120 else
5121 {
5122 int i;
5123 tree t;
5124 rtx ops[3];
5125
5126 for (t = arglist, i = 0; t; t = TREE_CHAIN (t), i++)
5796 case BUILT_IN_APPLY_ARGS:
5797 return expand_builtin_apply_args ();
5798
5799 /* __builtin_apply (FUNCTION, ARGUMENTS, ARGSIZE) invokes
5800 FUNCTION with a copy of the parameters described by
5801 ARGUMENTS, and ARGSIZE. It returns a block of memory
5802 allocated on the stack into which is stored all the registers
5803 that might possibly be used for returning the result of a

--- 10 unchanged lines hidden (view full) ---

5814 return const0_rtx;
5815 else
5816 {
5817 int i;
5818 tree t;
5819 rtx ops[3];
5820
5821 for (t = arglist, i = 0; t; t = TREE_CHAIN (t), i++)
5127 ops[i] = expand_expr (TREE_VALUE (t), NULL_RTX, VOIDmode, 0);
5822 ops[i] = expand_normal (TREE_VALUE (t));
5128
5129 return expand_builtin_apply (ops[0], ops[1], ops[2]);
5130 }
5131
5132 /* __builtin_return (RESULT) causes the function to return the
5133 value described by RESULT. RESULT is address of the block of
5134 memory returned by __builtin_apply. */
5135 case BUILT_IN_RETURN:
5136 if (validate_arglist (arglist, POINTER_TYPE, VOID_TYPE))
5823
5824 return expand_builtin_apply (ops[0], ops[1], ops[2]);
5825 }
5826
5827 /* __builtin_return (RESULT) causes the function to return the
5828 value described by RESULT. RESULT is address of the block of
5829 memory returned by __builtin_apply. */
5830 case BUILT_IN_RETURN:
5831 if (validate_arglist (arglist, POINTER_TYPE, VOID_TYPE))
5137 expand_builtin_return (expand_expr (TREE_VALUE (arglist),
5138 NULL_RTX, VOIDmode, 0));
5832 expand_builtin_return (expand_normal (TREE_VALUE (arglist)));
5139 return const0_rtx;
5140
5141 case BUILT_IN_SAVEREGS:
5142 return expand_builtin_saveregs ();
5143
5144 case BUILT_IN_ARGS_INFO:
5145 return expand_builtin_args_info (arglist);
5146
5147 /* Return the address of the first anonymous stack arg. */
5148 case BUILT_IN_NEXT_ARG:
5833 return const0_rtx;
5834
5835 case BUILT_IN_SAVEREGS:
5836 return expand_builtin_saveregs ();
5837
5838 case BUILT_IN_ARGS_INFO:
5839 return expand_builtin_args_info (arglist);
5840
5841 /* Return the address of the first anonymous stack arg. */
5842 case BUILT_IN_NEXT_ARG:
5149 return expand_builtin_next_arg (arglist);
5843 if (fold_builtin_next_arg (arglist))
5844 return const0_rtx;
5845 return expand_builtin_next_arg ();
5150
5151 case BUILT_IN_CLASSIFY_TYPE:
5152 return expand_builtin_classify_type (arglist);
5153
5154 case BUILT_IN_CONSTANT_P:
5846
5847 case BUILT_IN_CLASSIFY_TYPE:
5848 return expand_builtin_classify_type (arglist);
5849
5850 case BUILT_IN_CONSTANT_P:
5155 return expand_builtin_constant_p (arglist, target_mode);
5851 return const0_rtx;
5156
5157 case BUILT_IN_FRAME_ADDRESS:
5158 case BUILT_IN_RETURN_ADDRESS:
5159 return expand_builtin_frame_address (fndecl, arglist);
5160
5161 /* Returns the address of the area where the structure is returned.
5162 0 otherwise. */
5163 case BUILT_IN_AGGREGATE_INCOMING_ADDRESS:
5164 if (arglist != 0
5165 || ! AGGREGATE_TYPE_P (TREE_TYPE (TREE_TYPE (current_function_decl)))
5852
5853 case BUILT_IN_FRAME_ADDRESS:
5854 case BUILT_IN_RETURN_ADDRESS:
5855 return expand_builtin_frame_address (fndecl, arglist);
5856
5857 /* Returns the address of the area where the structure is returned.
5858 0 otherwise. */
5859 case BUILT_IN_AGGREGATE_INCOMING_ADDRESS:
5860 if (arglist != 0
5861 || ! AGGREGATE_TYPE_P (TREE_TYPE (TREE_TYPE (current_function_decl)))
5166 || GET_CODE (DECL_RTL (DECL_RESULT (current_function_decl))) != MEM)
5862 || !MEM_P (DECL_RTL (DECL_RESULT (current_function_decl))))
5167 return const0_rtx;
5168 else
5169 return XEXP (DECL_RTL (DECL_RESULT (current_function_decl)), 0);
5170
5171 case BUILT_IN_ALLOCA:
5172 target = expand_builtin_alloca (arglist, target);
5173 if (target)
5174 return target;
5175 break;
5176
5863 return const0_rtx;
5864 else
5865 return XEXP (DECL_RTL (DECL_RESULT (current_function_decl)), 0);
5866
5867 case BUILT_IN_ALLOCA:
5868 target = expand_builtin_alloca (arglist, target);
5869 if (target)
5870 return target;
5871 break;
5872
5177 case BUILT_IN_FFS:
5178 case BUILT_IN_FFSL:
5179 case BUILT_IN_FFSLL:
5873 case BUILT_IN_STACK_SAVE:
5874 return expand_stack_save ();
5875
5876 case BUILT_IN_STACK_RESTORE:
5877 expand_stack_restore (TREE_VALUE (arglist));
5878 return const0_rtx;
5879
5880 CASE_INT_FN (BUILT_IN_FFS):
5881 case BUILT_IN_FFSIMAX:
5180 target = expand_builtin_unop (target_mode, arglist, target,
5181 subtarget, ffs_optab);
5182 if (target)
5183 return target;
5184 break;
5185
5882 target = expand_builtin_unop (target_mode, arglist, target,
5883 subtarget, ffs_optab);
5884 if (target)
5885 return target;
5886 break;
5887
5186 case BUILT_IN_CLZ:
5187 case BUILT_IN_CLZL:
5188 case BUILT_IN_CLZLL:
5888 CASE_INT_FN (BUILT_IN_CLZ):
5889 case BUILT_IN_CLZIMAX:
5189 target = expand_builtin_unop (target_mode, arglist, target,
5190 subtarget, clz_optab);
5191 if (target)
5192 return target;
5193 break;
5194
5890 target = expand_builtin_unop (target_mode, arglist, target,
5891 subtarget, clz_optab);
5892 if (target)
5893 return target;
5894 break;
5895
5195 case BUILT_IN_CTZ:
5196 case BUILT_IN_CTZL:
5197 case BUILT_IN_CTZLL:
5896 CASE_INT_FN (BUILT_IN_CTZ):
5897 case BUILT_IN_CTZIMAX:
5198 target = expand_builtin_unop (target_mode, arglist, target,
5199 subtarget, ctz_optab);
5200 if (target)
5201 return target;
5202 break;
5203
5898 target = expand_builtin_unop (target_mode, arglist, target,
5899 subtarget, ctz_optab);
5900 if (target)
5901 return target;
5902 break;
5903
5204 case BUILT_IN_POPCOUNT:
5205 case BUILT_IN_POPCOUNTL:
5206 case BUILT_IN_POPCOUNTLL:
5904 CASE_INT_FN (BUILT_IN_POPCOUNT):
5905 case BUILT_IN_POPCOUNTIMAX:
5207 target = expand_builtin_unop (target_mode, arglist, target,
5208 subtarget, popcount_optab);
5209 if (target)
5210 return target;
5211 break;
5212
5906 target = expand_builtin_unop (target_mode, arglist, target,
5907 subtarget, popcount_optab);
5908 if (target)
5909 return target;
5910 break;
5911
5213 case BUILT_IN_PARITY:
5214 case BUILT_IN_PARITYL:
5215 case BUILT_IN_PARITYLL:
5912 CASE_INT_FN (BUILT_IN_PARITY):
5913 case BUILT_IN_PARITYIMAX:
5216 target = expand_builtin_unop (target_mode, arglist, target,
5217 subtarget, parity_optab);
5218 if (target)
5219 return target;
5220 break;
5221
5222 case BUILT_IN_STRLEN:
5223 target = expand_builtin_strlen (arglist, target, target_mode);
5224 if (target)
5225 return target;
5226 break;
5227
5228 case BUILT_IN_STRCPY:
5914 target = expand_builtin_unop (target_mode, arglist, target,
5915 subtarget, parity_optab);
5916 if (target)
5917 return target;
5918 break;
5919
5920 case BUILT_IN_STRLEN:
5921 target = expand_builtin_strlen (arglist, target, target_mode);
5922 if (target)
5923 return target;
5924 break;
5925
5926 case BUILT_IN_STRCPY:
5229 target = expand_builtin_strcpy (arglist, target, mode);
5927 target = expand_builtin_strcpy (fndecl, arglist, target, mode);
5230 if (target)
5231 return target;
5232 break;
5233
5234 case BUILT_IN_STRNCPY:
5928 if (target)
5929 return target;
5930 break;
5931
5932 case BUILT_IN_STRNCPY:
5235 target = expand_builtin_strncpy (arglist, target, mode);
5933 target = expand_builtin_strncpy (exp, target, mode);
5236 if (target)
5237 return target;
5238 break;
5239
5240 case BUILT_IN_STPCPY:
5934 if (target)
5935 return target;
5936 break;
5937
5938 case BUILT_IN_STPCPY:
5241 target = expand_builtin_stpcpy (arglist, target, mode);
5939 target = expand_builtin_stpcpy (exp, target, mode);
5242 if (target)
5243 return target;
5244 break;
5245
5246 case BUILT_IN_STRCAT:
5940 if (target)
5941 return target;
5942 break;
5943
5944 case BUILT_IN_STRCAT:
5247 target = expand_builtin_strcat (arglist, target, mode);
5945 target = expand_builtin_strcat (fndecl, arglist, target, mode);
5248 if (target)
5249 return target;
5250 break;
5251
5252 case BUILT_IN_STRNCAT:
5253 target = expand_builtin_strncat (arglist, target, mode);
5254 if (target)
5255 return target;

--- 7 unchanged lines hidden (view full) ---

5263
5264 case BUILT_IN_STRCSPN:
5265 target = expand_builtin_strcspn (arglist, target, mode);
5266 if (target)
5267 return target;
5268 break;
5269
5270 case BUILT_IN_STRSTR:
5946 if (target)
5947 return target;
5948 break;
5949
5950 case BUILT_IN_STRNCAT:
5951 target = expand_builtin_strncat (arglist, target, mode);
5952 if (target)
5953 return target;

--- 7 unchanged lines hidden (view full) ---

5961
5962 case BUILT_IN_STRCSPN:
5963 target = expand_builtin_strcspn (arglist, target, mode);
5964 if (target)
5965 return target;
5966 break;
5967
5968 case BUILT_IN_STRSTR:
5271 target = expand_builtin_strstr (arglist, target, mode);
5969 target = expand_builtin_strstr (arglist, TREE_TYPE (exp), target, mode);
5272 if (target)
5273 return target;
5274 break;
5275
5276 case BUILT_IN_STRPBRK:
5970 if (target)
5971 return target;
5972 break;
5973
5974 case BUILT_IN_STRPBRK:
5277 target = expand_builtin_strpbrk (arglist, target, mode);
5975 target = expand_builtin_strpbrk (arglist, TREE_TYPE (exp), target, mode);
5278 if (target)
5279 return target;
5280 break;
5281
5282 case BUILT_IN_INDEX:
5283 case BUILT_IN_STRCHR:
5976 if (target)
5977 return target;
5978 break;
5979
5980 case BUILT_IN_INDEX:
5981 case BUILT_IN_STRCHR:
5284 target = expand_builtin_strchr (arglist, target, mode);
5982 target = expand_builtin_strchr (arglist, TREE_TYPE (exp), target, mode);
5285 if (target)
5286 return target;
5287 break;
5288
5289 case BUILT_IN_RINDEX:
5290 case BUILT_IN_STRRCHR:
5983 if (target)
5984 return target;
5985 break;
5986
5987 case BUILT_IN_RINDEX:
5988 case BUILT_IN_STRRCHR:
5291 target = expand_builtin_strrchr (arglist, target, mode);
5989 target = expand_builtin_strrchr (arglist, TREE_TYPE (exp), target, mode);
5292 if (target)
5293 return target;
5294 break;
5295
5296 case BUILT_IN_MEMCPY:
5990 if (target)
5991 return target;
5992 break;
5993
5994 case BUILT_IN_MEMCPY:
5297 target = expand_builtin_memcpy (arglist, target, mode);
5995 target = expand_builtin_memcpy (exp, target, mode);
5298 if (target)
5299 return target;
5300 break;
5301
5302 case BUILT_IN_MEMPCPY:
5996 if (target)
5997 return target;
5998 break;
5999
6000 case BUILT_IN_MEMPCPY:
5303 target = expand_builtin_mempcpy (arglist, target, mode, /*endp=*/ 1);
6001 target = expand_builtin_mempcpy (arglist, TREE_TYPE (exp), target, mode, /*endp=*/ 1);
5304 if (target)
5305 return target;
5306 break;
5307
5308 case BUILT_IN_MEMMOVE:
6002 if (target)
6003 return target;
6004 break;
6005
6006 case BUILT_IN_MEMMOVE:
5309 target = expand_builtin_memmove (arglist, target, mode);
6007 target = expand_builtin_memmove (arglist, TREE_TYPE (exp), target,
6008 mode, exp);
5310 if (target)
5311 return target;
5312 break;
5313
5314 case BUILT_IN_BCOPY:
6009 if (target)
6010 return target;
6011 break;
6012
6013 case BUILT_IN_BCOPY:
5315 target = expand_builtin_bcopy (arglist);
6014 target = expand_builtin_bcopy (exp);
5316 if (target)
5317 return target;
5318 break;
5319
5320 case BUILT_IN_MEMSET:
6015 if (target)
6016 return target;
6017 break;
6018
6019 case BUILT_IN_MEMSET:
5321 target = expand_builtin_memset (arglist, target, mode);
6020 target = expand_builtin_memset (arglist, target, mode, exp);
5322 if (target)
5323 return target;
5324 break;
5325
5326 case BUILT_IN_BZERO:
6021 if (target)
6022 return target;
6023 break;
6024
6025 case BUILT_IN_BZERO:
5327 target = expand_builtin_bzero (arglist);
6026 target = expand_builtin_bzero (exp);
5328 if (target)
5329 return target;
5330 break;
5331
5332 case BUILT_IN_STRCMP:
5333 target = expand_builtin_strcmp (exp, target, mode);
5334 if (target)
5335 return target;

--- 8 unchanged lines hidden (view full) ---

5344 case BUILT_IN_BCMP:
5345 case BUILT_IN_MEMCMP:
5346 target = expand_builtin_memcmp (exp, arglist, target, mode);
5347 if (target)
5348 return target;
5349 break;
5350
5351 case BUILT_IN_SETJMP:
6027 if (target)
6028 return target;
6029 break;
6030
6031 case BUILT_IN_STRCMP:
6032 target = expand_builtin_strcmp (exp, target, mode);
6033 if (target)
6034 return target;

--- 8 unchanged lines hidden (view full) ---

6043 case BUILT_IN_BCMP:
6044 case BUILT_IN_MEMCMP:
6045 target = expand_builtin_memcmp (exp, arglist, target, mode);
6046 if (target)
6047 return target;
6048 break;
6049
6050 case BUILT_IN_SETJMP:
5352 target = expand_builtin_setjmp (arglist, target);
5353 if (target)
5354 return target;
6051 /* This should have been lowered to the builtins below. */
6052 gcc_unreachable ();
6053
6054 case BUILT_IN_SETJMP_SETUP:
6055 /* __builtin_setjmp_setup is passed a pointer to an array of five words
6056 and the receiver label. */
6057 if (validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
6058 {
6059 rtx buf_addr = expand_expr (TREE_VALUE (arglist), subtarget,
6060 VOIDmode, EXPAND_NORMAL);
6061 tree label = TREE_OPERAND (TREE_VALUE (TREE_CHAIN (arglist)), 0);
6062 rtx label_r = label_rtx (label);
6063
6064 /* This is copied from the handling of non-local gotos. */
6065 expand_builtin_setjmp_setup (buf_addr, label_r);
6066 nonlocal_goto_handler_labels
6067 = gen_rtx_EXPR_LIST (VOIDmode, label_r,
6068 nonlocal_goto_handler_labels);
6069 /* ??? Do not let expand_label treat us as such since we would
6070 not want to be both on the list of non-local labels and on
6071 the list of forced labels. */
6072 FORCED_LABEL (label) = 0;
6073 return const0_rtx;
6074 }
5355 break;
5356
6075 break;
6076
6077 case BUILT_IN_SETJMP_DISPATCHER:
6078 /* __builtin_setjmp_dispatcher is passed the dispatcher label. */
6079 if (validate_arglist (arglist, POINTER_TYPE, VOID_TYPE))
6080 {
6081 tree label = TREE_OPERAND (TREE_VALUE (arglist), 0);
6082 rtx label_r = label_rtx (label);
6083
6084 /* Remove the dispatcher label from the list of non-local labels
6085 since the receiver labels have been added to it above. */
6086 remove_node_from_expr_list (label_r, &nonlocal_goto_handler_labels);
6087 return const0_rtx;
6088 }
6089 break;
6090
6091 case BUILT_IN_SETJMP_RECEIVER:
6092 /* __builtin_setjmp_receiver is passed the receiver label. */
6093 if (validate_arglist (arglist, POINTER_TYPE, VOID_TYPE))
6094 {
6095 tree label = TREE_OPERAND (TREE_VALUE (arglist), 0);
6096 rtx label_r = label_rtx (label);
6097
6098 expand_builtin_setjmp_receiver (label_r);
6099 return const0_rtx;
6100 }
6101 break;
6102
5357 /* __builtin_longjmp is passed a pointer to an array of five words.
5358 It's similar to the C library longjmp function but works with
5359 __builtin_setjmp above. */
5360 case BUILT_IN_LONGJMP:
6103 /* __builtin_longjmp is passed a pointer to an array of five words.
6104 It's similar to the C library longjmp function but works with
6105 __builtin_setjmp above. */
6106 case BUILT_IN_LONGJMP:
5361 if (!validate_arglist (arglist, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
5362 break;
5363 else
6107 if (validate_arglist (arglist, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
5364 {
5365 rtx buf_addr = expand_expr (TREE_VALUE (arglist), subtarget,
6108 {
6109 rtx buf_addr = expand_expr (TREE_VALUE (arglist), subtarget,
5366 VOIDmode, 0);
5367 rtx value = expand_expr (TREE_VALUE (TREE_CHAIN (arglist)),
5368 NULL_RTX, VOIDmode, 0);
6110 VOIDmode, EXPAND_NORMAL);
6111 rtx value = expand_normal (TREE_VALUE (TREE_CHAIN (arglist)));
5369
5370 if (value != const1_rtx)
5371 {
6112
6113 if (value != const1_rtx)
6114 {
5372 error ("__builtin_longjmp second argument must be 1");
6115 error ("%<__builtin_longjmp%> second argument must be 1");
5373 return const0_rtx;
5374 }
5375
5376 expand_builtin_longjmp (buf_addr, value);
5377 return const0_rtx;
5378 }
6116 return const0_rtx;
6117 }
6118
6119 expand_builtin_longjmp (buf_addr, value);
6120 return const0_rtx;
6121 }
6122 break;
5379
6123
6124 case BUILT_IN_NONLOCAL_GOTO:
6125 target = expand_builtin_nonlocal_goto (arglist);
6126 if (target)
6127 return target;
6128 break;
6129
6130 /* This updates the setjmp buffer that is its argument with the value
6131 of the current stack pointer. */
6132 case BUILT_IN_UPDATE_SETJMP_BUF:
6133 if (validate_arglist (arglist, POINTER_TYPE, VOID_TYPE))
6134 {
6135 rtx buf_addr
6136 = expand_normal (TREE_VALUE (arglist));
6137
6138 expand_builtin_update_setjmp_buf (buf_addr);
6139 return const0_rtx;
6140 }
6141 break;
6142
5380 case BUILT_IN_TRAP:
5381 expand_builtin_trap ();
5382 return const0_rtx;
5383
5384 case BUILT_IN_PRINTF:
6143 case BUILT_IN_TRAP:
6144 expand_builtin_trap ();
6145 return const0_rtx;
6146
6147 case BUILT_IN_PRINTF:
5385 target = expand_builtin_printf (arglist, target, mode, false);
6148 target = expand_builtin_printf (exp, target, mode, false);
5386 if (target)
5387 return target;
5388 break;
5389
5390 case BUILT_IN_PRINTF_UNLOCKED:
6149 if (target)
6150 return target;
6151 break;
6152
6153 case BUILT_IN_PRINTF_UNLOCKED:
5391 target = expand_builtin_printf (arglist, target, mode, true);
6154 target = expand_builtin_printf (exp, target, mode, true);
5392 if (target)
5393 return target;
5394 break;
5395
5396 case BUILT_IN_FPUTS:
5397 target = expand_builtin_fputs (arglist, target, false);
5398 if (target)
5399 return target;
5400 break;
6155 if (target)
6156 return target;
6157 break;
6158
6159 case BUILT_IN_FPUTS:
6160 target = expand_builtin_fputs (arglist, target, false);
6161 if (target)
6162 return target;
6163 break;
5401
5402 case BUILT_IN_FPUTS_UNLOCKED:
5403 target = expand_builtin_fputs (arglist, target, true);
5404 if (target)
5405 return target;
5406 break;
5407
5408 case BUILT_IN_FPRINTF:
6164 case BUILT_IN_FPUTS_UNLOCKED:
6165 target = expand_builtin_fputs (arglist, target, true);
6166 if (target)
6167 return target;
6168 break;
6169
6170 case BUILT_IN_FPRINTF:
5409 target = expand_builtin_fprintf (arglist, target, mode, false);
6171 target = expand_builtin_fprintf (exp, target, mode, false);
5410 if (target)
5411 return target;
5412 break;
5413
5414 case BUILT_IN_FPRINTF_UNLOCKED:
6172 if (target)
6173 return target;
6174 break;
6175
6176 case BUILT_IN_FPRINTF_UNLOCKED:
5415 target = expand_builtin_fprintf (arglist, target, mode, true);
6177 target = expand_builtin_fprintf (exp, target, mode, true);
5416 if (target)
5417 return target;
5418 break;
5419
5420 case BUILT_IN_SPRINTF:
5421 target = expand_builtin_sprintf (arglist, target, mode);
5422 if (target)
5423 return target;
5424 break;
5425
6178 if (target)
6179 return target;
6180 break;
6181
6182 case BUILT_IN_SPRINTF:
6183 target = expand_builtin_sprintf (arglist, target, mode);
6184 if (target)
6185 return target;
6186 break;
6187
6188 CASE_FLT_FN (BUILT_IN_SIGNBIT):
6189 target = expand_builtin_signbit (exp, target);
6190 if (target)
6191 return target;
6192 break;
6193
5426 /* Various hooks for the DWARF 2 __throw routine. */
5427 case BUILT_IN_UNWIND_INIT:
5428 expand_builtin_unwind_init ();
5429 return const0_rtx;
5430 case BUILT_IN_DWARF_CFA:
5431 return virtual_cfa_rtx;
5432#ifdef DWARF2_UNWIND_INFO
5433 case BUILT_IN_DWARF_SP_COLUMN:

--- 25 unchanged lines hidden (view full) ---

5459 case BUILT_IN_VA_COPY:
5460 return expand_builtin_va_copy (arglist);
5461 case BUILT_IN_EXPECT:
5462 return expand_builtin_expect (arglist, target);
5463 case BUILT_IN_PREFETCH:
5464 expand_builtin_prefetch (arglist);
5465 return const0_rtx;
5466
6194 /* Various hooks for the DWARF 2 __throw routine. */
6195 case BUILT_IN_UNWIND_INIT:
6196 expand_builtin_unwind_init ();
6197 return const0_rtx;
6198 case BUILT_IN_DWARF_CFA:
6199 return virtual_cfa_rtx;
6200#ifdef DWARF2_UNWIND_INFO
6201 case BUILT_IN_DWARF_SP_COLUMN:

--- 25 unchanged lines hidden (view full) ---

6227 case BUILT_IN_VA_COPY:
6228 return expand_builtin_va_copy (arglist);
6229 case BUILT_IN_EXPECT:
6230 return expand_builtin_expect (arglist, target);
6231 case BUILT_IN_PREFETCH:
6232 expand_builtin_prefetch (arglist);
6233 return const0_rtx;
6234
6235 case BUILT_IN_PROFILE_FUNC_ENTER:
6236 return expand_builtin_profile_func (false);
6237 case BUILT_IN_PROFILE_FUNC_EXIT:
6238 return expand_builtin_profile_func (true);
5467
6239
6240 case BUILT_IN_INIT_TRAMPOLINE:
6241 return expand_builtin_init_trampoline (arglist);
6242 case BUILT_IN_ADJUST_TRAMPOLINE:
6243 return expand_builtin_adjust_trampoline (arglist);
6244
6245 case BUILT_IN_FORK:
6246 case BUILT_IN_EXECL:
6247 case BUILT_IN_EXECV:
6248 case BUILT_IN_EXECLP:
6249 case BUILT_IN_EXECLE:
6250 case BUILT_IN_EXECVP:
6251 case BUILT_IN_EXECVE:
6252 target = expand_builtin_fork_or_exec (fndecl, arglist, target, ignore);
6253 if (target)
6254 return target;
6255 break;
6256
6257 case BUILT_IN_FETCH_AND_ADD_1:
6258 case BUILT_IN_FETCH_AND_ADD_2:
6259 case BUILT_IN_FETCH_AND_ADD_4:
6260 case BUILT_IN_FETCH_AND_ADD_8:
6261 case BUILT_IN_FETCH_AND_ADD_16:
6262 mode = get_builtin_sync_mode (fcode - BUILT_IN_FETCH_AND_ADD_1);
6263 target = expand_builtin_sync_operation (mode, arglist, PLUS,
6264 false, target, ignore);
6265 if (target)
6266 return target;
6267 break;
6268
6269 case BUILT_IN_FETCH_AND_SUB_1:
6270 case BUILT_IN_FETCH_AND_SUB_2:
6271 case BUILT_IN_FETCH_AND_SUB_4:
6272 case BUILT_IN_FETCH_AND_SUB_8:
6273 case BUILT_IN_FETCH_AND_SUB_16:
6274 mode = get_builtin_sync_mode (fcode - BUILT_IN_FETCH_AND_SUB_1);
6275 target = expand_builtin_sync_operation (mode, arglist, MINUS,
6276 false, target, ignore);
6277 if (target)
6278 return target;
6279 break;
6280
6281 case BUILT_IN_FETCH_AND_OR_1:
6282 case BUILT_IN_FETCH_AND_OR_2:
6283 case BUILT_IN_FETCH_AND_OR_4:
6284 case BUILT_IN_FETCH_AND_OR_8:
6285 case BUILT_IN_FETCH_AND_OR_16:
6286 mode = get_builtin_sync_mode (fcode - BUILT_IN_FETCH_AND_OR_1);
6287 target = expand_builtin_sync_operation (mode, arglist, IOR,
6288 false, target, ignore);
6289 if (target)
6290 return target;
6291 break;
6292
6293 case BUILT_IN_FETCH_AND_AND_1:
6294 case BUILT_IN_FETCH_AND_AND_2:
6295 case BUILT_IN_FETCH_AND_AND_4:
6296 case BUILT_IN_FETCH_AND_AND_8:
6297 case BUILT_IN_FETCH_AND_AND_16:
6298 mode = get_builtin_sync_mode (fcode - BUILT_IN_FETCH_AND_AND_1);
6299 target = expand_builtin_sync_operation (mode, arglist, AND,
6300 false, target, ignore);
6301 if (target)
6302 return target;
6303 break;
6304
6305 case BUILT_IN_FETCH_AND_XOR_1:
6306 case BUILT_IN_FETCH_AND_XOR_2:
6307 case BUILT_IN_FETCH_AND_XOR_4:
6308 case BUILT_IN_FETCH_AND_XOR_8:
6309 case BUILT_IN_FETCH_AND_XOR_16:
6310 mode = get_builtin_sync_mode (fcode - BUILT_IN_FETCH_AND_XOR_1);
6311 target = expand_builtin_sync_operation (mode, arglist, XOR,
6312 false, target, ignore);
6313 if (target)
6314 return target;
6315 break;
6316
6317 case BUILT_IN_FETCH_AND_NAND_1:
6318 case BUILT_IN_FETCH_AND_NAND_2:
6319 case BUILT_IN_FETCH_AND_NAND_4:
6320 case BUILT_IN_FETCH_AND_NAND_8:
6321 case BUILT_IN_FETCH_AND_NAND_16:
6322 mode = get_builtin_sync_mode (fcode - BUILT_IN_FETCH_AND_NAND_1);
6323 target = expand_builtin_sync_operation (mode, arglist, NOT,
6324 false, target, ignore);
6325 if (target)
6326 return target;
6327 break;
6328
6329 case BUILT_IN_ADD_AND_FETCH_1:
6330 case BUILT_IN_ADD_AND_FETCH_2:
6331 case BUILT_IN_ADD_AND_FETCH_4:
6332 case BUILT_IN_ADD_AND_FETCH_8:
6333 case BUILT_IN_ADD_AND_FETCH_16:
6334 mode = get_builtin_sync_mode (fcode - BUILT_IN_ADD_AND_FETCH_1);
6335 target = expand_builtin_sync_operation (mode, arglist, PLUS,
6336 true, target, ignore);
6337 if (target)
6338 return target;
6339 break;
6340
6341 case BUILT_IN_SUB_AND_FETCH_1:
6342 case BUILT_IN_SUB_AND_FETCH_2:
6343 case BUILT_IN_SUB_AND_FETCH_4:
6344 case BUILT_IN_SUB_AND_FETCH_8:
6345 case BUILT_IN_SUB_AND_FETCH_16:
6346 mode = get_builtin_sync_mode (fcode - BUILT_IN_SUB_AND_FETCH_1);
6347 target = expand_builtin_sync_operation (mode, arglist, MINUS,
6348 true, target, ignore);
6349 if (target)
6350 return target;
6351 break;
6352
6353 case BUILT_IN_OR_AND_FETCH_1:
6354 case BUILT_IN_OR_AND_FETCH_2:
6355 case BUILT_IN_OR_AND_FETCH_4:
6356 case BUILT_IN_OR_AND_FETCH_8:
6357 case BUILT_IN_OR_AND_FETCH_16:
6358 mode = get_builtin_sync_mode (fcode - BUILT_IN_OR_AND_FETCH_1);
6359 target = expand_builtin_sync_operation (mode, arglist, IOR,
6360 true, target, ignore);
6361 if (target)
6362 return target;
6363 break;
6364
6365 case BUILT_IN_AND_AND_FETCH_1:
6366 case BUILT_IN_AND_AND_FETCH_2:
6367 case BUILT_IN_AND_AND_FETCH_4:
6368 case BUILT_IN_AND_AND_FETCH_8:
6369 case BUILT_IN_AND_AND_FETCH_16:
6370 mode = get_builtin_sync_mode (fcode - BUILT_IN_AND_AND_FETCH_1);
6371 target = expand_builtin_sync_operation (mode, arglist, AND,
6372 true, target, ignore);
6373 if (target)
6374 return target;
6375 break;
6376
6377 case BUILT_IN_XOR_AND_FETCH_1:
6378 case BUILT_IN_XOR_AND_FETCH_2:
6379 case BUILT_IN_XOR_AND_FETCH_4:
6380 case BUILT_IN_XOR_AND_FETCH_8:
6381 case BUILT_IN_XOR_AND_FETCH_16:
6382 mode = get_builtin_sync_mode (fcode - BUILT_IN_XOR_AND_FETCH_1);
6383 target = expand_builtin_sync_operation (mode, arglist, XOR,
6384 true, target, ignore);
6385 if (target)
6386 return target;
6387 break;
6388
6389 case BUILT_IN_NAND_AND_FETCH_1:
6390 case BUILT_IN_NAND_AND_FETCH_2:
6391 case BUILT_IN_NAND_AND_FETCH_4:
6392 case BUILT_IN_NAND_AND_FETCH_8:
6393 case BUILT_IN_NAND_AND_FETCH_16:
6394 mode = get_builtin_sync_mode (fcode - BUILT_IN_NAND_AND_FETCH_1);
6395 target = expand_builtin_sync_operation (mode, arglist, NOT,
6396 true, target, ignore);
6397 if (target)
6398 return target;
6399 break;
6400
6401 case BUILT_IN_BOOL_COMPARE_AND_SWAP_1:
6402 case BUILT_IN_BOOL_COMPARE_AND_SWAP_2:
6403 case BUILT_IN_BOOL_COMPARE_AND_SWAP_4:
6404 case BUILT_IN_BOOL_COMPARE_AND_SWAP_8:
6405 case BUILT_IN_BOOL_COMPARE_AND_SWAP_16:
6406 if (mode == VOIDmode)
6407 mode = TYPE_MODE (boolean_type_node);
6408 if (!target || !register_operand (target, mode))
6409 target = gen_reg_rtx (mode);
6410
6411 mode = get_builtin_sync_mode (fcode - BUILT_IN_BOOL_COMPARE_AND_SWAP_1);
6412 target = expand_builtin_compare_and_swap (mode, arglist, true, target);
6413 if (target)
6414 return target;
6415 break;
6416
6417 case BUILT_IN_VAL_COMPARE_AND_SWAP_1:
6418 case BUILT_IN_VAL_COMPARE_AND_SWAP_2:
6419 case BUILT_IN_VAL_COMPARE_AND_SWAP_4:
6420 case BUILT_IN_VAL_COMPARE_AND_SWAP_8:
6421 case BUILT_IN_VAL_COMPARE_AND_SWAP_16:
6422 mode = get_builtin_sync_mode (fcode - BUILT_IN_VAL_COMPARE_AND_SWAP_1);
6423 target = expand_builtin_compare_and_swap (mode, arglist, false, target);
6424 if (target)
6425 return target;
6426 break;
6427
6428 case BUILT_IN_LOCK_TEST_AND_SET_1:
6429 case BUILT_IN_LOCK_TEST_AND_SET_2:
6430 case BUILT_IN_LOCK_TEST_AND_SET_4:
6431 case BUILT_IN_LOCK_TEST_AND_SET_8:
6432 case BUILT_IN_LOCK_TEST_AND_SET_16:
6433 mode = get_builtin_sync_mode (fcode - BUILT_IN_LOCK_TEST_AND_SET_1);
6434 target = expand_builtin_lock_test_and_set (mode, arglist, target);
6435 if (target)
6436 return target;
6437 break;
6438
6439 case BUILT_IN_LOCK_RELEASE_1:
6440 case BUILT_IN_LOCK_RELEASE_2:
6441 case BUILT_IN_LOCK_RELEASE_4:
6442 case BUILT_IN_LOCK_RELEASE_8:
6443 case BUILT_IN_LOCK_RELEASE_16:
6444 mode = get_builtin_sync_mode (fcode - BUILT_IN_LOCK_RELEASE_1);
6445 expand_builtin_lock_release (mode, arglist);
6446 return const0_rtx;
6447
6448 case BUILT_IN_SYNCHRONIZE:
6449 expand_builtin_synchronize ();
6450 return const0_rtx;
6451
6452 case BUILT_IN_OBJECT_SIZE:
6453 return expand_builtin_object_size (exp);
6454
6455 case BUILT_IN_MEMCPY_CHK:
6456 case BUILT_IN_MEMPCPY_CHK:
6457 case BUILT_IN_MEMMOVE_CHK:
6458 case BUILT_IN_MEMSET_CHK:
6459 target = expand_builtin_memory_chk (exp, target, mode, fcode);
6460 if (target)
6461 return target;
6462 break;
6463
6464 case BUILT_IN_STRCPY_CHK:
6465 case BUILT_IN_STPCPY_CHK:
6466 case BUILT_IN_STRNCPY_CHK:
6467 case BUILT_IN_STRCAT_CHK:
6468 case BUILT_IN_SNPRINTF_CHK:
6469 case BUILT_IN_VSNPRINTF_CHK:
6470 maybe_emit_chk_warning (exp, fcode);
6471 break;
6472
6473 case BUILT_IN_SPRINTF_CHK:
6474 case BUILT_IN_VSPRINTF_CHK:
6475 maybe_emit_sprintf_chk_warning (exp, fcode);
6476 break;
6477
5468 default: /* just do library call, if unknown builtin */
6478 default: /* just do library call, if unknown builtin */
5469 if (!DECL_ASSEMBLER_NAME_SET_P (fndecl))
5470 error ("built-in function `%s' not currently supported",
5471 IDENTIFIER_POINTER (DECL_NAME (fndecl)));
6479 break;
5472 }
5473
5474 /* The switch statement above can drop through to cause the function
5475 to be called normally. */
5476 return expand_call (exp, target, ignore);
5477}
5478
5479/* Determine whether a tree node represents a call to a built-in

--- 80 unchanged lines hidden (view full) ---

5560 arglist = TREE_VALUE (arglist);
5561
5562 /* We return 1 for a numeric type that's known to be a constant
5563 value at compile-time or for an aggregate type that's a
5564 literal constant. */
5565 STRIP_NOPS (arglist);
5566
5567 /* If we know this is a constant, emit the constant of one. */
6480 }
6481
6482 /* The switch statement above can drop through to cause the function
6483 to be called normally. */
6484 return expand_call (exp, target, ignore);
6485}
6486
6487/* Determine whether a tree node represents a call to a built-in

--- 80 unchanged lines hidden (view full) ---

6568 arglist = TREE_VALUE (arglist);
6569
6570 /* We return 1 for a numeric type that's known to be a constant
6571 value at compile-time or for an aggregate type that's a
6572 literal constant. */
6573 STRIP_NOPS (arglist);
6574
6575 /* If we know this is a constant, emit the constant of one. */
5568 if (TREE_CODE_CLASS (TREE_CODE (arglist)) == 'c'
6576 if (CONSTANT_CLASS_P (arglist)
5569 || (TREE_CODE (arglist) == CONSTRUCTOR
6577 || (TREE_CODE (arglist) == CONSTRUCTOR
5570 && TREE_CONSTANT (arglist))
5571 || (TREE_CODE (arglist) == ADDR_EXPR
5572 && TREE_CODE (TREE_OPERAND (arglist, 0)) == STRING_CST))
6578 && TREE_CONSTANT (arglist)))
5573 return integer_one_node;
6579 return integer_one_node;
6580 if (TREE_CODE (arglist) == ADDR_EXPR)
6581 {
6582 tree op = TREE_OPERAND (arglist, 0);
6583 if (TREE_CODE (op) == STRING_CST
6584 || (TREE_CODE (op) == ARRAY_REF
6585 && integer_zerop (TREE_OPERAND (op, 1))
6586 && TREE_CODE (TREE_OPERAND (op, 0)) == STRING_CST))
6587 return integer_one_node;
6588 }
5574
5575 /* If this expression has side effects, show we don't know it to be a
5576 constant. Likewise if it's a pointer or aggregate type since in
5577 those case we only want literals, since those are only optimized
5578 when generating RTL, not later.
5579 And finally, if we are compiling an initializer, not code, we
5580 need to return a definite result now; there's not going to be any
5581 more optimization done. */
5582 if (TREE_SIDE_EFFECTS (arglist)
5583 || AGGREGATE_TYPE_P (TREE_TYPE (arglist))
5584 || POINTER_TYPE_P (TREE_TYPE (arglist))
6589
6590 /* If this expression has side effects, show we don't know it to be a
6591 constant. Likewise if it's a pointer or aggregate type since in
6592 those case we only want literals, since those are only optimized
6593 when generating RTL, not later.
6594 And finally, if we are compiling an initializer, not code, we
6595 need to return a definite result now; there's not going to be any
6596 more optimization done. */
6597 if (TREE_SIDE_EFFECTS (arglist)
6598 || AGGREGATE_TYPE_P (TREE_TYPE (arglist))
6599 || POINTER_TYPE_P (TREE_TYPE (arglist))
5585 || cfun == 0)
6600 || cfun == 0
6601 || folding_initializer)
5586 return integer_zero_node;
5587
5588 return 0;
5589}
5590
6602 return integer_zero_node;
6603
6604 return 0;
6605}
6606
6607/* Fold a call to __builtin_expect, if we expect that a comparison against
6608 the argument will fold to a constant. In practice, this means a true
6609 constant or the address of a non-weak symbol. ARGLIST is the argument
6610 list of the call. */
6611
6612static tree
6613fold_builtin_expect (tree arglist)
6614{
6615 tree arg, inner;
6616
6617 if (arglist == 0)
6618 return 0;
6619
6620 arg = TREE_VALUE (arglist);
6621
6622 /* If the argument isn't invariant, then there's nothing we can do. */
6623 if (!TREE_INVARIANT (arg))
6624 return 0;
6625
6626 /* If we're looking at an address of a weak decl, then do not fold. */
6627 inner = arg;
6628 STRIP_NOPS (inner);
6629 if (TREE_CODE (inner) == ADDR_EXPR)
6630 {
6631 do
6632 {
6633 inner = TREE_OPERAND (inner, 0);
6634 }
6635 while (TREE_CODE (inner) == COMPONENT_REF
6636 || TREE_CODE (inner) == ARRAY_REF);
6637 if (DECL_P (inner) && DECL_WEAK (inner))
6638 return 0;
6639 }
6640
6641 /* Otherwise, ARG already has the proper type for the return value. */
6642 return arg;
6643}
6644
5591/* Fold a call to __builtin_classify_type. */
5592
5593static tree
5594fold_builtin_classify_type (tree arglist)
5595{
5596 if (arglist == 0)
6645/* Fold a call to __builtin_classify_type. */
6646
6647static tree
6648fold_builtin_classify_type (tree arglist)
6649{
6650 if (arglist == 0)
5597 return build_int_2 (no_type_class, 0);
6651 return build_int_cst (NULL_TREE, no_type_class);
5598
6652
5599 return build_int_2 (type_to_class (TREE_TYPE (TREE_VALUE (arglist))), 0);
6653 return build_int_cst (NULL_TREE,
6654 type_to_class (TREE_TYPE (TREE_VALUE (arglist))));
5600}
5601
6655}
6656
6657/* Fold a call to __builtin_strlen. */
6658
6659static tree
6660fold_builtin_strlen (tree arglist)
6661{
6662 if (!validate_arglist (arglist, POINTER_TYPE, VOID_TYPE))
6663 return NULL_TREE;
6664 else
6665 {
6666 tree len = c_strlen (TREE_VALUE (arglist), 0);
6667
6668 if (len)
6669 {
6670 /* Convert from the internal "sizetype" type to "size_t". */
6671 if (size_type_node)
6672 len = fold_convert (size_type_node, len);
6673 return len;
6674 }
6675
6676 return NULL_TREE;
6677 }
6678}
6679
5602/* Fold a call to __builtin_inf or __builtin_huge_val. */
5603
5604static tree
5605fold_builtin_inf (tree type, int warn)
5606{
5607 REAL_VALUE_TYPE real;
5608
6680/* Fold a call to __builtin_inf or __builtin_huge_val. */
6681
6682static tree
6683fold_builtin_inf (tree type, int warn)
6684{
6685 REAL_VALUE_TYPE real;
6686
6687 /* __builtin_inff is intended to be usable to define INFINITY on all
6688 targets. If an infinity is not available, INFINITY expands "to a
6689 positive constant of type float that overflows at translation
6690 time", footnote "In this case, using INFINITY will violate the
6691 constraint in 6.4.4 and thus require a diagnostic." (C99 7.12#4).
6692 Thus we pedwarn to ensure this constraint violation is
6693 diagnosed. */
5609 if (!MODE_HAS_INFINITIES (TYPE_MODE (type)) && warn)
6694 if (!MODE_HAS_INFINITIES (TYPE_MODE (type)) && warn)
5610 warning ("target format does not support infinity");
6695 pedwarn ("target format does not support infinity");
5611
5612 real_inf (&real);
5613 return build_real (type, real);
5614}
5615
5616/* Fold a call to __builtin_nan or __builtin_nans. */
5617
5618static tree

--- 45 unchanged lines hidden (view full) ---

5664
5665 case COND_EXPR:
5666 return integer_valued_real_p (TREE_OPERAND (t, 1))
5667 && integer_valued_real_p (TREE_OPERAND (t, 2));
5668
5669 case REAL_CST:
5670 if (! TREE_CONSTANT_OVERFLOW (t))
5671 {
6696
6697 real_inf (&real);
6698 return build_real (type, real);
6699}
6700
6701/* Fold a call to __builtin_nan or __builtin_nans. */
6702
6703static tree

--- 45 unchanged lines hidden (view full) ---

6749
6750 case COND_EXPR:
6751 return integer_valued_real_p (TREE_OPERAND (t, 1))
6752 && integer_valued_real_p (TREE_OPERAND (t, 2));
6753
6754 case REAL_CST:
6755 if (! TREE_CONSTANT_OVERFLOW (t))
6756 {
5672 REAL_VALUE_TYPE c, cint;
6757 REAL_VALUE_TYPE c, cint;
5673
5674 c = TREE_REAL_CST (t);
5675 real_trunc (&cint, TYPE_MODE (TREE_TYPE (t)), &c);
5676 return real_identical (&c, &cint);
5677 }
6758
6759 c = TREE_REAL_CST (t);
6760 real_trunc (&cint, TYPE_MODE (TREE_TYPE (t)), &c);
6761 return real_identical (&c, &cint);
6762 }
6763 break;
5678
5679 case NOP_EXPR:
5680 {
5681 tree type = TREE_TYPE (TREE_OPERAND (t, 0));
5682 if (TREE_CODE (type) == INTEGER_TYPE)
5683 return true;
5684 if (TREE_CODE (type) == REAL_TYPE)
5685 return integer_valued_real_p (TREE_OPERAND (t, 0));
5686 break;
5687 }
5688
5689 case CALL_EXPR:
5690 switch (builtin_mathfn_code (t))
5691 {
6764
6765 case NOP_EXPR:
6766 {
6767 tree type = TREE_TYPE (TREE_OPERAND (t, 0));
6768 if (TREE_CODE (type) == INTEGER_TYPE)
6769 return true;
6770 if (TREE_CODE (type) == REAL_TYPE)
6771 return integer_valued_real_p (TREE_OPERAND (t, 0));
6772 break;
6773 }
6774
6775 case CALL_EXPR:
6776 switch (builtin_mathfn_code (t))
6777 {
5692 case BUILT_IN_CEIL:
5693 case BUILT_IN_CEILF:
5694 case BUILT_IN_CEILL:
5695 case BUILT_IN_FLOOR:
5696 case BUILT_IN_FLOORF:
5697 case BUILT_IN_FLOORL:
5698 case BUILT_IN_NEARBYINT:
5699 case BUILT_IN_NEARBYINTF:
5700 case BUILT_IN_NEARBYINTL:
5701 case BUILT_IN_ROUND:
5702 case BUILT_IN_ROUNDF:
5703 case BUILT_IN_ROUNDL:
5704 case BUILT_IN_TRUNC:
5705 case BUILT_IN_TRUNCF:
5706 case BUILT_IN_TRUNCL:
6778 CASE_FLT_FN (BUILT_IN_CEIL):
6779 CASE_FLT_FN (BUILT_IN_FLOOR):
6780 CASE_FLT_FN (BUILT_IN_NEARBYINT):
6781 CASE_FLT_FN (BUILT_IN_RINT):
6782 CASE_FLT_FN (BUILT_IN_ROUND):
6783 CASE_FLT_FN (BUILT_IN_TRUNC):
5707 return true;
5708
5709 default:
5710 break;
5711 }
5712 break;
5713
5714 default:
5715 break;
5716 }
5717 return false;
5718}
5719
5720/* EXP is assumed to be builtin call where truncation can be propagated
5721 across (for instance floor((double)f) == (double)floorf (f).
5722 Do the transformation. */
5723
5724static tree
6784 return true;
6785
6786 default:
6787 break;
6788 }
6789 break;
6790
6791 default:
6792 break;
6793 }
6794 return false;
6795}
6796
6797/* EXP is assumed to be builtin call where truncation can be propagated
6798 across (for instance floor((double)f) == (double)floorf (f).
6799 Do the transformation. */
6800
6801static tree
5725fold_trunc_transparent_mathfn (tree exp)
6802fold_trunc_transparent_mathfn (tree fndecl, tree arglist)
5726{
6803{
5727 tree fndecl = get_callee_fndecl (exp);
5728 tree arglist = TREE_OPERAND (exp, 1);
5729 enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
5730 tree arg;
5731
5732 if (! validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
5733 return 0;
5734
5735 arg = TREE_VALUE (arglist);
5736 /* Integer rounding functions are idempotent. */
5737 if (fcode == builtin_mathfn_code (arg))
5738 return arg;
5739
5740 /* If argument is already integer valued, and we don't need to worry
5741 about setting errno, there's no need to perform rounding. */
5742 if (! flag_errno_math && integer_valued_real_p (arg))
5743 return arg;
5744
5745 if (optimize)
5746 {
5747 tree arg0 = strip_float_extensions (arg);
6804 enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
6805 tree arg;
6806
6807 if (! validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
6808 return 0;
6809
6810 arg = TREE_VALUE (arglist);
6811 /* Integer rounding functions are idempotent. */
6812 if (fcode == builtin_mathfn_code (arg))
6813 return arg;
6814
6815 /* If argument is already integer valued, and we don't need to worry
6816 about setting errno, there's no need to perform rounding. */
6817 if (! flag_errno_math && integer_valued_real_p (arg))
6818 return arg;
6819
6820 if (optimize)
6821 {
6822 tree arg0 = strip_float_extensions (arg);
5748 tree ftype = TREE_TYPE (exp);
6823 tree ftype = TREE_TYPE (TREE_TYPE (fndecl));
5749 tree newtype = TREE_TYPE (arg0);
5750 tree decl;
5751
5752 if (TYPE_PRECISION (newtype) < TYPE_PRECISION (ftype)
5753 && (decl = mathfn_built_in (newtype, fcode)))
5754 {
5755 arglist =
6824 tree newtype = TREE_TYPE (arg0);
6825 tree decl;
6826
6827 if (TYPE_PRECISION (newtype) < TYPE_PRECISION (ftype)
6828 && (decl = mathfn_built_in (newtype, fcode)))
6829 {
6830 arglist =
5756 build_tree_list (NULL_TREE, fold (convert (newtype, arg0)));
5757 return convert (ftype,
5758 build_function_call_expr (decl, arglist));
6831 build_tree_list (NULL_TREE, fold_convert (newtype, arg0));
6832 return fold_convert (ftype,
6833 build_function_call_expr (decl, arglist));
5759 }
5760 }
5761 return 0;
5762}
5763
6834 }
6835 }
6836 return 0;
6837}
6838
5764/* Fold function call to builtin cabs, cabsf or cabsl. FNDECL is the
5765 function's DECL, ARGLIST is the argument list and TYPE is the return
5766 type. Return NULL_TREE if no simplification can be made. */
6839/* EXP is assumed to be builtin call which can narrow the FP type of
6840 the argument, for instance lround((double)f) -> lroundf (f). */
5767
5768static tree
6841
6842static tree
5769fold_builtin_cabs (tree fndecl, tree arglist, tree type)
6843fold_fixed_mathfn (tree fndecl, tree arglist)
5770{
6844{
6845 enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
5771 tree arg;
5772
6846 tree arg;
6847
6848 if (! validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
6849 return 0;
6850
6851 arg = TREE_VALUE (arglist);
6852
6853 /* If argument is already integer valued, and we don't need to worry
6854 about setting errno, there's no need to perform rounding. */
6855 if (! flag_errno_math && integer_valued_real_p (arg))
6856 return fold_build1 (FIX_TRUNC_EXPR, TREE_TYPE (TREE_TYPE (fndecl)), arg);
6857
6858 if (optimize)
6859 {
6860 tree ftype = TREE_TYPE (arg);
6861 tree arg0 = strip_float_extensions (arg);
6862 tree newtype = TREE_TYPE (arg0);
6863 tree decl;
6864
6865 if (TYPE_PRECISION (newtype) < TYPE_PRECISION (ftype)
6866 && (decl = mathfn_built_in (newtype, fcode)))
6867 {
6868 arglist =
6869 build_tree_list (NULL_TREE, fold_convert (newtype, arg0));
6870 return build_function_call_expr (decl, arglist);
6871 }
6872 }
6873
6874 /* Canonicalize llround (x) to lround (x) on LP64 targets where
6875 sizeof (long long) == sizeof (long). */
6876 if (TYPE_PRECISION (long_long_integer_type_node)
6877 == TYPE_PRECISION (long_integer_type_node))
6878 {
6879 tree newfn = NULL_TREE;
6880 switch (fcode)
6881 {
6882 CASE_FLT_FN (BUILT_IN_LLCEIL):
6883 newfn = mathfn_built_in (TREE_TYPE (arg), BUILT_IN_LCEIL);
6884 break;
6885
6886 CASE_FLT_FN (BUILT_IN_LLFLOOR):
6887 newfn = mathfn_built_in (TREE_TYPE (arg), BUILT_IN_LFLOOR);
6888 break;
6889
6890 CASE_FLT_FN (BUILT_IN_LLROUND):
6891 newfn = mathfn_built_in (TREE_TYPE (arg), BUILT_IN_LROUND);
6892 break;
6893
6894 CASE_FLT_FN (BUILT_IN_LLRINT):
6895 newfn = mathfn_built_in (TREE_TYPE (arg), BUILT_IN_LRINT);
6896 break;
6897
6898 default:
6899 break;
6900 }
6901
6902 if (newfn)
6903 {
6904 tree newcall = build_function_call_expr (newfn, arglist);
6905 return fold_convert (TREE_TYPE (TREE_TYPE (fndecl)), newcall);
6906 }
6907 }
6908
6909 return 0;
6910}
6911
6912/* Fold function call to builtin cabs, cabsf or cabsl. ARGLIST
6913 is the argument list, TYPE is the return type and FNDECL is the
6914 original function DECL. Return NULL_TREE if no if no simplification
6915 can be made. */
6916
6917static tree
6918fold_builtin_cabs (tree arglist, tree type, tree fndecl)
6919{
6920 tree arg;
6921
5773 if (!arglist || TREE_CHAIN (arglist))
5774 return NULL_TREE;
5775
5776 arg = TREE_VALUE (arglist);
5777 if (TREE_CODE (TREE_TYPE (arg)) != COMPLEX_TYPE
5778 || TREE_CODE (TREE_TYPE (TREE_TYPE (arg))) != REAL_TYPE)
5779 return NULL_TREE;
5780

--- 16 unchanged lines hidden (view full) ---

5797 if (real_sqrt (&r, TYPE_MODE (type), &r)
5798 || ! flag_trapping_math)
5799 return build_real (type, r);
5800 }
5801
5802 /* If either part is zero, cabs is fabs of the other. */
5803 if (TREE_CODE (arg) == COMPLEX_EXPR
5804 && real_zerop (TREE_OPERAND (arg, 0)))
6922 if (!arglist || TREE_CHAIN (arglist))
6923 return NULL_TREE;
6924
6925 arg = TREE_VALUE (arglist);
6926 if (TREE_CODE (TREE_TYPE (arg)) != COMPLEX_TYPE
6927 || TREE_CODE (TREE_TYPE (TREE_TYPE (arg))) != REAL_TYPE)
6928 return NULL_TREE;
6929

--- 16 unchanged lines hidden (view full) ---

6946 if (real_sqrt (&r, TYPE_MODE (type), &r)
6947 || ! flag_trapping_math)
6948 return build_real (type, r);
6949 }
6950
6951 /* If either part is zero, cabs is fabs of the other. */
6952 if (TREE_CODE (arg) == COMPLEX_EXPR
6953 && real_zerop (TREE_OPERAND (arg, 0)))
5805 return fold (build1 (ABS_EXPR, type, TREE_OPERAND (arg, 1)));
6954 return fold_build1 (ABS_EXPR, type, TREE_OPERAND (arg, 1));
5806 if (TREE_CODE (arg) == COMPLEX_EXPR
5807 && real_zerop (TREE_OPERAND (arg, 1)))
6955 if (TREE_CODE (arg) == COMPLEX_EXPR
6956 && real_zerop (TREE_OPERAND (arg, 1)))
5808 return fold (build1 (ABS_EXPR, type, TREE_OPERAND (arg, 0)));
6957 return fold_build1 (ABS_EXPR, type, TREE_OPERAND (arg, 0));
5809
6958
5810 if (flag_unsafe_math_optimizations)
6959 /* Optimize cabs(-z) and cabs(conj(z)) as cabs(z). */
6960 if (TREE_CODE (arg) == NEGATE_EXPR
6961 || TREE_CODE (arg) == CONJ_EXPR)
5811 {
6962 {
5812 enum built_in_function fcode;
5813 tree sqrtfn;
6963 tree arglist = build_tree_list (NULL_TREE, TREE_OPERAND (arg, 0));
6964 return build_function_call_expr (fndecl, arglist);
6965 }
5814
6966
5815 fcode = DECL_FUNCTION_CODE (fndecl);
5816 if (fcode == BUILT_IN_CABS)
5817 sqrtfn = implicit_built_in_decls[BUILT_IN_SQRT];
5818 else if (fcode == BUILT_IN_CABSF)
5819 sqrtfn = implicit_built_in_decls[BUILT_IN_SQRTF];
5820 else if (fcode == BUILT_IN_CABSL)
5821 sqrtfn = implicit_built_in_decls[BUILT_IN_SQRTL];
5822 else
5823 sqrtfn = NULL_TREE;
6967 /* Don't do this when optimizing for size. */
6968 if (flag_unsafe_math_optimizations
6969 && optimize && !optimize_size)
6970 {
6971 tree sqrtfn = mathfn_built_in (type, BUILT_IN_SQRT);
5824
5825 if (sqrtfn != NULL_TREE)
5826 {
5827 tree rpart, ipart, result, arglist;
5828
6972
6973 if (sqrtfn != NULL_TREE)
6974 {
6975 tree rpart, ipart, result, arglist;
6976
5829 arg = save_expr (arg);
6977 arg = builtin_save_expr (arg);
5830
6978
5831 rpart = fold (build1 (REALPART_EXPR, type, arg));
5832 ipart = fold (build1 (IMAGPART_EXPR, type, arg));
6979 rpart = fold_build1 (REALPART_EXPR, type, arg);
6980 ipart = fold_build1 (IMAGPART_EXPR, type, arg);
5833
6981
5834 rpart = save_expr (rpart);
5835 ipart = save_expr (ipart);
6982 rpart = builtin_save_expr (rpart);
6983 ipart = builtin_save_expr (ipart);
5836
6984
5837 result = fold (build (PLUS_EXPR, type,
5838 fold (build (MULT_EXPR, type,
5839 rpart, rpart)),
5840 fold (build (MULT_EXPR, type,
5841 ipart, ipart))));
6985 result = fold_build2 (PLUS_EXPR, type,
6986 fold_build2 (MULT_EXPR, type,
6987 rpart, rpart),
6988 fold_build2 (MULT_EXPR, type,
6989 ipart, ipart));
5842
5843 arglist = build_tree_list (NULL_TREE, result);
5844 return build_function_call_expr (sqrtfn, arglist);
5845 }
5846 }
5847
5848 return NULL_TREE;
5849}
5850
6990
6991 arglist = build_tree_list (NULL_TREE, result);
6992 return build_function_call_expr (sqrtfn, arglist);
6993 }
6994 }
6995
6996 return NULL_TREE;
6997}
6998
6999/* Fold a builtin function call to sqrt, sqrtf, or sqrtl. Return
7000 NULL_TREE if no simplification can be made. */
7001
7002static tree
7003fold_builtin_sqrt (tree arglist, tree type)
7004{
7005
7006 enum built_in_function fcode;
7007 tree arg = TREE_VALUE (arglist);
7008
7009 if (!validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
7010 return NULL_TREE;
7011
7012 /* Optimize sqrt of constant value. */
7013 if (TREE_CODE (arg) == REAL_CST
7014 && ! TREE_CONSTANT_OVERFLOW (arg))
7015 {
7016 REAL_VALUE_TYPE r, x;
7017
7018 x = TREE_REAL_CST (arg);
7019 if (real_sqrt (&r, TYPE_MODE (type), &x)
7020 || (!flag_trapping_math && !flag_errno_math))
7021 return build_real (type, r);
7022 }
7023
7024 /* Optimize sqrt(expN(x)) = expN(x*0.5). */
7025 fcode = builtin_mathfn_code (arg);
7026 if (flag_unsafe_math_optimizations && BUILTIN_EXPONENT_P (fcode))
7027 {
7028 tree expfn = TREE_OPERAND (TREE_OPERAND (arg, 0), 0);
7029 arg = fold_build2 (MULT_EXPR, type,
7030 TREE_VALUE (TREE_OPERAND (arg, 1)),
7031 build_real (type, dconsthalf));
7032 arglist = build_tree_list (NULL_TREE, arg);
7033 return build_function_call_expr (expfn, arglist);
7034 }
7035
7036 /* Optimize sqrt(Nroot(x)) -> pow(x,1/(2*N)). */
7037 if (flag_unsafe_math_optimizations && BUILTIN_ROOT_P (fcode))
7038 {
7039 tree powfn = mathfn_built_in (type, BUILT_IN_POW);
7040
7041 if (powfn)
7042 {
7043 tree arg0 = TREE_VALUE (TREE_OPERAND (arg, 1));
7044 tree tree_root;
7045 /* The inner root was either sqrt or cbrt. */
7046 REAL_VALUE_TYPE dconstroot =
7047 BUILTIN_SQRT_P (fcode) ? dconsthalf : dconstthird;
7048
7049 /* Adjust for the outer root. */
7050 SET_REAL_EXP (&dconstroot, REAL_EXP (&dconstroot) - 1);
7051 dconstroot = real_value_truncate (TYPE_MODE (type), dconstroot);
7052 tree_root = build_real (type, dconstroot);
7053 arglist = tree_cons (NULL_TREE, arg0,
7054 build_tree_list (NULL_TREE, tree_root));
7055 return build_function_call_expr (powfn, arglist);
7056 }
7057 }
7058
7059 /* Optimize sqrt(pow(x,y)) = pow(|x|,y*0.5). */
7060 if (flag_unsafe_math_optimizations
7061 && (fcode == BUILT_IN_POW
7062 || fcode == BUILT_IN_POWF
7063 || fcode == BUILT_IN_POWL))
7064 {
7065 tree powfn = TREE_OPERAND (TREE_OPERAND (arg, 0), 0);
7066 tree arg0 = TREE_VALUE (TREE_OPERAND (arg, 1));
7067 tree arg1 = TREE_VALUE (TREE_CHAIN (TREE_OPERAND (arg, 1)));
7068 tree narg1;
7069 if (!tree_expr_nonnegative_p (arg0))
7070 arg0 = build1 (ABS_EXPR, type, arg0);
7071 narg1 = fold_build2 (MULT_EXPR, type, arg1,
7072 build_real (type, dconsthalf));
7073 arglist = tree_cons (NULL_TREE, arg0,
7074 build_tree_list (NULL_TREE, narg1));
7075 return build_function_call_expr (powfn, arglist);
7076 }
7077
7078 return NULL_TREE;
7079}
7080
7081/* Fold a builtin function call to cbrt, cbrtf, or cbrtl. Return
7082 NULL_TREE if no simplification can be made. */
7083static tree
7084fold_builtin_cbrt (tree arglist, tree type)
7085{
7086 tree arg = TREE_VALUE (arglist);
7087 const enum built_in_function fcode = builtin_mathfn_code (arg);
7088
7089 if (!validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
7090 return NULL_TREE;
7091
7092 /* Optimize cbrt of constant value. */
7093 if (real_zerop (arg) || real_onep (arg) || real_minus_onep (arg))
7094 return arg;
7095
7096 if (flag_unsafe_math_optimizations)
7097 {
7098 /* Optimize cbrt(expN(x)) -> expN(x/3). */
7099 if (BUILTIN_EXPONENT_P (fcode))
7100 {
7101 tree expfn = TREE_OPERAND (TREE_OPERAND (arg, 0), 0);
7102 const REAL_VALUE_TYPE third_trunc =
7103 real_value_truncate (TYPE_MODE (type), dconstthird);
7104 arg = fold_build2 (MULT_EXPR, type,
7105 TREE_VALUE (TREE_OPERAND (arg, 1)),
7106 build_real (type, third_trunc));
7107 arglist = build_tree_list (NULL_TREE, arg);
7108 return build_function_call_expr (expfn, arglist);
7109 }
7110
7111 /* Optimize cbrt(sqrt(x)) -> pow(x,1/6). */
7112 if (BUILTIN_SQRT_P (fcode))
7113 {
7114 tree powfn = mathfn_built_in (type, BUILT_IN_POW);
7115
7116 if (powfn)
7117 {
7118 tree arg0 = TREE_VALUE (TREE_OPERAND (arg, 1));
7119 tree tree_root;
7120 REAL_VALUE_TYPE dconstroot = dconstthird;
7121
7122 SET_REAL_EXP (&dconstroot, REAL_EXP (&dconstroot) - 1);
7123 dconstroot = real_value_truncate (TYPE_MODE (type), dconstroot);
7124 tree_root = build_real (type, dconstroot);
7125 arglist = tree_cons (NULL_TREE, arg0,
7126 build_tree_list (NULL_TREE, tree_root));
7127 return build_function_call_expr (powfn, arglist);
7128 }
7129 }
7130
7131 /* Optimize cbrt(cbrt(x)) -> pow(x,1/9) iff x is nonnegative. */
7132 if (BUILTIN_CBRT_P (fcode))
7133 {
7134 tree arg0 = TREE_VALUE (TREE_OPERAND (arg, 1));
7135 if (tree_expr_nonnegative_p (arg0))
7136 {
7137 tree powfn = mathfn_built_in (type, BUILT_IN_POW);
7138
7139 if (powfn)
7140 {
7141 tree tree_root;
7142 REAL_VALUE_TYPE dconstroot;
7143
7144 real_arithmetic (&dconstroot, MULT_EXPR, &dconstthird, &dconstthird);
7145 dconstroot = real_value_truncate (TYPE_MODE (type), dconstroot);
7146 tree_root = build_real (type, dconstroot);
7147 arglist = tree_cons (NULL_TREE, arg0,
7148 build_tree_list (NULL_TREE, tree_root));
7149 return build_function_call_expr (powfn, arglist);
7150 }
7151 }
7152 }
7153
7154 /* Optimize cbrt(pow(x,y)) -> pow(x,y/3) iff x is nonnegative. */
7155 if (fcode == BUILT_IN_POW || fcode == BUILT_IN_POWF
7156 || fcode == BUILT_IN_POWL)
7157 {
7158 tree arg00 = TREE_VALUE (TREE_OPERAND (arg, 1));
7159 tree arg01 = TREE_VALUE (TREE_CHAIN (TREE_OPERAND (arg, 1)));
7160 if (tree_expr_nonnegative_p (arg00))
7161 {
7162 tree powfn = TREE_OPERAND (TREE_OPERAND (arg, 0), 0);
7163 const REAL_VALUE_TYPE dconstroot
7164 = real_value_truncate (TYPE_MODE (type), dconstthird);
7165 tree narg01 = fold_build2 (MULT_EXPR, type, arg01,
7166 build_real (type, dconstroot));
7167 arglist = tree_cons (NULL_TREE, arg00,
7168 build_tree_list (NULL_TREE, narg01));
7169 return build_function_call_expr (powfn, arglist);
7170 }
7171 }
7172 }
7173 return NULL_TREE;
7174}
7175
7176/* Fold function call to builtin sin, sinf, or sinl. Return
7177 NULL_TREE if no simplification can be made. */
7178static tree
7179fold_builtin_sin (tree arglist)
7180{
7181 tree arg = TREE_VALUE (arglist);
7182
7183 if (!validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
7184 return NULL_TREE;
7185
7186 /* Optimize sin (0.0) = 0.0. */
7187 if (real_zerop (arg))
7188 return arg;
7189
7190 return NULL_TREE;
7191}
7192
7193/* Fold function call to builtin cos, cosf, or cosl. Return
7194 NULL_TREE if no simplification can be made. */
7195static tree
7196fold_builtin_cos (tree arglist, tree type, tree fndecl)
7197{
7198 tree arg = TREE_VALUE (arglist);
7199
7200 if (!validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
7201 return NULL_TREE;
7202
7203 /* Optimize cos (0.0) = 1.0. */
7204 if (real_zerop (arg))
7205 return build_real (type, dconst1);
7206
7207 /* Optimize cos(-x) into cos (x). */
7208 if (TREE_CODE (arg) == NEGATE_EXPR)
7209 {
7210 tree args = build_tree_list (NULL_TREE,
7211 TREE_OPERAND (arg, 0));
7212 return build_function_call_expr (fndecl, args);
7213 }
7214
7215 return NULL_TREE;
7216}
7217
7218/* Fold function call to builtin tan, tanf, or tanl. Return
7219 NULL_TREE if no simplification can be made. */
7220static tree
7221fold_builtin_tan (tree arglist)
7222{
7223 enum built_in_function fcode;
7224 tree arg = TREE_VALUE (arglist);
7225
7226 if (!validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
7227 return NULL_TREE;
7228
7229 /* Optimize tan(0.0) = 0.0. */
7230 if (real_zerop (arg))
7231 return arg;
7232
7233 /* Optimize tan(atan(x)) = x. */
7234 fcode = builtin_mathfn_code (arg);
7235 if (flag_unsafe_math_optimizations
7236 && (fcode == BUILT_IN_ATAN
7237 || fcode == BUILT_IN_ATANF
7238 || fcode == BUILT_IN_ATANL))
7239 return TREE_VALUE (TREE_OPERAND (arg, 1));
7240
7241 return NULL_TREE;
7242}
7243
7244/* Fold function call to builtin atan, atanf, or atanl. Return
7245 NULL_TREE if no simplification can be made. */
7246
7247static tree
7248fold_builtin_atan (tree arglist, tree type)
7249{
7250
7251 tree arg = TREE_VALUE (arglist);
7252
7253 if (!validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
7254 return NULL_TREE;
7255
7256 /* Optimize atan(0.0) = 0.0. */
7257 if (real_zerop (arg))
7258 return arg;
7259
7260 /* Optimize atan(1.0) = pi/4. */
7261 if (real_onep (arg))
7262 {
7263 REAL_VALUE_TYPE cst;
7264
7265 real_convert (&cst, TYPE_MODE (type), &dconstpi);
7266 SET_REAL_EXP (&cst, REAL_EXP (&cst) - 2);
7267 return build_real (type, cst);
7268 }
7269
7270 return NULL_TREE;
7271}
7272
5851/* Fold function call to builtin trunc, truncf or truncl. Return
5852 NULL_TREE if no simplification can be made. */
5853
5854static tree
7273/* Fold function call to builtin trunc, truncf or truncl. Return
7274 NULL_TREE if no simplification can be made. */
7275
7276static tree
5855fold_builtin_trunc (tree exp)
7277fold_builtin_trunc (tree fndecl, tree arglist)
5856{
7278{
5857 tree arglist = TREE_OPERAND (exp, 1);
5858 tree arg;
5859
5860 if (! validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
5861 return 0;
5862
5863 /* Optimize trunc of constant value. */
5864 arg = TREE_VALUE (arglist);
5865 if (TREE_CODE (arg) == REAL_CST && ! TREE_CONSTANT_OVERFLOW (arg))
5866 {
5867 REAL_VALUE_TYPE r, x;
7279 tree arg;
7280
7281 if (! validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
7282 return 0;
7283
7284 /* Optimize trunc of constant value. */
7285 arg = TREE_VALUE (arglist);
7286 if (TREE_CODE (arg) == REAL_CST && ! TREE_CONSTANT_OVERFLOW (arg))
7287 {
7288 REAL_VALUE_TYPE r, x;
5868 tree type = TREE_TYPE (exp);
7289 tree type = TREE_TYPE (TREE_TYPE (fndecl));
5869
5870 x = TREE_REAL_CST (arg);
5871 real_trunc (&r, TYPE_MODE (type), &x);
5872 return build_real (type, r);
5873 }
5874
7290
7291 x = TREE_REAL_CST (arg);
7292 real_trunc (&r, TYPE_MODE (type), &x);
7293 return build_real (type, r);
7294 }
7295
5875 return fold_trunc_transparent_mathfn (exp);
7296 return fold_trunc_transparent_mathfn (fndecl, arglist);
5876}
5877
5878/* Fold function call to builtin floor, floorf or floorl. Return
5879 NULL_TREE if no simplification can be made. */
5880
5881static tree
7297}
7298
7299/* Fold function call to builtin floor, floorf or floorl. Return
7300 NULL_TREE if no simplification can be made. */
7301
7302static tree
5882fold_builtin_floor (tree exp)
7303fold_builtin_floor (tree fndecl, tree arglist)
5883{
7304{
5884 tree arglist = TREE_OPERAND (exp, 1);
5885 tree arg;
5886
5887 if (! validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
5888 return 0;
5889
5890 /* Optimize floor of constant value. */
5891 arg = TREE_VALUE (arglist);
5892 if (TREE_CODE (arg) == REAL_CST && ! TREE_CONSTANT_OVERFLOW (arg))
5893 {
5894 REAL_VALUE_TYPE x;
5895
5896 x = TREE_REAL_CST (arg);
5897 if (! REAL_VALUE_ISNAN (x) || ! flag_errno_math)
5898 {
7305 tree arg;
7306
7307 if (! validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
7308 return 0;
7309
7310 /* Optimize floor of constant value. */
7311 arg = TREE_VALUE (arglist);
7312 if (TREE_CODE (arg) == REAL_CST && ! TREE_CONSTANT_OVERFLOW (arg))
7313 {
7314 REAL_VALUE_TYPE x;
7315
7316 x = TREE_REAL_CST (arg);
7317 if (! REAL_VALUE_ISNAN (x) || ! flag_errno_math)
7318 {
5899 tree type = TREE_TYPE (exp);
7319 tree type = TREE_TYPE (TREE_TYPE (fndecl));
5900 REAL_VALUE_TYPE r;
5901
5902 real_floor (&r, TYPE_MODE (type), &x);
5903 return build_real (type, r);
5904 }
5905 }
5906
7320 REAL_VALUE_TYPE r;
7321
7322 real_floor (&r, TYPE_MODE (type), &x);
7323 return build_real (type, r);
7324 }
7325 }
7326
5907 return fold_trunc_transparent_mathfn (exp);
7327 return fold_trunc_transparent_mathfn (fndecl, arglist);
5908}
5909
5910/* Fold function call to builtin ceil, ceilf or ceill. Return
5911 NULL_TREE if no simplification can be made. */
5912
5913static tree
7328}
7329
7330/* Fold function call to builtin ceil, ceilf or ceill. Return
7331 NULL_TREE if no simplification can be made. */
7332
7333static tree
5914fold_builtin_ceil (tree exp)
7334fold_builtin_ceil (tree fndecl, tree arglist)
5915{
7335{
5916 tree arglist = TREE_OPERAND (exp, 1);
5917 tree arg;
5918
5919 if (! validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
5920 return 0;
5921
5922 /* Optimize ceil of constant value. */
5923 arg = TREE_VALUE (arglist);
5924 if (TREE_CODE (arg) == REAL_CST && ! TREE_CONSTANT_OVERFLOW (arg))
5925 {
5926 REAL_VALUE_TYPE x;
5927
5928 x = TREE_REAL_CST (arg);
5929 if (! REAL_VALUE_ISNAN (x) || ! flag_errno_math)
5930 {
7336 tree arg;
7337
7338 if (! validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
7339 return 0;
7340
7341 /* Optimize ceil of constant value. */
7342 arg = TREE_VALUE (arglist);
7343 if (TREE_CODE (arg) == REAL_CST && ! TREE_CONSTANT_OVERFLOW (arg))
7344 {
7345 REAL_VALUE_TYPE x;
7346
7347 x = TREE_REAL_CST (arg);
7348 if (! REAL_VALUE_ISNAN (x) || ! flag_errno_math)
7349 {
5931 tree type = TREE_TYPE (exp);
7350 tree type = TREE_TYPE (TREE_TYPE (fndecl));
5932 REAL_VALUE_TYPE r;
5933
5934 real_ceil (&r, TYPE_MODE (type), &x);
5935 return build_real (type, r);
5936 }
5937 }
5938
7351 REAL_VALUE_TYPE r;
7352
7353 real_ceil (&r, TYPE_MODE (type), &x);
7354 return build_real (type, r);
7355 }
7356 }
7357
5939 return fold_trunc_transparent_mathfn (exp);
7358 return fold_trunc_transparent_mathfn (fndecl, arglist);
5940}
5941
7359}
7360
7361/* Fold function call to builtin round, roundf or roundl. Return
7362 NULL_TREE if no simplification can be made. */
7363
7364static tree
7365fold_builtin_round (tree fndecl, tree arglist)
7366{
7367 tree arg;
7368
7369 if (! validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
7370 return 0;
7371
7372 /* Optimize round of constant value. */
7373 arg = TREE_VALUE (arglist);
7374 if (TREE_CODE (arg) == REAL_CST && ! TREE_CONSTANT_OVERFLOW (arg))
7375 {
7376 REAL_VALUE_TYPE x;
7377
7378 x = TREE_REAL_CST (arg);
7379 if (! REAL_VALUE_ISNAN (x) || ! flag_errno_math)
7380 {
7381 tree type = TREE_TYPE (TREE_TYPE (fndecl));
7382 REAL_VALUE_TYPE r;
7383
7384 real_round (&r, TYPE_MODE (type), &x);
7385 return build_real (type, r);
7386 }
7387 }
7388
7389 return fold_trunc_transparent_mathfn (fndecl, arglist);
7390}
7391
7392/* Fold function call to builtin lround, lroundf or lroundl (or the
7393 corresponding long long versions) and other rounding functions.
7394 Return NULL_TREE if no simplification can be made. */
7395
7396static tree
7397fold_builtin_int_roundingfn (tree fndecl, tree arglist)
7398{
7399 tree arg;
7400
7401 if (! validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
7402 return 0;
7403
7404 /* Optimize lround of constant value. */
7405 arg = TREE_VALUE (arglist);
7406 if (TREE_CODE (arg) == REAL_CST && ! TREE_CONSTANT_OVERFLOW (arg))
7407 {
7408 const REAL_VALUE_TYPE x = TREE_REAL_CST (arg);
7409
7410 if (! REAL_VALUE_ISNAN (x) && ! REAL_VALUE_ISINF (x))
7411 {
7412 tree itype = TREE_TYPE (TREE_TYPE (fndecl));
7413 tree ftype = TREE_TYPE (arg), result;
7414 HOST_WIDE_INT hi, lo;
7415 REAL_VALUE_TYPE r;
7416
7417 switch (DECL_FUNCTION_CODE (fndecl))
7418 {
7419 CASE_FLT_FN (BUILT_IN_LFLOOR):
7420 CASE_FLT_FN (BUILT_IN_LLFLOOR):
7421 real_floor (&r, TYPE_MODE (ftype), &x);
7422 break;
7423
7424 CASE_FLT_FN (BUILT_IN_LCEIL):
7425 CASE_FLT_FN (BUILT_IN_LLCEIL):
7426 real_ceil (&r, TYPE_MODE (ftype), &x);
7427 break;
7428
7429 CASE_FLT_FN (BUILT_IN_LROUND):
7430 CASE_FLT_FN (BUILT_IN_LLROUND):
7431 real_round (&r, TYPE_MODE (ftype), &x);
7432 break;
7433
7434 default:
7435 gcc_unreachable ();
7436 }
7437
7438 REAL_VALUE_TO_INT (&lo, &hi, r);
7439 result = build_int_cst_wide (NULL_TREE, lo, hi);
7440 if (int_fits_type_p (result, itype))
7441 return fold_convert (itype, result);
7442 }
7443 }
7444
7445 return fold_fixed_mathfn (fndecl, arglist);
7446}
7447
5942/* Fold function call to builtin ffs, clz, ctz, popcount and parity
5943 and their long and long long variants (i.e. ffsl and ffsll).
5944 Return NULL_TREE if no simplification can be made. */
5945
5946static tree
7448/* Fold function call to builtin ffs, clz, ctz, popcount and parity
7449 and their long and long long variants (i.e. ffsl and ffsll).
7450 Return NULL_TREE if no simplification can be made. */
7451
7452static tree
5947fold_builtin_bitop (tree exp)
7453fold_builtin_bitop (tree fndecl, tree arglist)
5948{
7454{
5949 tree fndecl = get_callee_fndecl (exp);
5950 tree arglist = TREE_OPERAND (exp, 1);
5951 tree arg;
5952
5953 if (! validate_arglist (arglist, INTEGER_TYPE, VOID_TYPE))
5954 return NULL_TREE;
5955
5956 /* Optimize for constant argument. */
5957 arg = TREE_VALUE (arglist);
5958 if (TREE_CODE (arg) == INTEGER_CST && ! TREE_CONSTANT_OVERFLOW (arg))
5959 {
5960 HOST_WIDE_INT hi, width, result;
5961 unsigned HOST_WIDE_INT lo;
7455 tree arg;
7456
7457 if (! validate_arglist (arglist, INTEGER_TYPE, VOID_TYPE))
7458 return NULL_TREE;
7459
7460 /* Optimize for constant argument. */
7461 arg = TREE_VALUE (arglist);
7462 if (TREE_CODE (arg) == INTEGER_CST && ! TREE_CONSTANT_OVERFLOW (arg))
7463 {
7464 HOST_WIDE_INT hi, width, result;
7465 unsigned HOST_WIDE_INT lo;
5962 tree type, t;
7466 tree type;
5963
5964 type = TREE_TYPE (arg);
5965 width = TYPE_PRECISION (type);
5966 lo = TREE_INT_CST_LOW (arg);
5967
5968 /* Clear all the bits that are beyond the type's precision. */
5969 if (width > HOST_BITS_PER_WIDE_INT)
5970 {

--- 5 unchanged lines hidden (view full) ---

5976 {
5977 hi = 0;
5978 if (width < HOST_BITS_PER_WIDE_INT)
5979 lo &= ~((unsigned HOST_WIDE_INT) (-1) << width);
5980 }
5981
5982 switch (DECL_FUNCTION_CODE (fndecl))
5983 {
7467
7468 type = TREE_TYPE (arg);
7469 width = TYPE_PRECISION (type);
7470 lo = TREE_INT_CST_LOW (arg);
7471
7472 /* Clear all the bits that are beyond the type's precision. */
7473 if (width > HOST_BITS_PER_WIDE_INT)
7474 {

--- 5 unchanged lines hidden (view full) ---

7480 {
7481 hi = 0;
7482 if (width < HOST_BITS_PER_WIDE_INT)
7483 lo &= ~((unsigned HOST_WIDE_INT) (-1) << width);
7484 }
7485
7486 switch (DECL_FUNCTION_CODE (fndecl))
7487 {
5984 case BUILT_IN_FFS:
5985 case BUILT_IN_FFSL:
5986 case BUILT_IN_FFSLL:
7488 CASE_INT_FN (BUILT_IN_FFS):
5987 if (lo != 0)
5988 result = exact_log2 (lo & -lo) + 1;
5989 else if (hi != 0)
5990 result = HOST_BITS_PER_WIDE_INT + exact_log2 (hi & -hi) + 1;
5991 else
5992 result = 0;
5993 break;
5994
7489 if (lo != 0)
7490 result = exact_log2 (lo & -lo) + 1;
7491 else if (hi != 0)
7492 result = HOST_BITS_PER_WIDE_INT + exact_log2 (hi & -hi) + 1;
7493 else
7494 result = 0;
7495 break;
7496
5995 case BUILT_IN_CLZ:
5996 case BUILT_IN_CLZL:
5997 case BUILT_IN_CLZLL:
7497 CASE_INT_FN (BUILT_IN_CLZ):
5998 if (hi != 0)
5999 result = width - floor_log2 (hi) - 1 - HOST_BITS_PER_WIDE_INT;
6000 else if (lo != 0)
6001 result = width - floor_log2 (lo) - 1;
6002 else if (! CLZ_DEFINED_VALUE_AT_ZERO (TYPE_MODE (type), result))
6003 result = width;
6004 break;
6005
7498 if (hi != 0)
7499 result = width - floor_log2 (hi) - 1 - HOST_BITS_PER_WIDE_INT;
7500 else if (lo != 0)
7501 result = width - floor_log2 (lo) - 1;
7502 else if (! CLZ_DEFINED_VALUE_AT_ZERO (TYPE_MODE (type), result))
7503 result = width;
7504 break;
7505
6006 case BUILT_IN_CTZ:
6007 case BUILT_IN_CTZL:
6008 case BUILT_IN_CTZLL:
7506 CASE_INT_FN (BUILT_IN_CTZ):
6009 if (lo != 0)
6010 result = exact_log2 (lo & -lo);
6011 else if (hi != 0)
6012 result = HOST_BITS_PER_WIDE_INT + exact_log2 (hi & -hi);
6013 else if (! CTZ_DEFINED_VALUE_AT_ZERO (TYPE_MODE (type), result))
6014 result = width;
6015 break;
6016
7507 if (lo != 0)
7508 result = exact_log2 (lo & -lo);
7509 else if (hi != 0)
7510 result = HOST_BITS_PER_WIDE_INT + exact_log2 (hi & -hi);
7511 else if (! CTZ_DEFINED_VALUE_AT_ZERO (TYPE_MODE (type), result))
7512 result = width;
7513 break;
7514
6017 case BUILT_IN_POPCOUNT:
6018 case BUILT_IN_POPCOUNTL:
6019 case BUILT_IN_POPCOUNTLL:
7515 CASE_INT_FN (BUILT_IN_POPCOUNT):
6020 result = 0;
6021 while (lo)
6022 result++, lo &= lo - 1;
6023 while (hi)
6024 result++, hi &= hi - 1;
6025 break;
6026
7516 result = 0;
7517 while (lo)
7518 result++, lo &= lo - 1;
7519 while (hi)
7520 result++, hi &= hi - 1;
7521 break;
7522
6027 case BUILT_IN_PARITY:
6028 case BUILT_IN_PARITYL:
6029 case BUILT_IN_PARITYLL:
7523 CASE_INT_FN (BUILT_IN_PARITY):
6030 result = 0;
6031 while (lo)
6032 result++, lo &= lo - 1;
6033 while (hi)
6034 result++, hi &= hi - 1;
6035 result &= 1;
6036 break;
6037
6038 default:
7524 result = 0;
7525 while (lo)
7526 result++, lo &= lo - 1;
7527 while (hi)
7528 result++, hi &= hi - 1;
7529 result &= 1;
7530 break;
7531
7532 default:
6039 abort();
7533 gcc_unreachable ();
6040 }
6041
7534 }
7535
6042 t = build_int_2 (result, 0);
6043 TREE_TYPE (t) = TREE_TYPE (exp);
6044 return t;
7536 return build_int_cst (TREE_TYPE (TREE_TYPE (fndecl)), result);
6045 }
6046
6047 return NULL_TREE;
6048}
6049
6050/* Return true if EXPR is the real constant contained in VALUE. */
6051
6052static bool
6053real_dconstp (tree expr, const REAL_VALUE_TYPE *value)
6054{
6055 STRIP_NOPS (expr);
6056
6057 return ((TREE_CODE (expr) == REAL_CST
7537 }
7538
7539 return NULL_TREE;
7540}
7541
7542/* Return true if EXPR is the real constant contained in VALUE. */
7543
7544static bool
7545real_dconstp (tree expr, const REAL_VALUE_TYPE *value)
7546{
7547 STRIP_NOPS (expr);
7548
7549 return ((TREE_CODE (expr) == REAL_CST
6058 && ! TREE_CONSTANT_OVERFLOW (expr)
6059 && REAL_VALUES_EQUAL (TREE_REAL_CST (expr), *value))
6060 || (TREE_CODE (expr) == COMPLEX_CST
6061 && real_dconstp (TREE_REALPART (expr), value)
6062 && real_zerop (TREE_IMAGPART (expr))));
7550 && ! TREE_CONSTANT_OVERFLOW (expr)
7551 && REAL_VALUES_EQUAL (TREE_REAL_CST (expr), *value))
7552 || (TREE_CODE (expr) == COMPLEX_CST
7553 && real_dconstp (TREE_REALPART (expr), value)
7554 && real_zerop (TREE_IMAGPART (expr))));
6063}
6064
6065/* A subroutine of fold_builtin to fold the various logarithmic
7555}
7556
7557/* A subroutine of fold_builtin to fold the various logarithmic
6066 functions. EXP is the CALL_EXPR of a call to a builtin log*
6067 function. VALUE is the base of the log* function. */
7558 functions. EXP is the CALL_EXPR of a call to a builtin logN
7559 function. VALUE is the base of the logN function. */
6068
6069static tree
7560
7561static tree
6070fold_builtin_logarithm (tree exp, const REAL_VALUE_TYPE *value)
7562fold_builtin_logarithm (tree fndecl, tree arglist,
7563 const REAL_VALUE_TYPE *value)
6071{
7564{
6072 tree arglist = TREE_OPERAND (exp, 1);
6073
6074 if (validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
6075 {
7565 if (validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
7566 {
6076 tree fndecl = get_callee_fndecl (exp);
6077 tree type = TREE_TYPE (TREE_TYPE (fndecl));
6078 tree arg = TREE_VALUE (arglist);
6079 const enum built_in_function fcode = builtin_mathfn_code (arg);
7567 tree type = TREE_TYPE (TREE_TYPE (fndecl));
7568 tree arg = TREE_VALUE (arglist);
7569 const enum built_in_function fcode = builtin_mathfn_code (arg);
6080
6081 /* Optimize log*(1.0) = 0.0. */
7570
7571 /* Optimize logN(1.0) = 0.0. */
6082 if (real_onep (arg))
6083 return build_real (type, dconst0);
6084
6085 /* Optimize logN(N) = 1.0. If N can't be truncated to MODE
7572 if (real_onep (arg))
7573 return build_real (type, dconst0);
7574
7575 /* Optimize logN(N) = 1.0. If N can't be truncated to MODE
6086 exactly, then only do this if flag_unsafe_math_optimizations. */
7576 exactly, then only do this if flag_unsafe_math_optimizations. */
6087 if (exact_real_truncate (TYPE_MODE (type), value)
6088 || flag_unsafe_math_optimizations)
7577 if (exact_real_truncate (TYPE_MODE (type), value)
7578 || flag_unsafe_math_optimizations)
6089 {
7579 {
6090 const REAL_VALUE_TYPE value_truncate =
6091 real_value_truncate (TYPE_MODE (type), *value);
6092 if (real_dconstp (arg, &value_truncate))
6093 return build_real (type, dconst1);
6094 }
7580 const REAL_VALUE_TYPE value_truncate =
7581 real_value_truncate (TYPE_MODE (type), *value);
7582 if (real_dconstp (arg, &value_truncate))
7583 return build_real (type, dconst1);
7584 }
6095
7585
6096 /* Special case, optimize logN(expN(x)) = x. */
6097 if (flag_unsafe_math_optimizations
6098 && ((value == &dconste
6099 && (fcode == BUILT_IN_EXP
6100 || fcode == BUILT_IN_EXPF
6101 || fcode == BUILT_IN_EXPL))
6102 || (value == &dconst2
6103 && (fcode == BUILT_IN_EXP2
6104 || fcode == BUILT_IN_EXP2F
6105 || fcode == BUILT_IN_EXP2L))
7586 /* Special case, optimize logN(expN(x)) = x. */
7587 if (flag_unsafe_math_optimizations
7588 && ((value == &dconste
7589 && (fcode == BUILT_IN_EXP
7590 || fcode == BUILT_IN_EXPF
7591 || fcode == BUILT_IN_EXPL))
7592 || (value == &dconst2
7593 && (fcode == BUILT_IN_EXP2
7594 || fcode == BUILT_IN_EXP2F
7595 || fcode == BUILT_IN_EXP2L))
6106 || (value == &dconst10
6107 && (fcode == BUILT_IN_EXP10
6108 || fcode == BUILT_IN_EXP10F
6109 || fcode == BUILT_IN_EXP10L))))
6110 return convert (type, TREE_VALUE (TREE_OPERAND (arg, 1)));
7596 || (value == &dconst10 && (BUILTIN_EXP10_P (fcode)))))
7597 return fold_convert (type, TREE_VALUE (TREE_OPERAND (arg, 1)));
6111
7598
6112 /* Optimize log*(func()) for various exponential functions. We
6113 want to determine the value "x" and the power "exponent" in
6114 order to transform logN(x**exponent) into exponent*logN(x). */
7599 /* Optimize logN(func()) for various exponential functions. We
7600 want to determine the value "x" and the power "exponent" in
7601 order to transform logN(x**exponent) into exponent*logN(x). */
6115 if (flag_unsafe_math_optimizations)
7602 if (flag_unsafe_math_optimizations)
6116 {
7603 {
6117 tree exponent = 0, x = 0;
7604 tree exponent = 0, x = 0;
6118
7605
6119 switch (fcode)
6120 {
7606 switch (fcode)
7607 {
6121 case BUILT_IN_EXP:
6122 case BUILT_IN_EXPF:
6123 case BUILT_IN_EXPL:
7608 CASE_FLT_FN (BUILT_IN_EXP):
6124 /* Prepare to do logN(exp(exponent) -> exponent*logN(e). */
6125 x = build_real (type,
6126 real_value_truncate (TYPE_MODE (type), dconste));
6127 exponent = TREE_VALUE (TREE_OPERAND (arg, 1));
6128 break;
7609 /* Prepare to do logN(exp(exponent) -> exponent*logN(e). */
7610 x = build_real (type,
7611 real_value_truncate (TYPE_MODE (type), dconste));
7612 exponent = TREE_VALUE (TREE_OPERAND (arg, 1));
7613 break;
6129 case BUILT_IN_EXP2:
6130 case BUILT_IN_EXP2F:
6131 case BUILT_IN_EXP2L:
7614 CASE_FLT_FN (BUILT_IN_EXP2):
6132 /* Prepare to do logN(exp2(exponent) -> exponent*logN(2). */
6133 x = build_real (type, dconst2);
6134 exponent = TREE_VALUE (TREE_OPERAND (arg, 1));
6135 break;
7615 /* Prepare to do logN(exp2(exponent) -> exponent*logN(2). */
7616 x = build_real (type, dconst2);
7617 exponent = TREE_VALUE (TREE_OPERAND (arg, 1));
7618 break;
6136 case BUILT_IN_EXP10:
6137 case BUILT_IN_EXP10F:
6138 case BUILT_IN_EXP10L:
6139 case BUILT_IN_POW10:
6140 case BUILT_IN_POW10F:
6141 case BUILT_IN_POW10L:
7619 CASE_FLT_FN (BUILT_IN_EXP10):
7620 CASE_FLT_FN (BUILT_IN_POW10):
6142 /* Prepare to do logN(exp10(exponent) -> exponent*logN(10). */
6143 x = build_real (type, dconst10);
6144 exponent = TREE_VALUE (TREE_OPERAND (arg, 1));
6145 break;
7621 /* Prepare to do logN(exp10(exponent) -> exponent*logN(10). */
7622 x = build_real (type, dconst10);
7623 exponent = TREE_VALUE (TREE_OPERAND (arg, 1));
7624 break;
6146 case BUILT_IN_SQRT:
6147 case BUILT_IN_SQRTF:
6148 case BUILT_IN_SQRTL:
7625 CASE_FLT_FN (BUILT_IN_SQRT):
6149 /* Prepare to do logN(sqrt(x) -> 0.5*logN(x). */
6150 x = TREE_VALUE (TREE_OPERAND (arg, 1));
6151 exponent = build_real (type, dconsthalf);
6152 break;
7626 /* Prepare to do logN(sqrt(x) -> 0.5*logN(x). */
7627 x = TREE_VALUE (TREE_OPERAND (arg, 1));
7628 exponent = build_real (type, dconsthalf);
7629 break;
6153 case BUILT_IN_CBRT:
6154 case BUILT_IN_CBRTF:
6155 case BUILT_IN_CBRTL:
7630 CASE_FLT_FN (BUILT_IN_CBRT):
6156 /* Prepare to do logN(cbrt(x) -> (1/3)*logN(x). */
6157 x = TREE_VALUE (TREE_OPERAND (arg, 1));
6158 exponent = build_real (type, real_value_truncate (TYPE_MODE (type),
6159 dconstthird));
6160 break;
7631 /* Prepare to do logN(cbrt(x) -> (1/3)*logN(x). */
7632 x = TREE_VALUE (TREE_OPERAND (arg, 1));
7633 exponent = build_real (type, real_value_truncate (TYPE_MODE (type),
7634 dconstthird));
7635 break;
6161 case BUILT_IN_POW:
6162 case BUILT_IN_POWF:
6163 case BUILT_IN_POWL:
7636 CASE_FLT_FN (BUILT_IN_POW):
6164 /* Prepare to do logN(pow(x,exponent) -> exponent*logN(x). */
6165 x = TREE_VALUE (TREE_OPERAND (arg, 1));
6166 exponent = TREE_VALUE (TREE_CHAIN (TREE_OPERAND (arg, 1)));
6167 break;
6168 default:
6169 break;
6170 }
6171
6172 /* Now perform the optimization. */
6173 if (x && exponent)
6174 {
6175 tree logfn;
6176 arglist = build_tree_list (NULL_TREE, x);
6177 logfn = build_function_call_expr (fndecl, arglist);
7637 /* Prepare to do logN(pow(x,exponent) -> exponent*logN(x). */
7638 x = TREE_VALUE (TREE_OPERAND (arg, 1));
7639 exponent = TREE_VALUE (TREE_CHAIN (TREE_OPERAND (arg, 1)));
7640 break;
7641 default:
7642 break;
7643 }
7644
7645 /* Now perform the optimization. */
7646 if (x && exponent)
7647 {
7648 tree logfn;
7649 arglist = build_tree_list (NULL_TREE, x);
7650 logfn = build_function_call_expr (fndecl, arglist);
6178 return fold (build (MULT_EXPR, type, exponent, logfn));
7651 return fold_build2 (MULT_EXPR, type, exponent, logfn);
6179 }
6180 }
6181 }
6182
6183 return 0;
6184}
7652 }
7653 }
7654 }
7655
7656 return 0;
7657}
6185
7658
7659/* Fold a builtin function call to pow, powf, or powl. Return
7660 NULL_TREE if no simplification can be made. */
7661static tree
7662fold_builtin_pow (tree fndecl, tree arglist, tree type)
7663{
7664 tree arg0 = TREE_VALUE (arglist);
7665 tree arg1 = TREE_VALUE (TREE_CHAIN (arglist));
7666
7667 if (!validate_arglist (arglist, REAL_TYPE, REAL_TYPE, VOID_TYPE))
7668 return NULL_TREE;
7669
7670 /* Optimize pow(1.0,y) = 1.0. */
7671 if (real_onep (arg0))
7672 return omit_one_operand (type, build_real (type, dconst1), arg1);
7673
7674 if (TREE_CODE (arg1) == REAL_CST
7675 && ! TREE_CONSTANT_OVERFLOW (arg1))
7676 {
7677 REAL_VALUE_TYPE cint;
7678 REAL_VALUE_TYPE c;
7679 HOST_WIDE_INT n;
7680
7681 c = TREE_REAL_CST (arg1);
7682
7683 /* Optimize pow(x,0.0) = 1.0. */
7684 if (REAL_VALUES_EQUAL (c, dconst0))
7685 return omit_one_operand (type, build_real (type, dconst1),
7686 arg0);
7687
7688 /* Optimize pow(x,1.0) = x. */
7689 if (REAL_VALUES_EQUAL (c, dconst1))
7690 return arg0;
7691
7692 /* Optimize pow(x,-1.0) = 1.0/x. */
7693 if (REAL_VALUES_EQUAL (c, dconstm1))
7694 return fold_build2 (RDIV_EXPR, type,
7695 build_real (type, dconst1), arg0);
7696
7697 /* Optimize pow(x,0.5) = sqrt(x). */
7698 if (flag_unsafe_math_optimizations
7699 && REAL_VALUES_EQUAL (c, dconsthalf))
7700 {
7701 tree sqrtfn = mathfn_built_in (type, BUILT_IN_SQRT);
7702
7703 if (sqrtfn != NULL_TREE)
7704 {
7705 tree arglist = build_tree_list (NULL_TREE, arg0);
7706 return build_function_call_expr (sqrtfn, arglist);
7707 }
7708 }
7709
7710 /* Check for an integer exponent. */
7711 n = real_to_integer (&c);
7712 real_from_integer (&cint, VOIDmode, n, n < 0 ? -1 : 0, 0);
7713 if (real_identical (&c, &cint))
7714 {
7715 /* Attempt to evaluate pow at compile-time. */
7716 if (TREE_CODE (arg0) == REAL_CST
7717 && ! TREE_CONSTANT_OVERFLOW (arg0))
7718 {
7719 REAL_VALUE_TYPE x;
7720 bool inexact;
7721
7722 x = TREE_REAL_CST (arg0);
7723 inexact = real_powi (&x, TYPE_MODE (type), &x, n);
7724 if (flag_unsafe_math_optimizations || !inexact)
7725 return build_real (type, x);
7726 }
7727
7728 /* Strip sign ops from even integer powers. */
7729 if ((n & 1) == 0 && flag_unsafe_math_optimizations)
7730 {
7731 tree narg0 = fold_strip_sign_ops (arg0);
7732 if (narg0)
7733 {
7734 arglist = build_tree_list (NULL_TREE, arg1);
7735 arglist = tree_cons (NULL_TREE, narg0, arglist);
7736 return build_function_call_expr (fndecl, arglist);
7737 }
7738 }
7739 }
7740 }
7741
7742 if (flag_unsafe_math_optimizations)
7743 {
7744 const enum built_in_function fcode = builtin_mathfn_code (arg0);
7745
7746 /* Optimize pow(expN(x),y) = expN(x*y). */
7747 if (BUILTIN_EXPONENT_P (fcode))
7748 {
7749 tree expfn = TREE_OPERAND (TREE_OPERAND (arg0, 0), 0);
7750 tree arg = TREE_VALUE (TREE_OPERAND (arg0, 1));
7751 arg = fold_build2 (MULT_EXPR, type, arg, arg1);
7752 arglist = build_tree_list (NULL_TREE, arg);
7753 return build_function_call_expr (expfn, arglist);
7754 }
7755
7756 /* Optimize pow(sqrt(x),y) = pow(x,y*0.5). */
7757 if (BUILTIN_SQRT_P (fcode))
7758 {
7759 tree narg0 = TREE_VALUE (TREE_OPERAND (arg0, 1));
7760 tree narg1 = fold_build2 (MULT_EXPR, type, arg1,
7761 build_real (type, dconsthalf));
7762
7763 arglist = tree_cons (NULL_TREE, narg0,
7764 build_tree_list (NULL_TREE, narg1));
7765 return build_function_call_expr (fndecl, arglist);
7766 }
7767
7768 /* Optimize pow(cbrt(x),y) = pow(x,y/3) iff x is nonnegative. */
7769 if (BUILTIN_CBRT_P (fcode))
7770 {
7771 tree arg = TREE_VALUE (TREE_OPERAND (arg0, 1));
7772 if (tree_expr_nonnegative_p (arg))
7773 {
7774 const REAL_VALUE_TYPE dconstroot
7775 = real_value_truncate (TYPE_MODE (type), dconstthird);
7776 tree narg1 = fold_build2 (MULT_EXPR, type, arg1,
7777 build_real (type, dconstroot));
7778 arglist = tree_cons (NULL_TREE, arg,
7779 build_tree_list (NULL_TREE, narg1));
7780 return build_function_call_expr (fndecl, arglist);
7781 }
7782 }
7783
7784 /* Optimize pow(pow(x,y),z) = pow(x,y*z). */
7785 if (fcode == BUILT_IN_POW || fcode == BUILT_IN_POWF
7786 || fcode == BUILT_IN_POWL)
7787 {
7788 tree arg00 = TREE_VALUE (TREE_OPERAND (arg0, 1));
7789 tree arg01 = TREE_VALUE (TREE_CHAIN (TREE_OPERAND (arg0, 1)));
7790 tree narg1 = fold_build2 (MULT_EXPR, type, arg01, arg1);
7791 arglist = tree_cons (NULL_TREE, arg00,
7792 build_tree_list (NULL_TREE, narg1));
7793 return build_function_call_expr (fndecl, arglist);
7794 }
7795 }
7796
7797 return NULL_TREE;
7798}
7799
7800/* Fold a builtin function call to powi, powif, or powil. Return
7801 NULL_TREE if no simplification can be made. */
7802static tree
7803fold_builtin_powi (tree fndecl ATTRIBUTE_UNUSED, tree arglist, tree type)
7804{
7805 tree arg0 = TREE_VALUE (arglist);
7806 tree arg1 = TREE_VALUE (TREE_CHAIN (arglist));
7807
7808 if (!validate_arglist (arglist, REAL_TYPE, INTEGER_TYPE, VOID_TYPE))
7809 return NULL_TREE;
7810
7811 /* Optimize pow(1.0,y) = 1.0. */
7812 if (real_onep (arg0))
7813 return omit_one_operand (type, build_real (type, dconst1), arg1);
7814
7815 if (host_integerp (arg1, 0))
7816 {
7817 HOST_WIDE_INT c = TREE_INT_CST_LOW (arg1);
7818
7819 /* Evaluate powi at compile-time. */
7820 if (TREE_CODE (arg0) == REAL_CST
7821 && ! TREE_CONSTANT_OVERFLOW (arg0))
7822 {
7823 REAL_VALUE_TYPE x;
7824 x = TREE_REAL_CST (arg0);
7825 real_powi (&x, TYPE_MODE (type), &x, c);
7826 return build_real (type, x);
7827 }
7828
7829 /* Optimize pow(x,0) = 1.0. */
7830 if (c == 0)
7831 return omit_one_operand (type, build_real (type, dconst1),
7832 arg0);
7833
7834 /* Optimize pow(x,1) = x. */
7835 if (c == 1)
7836 return arg0;
7837
7838 /* Optimize pow(x,-1) = 1.0/x. */
7839 if (c == -1)
7840 return fold_build2 (RDIV_EXPR, type,
7841 build_real (type, dconst1), arg0);
7842 }
7843
7844 return NULL_TREE;
7845}
7846
6186/* A subroutine of fold_builtin to fold the various exponent
6187 functions. EXP is the CALL_EXPR of a call to a builtin function.
6188 VALUE is the value which will be raised to a power. */
6189
6190static tree
7847/* A subroutine of fold_builtin to fold the various exponent
7848 functions. EXP is the CALL_EXPR of a call to a builtin function.
7849 VALUE is the value which will be raised to a power. */
7850
7851static tree
6191fold_builtin_exponent (tree exp, const REAL_VALUE_TYPE *value)
7852fold_builtin_exponent (tree fndecl, tree arglist,
7853 const REAL_VALUE_TYPE *value)
6192{
7854{
6193 tree arglist = TREE_OPERAND (exp, 1);
6194
6195 if (validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
6196 {
7855 if (validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
7856 {
6197 tree fndecl = get_callee_fndecl (exp);
6198 tree type = TREE_TYPE (TREE_TYPE (fndecl));
6199 tree arg = TREE_VALUE (arglist);
6200
6201 /* Optimize exp*(0.0) = 1.0. */
6202 if (real_zerop (arg))
6203 return build_real (type, dconst1);
6204
6205 /* Optimize expN(1.0) = N. */
6206 if (real_onep (arg))
7857 tree type = TREE_TYPE (TREE_TYPE (fndecl));
7858 tree arg = TREE_VALUE (arglist);
7859
7860 /* Optimize exp*(0.0) = 1.0. */
7861 if (real_zerop (arg))
7862 return build_real (type, dconst1);
7863
7864 /* Optimize expN(1.0) = N. */
7865 if (real_onep (arg))
6207 {
7866 {
6208 REAL_VALUE_TYPE cst;
6209
6210 real_convert (&cst, TYPE_MODE (type), value);
6211 return build_real (type, cst);
6212 }
6213
6214 /* Attempt to evaluate expN(integer) at compile-time. */
6215 if (flag_unsafe_math_optimizations
6216 && TREE_CODE (arg) == REAL_CST
6217 && ! TREE_CONSTANT_OVERFLOW (arg))
7867 REAL_VALUE_TYPE cst;
7868
7869 real_convert (&cst, TYPE_MODE (type), value);
7870 return build_real (type, cst);
7871 }
7872
7873 /* Attempt to evaluate expN(integer) at compile-time. */
7874 if (flag_unsafe_math_optimizations
7875 && TREE_CODE (arg) == REAL_CST
7876 && ! TREE_CONSTANT_OVERFLOW (arg))
6218 {
7877 {
6219 REAL_VALUE_TYPE cint;
6220 REAL_VALUE_TYPE c;
6221 HOST_WIDE_INT n;
6222
6223 c = TREE_REAL_CST (arg);
6224 n = real_to_integer (&c);
6225 real_from_integer (&cint, VOIDmode, n,
6226 n < 0 ? -1 : 0, 0);
6227 if (real_identical (&c, &cint))
6228 {
6229 REAL_VALUE_TYPE x;
6230
6231 real_powi (&x, TYPE_MODE (type), value, n);
6232 return build_real (type, x);
6233 }
6234 }
6235
6236 /* Optimize expN(logN(x)) = x. */
6237 if (flag_unsafe_math_optimizations)
7878 REAL_VALUE_TYPE cint;
7879 REAL_VALUE_TYPE c;
7880 HOST_WIDE_INT n;
7881
7882 c = TREE_REAL_CST (arg);
7883 n = real_to_integer (&c);
7884 real_from_integer (&cint, VOIDmode, n,
7885 n < 0 ? -1 : 0, 0);
7886 if (real_identical (&c, &cint))
7887 {
7888 REAL_VALUE_TYPE x;
7889
7890 real_powi (&x, TYPE_MODE (type), value, n);
7891 return build_real (type, x);
7892 }
7893 }
7894
7895 /* Optimize expN(logN(x)) = x. */
7896 if (flag_unsafe_math_optimizations)
6238 {
7897 {
6239 const enum built_in_function fcode = builtin_mathfn_code (arg);
6240
6241 if ((value == &dconste
6242 && (fcode == BUILT_IN_LOG
6243 || fcode == BUILT_IN_LOGF
6244 || fcode == BUILT_IN_LOGL))
6245 || (value == &dconst2
6246 && (fcode == BUILT_IN_LOG2
6247 || fcode == BUILT_IN_LOG2F
6248 || fcode == BUILT_IN_LOG2L))
6249 || (value == &dconst10
6250 && (fcode == BUILT_IN_LOG10
6251 || fcode == BUILT_IN_LOG10F
6252 || fcode == BUILT_IN_LOG10L)))
7898 const enum built_in_function fcode = builtin_mathfn_code (arg);
7899
7900 if ((value == &dconste
7901 && (fcode == BUILT_IN_LOG
7902 || fcode == BUILT_IN_LOGF
7903 || fcode == BUILT_IN_LOGL))
7904 || (value == &dconst2
7905 && (fcode == BUILT_IN_LOG2
7906 || fcode == BUILT_IN_LOG2F
7907 || fcode == BUILT_IN_LOG2L))
7908 || (value == &dconst10
7909 && (fcode == BUILT_IN_LOG10
7910 || fcode == BUILT_IN_LOG10F
7911 || fcode == BUILT_IN_LOG10L)))
6253 return convert (type, TREE_VALUE (TREE_OPERAND (arg, 1)));
7912 return fold_convert (type, TREE_VALUE (TREE_OPERAND (arg, 1)));
6254 }
6255 }
6256
6257 return 0;
6258}
6259
7913 }
7914 }
7915
7916 return 0;
7917}
7918
6260/* Fold function call to builtin memcpy. Return
7919/* Return true if VAR is a VAR_DECL or a component thereof. */
7920
7921static bool
7922var_decl_component_p (tree var)
7923{
7924 tree inner = var;
7925 while (handled_component_p (inner))
7926 inner = TREE_OPERAND (inner, 0);
7927 return SSA_VAR_P (inner);
7928}
7929
7930/* Fold function call to builtin memset. Return
6261 NULL_TREE if no simplification can be made. */
6262
6263static tree
7931 NULL_TREE if no simplification can be made. */
7932
7933static tree
6264fold_builtin_memcpy (tree exp)
7934fold_builtin_memset (tree arglist, tree type, bool ignore)
6265{
7935{
6266 tree arglist = TREE_OPERAND (exp, 1);
6267 tree dest, src, len;
7936 tree dest, c, len, var, ret;
7937 unsigned HOST_WIDE_INT length, cval;
6268
6269 if (!validate_arglist (arglist,
7938
7939 if (!validate_arglist (arglist,
6270 POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
7940 POINTER_TYPE, INTEGER_TYPE, INTEGER_TYPE, VOID_TYPE))
6271 return 0;
6272
6273 dest = TREE_VALUE (arglist);
7941 return 0;
7942
7943 dest = TREE_VALUE (arglist);
6274 src = TREE_VALUE (TREE_CHAIN (arglist));
7944 c = TREE_VALUE (TREE_CHAIN (arglist));
6275 len = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
6276
7945 len = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
7946
7947 if (! host_integerp (len, 1))
7948 return 0;
7949
6277 /* If the LEN parameter is zero, return DEST. */
6278 if (integer_zerop (len))
7950 /* If the LEN parameter is zero, return DEST. */
7951 if (integer_zerop (len))
6279 return omit_one_operand (TREE_TYPE (exp), dest, src);
7952 return omit_one_operand (type, dest, c);
6280
7953
6281 /* If SRC and DEST are the same (and not volatile), return DEST. */
6282 if (operand_equal_p (src, dest, 0))
6283 return omit_one_operand (TREE_TYPE (exp), dest, len);
7954 if (! host_integerp (c, 1) || TREE_SIDE_EFFECTS (dest))
7955 return 0;
6284
7956
6285 return 0;
7957 var = dest;
7958 STRIP_NOPS (var);
7959 if (TREE_CODE (var) != ADDR_EXPR)
7960 return 0;
7961
7962 var = TREE_OPERAND (var, 0);
7963 if (TREE_THIS_VOLATILE (var))
7964 return 0;
7965
7966 if (!INTEGRAL_TYPE_P (TREE_TYPE (var))
7967 && !POINTER_TYPE_P (TREE_TYPE (var)))
7968 return 0;
7969
7970 if (! var_decl_component_p (var))
7971 return 0;
7972
7973 length = tree_low_cst (len, 1);
7974 if (GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (var))) != length
7975 || get_pointer_alignment (dest, BIGGEST_ALIGNMENT) / BITS_PER_UNIT
7976 < (int) length)
7977 return 0;
7978
7979 if (length > HOST_BITS_PER_WIDE_INT / BITS_PER_UNIT)
7980 return 0;
7981
7982 if (integer_zerop (c))
7983 cval = 0;
7984 else
7985 {
7986 if (CHAR_BIT != 8 || BITS_PER_UNIT != 8 || HOST_BITS_PER_WIDE_INT > 64)
7987 return 0;
7988
7989 cval = tree_low_cst (c, 1);
7990 cval &= 0xff;
7991 cval |= cval << 8;
7992 cval |= cval << 16;
7993 cval |= (cval << 31) << 1;
7994 }
7995
7996 ret = build_int_cst_type (TREE_TYPE (var), cval);
7997 ret = build2 (MODIFY_EXPR, TREE_TYPE (var), var, ret);
7998 if (ignore)
7999 return ret;
8000
8001 return omit_one_operand (type, dest, ret);
6286}
6287
8002}
8003
6288/* Fold function call to builtin mempcpy. Return
8004/* Fold function call to builtin memset. Return
6289 NULL_TREE if no simplification can be made. */
6290
6291static tree
8005 NULL_TREE if no simplification can be made. */
8006
8007static tree
6292fold_builtin_mempcpy (tree exp)
8008fold_builtin_bzero (tree arglist, bool ignore)
6293{
8009{
6294 tree arglist = TREE_OPERAND (exp, 1);
6295 tree dest, src, len;
8010 tree dest, size, newarglist;
6296
8011
6297 if (!validate_arglist (arglist,
6298 POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
8012 if (!validate_arglist (arglist, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
6299 return 0;
6300
8013 return 0;
8014
8015 if (!ignore)
8016 return 0;
8017
6301 dest = TREE_VALUE (arglist);
8018 dest = TREE_VALUE (arglist);
8019 size = TREE_VALUE (TREE_CHAIN (arglist));
8020
8021 /* New argument list transforming bzero(ptr x, int y) to
8022 memset(ptr x, int 0, size_t y). This is done this way
8023 so that if it isn't expanded inline, we fallback to
8024 calling bzero instead of memset. */
8025
8026 newarglist = build_tree_list (NULL_TREE, fold_convert (sizetype, size));
8027 newarglist = tree_cons (NULL_TREE, integer_zero_node, newarglist);
8028 newarglist = tree_cons (NULL_TREE, dest, newarglist);
8029 return fold_builtin_memset (newarglist, void_type_node, ignore);
8030}
8031
8032/* Fold function call to builtin mem{{,p}cpy,move}. Return
8033 NULL_TREE if no simplification can be made.
8034 If ENDP is 0, return DEST (like memcpy).
8035 If ENDP is 1, return DEST+LEN (like mempcpy).
8036 If ENDP is 2, return DEST+LEN-1 (like stpcpy).
8037 If ENDP is 3, return DEST, additionally *SRC and *DEST may overlap
8038 (memmove). */
8039
8040static tree
8041fold_builtin_memory_op (tree arglist, tree type, bool ignore, int endp)
8042{
8043 tree dest, src, len, destvar, srcvar, expr;
8044 unsigned HOST_WIDE_INT length;
8045
8046 if (! validate_arglist (arglist,
8047 POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
8048 return 0;
8049
8050 dest = TREE_VALUE (arglist);
6302 src = TREE_VALUE (TREE_CHAIN (arglist));
6303 len = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
6304
6305 /* If the LEN parameter is zero, return DEST. */
6306 if (integer_zerop (len))
8051 src = TREE_VALUE (TREE_CHAIN (arglist));
8052 len = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
8053
8054 /* If the LEN parameter is zero, return DEST. */
8055 if (integer_zerop (len))
6307 return omit_one_operand (TREE_TYPE (exp), dest, src);
8056 return omit_one_operand (type, dest, src);
6308
8057
6309 /* If SRC and DEST are the same (and not volatile), return DEST+LEN. */
8058 /* If SRC and DEST are the same (and not volatile), return
8059 DEST{,+LEN,+LEN-1}. */
6310 if (operand_equal_p (src, dest, 0))
8060 if (operand_equal_p (src, dest, 0))
8061 expr = len;
8062 else
6311 {
8063 {
6312 tree temp = convert (TREE_TYPE (dest), len);
6313 temp = fold (build (PLUS_EXPR, TREE_TYPE (dest), dest, len));
6314 return convert (TREE_TYPE (exp), temp);
8064 if (! host_integerp (len, 1))
8065 return 0;
8066
8067 if (TREE_SIDE_EFFECTS (dest) || TREE_SIDE_EFFECTS (src))
8068 return 0;
8069
8070 destvar = dest;
8071 STRIP_NOPS (destvar);
8072 if (TREE_CODE (destvar) != ADDR_EXPR)
8073 return 0;
8074
8075 destvar = TREE_OPERAND (destvar, 0);
8076 if (TREE_THIS_VOLATILE (destvar))
8077 return 0;
8078
8079 if (!INTEGRAL_TYPE_P (TREE_TYPE (destvar))
8080 && !POINTER_TYPE_P (TREE_TYPE (destvar))
8081 && !SCALAR_FLOAT_TYPE_P (TREE_TYPE (destvar)))
8082 return 0;
8083
8084 if (! var_decl_component_p (destvar))
8085 return 0;
8086
8087 srcvar = src;
8088 STRIP_NOPS (srcvar);
8089 if (TREE_CODE (srcvar) != ADDR_EXPR)
8090 return 0;
8091
8092 srcvar = TREE_OPERAND (srcvar, 0);
8093 if (TREE_THIS_VOLATILE (srcvar))
8094 return 0;
8095
8096 if (!INTEGRAL_TYPE_P (TREE_TYPE (srcvar))
8097 && !POINTER_TYPE_P (TREE_TYPE (srcvar))
8098 && !SCALAR_FLOAT_TYPE_P (TREE_TYPE (srcvar)))
8099 return 0;
8100
8101 if (! var_decl_component_p (srcvar))
8102 return 0;
8103
8104 length = tree_low_cst (len, 1);
8105 if (GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (destvar))) != length
8106 || get_pointer_alignment (dest, BIGGEST_ALIGNMENT) / BITS_PER_UNIT
8107 < (int) length
8108 || GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (srcvar))) != length
8109 || get_pointer_alignment (src, BIGGEST_ALIGNMENT) / BITS_PER_UNIT
8110 < (int) length)
8111 return 0;
8112
8113 if ((INTEGRAL_TYPE_P (TREE_TYPE (srcvar))
8114 || POINTER_TYPE_P (TREE_TYPE (srcvar)))
8115 && (INTEGRAL_TYPE_P (TREE_TYPE (destvar))
8116 || POINTER_TYPE_P (TREE_TYPE (destvar))))
8117 expr = fold_convert (TREE_TYPE (destvar), srcvar);
8118 else
8119 expr = fold_build1 (VIEW_CONVERT_EXPR, TREE_TYPE (destvar), srcvar);
8120 expr = build2 (MODIFY_EXPR, TREE_TYPE (destvar), destvar, expr);
6315 }
6316
8121 }
8122
6317 return 0;
8123 if (ignore)
8124 return expr;
8125
8126 if (endp == 0 || endp == 3)
8127 return omit_one_operand (type, dest, expr);
8128
8129 if (expr == len)
8130 expr = 0;
8131
8132 if (endp == 2)
8133 len = fold_build2 (MINUS_EXPR, TREE_TYPE (len), len,
8134 ssize_int (1));
8135
8136 len = fold_convert (TREE_TYPE (dest), len);
8137 dest = fold_build2 (PLUS_EXPR, TREE_TYPE (dest), dest, len);
8138 dest = fold_convert (type, dest);
8139 if (expr)
8140 dest = omit_one_operand (type, dest, expr);
8141 return dest;
6318}
6319
8142}
8143
6320/* Fold function call to builtin memmove. Return
6321 NULL_TREE if no simplification can be made. */
8144/* Fold function call to builtin bcopy. Return NULL_TREE if no
8145 simplification can be made. */
6322
6323static tree
8146
8147static tree
6324fold_builtin_memmove (tree exp)
8148fold_builtin_bcopy (tree arglist, bool ignore)
6325{
8149{
6326 tree arglist = TREE_OPERAND (exp, 1);
6327 tree dest, src, len;
8150 tree src, dest, size, newarglist;
6328
6329 if (!validate_arglist (arglist,
6330 POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
6331 return 0;
6332
8151
8152 if (!validate_arglist (arglist,
8153 POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
8154 return 0;
8155
6333 dest = TREE_VALUE (arglist);
6334 src = TREE_VALUE (TREE_CHAIN (arglist));
6335 len = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
8156 if (! ignore)
8157 return 0;
6336
8158
6337 /* If the LEN parameter is zero, return DEST. */
6338 if (integer_zerop (len))
6339 return omit_one_operand (TREE_TYPE (exp), dest, src);
8159 src = TREE_VALUE (arglist);
8160 dest = TREE_VALUE (TREE_CHAIN (arglist));
8161 size = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
6340
8162
6341 /* If SRC and DEST are the same (and not volatile), return DEST. */
6342 if (operand_equal_p (src, dest, 0))
6343 return omit_one_operand (TREE_TYPE (exp), dest, len);
8163 /* New argument list transforming bcopy(ptr x, ptr y, int z) to
8164 memmove(ptr y, ptr x, size_t z). This is done this way
8165 so that if it isn't expanded inline, we fallback to
8166 calling bcopy instead of memmove. */
6344
8167
6345 return 0;
8168 newarglist = build_tree_list (NULL_TREE, fold_convert (sizetype, size));
8169 newarglist = tree_cons (NULL_TREE, src, newarglist);
8170 newarglist = tree_cons (NULL_TREE, dest, newarglist);
8171
8172 return fold_builtin_memory_op (newarglist, void_type_node, true, /*endp=*/3);
6346}
6347
8173}
8174
6348/* Fold function call to builtin strcpy. Return
6349 NULL_TREE if no simplification can be made. */
8175/* Fold function call to builtin strcpy. If LEN is not NULL, it represents
8176 the length of the string to be copied. Return NULL_TREE if no
8177 simplification can be made. */
6350
8178
6351static tree
6352fold_builtin_strcpy (tree exp)
8179tree
8180fold_builtin_strcpy (tree fndecl, tree arglist, tree len)
6353{
8181{
6354 tree arglist = TREE_OPERAND (exp, 1);
6355 tree dest, src;
8182 tree dest, src, fn;
6356
6357 if (!validate_arglist (arglist,
6358 POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
6359 return 0;
6360
6361 dest = TREE_VALUE (arglist);
6362 src = TREE_VALUE (TREE_CHAIN (arglist));
6363
6364 /* If SRC and DEST are the same (and not volatile), return DEST. */
6365 if (operand_equal_p (src, dest, 0))
8183
8184 if (!validate_arglist (arglist,
8185 POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
8186 return 0;
8187
8188 dest = TREE_VALUE (arglist);
8189 src = TREE_VALUE (TREE_CHAIN (arglist));
8190
8191 /* If SRC and DEST are the same (and not volatile), return DEST. */
8192 if (operand_equal_p (src, dest, 0))
6366 return convert (TREE_TYPE (exp), dest);
8193 return fold_convert (TREE_TYPE (TREE_TYPE (fndecl)), dest);
6367
8194
6368 return 0;
8195 if (optimize_size)
8196 return 0;
8197
8198 fn = implicit_built_in_decls[BUILT_IN_MEMCPY];
8199 if (!fn)
8200 return 0;
8201
8202 if (!len)
8203 {
8204 len = c_strlen (src, 1);
8205 if (! len || TREE_SIDE_EFFECTS (len))
8206 return 0;
8207 }
8208
8209 len = size_binop (PLUS_EXPR, len, ssize_int (1));
8210 arglist = build_tree_list (NULL_TREE, len);
8211 arglist = tree_cons (NULL_TREE, src, arglist);
8212 arglist = tree_cons (NULL_TREE, dest, arglist);
8213 return fold_convert (TREE_TYPE (TREE_TYPE (fndecl)),
8214 build_function_call_expr (fn, arglist));
6369}
6370
8215}
8216
6371/* Fold function call to builtin strncpy. Return
6372 NULL_TREE if no simplification can be made. */
8217/* Fold function call to builtin strncpy. If SLEN is not NULL, it represents
8218 the length of the source string. Return NULL_TREE if no simplification
8219 can be made. */
6373
8220
6374static tree
6375fold_builtin_strncpy (tree exp)
8221tree
8222fold_builtin_strncpy (tree fndecl, tree arglist, tree slen)
6376{
8223{
6377 tree arglist = TREE_OPERAND (exp, 1);
6378 tree dest, src, len;
8224 tree dest, src, len, fn;
6379
6380 if (!validate_arglist (arglist,
6381 POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
6382 return 0;
6383
6384 dest = TREE_VALUE (arglist);
6385 src = TREE_VALUE (TREE_CHAIN (arglist));
6386 len = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
6387
6388 /* If the LEN parameter is zero, return DEST. */
6389 if (integer_zerop (len))
8225
8226 if (!validate_arglist (arglist,
8227 POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
8228 return 0;
8229
8230 dest = TREE_VALUE (arglist);
8231 src = TREE_VALUE (TREE_CHAIN (arglist));
8232 len = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
8233
8234 /* If the LEN parameter is zero, return DEST. */
8235 if (integer_zerop (len))
6390 return omit_one_operand (TREE_TYPE (exp), dest, src);
8236 return omit_one_operand (TREE_TYPE (TREE_TYPE (fndecl)), dest, src);
6391
8237
6392 return 0;
8238 /* We can't compare slen with len as constants below if len is not a
8239 constant. */
8240 if (len == 0 || TREE_CODE (len) != INTEGER_CST)
8241 return 0;
8242
8243 if (!slen)
8244 slen = c_strlen (src, 1);
8245
8246 /* Now, we must be passed a constant src ptr parameter. */
8247 if (slen == 0 || TREE_CODE (slen) != INTEGER_CST)
8248 return 0;
8249
8250 slen = size_binop (PLUS_EXPR, slen, ssize_int (1));
8251
8252 /* We do not support simplification of this case, though we do
8253 support it when expanding trees into RTL. */
8254 /* FIXME: generate a call to __builtin_memset. */
8255 if (tree_int_cst_lt (slen, len))
8256 return 0;
8257
8258 /* OK transform into builtin memcpy. */
8259 fn = implicit_built_in_decls[BUILT_IN_MEMCPY];
8260 if (!fn)
8261 return 0;
8262 return fold_convert (TREE_TYPE (TREE_TYPE (fndecl)),
8263 build_function_call_expr (fn, arglist));
6393}
6394
6395/* Fold function call to builtin memcmp. Return
6396 NULL_TREE if no simplification can be made. */
6397
6398static tree
8264}
8265
8266/* Fold function call to builtin memcmp. Return
8267 NULL_TREE if no simplification can be made. */
8268
8269static tree
6399fold_builtin_memcmp (tree exp)
8270fold_builtin_memcmp (tree arglist)
6400{
8271{
6401 tree arglist = TREE_OPERAND (exp, 1);
6402 tree arg1, arg2, len;
8272 tree arg1, arg2, len;
8273 const char *p1, *p2;
6403
6404 if (!validate_arglist (arglist,
6405 POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
6406 return 0;
6407
6408 arg1 = TREE_VALUE (arglist);
6409 arg2 = TREE_VALUE (TREE_CHAIN (arglist));
6410 len = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
6411
6412 /* If the LEN parameter is zero, return zero. */
6413 if (integer_zerop (len))
8274
8275 if (!validate_arglist (arglist,
8276 POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
8277 return 0;
8278
8279 arg1 = TREE_VALUE (arglist);
8280 arg2 = TREE_VALUE (TREE_CHAIN (arglist));
8281 len = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
8282
8283 /* If the LEN parameter is zero, return zero. */
8284 if (integer_zerop (len))
6414 {
6415 tree temp = omit_one_operand (TREE_TYPE (exp), integer_zero_node, arg2);
6416 return omit_one_operand (TREE_TYPE (exp), temp, arg1);
6417 }
8285 return omit_two_operands (integer_type_node, integer_zero_node,
8286 arg1, arg2);
6418
6419 /* If ARG1 and ARG2 are the same (and not volatile), return zero. */
6420 if (operand_equal_p (arg1, arg2, 0))
8287
8288 /* If ARG1 and ARG2 are the same (and not volatile), return zero. */
8289 if (operand_equal_p (arg1, arg2, 0))
6421 return omit_one_operand (TREE_TYPE (exp), integer_zero_node, len);
8290 return omit_one_operand (integer_type_node, integer_zero_node, len);
6422
8291
8292 p1 = c_getstr (arg1);
8293 p2 = c_getstr (arg2);
8294
8295 /* If all arguments are constant, and the value of len is not greater
8296 than the lengths of arg1 and arg2, evaluate at compile-time. */
8297 if (host_integerp (len, 1) && p1 && p2
8298 && compare_tree_int (len, strlen (p1) + 1) <= 0
8299 && compare_tree_int (len, strlen (p2) + 1) <= 0)
8300 {
8301 const int r = memcmp (p1, p2, tree_low_cst (len, 1));
8302
8303 if (r > 0)
8304 return integer_one_node;
8305 else if (r < 0)
8306 return integer_minus_one_node;
8307 else
8308 return integer_zero_node;
8309 }
8310
8311 /* If len parameter is one, return an expression corresponding to
8312 (*(const unsigned char*)arg1 - (const unsigned char*)arg2). */
8313 if (host_integerp (len, 1) && tree_low_cst (len, 1) == 1)
8314 {
8315 tree cst_uchar_node = build_type_variant (unsigned_char_type_node, 1, 0);
8316 tree cst_uchar_ptr_node
8317 = build_pointer_type_for_mode (cst_uchar_node, ptr_mode, true);
8318
8319 tree ind1 = fold_convert (integer_type_node,
8320 build1 (INDIRECT_REF, cst_uchar_node,
8321 fold_convert (cst_uchar_ptr_node,
8322 arg1)));
8323 tree ind2 = fold_convert (integer_type_node,
8324 build1 (INDIRECT_REF, cst_uchar_node,
8325 fold_convert (cst_uchar_ptr_node,
8326 arg2)));
8327 return fold_build2 (MINUS_EXPR, integer_type_node, ind1, ind2);
8328 }
8329
6423 return 0;
6424}
6425
6426/* Fold function call to builtin strcmp. Return
6427 NULL_TREE if no simplification can be made. */
6428
6429static tree
8330 return 0;
8331}
8332
8333/* Fold function call to builtin strcmp. Return
8334 NULL_TREE if no simplification can be made. */
8335
8336static tree
6430fold_builtin_strcmp (tree exp)
8337fold_builtin_strcmp (tree arglist)
6431{
8338{
6432 tree arglist = TREE_OPERAND (exp, 1);
6433 tree arg1, arg2;
6434 const char *p1, *p2;
6435
8339 tree arg1, arg2;
8340 const char *p1, *p2;
8341
6436 if (!validate_arglist (arglist,
6437 POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
8342 if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
6438 return 0;
6439
6440 arg1 = TREE_VALUE (arglist);
6441 arg2 = TREE_VALUE (TREE_CHAIN (arglist));
6442
6443 /* If ARG1 and ARG2 are the same (and not volatile), return zero. */
6444 if (operand_equal_p (arg1, arg2, 0))
8343 return 0;
8344
8345 arg1 = TREE_VALUE (arglist);
8346 arg2 = TREE_VALUE (TREE_CHAIN (arglist));
8347
8348 /* If ARG1 and ARG2 are the same (and not volatile), return zero. */
8349 if (operand_equal_p (arg1, arg2, 0))
6445 return convert (TREE_TYPE (exp), integer_zero_node);
8350 return integer_zero_node;
6446
6447 p1 = c_getstr (arg1);
6448 p2 = c_getstr (arg2);
6449
6450 if (p1 && p2)
6451 {
8351
8352 p1 = c_getstr (arg1);
8353 p2 = c_getstr (arg2);
8354
8355 if (p1 && p2)
8356 {
6452 tree temp;
6453 const int i = strcmp (p1, p2);
6454 if (i < 0)
8357 const int i = strcmp (p1, p2);
8358 if (i < 0)
6455 temp = integer_minus_one_node;
8359 return integer_minus_one_node;
6456 else if (i > 0)
8360 else if (i > 0)
6457 temp = integer_one_node;
8361 return integer_one_node;
6458 else
8362 else
6459 temp = integer_zero_node;
6460 return convert (TREE_TYPE (exp), temp);
8363 return integer_zero_node;
6461 }
6462
8364 }
8365
8366 /* If the second arg is "", return *(const unsigned char*)arg1. */
8367 if (p2 && *p2 == '\0')
8368 {
8369 tree cst_uchar_node = build_type_variant (unsigned_char_type_node, 1, 0);
8370 tree cst_uchar_ptr_node
8371 = build_pointer_type_for_mode (cst_uchar_node, ptr_mode, true);
8372
8373 return fold_convert (integer_type_node,
8374 build1 (INDIRECT_REF, cst_uchar_node,
8375 fold_convert (cst_uchar_ptr_node,
8376 arg1)));
8377 }
8378
8379 /* If the first arg is "", return -*(const unsigned char*)arg2. */
8380 if (p1 && *p1 == '\0')
8381 {
8382 tree cst_uchar_node = build_type_variant (unsigned_char_type_node, 1, 0);
8383 tree cst_uchar_ptr_node
8384 = build_pointer_type_for_mode (cst_uchar_node, ptr_mode, true);
8385
8386 tree temp = fold_convert (integer_type_node,
8387 build1 (INDIRECT_REF, cst_uchar_node,
8388 fold_convert (cst_uchar_ptr_node,
8389 arg2)));
8390 return fold_build1 (NEGATE_EXPR, integer_type_node, temp);
8391 }
8392
6463 return 0;
6464}
6465
6466/* Fold function call to builtin strncmp. Return
6467 NULL_TREE if no simplification can be made. */
6468
6469static tree
8393 return 0;
8394}
8395
8396/* Fold function call to builtin strncmp. Return
8397 NULL_TREE if no simplification can be made. */
8398
8399static tree
6470fold_builtin_strncmp (tree exp)
8400fold_builtin_strncmp (tree arglist)
6471{
8401{
6472 tree arglist = TREE_OPERAND (exp, 1);
6473 tree arg1, arg2, len;
6474 const char *p1, *p2;
6475
6476 if (!validate_arglist (arglist,
6477 POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
6478 return 0;
6479
6480 arg1 = TREE_VALUE (arglist);
6481 arg2 = TREE_VALUE (TREE_CHAIN (arglist));
6482 len = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
6483
6484 /* If the LEN parameter is zero, return zero. */
6485 if (integer_zerop (len))
8402 tree arg1, arg2, len;
8403 const char *p1, *p2;
8404
8405 if (!validate_arglist (arglist,
8406 POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
8407 return 0;
8408
8409 arg1 = TREE_VALUE (arglist);
8410 arg2 = TREE_VALUE (TREE_CHAIN (arglist));
8411 len = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
8412
8413 /* If the LEN parameter is zero, return zero. */
8414 if (integer_zerop (len))
6486 {
6487 tree temp = omit_one_operand (TREE_TYPE (exp), integer_zero_node, arg2);
6488 return omit_one_operand (TREE_TYPE (exp), temp, arg1);
6489 }
8415 return omit_two_operands (integer_type_node, integer_zero_node,
8416 arg1, arg2);
6490
6491 /* If ARG1 and ARG2 are the same (and not volatile), return zero. */
6492 if (operand_equal_p (arg1, arg2, 0))
8417
8418 /* If ARG1 and ARG2 are the same (and not volatile), return zero. */
8419 if (operand_equal_p (arg1, arg2, 0))
6493 return omit_one_operand (TREE_TYPE (exp), integer_zero_node, len);
8420 return omit_one_operand (integer_type_node, integer_zero_node, len);
6494
6495 p1 = c_getstr (arg1);
6496 p2 = c_getstr (arg2);
6497
6498 if (host_integerp (len, 1) && p1 && p2)
6499 {
8421
8422 p1 = c_getstr (arg1);
8423 p2 = c_getstr (arg2);
8424
8425 if (host_integerp (len, 1) && p1 && p2)
8426 {
6500 tree temp;
6501 const int i = strncmp (p1, p2, tree_low_cst (len, 1));
8427 const int i = strncmp (p1, p2, tree_low_cst (len, 1));
6502 if (i < 0)
6503 temp = integer_minus_one_node;
6504 else if (i > 0)
6505 temp = integer_one_node;
8428 if (i > 0)
8429 return integer_one_node;
8430 else if (i < 0)
8431 return integer_minus_one_node;
6506 else
8432 else
6507 temp = integer_zero_node;
6508 return convert (TREE_TYPE (exp), temp);
8433 return integer_zero_node;
6509 }
6510
8434 }
8435
8436 /* If the second arg is "", and the length is greater than zero,
8437 return *(const unsigned char*)arg1. */
8438 if (p2 && *p2 == '\0'
8439 && TREE_CODE (len) == INTEGER_CST
8440 && tree_int_cst_sgn (len) == 1)
8441 {
8442 tree cst_uchar_node = build_type_variant (unsigned_char_type_node, 1, 0);
8443 tree cst_uchar_ptr_node
8444 = build_pointer_type_for_mode (cst_uchar_node, ptr_mode, true);
8445
8446 return fold_convert (integer_type_node,
8447 build1 (INDIRECT_REF, cst_uchar_node,
8448 fold_convert (cst_uchar_ptr_node,
8449 arg1)));
8450 }
8451
8452 /* If the first arg is "", and the length is greater than zero,
8453 return -*(const unsigned char*)arg2. */
8454 if (p1 && *p1 == '\0'
8455 && TREE_CODE (len) == INTEGER_CST
8456 && tree_int_cst_sgn (len) == 1)
8457 {
8458 tree cst_uchar_node = build_type_variant (unsigned_char_type_node, 1, 0);
8459 tree cst_uchar_ptr_node
8460 = build_pointer_type_for_mode (cst_uchar_node, ptr_mode, true);
8461
8462 tree temp = fold_convert (integer_type_node,
8463 build1 (INDIRECT_REF, cst_uchar_node,
8464 fold_convert (cst_uchar_ptr_node,
8465 arg2)));
8466 return fold_build1 (NEGATE_EXPR, integer_type_node, temp);
8467 }
8468
8469 /* If len parameter is one, return an expression corresponding to
8470 (*(const unsigned char*)arg1 - (const unsigned char*)arg2). */
8471 if (host_integerp (len, 1) && tree_low_cst (len, 1) == 1)
8472 {
8473 tree cst_uchar_node = build_type_variant (unsigned_char_type_node, 1, 0);
8474 tree cst_uchar_ptr_node
8475 = build_pointer_type_for_mode (cst_uchar_node, ptr_mode, true);
8476
8477 tree ind1 = fold_convert (integer_type_node,
8478 build1 (INDIRECT_REF, cst_uchar_node,
8479 fold_convert (cst_uchar_ptr_node,
8480 arg1)));
8481 tree ind2 = fold_convert (integer_type_node,
8482 build1 (INDIRECT_REF, cst_uchar_node,
8483 fold_convert (cst_uchar_ptr_node,
8484 arg2)));
8485 return fold_build2 (MINUS_EXPR, integer_type_node, ind1, ind2);
8486 }
8487
6511 return 0;
6512}
6513
8488 return 0;
8489}
8490
6514/* Used by constant folding to eliminate some builtin calls early. EXP is
6515 the CALL_EXPR of a call to a builtin function. */
8491/* Fold function call to builtin signbit, signbitf or signbitl. Return
8492 NULL_TREE if no simplification can be made. */
6516
8493
6517tree
6518fold_builtin (tree exp)
8494static tree
8495fold_builtin_signbit (tree fndecl, tree arglist)
6519{
8496{
6520 tree fndecl = get_callee_fndecl (exp);
6521 tree arglist = TREE_OPERAND (exp, 1);
6522 tree type = TREE_TYPE (TREE_TYPE (fndecl));
8497 tree type = TREE_TYPE (TREE_TYPE (fndecl));
8498 tree arg, temp;
6523
8499
6524 if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_MD)
8500 if (!validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
8501 return NULL_TREE;
8502
8503 arg = TREE_VALUE (arglist);
8504
8505 /* If ARG is a compile-time constant, determine the result. */
8506 if (TREE_CODE (arg) == REAL_CST
8507 && !TREE_CONSTANT_OVERFLOW (arg))
8508 {
8509 REAL_VALUE_TYPE c;
8510
8511 c = TREE_REAL_CST (arg);
8512 temp = REAL_VALUE_NEGATIVE (c) ? integer_one_node : integer_zero_node;
8513 return fold_convert (type, temp);
8514 }
8515
8516 /* If ARG is non-negative, the result is always zero. */
8517 if (tree_expr_nonnegative_p (arg))
8518 return omit_one_operand (type, integer_zero_node, arg);
8519
8520 /* If ARG's format doesn't have signed zeros, return "arg < 0.0". */
8521 if (!HONOR_SIGNED_ZEROS (TYPE_MODE (TREE_TYPE (arg))))
8522 return fold_build2 (LT_EXPR, type, arg,
8523 build_real (TREE_TYPE (arg), dconst0));
8524
8525 return NULL_TREE;
8526}
8527
8528/* Fold function call to builtin copysign, copysignf or copysignl.
8529 Return NULL_TREE if no simplification can be made. */
8530
8531static tree
8532fold_builtin_copysign (tree fndecl, tree arglist, tree type)
8533{
8534 tree arg1, arg2, tem;
8535
8536 if (!validate_arglist (arglist, REAL_TYPE, REAL_TYPE, VOID_TYPE))
8537 return NULL_TREE;
8538
8539 arg1 = TREE_VALUE (arglist);
8540 arg2 = TREE_VALUE (TREE_CHAIN (arglist));
8541
8542 /* copysign(X,X) is X. */
8543 if (operand_equal_p (arg1, arg2, 0))
8544 return fold_convert (type, arg1);
8545
8546 /* If ARG1 and ARG2 are compile-time constants, determine the result. */
8547 if (TREE_CODE (arg1) == REAL_CST
8548 && TREE_CODE (arg2) == REAL_CST
8549 && !TREE_CONSTANT_OVERFLOW (arg1)
8550 && !TREE_CONSTANT_OVERFLOW (arg2))
8551 {
8552 REAL_VALUE_TYPE c1, c2;
8553
8554 c1 = TREE_REAL_CST (arg1);
8555 c2 = TREE_REAL_CST (arg2);
8556 /* c1.sign := c2.sign. */
8557 real_copysign (&c1, &c2);
8558 return build_real (type, c1);
8559 }
8560
8561 /* copysign(X, Y) is fabs(X) when Y is always non-negative.
8562 Remember to evaluate Y for side-effects. */
8563 if (tree_expr_nonnegative_p (arg2))
8564 return omit_one_operand (type,
8565 fold_build1 (ABS_EXPR, type, arg1),
8566 arg2);
8567
8568 /* Strip sign changing operations for the first argument. */
8569 tem = fold_strip_sign_ops (arg1);
8570 if (tem)
8571 {
8572 arglist = tree_cons (NULL_TREE, tem, TREE_CHAIN (arglist));
8573 return build_function_call_expr (fndecl, arglist);
8574 }
8575
8576 return NULL_TREE;
8577}
8578
8579/* Fold a call to builtin isascii. */
8580
8581static tree
8582fold_builtin_isascii (tree arglist)
8583{
8584 if (! validate_arglist (arglist, INTEGER_TYPE, VOID_TYPE))
6525 return 0;
8585 return 0;
8586 else
8587 {
8588 /* Transform isascii(c) -> ((c & ~0x7f) == 0). */
8589 tree arg = TREE_VALUE (arglist);
6526
8590
6527 switch (DECL_FUNCTION_CODE (fndecl))
8591 arg = build2 (BIT_AND_EXPR, integer_type_node, arg,
8592 build_int_cst (NULL_TREE,
8593 ~ (unsigned HOST_WIDE_INT) 0x7f));
8594 arg = fold_build2 (EQ_EXPR, integer_type_node,
8595 arg, integer_zero_node);
8596
8597 if (in_gimple_form && !TREE_CONSTANT (arg))
8598 return NULL_TREE;
8599 else
8600 return arg;
8601 }
8602}
8603
8604/* Fold a call to builtin toascii. */
8605
8606static tree
8607fold_builtin_toascii (tree arglist)
8608{
8609 if (! validate_arglist (arglist, INTEGER_TYPE, VOID_TYPE))
8610 return 0;
8611 else
6528 {
8612 {
6529 case BUILT_IN_CONSTANT_P:
6530 return fold_builtin_constant_p (arglist);
8613 /* Transform toascii(c) -> (c & 0x7f). */
8614 tree arg = TREE_VALUE (arglist);
6531
8615
6532 case BUILT_IN_CLASSIFY_TYPE:
6533 return fold_builtin_classify_type (arglist);
8616 return fold_build2 (BIT_AND_EXPR, integer_type_node, arg,
8617 build_int_cst (NULL_TREE, 0x7f));
8618 }
8619}
6534
8620
6535 case BUILT_IN_STRLEN:
6536 if (validate_arglist (arglist, POINTER_TYPE, VOID_TYPE))
6537 {
6538 tree len = c_strlen (TREE_VALUE (arglist), 0);
6539 if (len)
6540 {
6541 /* Convert from the internal "sizetype" type to "size_t". */
6542 if (size_type_node)
6543 len = convert (size_type_node, len);
6544 return len;
6545 }
6546 }
6547 break;
8621/* Fold a call to builtin isdigit. */
6548
8622
6549 case BUILT_IN_FABS:
6550 case BUILT_IN_FABSF:
6551 case BUILT_IN_FABSL:
6552 if (validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
6553 return fold (build1 (ABS_EXPR, type, TREE_VALUE (arglist)));
6554 break;
8623static tree
8624fold_builtin_isdigit (tree arglist)
8625{
8626 if (! validate_arglist (arglist, INTEGER_TYPE, VOID_TYPE))
8627 return 0;
8628 else
8629 {
8630 /* Transform isdigit(c) -> (unsigned)(c) - '0' <= 9. */
8631 /* According to the C standard, isdigit is unaffected by locale.
8632 However, it definitely is affected by the target character set. */
8633 tree arg;
8634 unsigned HOST_WIDE_INT target_digit0
8635 = lang_hooks.to_target_charset ('0');
6555
8636
6556 case BUILT_IN_CABS:
6557 case BUILT_IN_CABSF:
6558 case BUILT_IN_CABSL:
6559 return fold_builtin_cabs (fndecl, arglist, type);
8637 if (target_digit0 == 0)
8638 return NULL_TREE;
6560
8639
6561 case BUILT_IN_SQRT:
6562 case BUILT_IN_SQRTF:
6563 case BUILT_IN_SQRTL:
6564 if (validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
6565 {
6566 enum built_in_function fcode;
6567 tree arg = TREE_VALUE (arglist);
8640 arg = fold_convert (unsigned_type_node, TREE_VALUE (arglist));
8641 arg = build2 (MINUS_EXPR, unsigned_type_node, arg,
8642 build_int_cst (unsigned_type_node, target_digit0));
8643 arg = fold_build2 (LE_EXPR, integer_type_node, arg,
8644 build_int_cst (unsigned_type_node, 9));
8645 if (in_gimple_form && !TREE_CONSTANT (arg))
8646 return NULL_TREE;
8647 else
8648 return arg;
8649 }
8650}
6568
8651
6569 /* Optimize sqrt of constant value. */
6570 if (TREE_CODE (arg) == REAL_CST
6571 && ! TREE_CONSTANT_OVERFLOW (arg))
6572 {
6573 REAL_VALUE_TYPE r, x;
8652/* Fold a call to fabs, fabsf or fabsl. */
6574
8653
6575 x = TREE_REAL_CST (arg);
6576 if (real_sqrt (&r, TYPE_MODE (type), &x)
6577 || (!flag_trapping_math && !flag_errno_math))
6578 return build_real (type, r);
6579 }
8654static tree
8655fold_builtin_fabs (tree arglist, tree type)
8656{
8657 tree arg;
6580
8658
6581 /* Optimize sqrt(exp(x)) = exp(x*0.5). */
6582 fcode = builtin_mathfn_code (arg);
6583 if (flag_unsafe_math_optimizations
6584 && (fcode == BUILT_IN_EXP
6585 || fcode == BUILT_IN_EXPF
6586 || fcode == BUILT_IN_EXPL))
6587 {
6588 tree expfn = TREE_OPERAND (TREE_OPERAND (arg, 0), 0);
6589 arg = fold (build (MULT_EXPR, type,
6590 TREE_VALUE (TREE_OPERAND (arg, 1)),
6591 build_real (type, dconsthalf)));
6592 arglist = build_tree_list (NULL_TREE, arg);
6593 return build_function_call_expr (expfn, arglist);
6594 }
8659 if (!validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
8660 return 0;
6595
8661
6596 /* Optimize sqrt(pow(x,y)) = pow(|x|,y*0.5). */
6597 if (flag_unsafe_math_optimizations
6598 && (fcode == BUILT_IN_POW
6599 || fcode == BUILT_IN_POWF
6600 || fcode == BUILT_IN_POWL))
6601 {
6602 tree powfn = TREE_OPERAND (TREE_OPERAND (arg, 0), 0);
6603 tree arg0 = TREE_VALUE (TREE_OPERAND (arg, 1));
6604 tree arg1 = TREE_VALUE (TREE_CHAIN (TREE_OPERAND (arg, 1)));
6605 tree narg1;
6606 if (!tree_expr_nonnegative_p (arg0))
6607 arg0 = build1 (ABS_EXPR, type, arg0);
6608 narg1 = fold (build (MULT_EXPR, type, arg1,
6609 build_real (type, dconsthalf)));
6610 arglist = tree_cons (NULL_TREE, arg0,
6611 build_tree_list (NULL_TREE, narg1));
6612 return build_function_call_expr (powfn, arglist);
6613 }
6614 }
6615 break;
8662 arg = TREE_VALUE (arglist);
8663 arg = fold_convert (type, arg);
8664 if (TREE_CODE (arg) == REAL_CST)
8665 return fold_abs_const (arg, type);
8666 return fold_build1 (ABS_EXPR, type, arg);
8667}
6616
8668
6617 case BUILT_IN_SIN:
6618 case BUILT_IN_SINF:
6619 case BUILT_IN_SINL:
6620 if (validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
6621 {
6622 tree arg = TREE_VALUE (arglist);
8669/* Fold a call to abs, labs, llabs or imaxabs. */
6623
8670
6624 /* Optimize sin(0.0) = 0.0. */
6625 if (real_zerop (arg))
6626 return arg;
6627 }
6628 break;
8671static tree
8672fold_builtin_abs (tree arglist, tree type)
8673{
8674 tree arg;
6629
8675
6630 case BUILT_IN_COS:
6631 case BUILT_IN_COSF:
6632 case BUILT_IN_COSL:
6633 if (validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
6634 {
6635 tree arg = TREE_VALUE (arglist);
8676 if (!validate_arglist (arglist, INTEGER_TYPE, VOID_TYPE))
8677 return 0;
6636
8678
6637 /* Optimize cos(0.0) = 1.0. */
6638 if (real_zerop (arg))
6639 return build_real (type, dconst1);
8679 arg = TREE_VALUE (arglist);
8680 arg = fold_convert (type, arg);
8681 if (TREE_CODE (arg) == INTEGER_CST)
8682 return fold_abs_const (arg, type);
8683 return fold_build1 (ABS_EXPR, type, arg);
8684}
6640
8685
6641 /* Optimize cos(-x) into cos(x). */
6642 if (TREE_CODE (arg) == NEGATE_EXPR)
6643 {
6644 tree arglist = build_tree_list (NULL_TREE,
6645 TREE_OPERAND (arg, 0));
6646 return build_function_call_expr (fndecl, arglist);
6647 }
6648 }
6649 break;
8686/* Fold a call to __builtin_isnan(), __builtin_isinf, __builtin_finite.
8687 EXP is the CALL_EXPR for the call. */
6650
8688
6651 case BUILT_IN_EXP:
6652 case BUILT_IN_EXPF:
6653 case BUILT_IN_EXPL:
6654 return fold_builtin_exponent (exp, &dconste);
6655 case BUILT_IN_EXP2:
6656 case BUILT_IN_EXP2F:
6657 case BUILT_IN_EXP2L:
6658 return fold_builtin_exponent (exp, &dconst2);
6659 case BUILT_IN_EXP10:
6660 case BUILT_IN_EXP10F:
6661 case BUILT_IN_EXP10L:
6662 case BUILT_IN_POW10:
6663 case BUILT_IN_POW10F:
6664 case BUILT_IN_POW10L:
6665 return fold_builtin_exponent (exp, &dconst10);
6666 case BUILT_IN_LOG:
6667 case BUILT_IN_LOGF:
6668 case BUILT_IN_LOGL:
6669 return fold_builtin_logarithm (exp, &dconste);
6670 break;
6671 case BUILT_IN_LOG2:
6672 case BUILT_IN_LOG2F:
6673 case BUILT_IN_LOG2L:
6674 return fold_builtin_logarithm (exp, &dconst2);
6675 break;
6676 case BUILT_IN_LOG10:
6677 case BUILT_IN_LOG10F:
6678 case BUILT_IN_LOG10L:
6679 return fold_builtin_logarithm (exp, &dconst10);
6680 break;
8689static tree
8690fold_builtin_classify (tree fndecl, tree arglist, int builtin_index)
8691{
8692 tree type = TREE_TYPE (TREE_TYPE (fndecl));
8693 tree arg;
8694 REAL_VALUE_TYPE r;
6681
8695
6682 case BUILT_IN_TAN:
6683 case BUILT_IN_TANF:
6684 case BUILT_IN_TANL:
6685 if (validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
8696 if (!validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
8697 {
8698 /* Check that we have exactly one argument. */
8699 if (arglist == 0)
6686 {
8700 {
6687 enum built_in_function fcode;
6688 tree arg = TREE_VALUE (arglist);
8701 error ("too few arguments to function %qs",
8702 IDENTIFIER_POINTER (DECL_NAME (fndecl)));
8703 return error_mark_node;
8704 }
8705 else if (TREE_CHAIN (arglist) != 0)
8706 {
8707 error ("too many arguments to function %qs",
8708 IDENTIFIER_POINTER (DECL_NAME (fndecl)));
8709 return error_mark_node;
8710 }
8711 else
8712 {
8713 error ("non-floating-point argument to function %qs",
8714 IDENTIFIER_POINTER (DECL_NAME (fndecl)));
8715 return error_mark_node;
8716 }
8717 }
6689
8718
6690 /* Optimize tan(0.0) = 0.0. */
6691 if (real_zerop (arg))
6692 return arg;
8719 arg = TREE_VALUE (arglist);
8720 switch (builtin_index)
8721 {
8722 case BUILT_IN_ISINF:
8723 if (!MODE_HAS_INFINITIES (TYPE_MODE (TREE_TYPE (arg))))
8724 return omit_one_operand (type, integer_zero_node, arg);
6693
8725
6694 /* Optimize tan(atan(x)) = x. */
6695 fcode = builtin_mathfn_code (arg);
6696 if (flag_unsafe_math_optimizations
6697 && (fcode == BUILT_IN_ATAN
6698 || fcode == BUILT_IN_ATANF
6699 || fcode == BUILT_IN_ATANL))
6700 return TREE_VALUE (TREE_OPERAND (arg, 1));
8726 if (TREE_CODE (arg) == REAL_CST)
8727 {
8728 r = TREE_REAL_CST (arg);
8729 if (real_isinf (&r))
8730 return real_compare (GT_EXPR, &r, &dconst0)
8731 ? integer_one_node : integer_minus_one_node;
8732 else
8733 return integer_zero_node;
6701 }
8734 }
6702 break;
6703
8735
6704 case BUILT_IN_ATAN:
6705 case BUILT_IN_ATANF:
6706 case BUILT_IN_ATANL:
6707 if (validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
8736 return NULL_TREE;
8737
8738 case BUILT_IN_FINITE:
8739 if (!MODE_HAS_NANS (TYPE_MODE (TREE_TYPE (arg)))
8740 && !MODE_HAS_INFINITIES (TYPE_MODE (TREE_TYPE (arg))))
8741 return omit_one_operand (type, integer_zero_node, arg);
8742
8743 if (TREE_CODE (arg) == REAL_CST)
6708 {
8744 {
6709 tree arg = TREE_VALUE (arglist);
8745 r = TREE_REAL_CST (arg);
8746 return real_isinf (&r) || real_isnan (&r)
8747 ? integer_zero_node : integer_one_node;
8748 }
6710
8749
6711 /* Optimize atan(0.0) = 0.0. */
6712 if (real_zerop (arg))
6713 return arg;
8750 return NULL_TREE;
6714
8751
6715 /* Optimize atan(1.0) = pi/4. */
6716 if (real_onep (arg))
6717 {
6718 REAL_VALUE_TYPE cst;
8752 case BUILT_IN_ISNAN:
8753 if (!MODE_HAS_NANS (TYPE_MODE (TREE_TYPE (arg))))
8754 return omit_one_operand (type, integer_zero_node, arg);
6719
8755
6720 real_convert (&cst, TYPE_MODE (type), &dconstpi);
6721 cst.exp -= 2;
6722 return build_real (type, cst);
6723 }
8756 if (TREE_CODE (arg) == REAL_CST)
8757 {
8758 r = TREE_REAL_CST (arg);
8759 return real_isnan (&r) ? integer_one_node : integer_zero_node;
6724 }
8760 }
6725 break;
6726
8761
6727 case BUILT_IN_POW:
6728 case BUILT_IN_POWF:
6729 case BUILT_IN_POWL:
6730 if (validate_arglist (arglist, REAL_TYPE, REAL_TYPE, VOID_TYPE))
8762 arg = builtin_save_expr (arg);
8763 return fold_build2 (UNORDERED_EXPR, type, arg, arg);
8764
8765 default:
8766 gcc_unreachable ();
8767 }
8768}
8769
8770/* Fold a call to an unordered comparison function such as
8771 __builtin_isgreater(). FNDECL is the FUNCTION_DECL for the function
8772 being called and ARGLIST is the argument list for the call.
8773 UNORDERED_CODE and ORDERED_CODE are comparison codes that give
8774 the opposite of the desired result. UNORDERED_CODE is used
8775 for modes that can hold NaNs and ORDERED_CODE is used for
8776 the rest. */
8777
8778static tree
8779fold_builtin_unordered_cmp (tree fndecl, tree arglist,
8780 enum tree_code unordered_code,
8781 enum tree_code ordered_code)
8782{
8783 tree type = TREE_TYPE (TREE_TYPE (fndecl));
8784 enum tree_code code;
8785 tree arg0, arg1;
8786 tree type0, type1;
8787 enum tree_code code0, code1;
8788 tree cmp_type = NULL_TREE;
8789
8790 if (!validate_arglist (arglist, REAL_TYPE, REAL_TYPE, VOID_TYPE))
8791 {
8792 /* Check that we have exactly two arguments. */
8793 if (arglist == 0 || TREE_CHAIN (arglist) == 0)
6731 {
8794 {
6732 enum built_in_function fcode;
6733 tree arg0 = TREE_VALUE (arglist);
6734 tree arg1 = TREE_VALUE (TREE_CHAIN (arglist));
8795 error ("too few arguments to function %qs",
8796 IDENTIFIER_POINTER (DECL_NAME (fndecl)));
8797 return error_mark_node;
8798 }
8799 else if (TREE_CHAIN (TREE_CHAIN (arglist)) != 0)
8800 {
8801 error ("too many arguments to function %qs",
8802 IDENTIFIER_POINTER (DECL_NAME (fndecl)));
8803 return error_mark_node;
8804 }
8805 }
6735
8806
6736 /* Optimize pow(1.0,y) = 1.0. */
6737 if (real_onep (arg0))
6738 return omit_one_operand (type, build_real (type, dconst1), arg1);
8807 arg0 = TREE_VALUE (arglist);
8808 arg1 = TREE_VALUE (TREE_CHAIN (arglist));
6739
8809
6740 if (TREE_CODE (arg1) == REAL_CST
6741 && ! TREE_CONSTANT_OVERFLOW (arg1))
6742 {
6743 REAL_VALUE_TYPE c;
6744 c = TREE_REAL_CST (arg1);
8810 type0 = TREE_TYPE (arg0);
8811 type1 = TREE_TYPE (arg1);
6745
8812
6746 /* Optimize pow(x,0.0) = 1.0. */
6747 if (REAL_VALUES_EQUAL (c, dconst0))
6748 return omit_one_operand (type, build_real (type, dconst1),
6749 arg0);
8813 code0 = TREE_CODE (type0);
8814 code1 = TREE_CODE (type1);
6750
8815
6751 /* Optimize pow(x,1.0) = x. */
6752 if (REAL_VALUES_EQUAL (c, dconst1))
6753 return arg0;
8816 if (code0 == REAL_TYPE && code1 == REAL_TYPE)
8817 /* Choose the wider of two real types. */
8818 cmp_type = TYPE_PRECISION (type0) >= TYPE_PRECISION (type1)
8819 ? type0 : type1;
8820 else if (code0 == REAL_TYPE && code1 == INTEGER_TYPE)
8821 cmp_type = type0;
8822 else if (code0 == INTEGER_TYPE && code1 == REAL_TYPE)
8823 cmp_type = type1;
8824 else
8825 {
8826 error ("non-floating-point argument to function %qs",
8827 IDENTIFIER_POINTER (DECL_NAME (fndecl)));
8828 return error_mark_node;
8829 }
6754
8830
6755 /* Optimize pow(x,-1.0) = 1.0/x. */
6756 if (REAL_VALUES_EQUAL (c, dconstm1))
6757 return fold (build (RDIV_EXPR, type,
6758 build_real (type, dconst1),
6759 arg0));
8831 arg0 = fold_convert (cmp_type, arg0);
8832 arg1 = fold_convert (cmp_type, arg1);
6760
8833
6761 /* Optimize pow(x,0.5) = sqrt(x). */
6762 if (flag_unsafe_math_optimizations
6763 && REAL_VALUES_EQUAL (c, dconsthalf))
6764 {
6765 tree sqrtfn;
8834 if (unordered_code == UNORDERED_EXPR)
8835 {
8836 if (!MODE_HAS_NANS (TYPE_MODE (TREE_TYPE (arg0))))
8837 return omit_two_operands (type, integer_zero_node, arg0, arg1);
8838 return fold_build2 (UNORDERED_EXPR, type, arg0, arg1);
8839 }
6766
8840
6767 fcode = DECL_FUNCTION_CODE (fndecl);
6768 if (fcode == BUILT_IN_POW)
6769 sqrtfn = implicit_built_in_decls[BUILT_IN_SQRT];
6770 else if (fcode == BUILT_IN_POWF)
6771 sqrtfn = implicit_built_in_decls[BUILT_IN_SQRTF];
6772 else if (fcode == BUILT_IN_POWL)
6773 sqrtfn = implicit_built_in_decls[BUILT_IN_SQRTL];
6774 else
6775 sqrtfn = NULL_TREE;
8841 code = MODE_HAS_NANS (TYPE_MODE (TREE_TYPE (arg0))) ? unordered_code
8842 : ordered_code;
8843 return fold_build1 (TRUTH_NOT_EXPR, type,
8844 fold_build2 (code, type, arg0, arg1));
8845}
6776
8846
6777 if (sqrtfn != NULL_TREE)
6778 {
6779 tree arglist = build_tree_list (NULL_TREE, arg0);
6780 return build_function_call_expr (sqrtfn, arglist);
6781 }
6782 }
8847/* Used by constant folding to simplify calls to builtin functions. EXP is
8848 the CALL_EXPR of a call to a builtin function. IGNORE is true if the
8849 result of the function call is ignored. This function returns NULL_TREE
8850 if no simplification was possible. */
6783
8851
6784 /* Attempt to evaluate pow at compile-time. */
6785 if (TREE_CODE (arg0) == REAL_CST
6786 && ! TREE_CONSTANT_OVERFLOW (arg0))
6787 {
6788 REAL_VALUE_TYPE cint;
6789 HOST_WIDE_INT n;
8852static tree
8853fold_builtin_1 (tree fndecl, tree arglist, bool ignore)
8854{
8855 tree type = TREE_TYPE (TREE_TYPE (fndecl));
8856 enum built_in_function fcode;
6790
8857
6791 n = real_to_integer (&c);
6792 real_from_integer (&cint, VOIDmode, n,
6793 n < 0 ? -1 : 0, 0);
6794 if (real_identical (&c, &cint))
6795 {
6796 REAL_VALUE_TYPE x;
6797 bool inexact;
8858 if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_MD)
8859 return targetm.fold_builtin (fndecl, arglist, ignore);
6798
8860
6799 x = TREE_REAL_CST (arg0);
6800 inexact = real_powi (&x, TYPE_MODE (type), &x, n);
6801 if (flag_unsafe_math_optimizations || !inexact)
6802 return build_real (type, x);
6803 }
6804 }
6805 }
8861 fcode = DECL_FUNCTION_CODE (fndecl);
8862 switch (fcode)
8863 {
8864 case BUILT_IN_FPUTS:
8865 return fold_builtin_fputs (arglist, ignore, false, NULL_TREE);
6806
8866
6807 /* Optimize pow(exp(x),y) = exp(x*y). */
6808 fcode = builtin_mathfn_code (arg0);
6809 if (flag_unsafe_math_optimizations
6810 && (fcode == BUILT_IN_EXP
6811 || fcode == BUILT_IN_EXPF
6812 || fcode == BUILT_IN_EXPL))
6813 {
6814 tree expfn = TREE_OPERAND (TREE_OPERAND (arg0, 0), 0);
6815 tree arg = TREE_VALUE (TREE_OPERAND (arg0, 1));
6816 arg = fold (build (MULT_EXPR, type, arg, arg1));
6817 arglist = build_tree_list (NULL_TREE, arg);
6818 return build_function_call_expr (expfn, arglist);
6819 }
8867 case BUILT_IN_FPUTS_UNLOCKED:
8868 return fold_builtin_fputs (arglist, ignore, true, NULL_TREE);
6820
8869
6821 /* Optimize pow(sqrt(x),y) = pow(x,y*0.5). */
6822 if (flag_unsafe_math_optimizations
6823 && (fcode == BUILT_IN_SQRT
6824 || fcode == BUILT_IN_SQRTF
6825 || fcode == BUILT_IN_SQRTL))
6826 {
6827 tree narg0 = TREE_VALUE (TREE_OPERAND (arg0, 1));
6828 tree narg1 = fold (build (MULT_EXPR, type, arg1,
6829 build_real (type, dconsthalf)));
8870 case BUILT_IN_STRSTR:
8871 return fold_builtin_strstr (arglist, type);
6830
8872
6831 arglist = tree_cons (NULL_TREE, narg0,
6832 build_tree_list (NULL_TREE, narg1));
6833 return build_function_call_expr (fndecl, arglist);
6834 }
8873 case BUILT_IN_STRCAT:
8874 return fold_builtin_strcat (arglist);
6835
8875
6836 /* Optimize pow(pow(x,y),z) = pow(x,y*z). */
6837 if (flag_unsafe_math_optimizations
6838 && (fcode == BUILT_IN_POW
6839 || fcode == BUILT_IN_POWF
6840 || fcode == BUILT_IN_POWL))
6841 {
6842 tree arg00 = TREE_VALUE (TREE_OPERAND (arg0, 1));
6843 tree arg01 = TREE_VALUE (TREE_CHAIN (TREE_OPERAND (arg0, 1)));
6844 tree narg1 = fold (build (MULT_EXPR, type, arg01, arg1));
6845 arglist = tree_cons (NULL_TREE, arg00,
6846 build_tree_list (NULL_TREE, narg1));
6847 return build_function_call_expr (fndecl, arglist);
6848 }
6849 }
8876 case BUILT_IN_STRNCAT:
8877 return fold_builtin_strncat (arglist);
8878
8879 case BUILT_IN_STRSPN:
8880 return fold_builtin_strspn (arglist);
8881
8882 case BUILT_IN_STRCSPN:
8883 return fold_builtin_strcspn (arglist);
8884
8885 case BUILT_IN_STRCHR:
8886 case BUILT_IN_INDEX:
8887 return fold_builtin_strchr (arglist, type);
8888
8889 case BUILT_IN_STRRCHR:
8890 case BUILT_IN_RINDEX:
8891 return fold_builtin_strrchr (arglist, type);
8892
8893 case BUILT_IN_STRCPY:
8894 return fold_builtin_strcpy (fndecl, arglist, NULL_TREE);
8895
8896 case BUILT_IN_STRNCPY:
8897 return fold_builtin_strncpy (fndecl, arglist, NULL_TREE);
8898
8899 case BUILT_IN_STRCMP:
8900 return fold_builtin_strcmp (arglist);
8901
8902 case BUILT_IN_STRNCMP:
8903 return fold_builtin_strncmp (arglist);
8904
8905 case BUILT_IN_STRPBRK:
8906 return fold_builtin_strpbrk (arglist, type);
8907
8908 case BUILT_IN_BCMP:
8909 case BUILT_IN_MEMCMP:
8910 return fold_builtin_memcmp (arglist);
8911
8912 case BUILT_IN_SPRINTF:
8913 return fold_builtin_sprintf (arglist, ignore);
8914
8915 case BUILT_IN_CONSTANT_P:
8916 {
8917 tree val;
8918
8919 val = fold_builtin_constant_p (arglist);
8920 /* Gimplification will pull the CALL_EXPR for the builtin out of
8921 an if condition. When not optimizing, we'll not CSE it back.
8922 To avoid link error types of regressions, return false now. */
8923 if (!val && !optimize)
8924 val = integer_zero_node;
8925
8926 return val;
8927 }
8928
8929 case BUILT_IN_EXPECT:
8930 return fold_builtin_expect (arglist);
8931
8932 case BUILT_IN_CLASSIFY_TYPE:
8933 return fold_builtin_classify_type (arglist);
8934
8935 case BUILT_IN_STRLEN:
8936 return fold_builtin_strlen (arglist);
8937
8938 CASE_FLT_FN (BUILT_IN_FABS):
8939 return fold_builtin_fabs (arglist, type);
8940
8941 case BUILT_IN_ABS:
8942 case BUILT_IN_LABS:
8943 case BUILT_IN_LLABS:
8944 case BUILT_IN_IMAXABS:
8945 return fold_builtin_abs (arglist, type);
8946
8947 CASE_FLT_FN (BUILT_IN_CONJ):
8948 if (validate_arglist (arglist, COMPLEX_TYPE, VOID_TYPE))
8949 return fold_build1 (CONJ_EXPR, type, TREE_VALUE (arglist));
6850 break;
6851
8950 break;
8951
6852 case BUILT_IN_INF:
6853 case BUILT_IN_INFF:
6854 case BUILT_IN_INFL:
8952 CASE_FLT_FN (BUILT_IN_CREAL):
8953 if (validate_arglist (arglist, COMPLEX_TYPE, VOID_TYPE))
8954 return non_lvalue (fold_build1 (REALPART_EXPR, type,
8955 TREE_VALUE (arglist)));
8956 break;
8957
8958 CASE_FLT_FN (BUILT_IN_CIMAG):
8959 if (validate_arglist (arglist, COMPLEX_TYPE, VOID_TYPE))
8960 return non_lvalue (fold_build1 (IMAGPART_EXPR, type,
8961 TREE_VALUE (arglist)));
8962 break;
8963
8964 CASE_FLT_FN (BUILT_IN_CABS):
8965 return fold_builtin_cabs (arglist, type, fndecl);
8966
8967 CASE_FLT_FN (BUILT_IN_SQRT):
8968 return fold_builtin_sqrt (arglist, type);
8969
8970 CASE_FLT_FN (BUILT_IN_CBRT):
8971 return fold_builtin_cbrt (arglist, type);
8972
8973 CASE_FLT_FN (BUILT_IN_SIN):
8974 return fold_builtin_sin (arglist);
8975
8976 CASE_FLT_FN (BUILT_IN_COS):
8977 return fold_builtin_cos (arglist, type, fndecl);
8978
8979 CASE_FLT_FN (BUILT_IN_EXP):
8980 return fold_builtin_exponent (fndecl, arglist, &dconste);
8981
8982 CASE_FLT_FN (BUILT_IN_EXP2):
8983 return fold_builtin_exponent (fndecl, arglist, &dconst2);
8984
8985 CASE_FLT_FN (BUILT_IN_EXP10):
8986 CASE_FLT_FN (BUILT_IN_POW10):
8987 return fold_builtin_exponent (fndecl, arglist, &dconst10);
8988
8989 CASE_FLT_FN (BUILT_IN_LOG):
8990 return fold_builtin_logarithm (fndecl, arglist, &dconste);
8991
8992 CASE_FLT_FN (BUILT_IN_LOG2):
8993 return fold_builtin_logarithm (fndecl, arglist, &dconst2);
8994
8995 CASE_FLT_FN (BUILT_IN_LOG10):
8996 return fold_builtin_logarithm (fndecl, arglist, &dconst10);
8997
8998 CASE_FLT_FN (BUILT_IN_TAN):
8999 return fold_builtin_tan (arglist);
9000
9001 CASE_FLT_FN (BUILT_IN_ATAN):
9002 return fold_builtin_atan (arglist, type);
9003
9004 CASE_FLT_FN (BUILT_IN_POW):
9005 return fold_builtin_pow (fndecl, arglist, type);
9006
9007 CASE_FLT_FN (BUILT_IN_POWI):
9008 return fold_builtin_powi (fndecl, arglist, type);
9009
9010 CASE_FLT_FN (BUILT_IN_INF):
9011 case BUILT_IN_INFD32:
9012 case BUILT_IN_INFD64:
9013 case BUILT_IN_INFD128:
6855 return fold_builtin_inf (type, true);
6856
9014 return fold_builtin_inf (type, true);
9015
6857 case BUILT_IN_HUGE_VAL:
6858 case BUILT_IN_HUGE_VALF:
6859 case BUILT_IN_HUGE_VALL:
9016 CASE_FLT_FN (BUILT_IN_HUGE_VAL):
6860 return fold_builtin_inf (type, false);
6861
9017 return fold_builtin_inf (type, false);
9018
6862 case BUILT_IN_NAN:
6863 case BUILT_IN_NANF:
6864 case BUILT_IN_NANL:
9019 CASE_FLT_FN (BUILT_IN_NAN):
9020 case BUILT_IN_NAND32:
9021 case BUILT_IN_NAND64:
9022 case BUILT_IN_NAND128:
6865 return fold_builtin_nan (arglist, type, true);
6866
9023 return fold_builtin_nan (arglist, type, true);
9024
6867 case BUILT_IN_NANS:
6868 case BUILT_IN_NANSF:
6869 case BUILT_IN_NANSL:
9025 CASE_FLT_FN (BUILT_IN_NANS):
6870 return fold_builtin_nan (arglist, type, false);
6871
9026 return fold_builtin_nan (arglist, type, false);
9027
6872 case BUILT_IN_FLOOR:
6873 case BUILT_IN_FLOORF:
6874 case BUILT_IN_FLOORL:
6875 return fold_builtin_floor (exp);
9028 CASE_FLT_FN (BUILT_IN_FLOOR):
9029 return fold_builtin_floor (fndecl, arglist);
6876
9030
6877 case BUILT_IN_CEIL:
6878 case BUILT_IN_CEILF:
6879 case BUILT_IN_CEILL:
6880 return fold_builtin_ceil (exp);
9031 CASE_FLT_FN (BUILT_IN_CEIL):
9032 return fold_builtin_ceil (fndecl, arglist);
6881
9033
6882 case BUILT_IN_TRUNC:
6883 case BUILT_IN_TRUNCF:
6884 case BUILT_IN_TRUNCL:
6885 return fold_builtin_trunc (exp);
9034 CASE_FLT_FN (BUILT_IN_TRUNC):
9035 return fold_builtin_trunc (fndecl, arglist);
6886
9036
6887 case BUILT_IN_ROUND:
6888 case BUILT_IN_ROUNDF:
6889 case BUILT_IN_ROUNDL:
6890 case BUILT_IN_NEARBYINT:
6891 case BUILT_IN_NEARBYINTF:
6892 case BUILT_IN_NEARBYINTL:
6893 return fold_trunc_transparent_mathfn (exp);
9037 CASE_FLT_FN (BUILT_IN_ROUND):
9038 return fold_builtin_round (fndecl, arglist);
6894
9039
6895 case BUILT_IN_FFS:
6896 case BUILT_IN_FFSL:
6897 case BUILT_IN_FFSLL:
6898 case BUILT_IN_CLZ:
6899 case BUILT_IN_CLZL:
6900 case BUILT_IN_CLZLL:
6901 case BUILT_IN_CTZ:
6902 case BUILT_IN_CTZL:
6903 case BUILT_IN_CTZLL:
6904 case BUILT_IN_POPCOUNT:
6905 case BUILT_IN_POPCOUNTL:
6906 case BUILT_IN_POPCOUNTLL:
6907 case BUILT_IN_PARITY:
6908 case BUILT_IN_PARITYL:
6909 case BUILT_IN_PARITYLL:
6910 return fold_builtin_bitop (exp);
9040 CASE_FLT_FN (BUILT_IN_NEARBYINT):
9041 CASE_FLT_FN (BUILT_IN_RINT):
9042 return fold_trunc_transparent_mathfn (fndecl, arglist);
6911
9043
9044 CASE_FLT_FN (BUILT_IN_LCEIL):
9045 CASE_FLT_FN (BUILT_IN_LLCEIL):
9046 CASE_FLT_FN (BUILT_IN_LFLOOR):
9047 CASE_FLT_FN (BUILT_IN_LLFLOOR):
9048 CASE_FLT_FN (BUILT_IN_LROUND):
9049 CASE_FLT_FN (BUILT_IN_LLROUND):
9050 return fold_builtin_int_roundingfn (fndecl, arglist);
9051
9052 CASE_FLT_FN (BUILT_IN_LRINT):
9053 CASE_FLT_FN (BUILT_IN_LLRINT):
9054 return fold_fixed_mathfn (fndecl, arglist);
9055
9056 CASE_INT_FN (BUILT_IN_FFS):
9057 CASE_INT_FN (BUILT_IN_CLZ):
9058 CASE_INT_FN (BUILT_IN_CTZ):
9059 CASE_INT_FN (BUILT_IN_POPCOUNT):
9060 CASE_INT_FN (BUILT_IN_PARITY):
9061 return fold_builtin_bitop (fndecl, arglist);
9062
9063 case BUILT_IN_MEMSET:
9064 return fold_builtin_memset (arglist, type, ignore);
9065
6912 case BUILT_IN_MEMCPY:
9066 case BUILT_IN_MEMCPY:
6913 return fold_builtin_memcpy (exp);
9067 return fold_builtin_memory_op (arglist, type, ignore, /*endp=*/0);
6914
6915 case BUILT_IN_MEMPCPY:
9068
9069 case BUILT_IN_MEMPCPY:
6916 return fold_builtin_mempcpy (exp);
9070 return fold_builtin_memory_op (arglist, type, ignore, /*endp=*/1);
6917
6918 case BUILT_IN_MEMMOVE:
9071
9072 case BUILT_IN_MEMMOVE:
6919 return fold_builtin_memmove (exp);
9073 return fold_builtin_memory_op (arglist, type, ignore, /*endp=*/3);
6920
9074
6921 case BUILT_IN_STRCPY:
6922 return fold_builtin_strcpy (exp);
9075 case BUILT_IN_BZERO:
9076 return fold_builtin_bzero (arglist, ignore);
6923
9077
6924 case BUILT_IN_STRNCPY:
6925 return fold_builtin_strncpy (exp);
9078 case BUILT_IN_BCOPY:
9079 return fold_builtin_bcopy (arglist, ignore);
6926
9080
6927 case BUILT_IN_MEMCMP:
6928 return fold_builtin_memcmp (exp);
9081 CASE_FLT_FN (BUILT_IN_SIGNBIT):
9082 return fold_builtin_signbit (fndecl, arglist);
6929
9083
6930 case BUILT_IN_STRCMP:
6931 return fold_builtin_strcmp (exp);
9084 case BUILT_IN_ISASCII:
9085 return fold_builtin_isascii (arglist);
6932
9086
6933 case BUILT_IN_STRNCMP:
6934 return fold_builtin_strncmp (exp);
9087 case BUILT_IN_TOASCII:
9088 return fold_builtin_toascii (arglist);
6935
9089
9090 case BUILT_IN_ISDIGIT:
9091 return fold_builtin_isdigit (arglist);
9092
9093 CASE_FLT_FN (BUILT_IN_COPYSIGN):
9094 return fold_builtin_copysign (fndecl, arglist, type);
9095
9096 CASE_FLT_FN (BUILT_IN_FINITE):
9097 case BUILT_IN_FINITED32:
9098 case BUILT_IN_FINITED64:
9099 case BUILT_IN_FINITED128:
9100 return fold_builtin_classify (fndecl, arglist, BUILT_IN_FINITE);
9101
9102 CASE_FLT_FN (BUILT_IN_ISINF):
9103 case BUILT_IN_ISINFD32:
9104 case BUILT_IN_ISINFD64:
9105 case BUILT_IN_ISINFD128:
9106 return fold_builtin_classify (fndecl, arglist, BUILT_IN_ISINF);
9107
9108 CASE_FLT_FN (BUILT_IN_ISNAN):
9109 case BUILT_IN_ISNAND32:
9110 case BUILT_IN_ISNAND64:
9111 case BUILT_IN_ISNAND128:
9112 return fold_builtin_classify (fndecl, arglist, BUILT_IN_ISNAN);
9113
9114 case BUILT_IN_ISGREATER:
9115 return fold_builtin_unordered_cmp (fndecl, arglist, UNLE_EXPR, LE_EXPR);
9116 case BUILT_IN_ISGREATEREQUAL:
9117 return fold_builtin_unordered_cmp (fndecl, arglist, UNLT_EXPR, LT_EXPR);
9118 case BUILT_IN_ISLESS:
9119 return fold_builtin_unordered_cmp (fndecl, arglist, UNGE_EXPR, GE_EXPR);
9120 case BUILT_IN_ISLESSEQUAL:
9121 return fold_builtin_unordered_cmp (fndecl, arglist, UNGT_EXPR, GT_EXPR);
9122 case BUILT_IN_ISLESSGREATER:
9123 return fold_builtin_unordered_cmp (fndecl, arglist, UNEQ_EXPR, EQ_EXPR);
9124 case BUILT_IN_ISUNORDERED:
9125 return fold_builtin_unordered_cmp (fndecl, arglist, UNORDERED_EXPR,
9126 NOP_EXPR);
9127
9128 /* We do the folding for va_start in the expander. */
9129 case BUILT_IN_VA_START:
9130 break;
9131
9132 case BUILT_IN_OBJECT_SIZE:
9133 return fold_builtin_object_size (arglist);
9134 case BUILT_IN_MEMCPY_CHK:
9135 case BUILT_IN_MEMPCPY_CHK:
9136 case BUILT_IN_MEMMOVE_CHK:
9137 case BUILT_IN_MEMSET_CHK:
9138 return fold_builtin_memory_chk (fndecl, arglist, NULL_TREE, ignore,
9139 DECL_FUNCTION_CODE (fndecl));
9140 case BUILT_IN_STRCPY_CHK:
9141 case BUILT_IN_STPCPY_CHK:
9142 return fold_builtin_stxcpy_chk (fndecl, arglist, NULL_TREE, ignore,
9143 DECL_FUNCTION_CODE (fndecl));
9144 case BUILT_IN_STRNCPY_CHK:
9145 return fold_builtin_strncpy_chk (arglist, NULL_TREE);
9146 case BUILT_IN_STRCAT_CHK:
9147 return fold_builtin_strcat_chk (fndecl, arglist);
9148 case BUILT_IN_STRNCAT_CHK:
9149 return fold_builtin_strncat_chk (fndecl, arglist);
9150 case BUILT_IN_SPRINTF_CHK:
9151 case BUILT_IN_VSPRINTF_CHK:
9152 return fold_builtin_sprintf_chk (arglist, DECL_FUNCTION_CODE (fndecl));
9153 case BUILT_IN_SNPRINTF_CHK:
9154 case BUILT_IN_VSNPRINTF_CHK:
9155 return fold_builtin_snprintf_chk (arglist, NULL_TREE,
9156 DECL_FUNCTION_CODE (fndecl));
9157
9158 case BUILT_IN_PRINTF:
9159 case BUILT_IN_PRINTF_UNLOCKED:
9160 case BUILT_IN_VPRINTF:
9161 case BUILT_IN_PRINTF_CHK:
9162 case BUILT_IN_VPRINTF_CHK:
9163 return fold_builtin_printf (fndecl, arglist, ignore,
9164 DECL_FUNCTION_CODE (fndecl));
9165
9166 case BUILT_IN_FPRINTF:
9167 case BUILT_IN_FPRINTF_UNLOCKED:
9168 case BUILT_IN_VFPRINTF:
9169 case BUILT_IN_FPRINTF_CHK:
9170 case BUILT_IN_VFPRINTF_CHK:
9171 return fold_builtin_fprintf (fndecl, arglist, ignore,
9172 DECL_FUNCTION_CODE (fndecl));
9173
6936 default:
6937 break;
6938 }
6939
6940 return 0;
6941}
6942
9174 default:
9175 break;
9176 }
9177
9178 return 0;
9179}
9180
9181/* A wrapper function for builtin folding that prevents warnings for
9182 "statement without effect" and the like, caused by removing the
9183 call node earlier than the warning is generated. */
9184
9185tree
9186fold_builtin (tree fndecl, tree arglist, bool ignore)
9187{
9188 tree exp = fold_builtin_1 (fndecl, arglist, ignore);
9189 if (exp)
9190 {
9191 exp = build1 (NOP_EXPR, TREE_TYPE (exp), exp);
9192 TREE_NO_WARNING (exp) = 1;
9193 }
9194
9195 return exp;
9196}
9197
6943/* Conveniently construct a function call expression. */
6944
6945tree
6946build_function_call_expr (tree fn, tree arglist)
6947{
6948 tree call_expr;
6949
6950 call_expr = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (fn)), fn);
9198/* Conveniently construct a function call expression. */
9199
9200tree
9201build_function_call_expr (tree fn, tree arglist)
9202{
9203 tree call_expr;
9204
9205 call_expr = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (fn)), fn);
6951 call_expr = build (CALL_EXPR, TREE_TYPE (TREE_TYPE (fn)),
6952 call_expr, arglist);
6953 return fold (call_expr);
9206 return fold_build3 (CALL_EXPR, TREE_TYPE (TREE_TYPE (fn)),
9207 call_expr, arglist, NULL_TREE);
6954}
6955
6956/* This function validates the types of a function call argument list
6957 represented as a tree chain of parameters against a specified list
6958 of tree_codes. If the last specifier is a 0, that represents an
6959 ellipses, otherwise the last specifier must be a VOID_TYPE. */
6960
6961static int

--- 18 unchanged lines hidden (view full) ---

6980 /* This signifies an endlink, if no arguments remain, return
6981 true, otherwise return false. */
6982 res = arglist == 0;
6983 goto end;
6984 default:
6985 /* If no parameters remain or the parameter's code does not
6986 match the specified code, return false. Otherwise continue
6987 checking any remaining arguments. */
9208}
9209
9210/* This function validates the types of a function call argument list
9211 represented as a tree chain of parameters against a specified list
9212 of tree_codes. If the last specifier is a 0, that represents an
9213 ellipses, otherwise the last specifier must be a VOID_TYPE. */
9214
9215static int

--- 18 unchanged lines hidden (view full) ---

9234 /* This signifies an endlink, if no arguments remain, return
9235 true, otherwise return false. */
9236 res = arglist == 0;
9237 goto end;
9238 default:
9239 /* If no parameters remain or the parameter's code does not
9240 match the specified code, return false. Otherwise continue
9241 checking any remaining arguments. */
6988 if (arglist == 0
6989 || code != TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))))
9242 if (arglist == 0)
6990 goto end;
9243 goto end;
9244 if (code == POINTER_TYPE)
9245 {
9246 if (! POINTER_TYPE_P (TREE_TYPE (TREE_VALUE (arglist))))
9247 goto end;
9248 }
9249 else if (code != TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))))
9250 goto end;
6991 break;
6992 }
6993 arglist = TREE_CHAIN (arglist);
6994 }
6995 while (1);
6996
6997 /* We need gotos here since we can only have one VA_CLOSE in a
6998 function. */

--- 10 unchanged lines hidden (view full) ---

7009 rtx target ATTRIBUTE_UNUSED,
7010 rtx subtarget ATTRIBUTE_UNUSED,
7011 enum machine_mode mode ATTRIBUTE_UNUSED,
7012 int ignore ATTRIBUTE_UNUSED)
7013{
7014 return NULL_RTX;
7015}
7016
9251 break;
9252 }
9253 arglist = TREE_CHAIN (arglist);
9254 }
9255 while (1);
9256
9257 /* We need gotos here since we can only have one VA_CLOSE in a
9258 function. */

--- 10 unchanged lines hidden (view full) ---

9269 rtx target ATTRIBUTE_UNUSED,
9270 rtx subtarget ATTRIBUTE_UNUSED,
9271 enum machine_mode mode ATTRIBUTE_UNUSED,
9272 int ignore ATTRIBUTE_UNUSED)
9273{
9274 return NULL_RTX;
9275}
9276
7017/* Instantiate all remaining CONSTANT_P_RTX nodes. */
9277/* Returns true is EXP represents data that would potentially reside
9278 in a readonly section. */
7018
9279
7019void
7020purge_builtin_constant_p (void)
9280static bool
9281readonly_data_expr (tree exp)
7021{
9282{
7022 rtx insn, set, arg, new, note;
9283 STRIP_NOPS (exp);
7023
9284
7024 for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
7025 if (INSN_P (insn)
7026 && (set = single_set (insn)) != NULL_RTX
7027 && (GET_CODE (arg = SET_SRC (set)) == CONSTANT_P_RTX
7028 || (GET_CODE (arg) == SUBREG
7029 && (GET_CODE (arg = SUBREG_REG (arg))
7030 == CONSTANT_P_RTX))))
9285 if (TREE_CODE (exp) != ADDR_EXPR)
9286 return false;
9287
9288 exp = get_base_address (TREE_OPERAND (exp, 0));
9289 if (!exp)
9290 return false;
9291
9292 /* Make sure we call decl_readonly_section only for trees it
9293 can handle (since it returns true for everything it doesn't
9294 understand). */
9295 if (TREE_CODE (exp) == STRING_CST
9296 || TREE_CODE (exp) == CONSTRUCTOR
9297 || (TREE_CODE (exp) == VAR_DECL && TREE_STATIC (exp)))
9298 return decl_readonly_section (exp, 0);
9299 else
9300 return false;
9301}
9302
9303/* Simplify a call to the strstr builtin.
9304
9305 Return 0 if no simplification was possible, otherwise return the
9306 simplified form of the call as a tree.
9307
9308 The simplified form may be a constant or other expression which
9309 computes the same value, but in a more efficient manner (including
9310 calls to other builtin functions).
9311
9312 The call may contain arguments which need to be evaluated, but
9313 which are not useful to determine the result of the call. In
9314 this case we return a chain of COMPOUND_EXPRs. The LHS of each
9315 COMPOUND_EXPR will be an argument which must be evaluated.
9316 COMPOUND_EXPRs are chained through their RHS. The RHS of the last
9317 COMPOUND_EXPR in the chain will contain the tree for the simplified
9318 form of the builtin function call. */
9319
9320static tree
9321fold_builtin_strstr (tree arglist, tree type)
9322{
9323 if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
9324 return 0;
9325 else
9326 {
9327 tree s1 = TREE_VALUE (arglist), s2 = TREE_VALUE (TREE_CHAIN (arglist));
9328 tree fn;
9329 const char *p1, *p2;
9330
9331 p2 = c_getstr (s2);
9332 if (p2 == NULL)
9333 return 0;
9334
9335 p1 = c_getstr (s1);
9336 if (p1 != NULL)
9337 {
9338 const char *r = strstr (p1, p2);
9339 tree tem;
9340
9341 if (r == NULL)
9342 return build_int_cst (TREE_TYPE (s1), 0);
9343
9344 /* Return an offset into the constant string argument. */
9345 tem = fold_build2 (PLUS_EXPR, TREE_TYPE (s1),
9346 s1, build_int_cst (TREE_TYPE (s1), r - p1));
9347 return fold_convert (type, tem);
9348 }
9349
9350 /* The argument is const char *, and the result is char *, so we need
9351 a type conversion here to avoid a warning. */
9352 if (p2[0] == '\0')
9353 return fold_convert (type, s1);
9354
9355 if (p2[1] != '\0')
9356 return 0;
9357
9358 fn = implicit_built_in_decls[BUILT_IN_STRCHR];
9359 if (!fn)
9360 return 0;
9361
9362 /* New argument list transforming strstr(s1, s2) to
9363 strchr(s1, s2[0]). */
9364 arglist = build_tree_list (NULL_TREE,
9365 build_int_cst (NULL_TREE, p2[0]));
9366 arglist = tree_cons (NULL_TREE, s1, arglist);
9367 return build_function_call_expr (fn, arglist);
9368 }
9369}
9370
9371/* Simplify a call to the strchr builtin.
9372
9373 Return 0 if no simplification was possible, otherwise return the
9374 simplified form of the call as a tree.
9375
9376 The simplified form may be a constant or other expression which
9377 computes the same value, but in a more efficient manner (including
9378 calls to other builtin functions).
9379
9380 The call may contain arguments which need to be evaluated, but
9381 which are not useful to determine the result of the call. In
9382 this case we return a chain of COMPOUND_EXPRs. The LHS of each
9383 COMPOUND_EXPR will be an argument which must be evaluated.
9384 COMPOUND_EXPRs are chained through their RHS. The RHS of the last
9385 COMPOUND_EXPR in the chain will contain the tree for the simplified
9386 form of the builtin function call. */
9387
9388static tree
9389fold_builtin_strchr (tree arglist, tree type)
9390{
9391 if (!validate_arglist (arglist, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
9392 return 0;
9393 else
9394 {
9395 tree s1 = TREE_VALUE (arglist), s2 = TREE_VALUE (TREE_CHAIN (arglist));
9396 const char *p1;
9397
9398 if (TREE_CODE (s2) != INTEGER_CST)
9399 return 0;
9400
9401 p1 = c_getstr (s1);
9402 if (p1 != NULL)
9403 {
9404 char c;
9405 const char *r;
9406 tree tem;
9407
9408 if (target_char_cast (s2, &c))
9409 return 0;
9410
9411 r = strchr (p1, c);
9412
9413 if (r == NULL)
9414 return build_int_cst (TREE_TYPE (s1), 0);
9415
9416 /* Return an offset into the constant string argument. */
9417 tem = fold_build2 (PLUS_EXPR, TREE_TYPE (s1),
9418 s1, build_int_cst (TREE_TYPE (s1), r - p1));
9419 return fold_convert (type, tem);
9420 }
9421 return 0;
9422 }
9423}
9424
9425/* Simplify a call to the strrchr builtin.
9426
9427 Return 0 if no simplification was possible, otherwise return the
9428 simplified form of the call as a tree.
9429
9430 The simplified form may be a constant or other expression which
9431 computes the same value, but in a more efficient manner (including
9432 calls to other builtin functions).
9433
9434 The call may contain arguments which need to be evaluated, but
9435 which are not useful to determine the result of the call. In
9436 this case we return a chain of COMPOUND_EXPRs. The LHS of each
9437 COMPOUND_EXPR will be an argument which must be evaluated.
9438 COMPOUND_EXPRs are chained through their RHS. The RHS of the last
9439 COMPOUND_EXPR in the chain will contain the tree for the simplified
9440 form of the builtin function call. */
9441
9442static tree
9443fold_builtin_strrchr (tree arglist, tree type)
9444{
9445 if (!validate_arglist (arglist, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
9446 return 0;
9447 else
9448 {
9449 tree s1 = TREE_VALUE (arglist), s2 = TREE_VALUE (TREE_CHAIN (arglist));
9450 tree fn;
9451 const char *p1;
9452
9453 if (TREE_CODE (s2) != INTEGER_CST)
9454 return 0;
9455
9456 p1 = c_getstr (s1);
9457 if (p1 != NULL)
9458 {
9459 char c;
9460 const char *r;
9461 tree tem;
9462
9463 if (target_char_cast (s2, &c))
9464 return 0;
9465
9466 r = strrchr (p1, c);
9467
9468 if (r == NULL)
9469 return build_int_cst (TREE_TYPE (s1), 0);
9470
9471 /* Return an offset into the constant string argument. */
9472 tem = fold_build2 (PLUS_EXPR, TREE_TYPE (s1),
9473 s1, build_int_cst (TREE_TYPE (s1), r - p1));
9474 return fold_convert (type, tem);
9475 }
9476
9477 if (! integer_zerop (s2))
9478 return 0;
9479
9480 fn = implicit_built_in_decls[BUILT_IN_STRCHR];
9481 if (!fn)
9482 return 0;
9483
9484 /* Transform strrchr(s1, '\0') to strchr(s1, '\0'). */
9485 return build_function_call_expr (fn, arglist);
9486 }
9487}
9488
9489/* Simplify a call to the strpbrk builtin.
9490
9491 Return 0 if no simplification was possible, otherwise return the
9492 simplified form of the call as a tree.
9493
9494 The simplified form may be a constant or other expression which
9495 computes the same value, but in a more efficient manner (including
9496 calls to other builtin functions).
9497
9498 The call may contain arguments which need to be evaluated, but
9499 which are not useful to determine the result of the call. In
9500 this case we return a chain of COMPOUND_EXPRs. The LHS of each
9501 COMPOUND_EXPR will be an argument which must be evaluated.
9502 COMPOUND_EXPRs are chained through their RHS. The RHS of the last
9503 COMPOUND_EXPR in the chain will contain the tree for the simplified
9504 form of the builtin function call. */
9505
9506static tree
9507fold_builtin_strpbrk (tree arglist, tree type)
9508{
9509 if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
9510 return 0;
9511 else
9512 {
9513 tree s1 = TREE_VALUE (arglist), s2 = TREE_VALUE (TREE_CHAIN (arglist));
9514 tree fn;
9515 const char *p1, *p2;
9516
9517 p2 = c_getstr (s2);
9518 if (p2 == NULL)
9519 return 0;
9520
9521 p1 = c_getstr (s1);
9522 if (p1 != NULL)
9523 {
9524 const char *r = strpbrk (p1, p2);
9525 tree tem;
9526
9527 if (r == NULL)
9528 return build_int_cst (TREE_TYPE (s1), 0);
9529
9530 /* Return an offset into the constant string argument. */
9531 tem = fold_build2 (PLUS_EXPR, TREE_TYPE (s1),
9532 s1, build_int_cst (TREE_TYPE (s1), r - p1));
9533 return fold_convert (type, tem);
9534 }
9535
9536 if (p2[0] == '\0')
9537 /* strpbrk(x, "") == NULL.
9538 Evaluate and ignore s1 in case it had side-effects. */
9539 return omit_one_operand (TREE_TYPE (s1), integer_zero_node, s1);
9540
9541 if (p2[1] != '\0')
9542 return 0; /* Really call strpbrk. */
9543
9544 fn = implicit_built_in_decls[BUILT_IN_STRCHR];
9545 if (!fn)
9546 return 0;
9547
9548 /* New argument list transforming strpbrk(s1, s2) to
9549 strchr(s1, s2[0]). */
9550 arglist = build_tree_list (NULL_TREE,
9551 build_int_cst (NULL_TREE, p2[0]));
9552 arglist = tree_cons (NULL_TREE, s1, arglist);
9553 return build_function_call_expr (fn, arglist);
9554 }
9555}
9556
9557/* Simplify a call to the strcat builtin.
9558
9559 Return 0 if no simplification was possible, otherwise return the
9560 simplified form of the call as a tree.
9561
9562 The simplified form may be a constant or other expression which
9563 computes the same value, but in a more efficient manner (including
9564 calls to other builtin functions).
9565
9566 The call may contain arguments which need to be evaluated, but
9567 which are not useful to determine the result of the call. In
9568 this case we return a chain of COMPOUND_EXPRs. The LHS of each
9569 COMPOUND_EXPR will be an argument which must be evaluated.
9570 COMPOUND_EXPRs are chained through their RHS. The RHS of the last
9571 COMPOUND_EXPR in the chain will contain the tree for the simplified
9572 form of the builtin function call. */
9573
9574static tree
9575fold_builtin_strcat (tree arglist)
9576{
9577 if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
9578 return 0;
9579 else
9580 {
9581 tree dst = TREE_VALUE (arglist),
9582 src = TREE_VALUE (TREE_CHAIN (arglist));
9583 const char *p = c_getstr (src);
9584
9585 /* If the string length is zero, return the dst parameter. */
9586 if (p && *p == '\0')
9587 return dst;
9588
9589 return 0;
9590 }
9591}
9592
9593/* Simplify a call to the strncat builtin.
9594
9595 Return 0 if no simplification was possible, otherwise return the
9596 simplified form of the call as a tree.
9597
9598 The simplified form may be a constant or other expression which
9599 computes the same value, but in a more efficient manner (including
9600 calls to other builtin functions).
9601
9602 The call may contain arguments which need to be evaluated, but
9603 which are not useful to determine the result of the call. In
9604 this case we return a chain of COMPOUND_EXPRs. The LHS of each
9605 COMPOUND_EXPR will be an argument which must be evaluated.
9606 COMPOUND_EXPRs are chained through their RHS. The RHS of the last
9607 COMPOUND_EXPR in the chain will contain the tree for the simplified
9608 form of the builtin function call. */
9609
9610static tree
9611fold_builtin_strncat (tree arglist)
9612{
9613 if (!validate_arglist (arglist,
9614 POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
9615 return 0;
9616 else
9617 {
9618 tree dst = TREE_VALUE (arglist);
9619 tree src = TREE_VALUE (TREE_CHAIN (arglist));
9620 tree len = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
9621 const char *p = c_getstr (src);
9622
9623 /* If the requested length is zero, or the src parameter string
9624 length is zero, return the dst parameter. */
9625 if (integer_zerop (len) || (p && *p == '\0'))
9626 return omit_two_operands (TREE_TYPE (dst), dst, src, len);
9627
9628 /* If the requested len is greater than or equal to the string
9629 length, call strcat. */
9630 if (TREE_CODE (len) == INTEGER_CST && p
9631 && compare_tree_int (len, strlen (p)) >= 0)
9632 {
9633 tree newarglist
9634 = tree_cons (NULL_TREE, dst, build_tree_list (NULL_TREE, src));
9635 tree fn = implicit_built_in_decls[BUILT_IN_STRCAT];
9636
9637 /* If the replacement _DECL isn't initialized, don't do the
9638 transformation. */
9639 if (!fn)
9640 return 0;
9641
9642 return build_function_call_expr (fn, newarglist);
9643 }
9644 return 0;
9645 }
9646}
9647
9648/* Simplify a call to the strspn builtin.
9649
9650 Return 0 if no simplification was possible, otherwise return the
9651 simplified form of the call as a tree.
9652
9653 The simplified form may be a constant or other expression which
9654 computes the same value, but in a more efficient manner (including
9655 calls to other builtin functions).
9656
9657 The call may contain arguments which need to be evaluated, but
9658 which are not useful to determine the result of the call. In
9659 this case we return a chain of COMPOUND_EXPRs. The LHS of each
9660 COMPOUND_EXPR will be an argument which must be evaluated.
9661 COMPOUND_EXPRs are chained through their RHS. The RHS of the last
9662 COMPOUND_EXPR in the chain will contain the tree for the simplified
9663 form of the builtin function call. */
9664
9665static tree
9666fold_builtin_strspn (tree arglist)
9667{
9668 if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
9669 return 0;
9670 else
9671 {
9672 tree s1 = TREE_VALUE (arglist), s2 = TREE_VALUE (TREE_CHAIN (arglist));
9673 const char *p1 = c_getstr (s1), *p2 = c_getstr (s2);
9674
9675 /* If both arguments are constants, evaluate at compile-time. */
9676 if (p1 && p2)
9677 {
9678 const size_t r = strspn (p1, p2);
9679 return size_int (r);
9680 }
9681
9682 /* If either argument is "", return 0. */
9683 if ((p1 && *p1 == '\0') || (p2 && *p2 == '\0'))
9684 /* Evaluate and ignore both arguments in case either one has
9685 side-effects. */
9686 return omit_two_operands (integer_type_node, integer_zero_node,
9687 s1, s2);
9688 return 0;
9689 }
9690}
9691
9692/* Simplify a call to the strcspn builtin.
9693
9694 Return 0 if no simplification was possible, otherwise return the
9695 simplified form of the call as a tree.
9696
9697 The simplified form may be a constant or other expression which
9698 computes the same value, but in a more efficient manner (including
9699 calls to other builtin functions).
9700
9701 The call may contain arguments which need to be evaluated, but
9702 which are not useful to determine the result of the call. In
9703 this case we return a chain of COMPOUND_EXPRs. The LHS of each
9704 COMPOUND_EXPR will be an argument which must be evaluated.
9705 COMPOUND_EXPRs are chained through their RHS. The RHS of the last
9706 COMPOUND_EXPR in the chain will contain the tree for the simplified
9707 form of the builtin function call. */
9708
9709static tree
9710fold_builtin_strcspn (tree arglist)
9711{
9712 if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
9713 return 0;
9714 else
9715 {
9716 tree s1 = TREE_VALUE (arglist), s2 = TREE_VALUE (TREE_CHAIN (arglist));
9717 const char *p1 = c_getstr (s1), *p2 = c_getstr (s2);
9718
9719 /* If both arguments are constants, evaluate at compile-time. */
9720 if (p1 && p2)
9721 {
9722 const size_t r = strcspn (p1, p2);
9723 return size_int (r);
9724 }
9725
9726 /* If the first argument is "", return 0. */
9727 if (p1 && *p1 == '\0')
9728 {
9729 /* Evaluate and ignore argument s2 in case it has
9730 side-effects. */
9731 return omit_one_operand (integer_type_node,
9732 integer_zero_node, s2);
9733 }
9734
9735 /* If the second argument is "", return __builtin_strlen(s1). */
9736 if (p2 && *p2 == '\0')
9737 {
9738 tree newarglist = build_tree_list (NULL_TREE, s1),
9739 fn = implicit_built_in_decls[BUILT_IN_STRLEN];
9740
9741 /* If the replacement _DECL isn't initialized, don't do the
9742 transformation. */
9743 if (!fn)
9744 return 0;
9745
9746 return build_function_call_expr (fn, newarglist);
9747 }
9748 return 0;
9749 }
9750}
9751
9752/* Fold a call to the fputs builtin. IGNORE is true if the value returned
9753 by the builtin will be ignored. UNLOCKED is true is true if this
9754 actually a call to fputs_unlocked. If LEN in non-NULL, it represents
9755 the known length of the string. Return NULL_TREE if no simplification
9756 was possible. */
9757
9758tree
9759fold_builtin_fputs (tree arglist, bool ignore, bool unlocked, tree len)
9760{
9761 tree fn;
9762 /* If we're using an unlocked function, assume the other unlocked
9763 functions exist explicitly. */
9764 tree const fn_fputc = unlocked ? built_in_decls[BUILT_IN_FPUTC_UNLOCKED]
9765 : implicit_built_in_decls[BUILT_IN_FPUTC];
9766 tree const fn_fwrite = unlocked ? built_in_decls[BUILT_IN_FWRITE_UNLOCKED]
9767 : implicit_built_in_decls[BUILT_IN_FWRITE];
9768
9769 /* If the return value is used, don't do the transformation. */
9770 if (!ignore)
9771 return 0;
9772
9773 /* Verify the arguments in the original call. */
9774 if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
9775 return 0;
9776
9777 if (! len)
9778 len = c_strlen (TREE_VALUE (arglist), 0);
9779
9780 /* Get the length of the string passed to fputs. If the length
9781 can't be determined, punt. */
9782 if (!len
9783 || TREE_CODE (len) != INTEGER_CST)
9784 return 0;
9785
9786 switch (compare_tree_int (len, 1))
9787 {
9788 case -1: /* length is 0, delete the call entirely . */
9789 return omit_one_operand (integer_type_node, integer_zero_node,
9790 TREE_VALUE (TREE_CHAIN (arglist)));
9791
9792 case 0: /* length is 1, call fputc. */
7031 {
9793 {
7032 arg = XEXP (arg, 0);
7033 new = CONSTANT_P (arg) ? const1_rtx : const0_rtx;
7034 validate_change (insn, &SET_SRC (set), new, 0);
9794 const char *p = c_getstr (TREE_VALUE (arglist));
7035
9795
7036 /* Remove the REG_EQUAL note from the insn. */
7037 if ((note = find_reg_note (insn, REG_EQUAL, NULL_RTX)) != 0)
7038 remove_note (insn, note);
9796 if (p != NULL)
9797 {
9798 /* New argument list transforming fputs(string, stream) to
9799 fputc(string[0], stream). */
9800 arglist = build_tree_list (NULL_TREE,
9801 TREE_VALUE (TREE_CHAIN (arglist)));
9802 arglist = tree_cons (NULL_TREE,
9803 build_int_cst (NULL_TREE, p[0]),
9804 arglist);
9805 fn = fn_fputc;
9806 break;
9807 }
7039 }
9808 }
9809 /* FALLTHROUGH */
9810 case 1: /* length is greater than 1, call fwrite. */
9811 {
9812 tree string_arg;
9813
9814 /* If optimizing for size keep fputs. */
9815 if (optimize_size)
9816 return 0;
9817 string_arg = TREE_VALUE (arglist);
9818 /* New argument list transforming fputs(string, stream) to
9819 fwrite(string, 1, len, stream). */
9820 arglist = build_tree_list (NULL_TREE,
9821 TREE_VALUE (TREE_CHAIN (arglist)));
9822 arglist = tree_cons (NULL_TREE, len, arglist);
9823 arglist = tree_cons (NULL_TREE, size_one_node, arglist);
9824 arglist = tree_cons (NULL_TREE, string_arg, arglist);
9825 fn = fn_fwrite;
9826 break;
9827 }
9828 default:
9829 gcc_unreachable ();
9830 }
9831
9832 /* If the replacement _DECL isn't initialized, don't do the
9833 transformation. */
9834 if (!fn)
9835 return 0;
9836
9837 /* These optimizations are only performed when the result is ignored,
9838 hence there's no need to cast the result to integer_type_node. */
9839 return build_function_call_expr (fn, arglist);
7040}
7041
9840}
9841
7042/* Returns true is EXP represents data that would potentially reside
7043 in a readonly section. */
9842/* Fold the new_arg's arguments (ARGLIST). Returns true if there was an error
9843 produced. False otherwise. This is done so that we don't output the error
9844 or warning twice or three times. */
9845bool
9846fold_builtin_next_arg (tree arglist)
9847{
9848 tree fntype = TREE_TYPE (current_function_decl);
7044
9849
7045static bool
7046readonly_data_expr (tree exp)
9850 if (TYPE_ARG_TYPES (fntype) == 0
9851 || (TREE_VALUE (tree_last (TYPE_ARG_TYPES (fntype)))
9852 == void_type_node))
9853 {
9854 error ("%<va_start%> used in function with fixed args");
9855 return true;
9856 }
9857 else if (!arglist)
9858 {
9859 /* Evidently an out of date version of <stdarg.h>; can't validate
9860 va_start's second argument, but can still work as intended. */
9861 warning (0, "%<__builtin_next_arg%> called without an argument");
9862 return true;
9863 }
9864 /* We use __builtin_va_start (ap, 0, 0) or __builtin_next_arg (0, 0)
9865 when we checked the arguments and if needed issued a warning. */
9866 else if (!TREE_CHAIN (arglist)
9867 || !integer_zerop (TREE_VALUE (arglist))
9868 || !integer_zerop (TREE_VALUE (TREE_CHAIN (arglist)))
9869 || TREE_CHAIN (TREE_CHAIN (arglist)))
9870 {
9871 tree last_parm = tree_last (DECL_ARGUMENTS (current_function_decl));
9872 tree arg = TREE_VALUE (arglist);
9873
9874 if (TREE_CHAIN (arglist))
9875 {
9876 error ("%<va_start%> used with too many arguments");
9877 return true;
9878 }
9879
9880 /* Strip off all nops for the sake of the comparison. This
9881 is not quite the same as STRIP_NOPS. It does more.
9882 We must also strip off INDIRECT_EXPR for C++ reference
9883 parameters. */
9884 while (TREE_CODE (arg) == NOP_EXPR
9885 || TREE_CODE (arg) == CONVERT_EXPR
9886 || TREE_CODE (arg) == NON_LVALUE_EXPR
9887 || TREE_CODE (arg) == INDIRECT_REF)
9888 arg = TREE_OPERAND (arg, 0);
9889 if (arg != last_parm)
9890 {
9891 /* FIXME: Sometimes with the tree optimizers we can get the
9892 not the last argument even though the user used the last
9893 argument. We just warn and set the arg to be the last
9894 argument so that we will get wrong-code because of
9895 it. */
9896 warning (0, "second parameter of %<va_start%> not last named argument");
9897 }
9898 /* We want to verify the second parameter just once before the tree
9899 optimizers are run and then avoid keeping it in the tree,
9900 as otherwise we could warn even for correct code like:
9901 void foo (int i, ...)
9902 { va_list ap; i++; va_start (ap, i); va_end (ap); } */
9903 TREE_VALUE (arglist) = integer_zero_node;
9904 TREE_CHAIN (arglist) = build_tree_list (NULL, integer_zero_node);
9905 }
9906 return false;
9907}
9908
9909
9910/* Simplify a call to the sprintf builtin.
9911
9912 Return 0 if no simplification was possible, otherwise return the
9913 simplified form of the call as a tree. If IGNORED is true, it means that
9914 the caller does not use the returned value of the function. */
9915
9916static tree
9917fold_builtin_sprintf (tree arglist, int ignored)
7047{
9918{
7048 STRIP_NOPS (exp);
9919 tree call, retval, dest, fmt;
9920 const char *fmt_str = NULL;
7049
9921
7050 if (TREE_CODE (exp) == ADDR_EXPR)
7051 return decl_readonly_section (TREE_OPERAND (exp, 0), 0);
9922 /* Verify the required arguments in the original call. We deal with two
9923 types of sprintf() calls: 'sprintf (str, fmt)' and
9924 'sprintf (dest, "%s", orig)'. */
9925 if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE)
9926 && !validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, POINTER_TYPE,
9927 VOID_TYPE))
9928 return NULL_TREE;
9929
9930 /* Get the destination string and the format specifier. */
9931 dest = TREE_VALUE (arglist);
9932 fmt = TREE_VALUE (TREE_CHAIN (arglist));
9933 arglist = TREE_CHAIN (TREE_CHAIN (arglist));
9934
9935 /* Check whether the format is a literal string constant. */
9936 fmt_str = c_getstr (fmt);
9937 if (fmt_str == NULL)
9938 return NULL_TREE;
9939
9940 call = NULL_TREE;
9941 retval = NULL_TREE;
9942
9943 if (!init_target_chars())
9944 return 0;
9945
9946 /* If the format doesn't contain % args or %%, use strcpy. */
9947 if (strchr (fmt_str, target_percent) == NULL)
9948 {
9949 tree fn = implicit_built_in_decls[BUILT_IN_STRCPY];
9950
9951 if (!fn)
9952 return NULL_TREE;
9953
9954 /* Don't optimize sprintf (buf, "abc", ptr++). */
9955 if (arglist)
9956 return NULL_TREE;
9957
9958 /* Convert sprintf (str, fmt) into strcpy (str, fmt) when
9959 'format' is known to contain no % formats. */
9960 arglist = build_tree_list (NULL_TREE, fmt);
9961 arglist = tree_cons (NULL_TREE, dest, arglist);
9962 call = build_function_call_expr (fn, arglist);
9963 if (!ignored)
9964 retval = build_int_cst (NULL_TREE, strlen (fmt_str));
9965 }
9966
9967 /* If the format is "%s", use strcpy if the result isn't used. */
9968 else if (fmt_str && strcmp (fmt_str, target_percent_s) == 0)
9969 {
9970 tree fn, orig;
9971 fn = implicit_built_in_decls[BUILT_IN_STRCPY];
9972
9973 if (!fn)
9974 return NULL_TREE;
9975
9976 /* Don't crash on sprintf (str1, "%s"). */
9977 if (!arglist)
9978 return NULL_TREE;
9979
9980 /* Convert sprintf (str1, "%s", str2) into strcpy (str1, str2). */
9981 orig = TREE_VALUE (arglist);
9982 arglist = build_tree_list (NULL_TREE, orig);
9983 arglist = tree_cons (NULL_TREE, dest, arglist);
9984 if (!ignored)
9985 {
9986 retval = c_strlen (orig, 1);
9987 if (!retval || TREE_CODE (retval) != INTEGER_CST)
9988 return NULL_TREE;
9989 }
9990 call = build_function_call_expr (fn, arglist);
9991 }
9992
9993 if (call && retval)
9994 {
9995 retval = fold_convert
9996 (TREE_TYPE (TREE_TYPE (implicit_built_in_decls[BUILT_IN_SPRINTF])),
9997 retval);
9998 return build2 (COMPOUND_EXPR, TREE_TYPE (retval), call, retval);
9999 }
7052 else
10000 else
7053 return false;
10001 return call;
7054}
10002}
10003
10004/* Expand a call to __builtin_object_size. */
10005
10006rtx
10007expand_builtin_object_size (tree exp)
10008{
10009 tree ost;
10010 int object_size_type;
10011 tree fndecl = get_callee_fndecl (exp);
10012 tree arglist = TREE_OPERAND (exp, 1);
10013 location_t locus = EXPR_LOCATION (exp);
10014
10015 if (!validate_arglist (arglist, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
10016 {
10017 error ("%Hfirst argument of %D must be a pointer, second integer constant",
10018 &locus, fndecl);
10019 expand_builtin_trap ();
10020 return const0_rtx;
10021 }
10022
10023 ost = TREE_VALUE (TREE_CHAIN (arglist));
10024 STRIP_NOPS (ost);
10025
10026 if (TREE_CODE (ost) != INTEGER_CST
10027 || tree_int_cst_sgn (ost) < 0
10028 || compare_tree_int (ost, 3) > 0)
10029 {
10030 error ("%Hlast argument of %D is not integer constant between 0 and 3",
10031 &locus, fndecl);
10032 expand_builtin_trap ();
10033 return const0_rtx;
10034 }
10035
10036 object_size_type = tree_low_cst (ost, 0);
10037
10038 return object_size_type < 2 ? constm1_rtx : const0_rtx;
10039}
10040
10041/* Expand EXP, a call to the __mem{cpy,pcpy,move,set}_chk builtin.
10042 FCODE is the BUILT_IN_* to use.
10043 Return 0 if we failed; the caller should emit a normal call,
10044 otherwise try to get the result in TARGET, if convenient (and in
10045 mode MODE if that's convenient). */
10046
10047static rtx
10048expand_builtin_memory_chk (tree exp, rtx target, enum machine_mode mode,
10049 enum built_in_function fcode)
10050{
10051 tree arglist = TREE_OPERAND (exp, 1);
10052 tree dest, src, len, size;
10053
10054 if (!validate_arglist (arglist,
10055 POINTER_TYPE,
10056 fcode == BUILT_IN_MEMSET_CHK
10057 ? INTEGER_TYPE : POINTER_TYPE,
10058 INTEGER_TYPE, INTEGER_TYPE, VOID_TYPE))
10059 return 0;
10060
10061 dest = TREE_VALUE (arglist);
10062 src = TREE_VALUE (TREE_CHAIN (arglist));
10063 len = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
10064 size = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (arglist))));
10065
10066 if (! host_integerp (size, 1))
10067 return 0;
10068
10069 if (host_integerp (len, 1) || integer_all_onesp (size))
10070 {
10071 tree fn;
10072
10073 if (! integer_all_onesp (size) && tree_int_cst_lt (size, len))
10074 {
10075 location_t locus = EXPR_LOCATION (exp);
10076 warning (0, "%Hcall to %D will always overflow destination buffer",
10077 &locus, get_callee_fndecl (exp));
10078 return 0;
10079 }
10080
10081 arglist = build_tree_list (NULL_TREE, len);
10082 arglist = tree_cons (NULL_TREE, src, arglist);
10083 arglist = tree_cons (NULL_TREE, dest, arglist);
10084
10085 fn = NULL_TREE;
10086 /* If __builtin_mem{cpy,pcpy,move,set}_chk is used, assume
10087 mem{cpy,pcpy,move,set} is available. */
10088 switch (fcode)
10089 {
10090 case BUILT_IN_MEMCPY_CHK:
10091 fn = built_in_decls[BUILT_IN_MEMCPY];
10092 break;
10093 case BUILT_IN_MEMPCPY_CHK:
10094 fn = built_in_decls[BUILT_IN_MEMPCPY];
10095 break;
10096 case BUILT_IN_MEMMOVE_CHK:
10097 fn = built_in_decls[BUILT_IN_MEMMOVE];
10098 break;
10099 case BUILT_IN_MEMSET_CHK:
10100 fn = built_in_decls[BUILT_IN_MEMSET];
10101 break;
10102 default:
10103 break;
10104 }
10105
10106 if (! fn)
10107 return 0;
10108
10109 fn = build_function_call_expr (fn, arglist);
10110 if (TREE_CODE (fn) == CALL_EXPR)
10111 CALL_EXPR_TAILCALL (fn) = CALL_EXPR_TAILCALL (exp);
10112 return expand_expr (fn, target, mode, EXPAND_NORMAL);
10113 }
10114 else if (fcode == BUILT_IN_MEMSET_CHK)
10115 return 0;
10116 else
10117 {
10118 unsigned int dest_align
10119 = get_pointer_alignment (dest, BIGGEST_ALIGNMENT);
10120
10121 /* If DEST is not a pointer type, call the normal function. */
10122 if (dest_align == 0)
10123 return 0;
10124
10125 /* If SRC and DEST are the same (and not volatile), do nothing. */
10126 if (operand_equal_p (src, dest, 0))
10127 {
10128 tree expr;
10129
10130 if (fcode != BUILT_IN_MEMPCPY_CHK)
10131 {
10132 /* Evaluate and ignore LEN in case it has side-effects. */
10133 expand_expr (len, const0_rtx, VOIDmode, EXPAND_NORMAL);
10134 return expand_expr (dest, target, mode, EXPAND_NORMAL);
10135 }
10136
10137 len = fold_convert (TREE_TYPE (dest), len);
10138 expr = fold_build2 (PLUS_EXPR, TREE_TYPE (dest), dest, len);
10139 return expand_expr (expr, target, mode, EXPAND_NORMAL);
10140 }
10141
10142 /* __memmove_chk special case. */
10143 if (fcode == BUILT_IN_MEMMOVE_CHK)
10144 {
10145 unsigned int src_align
10146 = get_pointer_alignment (src, BIGGEST_ALIGNMENT);
10147
10148 if (src_align == 0)
10149 return 0;
10150
10151 /* If src is categorized for a readonly section we can use
10152 normal __memcpy_chk. */
10153 if (readonly_data_expr (src))
10154 {
10155 tree fn = built_in_decls[BUILT_IN_MEMCPY_CHK];
10156 if (!fn)
10157 return 0;
10158 fn = build_function_call_expr (fn, arglist);
10159 if (TREE_CODE (fn) == CALL_EXPR)
10160 CALL_EXPR_TAILCALL (fn) = CALL_EXPR_TAILCALL (exp);
10161 return expand_expr (fn, target, mode, EXPAND_NORMAL);
10162 }
10163 }
10164 return 0;
10165 }
10166}
10167
10168/* Emit warning if a buffer overflow is detected at compile time. */
10169
10170static void
10171maybe_emit_chk_warning (tree exp, enum built_in_function fcode)
10172{
10173 int arg_mask, is_strlen = 0;
10174 tree arglist = TREE_OPERAND (exp, 1), a;
10175 tree len, size;
10176 location_t locus;
10177
10178 switch (fcode)
10179 {
10180 case BUILT_IN_STRCPY_CHK:
10181 case BUILT_IN_STPCPY_CHK:
10182 /* For __strcat_chk the warning will be emitted only if overflowing
10183 by at least strlen (dest) + 1 bytes. */
10184 case BUILT_IN_STRCAT_CHK:
10185 arg_mask = 6;
10186 is_strlen = 1;
10187 break;
10188 case BUILT_IN_STRNCPY_CHK:
10189 arg_mask = 12;
10190 break;
10191 case BUILT_IN_SNPRINTF_CHK:
10192 case BUILT_IN_VSNPRINTF_CHK:
10193 arg_mask = 10;
10194 break;
10195 default:
10196 gcc_unreachable ();
10197 }
10198
10199 len = NULL_TREE;
10200 size = NULL_TREE;
10201 for (a = arglist; a && arg_mask; a = TREE_CHAIN (a), arg_mask >>= 1)
10202 if (arg_mask & 1)
10203 {
10204 if (len)
10205 size = a;
10206 else
10207 len = a;
10208 }
10209
10210 if (!len || !size)
10211 return;
10212
10213 len = TREE_VALUE (len);
10214 size = TREE_VALUE (size);
10215
10216 if (! host_integerp (size, 1) || integer_all_onesp (size))
10217 return;
10218
10219 if (is_strlen)
10220 {
10221 len = c_strlen (len, 1);
10222 if (! len || ! host_integerp (len, 1) || tree_int_cst_lt (len, size))
10223 return;
10224 }
10225 else if (! host_integerp (len, 1) || ! tree_int_cst_lt (size, len))
10226 return;
10227
10228 locus = EXPR_LOCATION (exp);
10229 warning (0, "%Hcall to %D will always overflow destination buffer",
10230 &locus, get_callee_fndecl (exp));
10231}
10232
10233/* Emit warning if a buffer overflow is detected at compile time
10234 in __sprintf_chk/__vsprintf_chk calls. */
10235
10236static void
10237maybe_emit_sprintf_chk_warning (tree exp, enum built_in_function fcode)
10238{
10239 tree arglist = TREE_OPERAND (exp, 1);
10240 tree dest, size, len, fmt, flag;
10241 const char *fmt_str;
10242
10243 /* Verify the required arguments in the original call. */
10244 if (! arglist)
10245 return;
10246 dest = TREE_VALUE (arglist);
10247 arglist = TREE_CHAIN (arglist);
10248 if (! arglist)
10249 return;
10250 flag = TREE_VALUE (arglist);
10251 arglist = TREE_CHAIN (arglist);
10252 if (! arglist)
10253 return;
10254 size = TREE_VALUE (arglist);
10255 arglist = TREE_CHAIN (arglist);
10256 if (! arglist)
10257 return;
10258 fmt = TREE_VALUE (arglist);
10259 arglist = TREE_CHAIN (arglist);
10260
10261 if (! host_integerp (size, 1) || integer_all_onesp (size))
10262 return;
10263
10264 /* Check whether the format is a literal string constant. */
10265 fmt_str = c_getstr (fmt);
10266 if (fmt_str == NULL)
10267 return;
10268
10269 if (!init_target_chars())
10270 return;
10271
10272 /* If the format doesn't contain % args or %%, we know its size. */
10273 if (strchr (fmt_str, target_percent) == 0)
10274 len = build_int_cstu (size_type_node, strlen (fmt_str));
10275 /* If the format is "%s" and first ... argument is a string literal,
10276 we know it too. */
10277 else if (fcode == BUILT_IN_SPRINTF_CHK && strcmp (fmt_str, target_percent_s) == 0)
10278 {
10279 tree arg;
10280
10281 if (! arglist)
10282 return;
10283 arg = TREE_VALUE (arglist);
10284 if (! POINTER_TYPE_P (TREE_TYPE (arg)))
10285 return;
10286
10287 len = c_strlen (arg, 1);
10288 if (!len || ! host_integerp (len, 1))
10289 return;
10290 }
10291 else
10292 return;
10293
10294 if (! tree_int_cst_lt (len, size))
10295 {
10296 location_t locus = EXPR_LOCATION (exp);
10297 warning (0, "%Hcall to %D will always overflow destination buffer",
10298 &locus, get_callee_fndecl (exp));
10299 }
10300}
10301
10302/* Fold a call to __builtin_object_size, if possible. */
10303
10304tree
10305fold_builtin_object_size (tree arglist)
10306{
10307 tree ptr, ost, ret = 0;
10308 int object_size_type;
10309
10310 if (!validate_arglist (arglist, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
10311 return 0;
10312
10313 ptr = TREE_VALUE (arglist);
10314 ost = TREE_VALUE (TREE_CHAIN (arglist));
10315 STRIP_NOPS (ost);
10316
10317 if (TREE_CODE (ost) != INTEGER_CST
10318 || tree_int_cst_sgn (ost) < 0
10319 || compare_tree_int (ost, 3) > 0)
10320 return 0;
10321
10322 object_size_type = tree_low_cst (ost, 0);
10323
10324 /* __builtin_object_size doesn't evaluate side-effects in its arguments;
10325 if there are any side-effects, it returns (size_t) -1 for types 0 and 1
10326 and (size_t) 0 for types 2 and 3. */
10327 if (TREE_SIDE_EFFECTS (ptr))
10328 return fold_convert (size_type_node,
10329 object_size_type < 2
10330 ? integer_minus_one_node : integer_zero_node);
10331
10332 if (TREE_CODE (ptr) == ADDR_EXPR)
10333 ret = build_int_cstu (size_type_node,
10334 compute_builtin_object_size (ptr, object_size_type));
10335
10336 else if (TREE_CODE (ptr) == SSA_NAME)
10337 {
10338 unsigned HOST_WIDE_INT bytes;
10339
10340 /* If object size is not known yet, delay folding until
10341 later. Maybe subsequent passes will help determining
10342 it. */
10343 bytes = compute_builtin_object_size (ptr, object_size_type);
10344 if (bytes != (unsigned HOST_WIDE_INT) (object_size_type < 2
10345 ? -1 : 0))
10346 ret = build_int_cstu (size_type_node, bytes);
10347 }
10348
10349 if (ret)
10350 {
10351 ret = force_fit_type (ret, -1, false, false);
10352 if (TREE_CONSTANT_OVERFLOW (ret))
10353 ret = 0;
10354 }
10355
10356 return ret;
10357}
10358
10359/* Fold a call to the __mem{cpy,pcpy,move,set}_chk builtin.
10360 IGNORE is true, if return value can be ignored. FCODE is the BUILT_IN_*
10361 code of the builtin. If MAXLEN is not NULL, it is maximum length
10362 passed as third argument. */
10363
10364tree
10365fold_builtin_memory_chk (tree fndecl, tree arglist, tree maxlen, bool ignore,
10366 enum built_in_function fcode)
10367{
10368 tree dest, src, len, size, fn;
10369
10370 if (!validate_arglist (arglist,
10371 POINTER_TYPE,
10372 fcode == BUILT_IN_MEMSET_CHK
10373 ? INTEGER_TYPE : POINTER_TYPE,
10374 INTEGER_TYPE, INTEGER_TYPE, VOID_TYPE))
10375 return 0;
10376
10377 dest = TREE_VALUE (arglist);
10378 /* Actually val for __memset_chk, but it doesn't matter. */
10379 src = TREE_VALUE (TREE_CHAIN (arglist));
10380 len = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
10381 size = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (arglist))));
10382
10383 /* If SRC and DEST are the same (and not volatile), return DEST
10384 (resp. DEST+LEN for __mempcpy_chk). */
10385 if (fcode != BUILT_IN_MEMSET_CHK && operand_equal_p (src, dest, 0))
10386 {
10387 if (fcode != BUILT_IN_MEMPCPY_CHK)
10388 return omit_one_operand (TREE_TYPE (TREE_TYPE (fndecl)), dest, len);
10389 else
10390 {
10391 tree temp = fold_convert (TREE_TYPE (dest), len);
10392 temp = fold_build2 (PLUS_EXPR, TREE_TYPE (dest), dest, temp);
10393 return fold_convert (TREE_TYPE (TREE_TYPE (fndecl)), temp);
10394 }
10395 }
10396
10397 if (! host_integerp (size, 1))
10398 return 0;
10399
10400 if (! integer_all_onesp (size))
10401 {
10402 if (! host_integerp (len, 1))
10403 {
10404 /* If LEN is not constant, try MAXLEN too.
10405 For MAXLEN only allow optimizing into non-_ocs function
10406 if SIZE is >= MAXLEN, never convert to __ocs_fail (). */
10407 if (maxlen == NULL_TREE || ! host_integerp (maxlen, 1))
10408 {
10409 if (fcode == BUILT_IN_MEMPCPY_CHK && ignore)
10410 {
10411 /* (void) __mempcpy_chk () can be optimized into
10412 (void) __memcpy_chk (). */
10413 fn = built_in_decls[BUILT_IN_MEMCPY_CHK];
10414 if (!fn)
10415 return 0;
10416
10417 return build_function_call_expr (fn, arglist);
10418 }
10419 return 0;
10420 }
10421 }
10422 else
10423 maxlen = len;
10424
10425 if (tree_int_cst_lt (size, maxlen))
10426 return 0;
10427 }
10428
10429 arglist = build_tree_list (NULL_TREE, len);
10430 arglist = tree_cons (NULL_TREE, src, arglist);
10431 arglist = tree_cons (NULL_TREE, dest, arglist);
10432
10433 fn = NULL_TREE;
10434 /* If __builtin_mem{cpy,pcpy,move,set}_chk is used, assume
10435 mem{cpy,pcpy,move,set} is available. */
10436 switch (fcode)
10437 {
10438 case BUILT_IN_MEMCPY_CHK:
10439 fn = built_in_decls[BUILT_IN_MEMCPY];
10440 break;
10441 case BUILT_IN_MEMPCPY_CHK:
10442 fn = built_in_decls[BUILT_IN_MEMPCPY];
10443 break;
10444 case BUILT_IN_MEMMOVE_CHK:
10445 fn = built_in_decls[BUILT_IN_MEMMOVE];
10446 break;
10447 case BUILT_IN_MEMSET_CHK:
10448 fn = built_in_decls[BUILT_IN_MEMSET];
10449 break;
10450 default:
10451 break;
10452 }
10453
10454 if (!fn)
10455 return 0;
10456
10457 return build_function_call_expr (fn, arglist);
10458}
10459
10460/* Fold a call to the __st[rp]cpy_chk builtin.
10461 IGNORE is true, if return value can be ignored. FCODE is the BUILT_IN_*
10462 code of the builtin. If MAXLEN is not NULL, it is maximum length of
10463 strings passed as second argument. */
10464
10465tree
10466fold_builtin_stxcpy_chk (tree fndecl, tree arglist, tree maxlen, bool ignore,
10467 enum built_in_function fcode)
10468{
10469 tree dest, src, size, len, fn;
10470
10471 if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE,
10472 VOID_TYPE))
10473 return 0;
10474
10475 dest = TREE_VALUE (arglist);
10476 src = TREE_VALUE (TREE_CHAIN (arglist));
10477 size = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
10478
10479 /* If SRC and DEST are the same (and not volatile), return DEST. */
10480 if (fcode == BUILT_IN_STRCPY_CHK && operand_equal_p (src, dest, 0))
10481 return fold_convert (TREE_TYPE (TREE_TYPE (fndecl)), dest);
10482
10483 if (! host_integerp (size, 1))
10484 return 0;
10485
10486 if (! integer_all_onesp (size))
10487 {
10488 len = c_strlen (src, 1);
10489 if (! len || ! host_integerp (len, 1))
10490 {
10491 /* If LEN is not constant, try MAXLEN too.
10492 For MAXLEN only allow optimizing into non-_ocs function
10493 if SIZE is >= MAXLEN, never convert to __ocs_fail (). */
10494 if (maxlen == NULL_TREE || ! host_integerp (maxlen, 1))
10495 {
10496 if (fcode == BUILT_IN_STPCPY_CHK)
10497 {
10498 if (! ignore)
10499 return 0;
10500
10501 /* If return value of __stpcpy_chk is ignored,
10502 optimize into __strcpy_chk. */
10503 fn = built_in_decls[BUILT_IN_STRCPY_CHK];
10504 if (!fn)
10505 return 0;
10506
10507 return build_function_call_expr (fn, arglist);
10508 }
10509
10510 if (! len || TREE_SIDE_EFFECTS (len))
10511 return 0;
10512
10513 /* If c_strlen returned something, but not a constant,
10514 transform __strcpy_chk into __memcpy_chk. */
10515 fn = built_in_decls[BUILT_IN_MEMCPY_CHK];
10516 if (!fn)
10517 return 0;
10518
10519 len = size_binop (PLUS_EXPR, len, ssize_int (1));
10520 arglist = build_tree_list (NULL_TREE, size);
10521 arglist = tree_cons (NULL_TREE, len, arglist);
10522 arglist = tree_cons (NULL_TREE, src, arglist);
10523 arglist = tree_cons (NULL_TREE, dest, arglist);
10524 return fold_convert (TREE_TYPE (TREE_TYPE (fndecl)),
10525 build_function_call_expr (fn, arglist));
10526 }
10527 }
10528 else
10529 maxlen = len;
10530
10531 if (! tree_int_cst_lt (maxlen, size))
10532 return 0;
10533 }
10534
10535 arglist = build_tree_list (NULL_TREE, src);
10536 arglist = tree_cons (NULL_TREE, dest, arglist);
10537
10538 /* If __builtin_st{r,p}cpy_chk is used, assume st{r,p}cpy is available. */
10539 fn = built_in_decls[fcode == BUILT_IN_STPCPY_CHK
10540 ? BUILT_IN_STPCPY : BUILT_IN_STRCPY];
10541 if (!fn)
10542 return 0;
10543
10544 return build_function_call_expr (fn, arglist);
10545}
10546
10547/* Fold a call to the __strncpy_chk builtin.
10548 If MAXLEN is not NULL, it is maximum length passed as third argument. */
10549
10550tree
10551fold_builtin_strncpy_chk (tree arglist, tree maxlen)
10552{
10553 tree dest, src, size, len, fn;
10554
10555 if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE,
10556 INTEGER_TYPE, VOID_TYPE))
10557 return 0;
10558
10559 dest = TREE_VALUE (arglist);
10560 src = TREE_VALUE (TREE_CHAIN (arglist));
10561 len = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
10562 size = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (arglist))));
10563
10564 if (! host_integerp (size, 1))
10565 return 0;
10566
10567 if (! integer_all_onesp (size))
10568 {
10569 if (! host_integerp (len, 1))
10570 {
10571 /* If LEN is not constant, try MAXLEN too.
10572 For MAXLEN only allow optimizing into non-_ocs function
10573 if SIZE is >= MAXLEN, never convert to __ocs_fail (). */
10574 if (maxlen == NULL_TREE || ! host_integerp (maxlen, 1))
10575 return 0;
10576 }
10577 else
10578 maxlen = len;
10579
10580 if (tree_int_cst_lt (size, maxlen))
10581 return 0;
10582 }
10583
10584 arglist = build_tree_list (NULL_TREE, len);
10585 arglist = tree_cons (NULL_TREE, src, arglist);
10586 arglist = tree_cons (NULL_TREE, dest, arglist);
10587
10588 /* If __builtin_strncpy_chk is used, assume strncpy is available. */
10589 fn = built_in_decls[BUILT_IN_STRNCPY];
10590 if (!fn)
10591 return 0;
10592
10593 return build_function_call_expr (fn, arglist);
10594}
10595
10596/* Fold a call to the __strcat_chk builtin FNDECL with ARGLIST. */
10597
10598static tree
10599fold_builtin_strcat_chk (tree fndecl, tree arglist)
10600{
10601 tree dest, src, size, fn;
10602 const char *p;
10603
10604 if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE,
10605 VOID_TYPE))
10606 return 0;
10607
10608 dest = TREE_VALUE (arglist);
10609 src = TREE_VALUE (TREE_CHAIN (arglist));
10610 size = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
10611
10612 p = c_getstr (src);
10613 /* If the SRC parameter is "", return DEST. */
10614 if (p && *p == '\0')
10615 return omit_one_operand (TREE_TYPE (TREE_TYPE (fndecl)), dest, src);
10616
10617 if (! host_integerp (size, 1) || ! integer_all_onesp (size))
10618 return 0;
10619
10620 arglist = build_tree_list (NULL_TREE, src);
10621 arglist = tree_cons (NULL_TREE, dest, arglist);
10622
10623 /* If __builtin_strcat_chk is used, assume strcat is available. */
10624 fn = built_in_decls[BUILT_IN_STRCAT];
10625 if (!fn)
10626 return 0;
10627
10628 return build_function_call_expr (fn, arglist);
10629}
10630
10631/* Fold a call to the __strncat_chk builtin EXP. */
10632
10633static tree
10634fold_builtin_strncat_chk (tree fndecl, tree arglist)
10635{
10636 tree dest, src, size, len, fn;
10637 const char *p;
10638
10639 if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE,
10640 INTEGER_TYPE, VOID_TYPE))
10641 return 0;
10642
10643 dest = TREE_VALUE (arglist);
10644 src = TREE_VALUE (TREE_CHAIN (arglist));
10645 len = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
10646 size = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (arglist))));
10647
10648 p = c_getstr (src);
10649 /* If the SRC parameter is "" or if LEN is 0, return DEST. */
10650 if (p && *p == '\0')
10651 return omit_one_operand (TREE_TYPE (TREE_TYPE (fndecl)), dest, len);
10652 else if (integer_zerop (len))
10653 return omit_one_operand (TREE_TYPE (TREE_TYPE (fndecl)), dest, src);
10654
10655 if (! host_integerp (size, 1))
10656 return 0;
10657
10658 if (! integer_all_onesp (size))
10659 {
10660 tree src_len = c_strlen (src, 1);
10661 if (src_len
10662 && host_integerp (src_len, 1)
10663 && host_integerp (len, 1)
10664 && ! tree_int_cst_lt (len, src_len))
10665 {
10666 /* If LEN >= strlen (SRC), optimize into __strcat_chk. */
10667 fn = built_in_decls[BUILT_IN_STRCAT_CHK];
10668 if (!fn)
10669 return 0;
10670
10671 arglist = build_tree_list (NULL_TREE, size);
10672 arglist = tree_cons (NULL_TREE, src, arglist);
10673 arglist = tree_cons (NULL_TREE, dest, arglist);
10674 return build_function_call_expr (fn, arglist);
10675 }
10676 return 0;
10677 }
10678
10679 arglist = build_tree_list (NULL_TREE, len);
10680 arglist = tree_cons (NULL_TREE, src, arglist);
10681 arglist = tree_cons (NULL_TREE, dest, arglist);
10682
10683 /* If __builtin_strncat_chk is used, assume strncat is available. */
10684 fn = built_in_decls[BUILT_IN_STRNCAT];
10685 if (!fn)
10686 return 0;
10687
10688 return build_function_call_expr (fn, arglist);
10689}
10690
10691/* Fold a call to __{,v}sprintf_chk with argument list ARGLIST. Return 0 if
10692 a normal call should be emitted rather than expanding the function
10693 inline. FCODE is either BUILT_IN_SPRINTF_CHK or BUILT_IN_VSPRINTF_CHK. */
10694
10695static tree
10696fold_builtin_sprintf_chk (tree arglist, enum built_in_function fcode)
10697{
10698 tree dest, size, len, fn, fmt, flag;
10699 const char *fmt_str;
10700
10701 /* Verify the required arguments in the original call. */
10702 if (! arglist)
10703 return 0;
10704 dest = TREE_VALUE (arglist);
10705 if (! POINTER_TYPE_P (TREE_TYPE (dest)))
10706 return 0;
10707 arglist = TREE_CHAIN (arglist);
10708 if (! arglist)
10709 return 0;
10710 flag = TREE_VALUE (arglist);
10711 if (TREE_CODE (TREE_TYPE (flag)) != INTEGER_TYPE)
10712 return 0;
10713 arglist = TREE_CHAIN (arglist);
10714 if (! arglist)
10715 return 0;
10716 size = TREE_VALUE (arglist);
10717 if (TREE_CODE (TREE_TYPE (size)) != INTEGER_TYPE)
10718 return 0;
10719 arglist = TREE_CHAIN (arglist);
10720 if (! arglist)
10721 return 0;
10722 fmt = TREE_VALUE (arglist);
10723 if (! POINTER_TYPE_P (TREE_TYPE (fmt)))
10724 return 0;
10725 arglist = TREE_CHAIN (arglist);
10726
10727 if (! host_integerp (size, 1))
10728 return 0;
10729
10730 len = NULL_TREE;
10731
10732 if (!init_target_chars())
10733 return 0;
10734
10735 /* Check whether the format is a literal string constant. */
10736 fmt_str = c_getstr (fmt);
10737 if (fmt_str != NULL)
10738 {
10739 /* If the format doesn't contain % args or %%, we know the size. */
10740 if (strchr (fmt_str, target_percent) == 0)
10741 {
10742 if (fcode != BUILT_IN_SPRINTF_CHK || arglist == NULL_TREE)
10743 len = build_int_cstu (size_type_node, strlen (fmt_str));
10744 }
10745 /* If the format is "%s" and first ... argument is a string literal,
10746 we know the size too. */
10747 else if (fcode == BUILT_IN_SPRINTF_CHK && strcmp (fmt_str, target_percent_s) == 0)
10748 {
10749 tree arg;
10750
10751 if (arglist && !TREE_CHAIN (arglist))
10752 {
10753 arg = TREE_VALUE (arglist);
10754 if (POINTER_TYPE_P (TREE_TYPE (arg)))
10755 {
10756 len = c_strlen (arg, 1);
10757 if (! len || ! host_integerp (len, 1))
10758 len = NULL_TREE;
10759 }
10760 }
10761 }
10762 }
10763
10764 if (! integer_all_onesp (size))
10765 {
10766 if (! len || ! tree_int_cst_lt (len, size))
10767 return 0;
10768 }
10769
10770 /* Only convert __{,v}sprintf_chk to {,v}sprintf if flag is 0
10771 or if format doesn't contain % chars or is "%s". */
10772 if (! integer_zerop (flag))
10773 {
10774 if (fmt_str == NULL)
10775 return 0;
10776 if (strchr (fmt_str, target_percent) != NULL && strcmp (fmt_str, target_percent_s))
10777 return 0;
10778 }
10779
10780 arglist = tree_cons (NULL_TREE, fmt, arglist);
10781 arglist = tree_cons (NULL_TREE, dest, arglist);
10782
10783 /* If __builtin_{,v}sprintf_chk is used, assume {,v}sprintf is available. */
10784 fn = built_in_decls[fcode == BUILT_IN_VSPRINTF_CHK
10785 ? BUILT_IN_VSPRINTF : BUILT_IN_SPRINTF];
10786 if (!fn)
10787 return 0;
10788
10789 return build_function_call_expr (fn, arglist);
10790}
10791
10792/* Fold a call to {,v}snprintf with argument list ARGLIST. Return 0 if
10793 a normal call should be emitted rather than expanding the function
10794 inline. FCODE is either BUILT_IN_SNPRINTF_CHK or
10795 BUILT_IN_VSNPRINTF_CHK. If MAXLEN is not NULL, it is maximum length
10796 passed as second argument. */
10797
10798tree
10799fold_builtin_snprintf_chk (tree arglist, tree maxlen,
10800 enum built_in_function fcode)
10801{
10802 tree dest, size, len, fn, fmt, flag;
10803 const char *fmt_str;
10804
10805 /* Verify the required arguments in the original call. */
10806 if (! arglist)
10807 return 0;
10808 dest = TREE_VALUE (arglist);
10809 if (! POINTER_TYPE_P (TREE_TYPE (dest)))
10810 return 0;
10811 arglist = TREE_CHAIN (arglist);
10812 if (! arglist)
10813 return 0;
10814 len = TREE_VALUE (arglist);
10815 if (TREE_CODE (TREE_TYPE (len)) != INTEGER_TYPE)
10816 return 0;
10817 arglist = TREE_CHAIN (arglist);
10818 if (! arglist)
10819 return 0;
10820 flag = TREE_VALUE (arglist);
10821 if (TREE_CODE (TREE_TYPE (len)) != INTEGER_TYPE)
10822 return 0;
10823 arglist = TREE_CHAIN (arglist);
10824 if (! arglist)
10825 return 0;
10826 size = TREE_VALUE (arglist);
10827 if (TREE_CODE (TREE_TYPE (size)) != INTEGER_TYPE)
10828 return 0;
10829 arglist = TREE_CHAIN (arglist);
10830 if (! arglist)
10831 return 0;
10832 fmt = TREE_VALUE (arglist);
10833 if (! POINTER_TYPE_P (TREE_TYPE (fmt)))
10834 return 0;
10835 arglist = TREE_CHAIN (arglist);
10836
10837 if (! host_integerp (size, 1))
10838 return 0;
10839
10840 if (! integer_all_onesp (size))
10841 {
10842 if (! host_integerp (len, 1))
10843 {
10844 /* If LEN is not constant, try MAXLEN too.
10845 For MAXLEN only allow optimizing into non-_ocs function
10846 if SIZE is >= MAXLEN, never convert to __ocs_fail (). */
10847 if (maxlen == NULL_TREE || ! host_integerp (maxlen, 1))
10848 return 0;
10849 }
10850 else
10851 maxlen = len;
10852
10853 if (tree_int_cst_lt (size, maxlen))
10854 return 0;
10855 }
10856
10857 if (!init_target_chars())
10858 return 0;
10859
10860 /* Only convert __{,v}snprintf_chk to {,v}snprintf if flag is 0
10861 or if format doesn't contain % chars or is "%s". */
10862 if (! integer_zerop (flag))
10863 {
10864 fmt_str = c_getstr (fmt);
10865 if (fmt_str == NULL)
10866 return 0;
10867 if (strchr (fmt_str, target_percent) != NULL && strcmp (fmt_str, target_percent_s))
10868 return 0;
10869 }
10870
10871 arglist = tree_cons (NULL_TREE, fmt, arglist);
10872 arglist = tree_cons (NULL_TREE, len, arglist);
10873 arglist = tree_cons (NULL_TREE, dest, arglist);
10874
10875 /* If __builtin_{,v}snprintf_chk is used, assume {,v}snprintf is
10876 available. */
10877 fn = built_in_decls[fcode == BUILT_IN_VSNPRINTF_CHK
10878 ? BUILT_IN_VSNPRINTF : BUILT_IN_SNPRINTF];
10879 if (!fn)
10880 return 0;
10881
10882 return build_function_call_expr (fn, arglist);
10883}
10884
10885/* Fold a call to the {,v}printf{,_unlocked} and __{,v}printf_chk builtins.
10886
10887 Return 0 if no simplification was possible, otherwise return the
10888 simplified form of the call as a tree. FCODE is the BUILT_IN_*
10889 code of the function to be simplified. */
10890
10891static tree
10892fold_builtin_printf (tree fndecl, tree arglist, bool ignore,
10893 enum built_in_function fcode)
10894{
10895 tree fmt, fn = NULL_TREE, fn_putchar, fn_puts, arg, call;
10896 const char *fmt_str = NULL;
10897
10898 /* If the return value is used, don't do the transformation. */
10899 if (! ignore)
10900 return 0;
10901
10902 /* Verify the required arguments in the original call. */
10903 if (fcode == BUILT_IN_PRINTF_CHK || fcode == BUILT_IN_VPRINTF_CHK)
10904 {
10905 tree flag;
10906
10907 if (! arglist)
10908 return 0;
10909 flag = TREE_VALUE (arglist);
10910 if (TREE_CODE (TREE_TYPE (flag)) != INTEGER_TYPE
10911 || TREE_SIDE_EFFECTS (flag))
10912 return 0;
10913 arglist = TREE_CHAIN (arglist);
10914 }
10915
10916 if (! arglist)
10917 return 0;
10918 fmt = TREE_VALUE (arglist);
10919 if (! POINTER_TYPE_P (TREE_TYPE (fmt)))
10920 return 0;
10921 arglist = TREE_CHAIN (arglist);
10922
10923 /* Check whether the format is a literal string constant. */
10924 fmt_str = c_getstr (fmt);
10925 if (fmt_str == NULL)
10926 return NULL_TREE;
10927
10928 if (fcode == BUILT_IN_PRINTF_UNLOCKED)
10929 {
10930 /* If we're using an unlocked function, assume the other
10931 unlocked functions exist explicitly. */
10932 fn_putchar = built_in_decls[BUILT_IN_PUTCHAR_UNLOCKED];
10933 fn_puts = built_in_decls[BUILT_IN_PUTS_UNLOCKED];
10934 }
10935 else
10936 {
10937 fn_putchar = implicit_built_in_decls[BUILT_IN_PUTCHAR];
10938 fn_puts = implicit_built_in_decls[BUILT_IN_PUTS];
10939 }
10940
10941 if (!init_target_chars())
10942 return 0;
10943
10944 if (strcmp (fmt_str, target_percent_s) == 0 || strchr (fmt_str, target_percent) == NULL)
10945 {
10946 const char *str;
10947
10948 if (strcmp (fmt_str, target_percent_s) == 0)
10949 {
10950 if (fcode == BUILT_IN_VPRINTF || fcode == BUILT_IN_VPRINTF_CHK)
10951 return 0;
10952
10953 if (! arglist
10954 || ! POINTER_TYPE_P (TREE_TYPE (TREE_VALUE (arglist)))
10955 || TREE_CHAIN (arglist))
10956 return 0;
10957
10958 str = c_getstr (TREE_VALUE (arglist));
10959 if (str == NULL)
10960 return 0;
10961 }
10962 else
10963 {
10964 /* The format specifier doesn't contain any '%' characters. */
10965 if (fcode != BUILT_IN_VPRINTF && fcode != BUILT_IN_VPRINTF_CHK
10966 && arglist)
10967 return 0;
10968 str = fmt_str;
10969 }
10970
10971 /* If the string was "", printf does nothing. */
10972 if (str[0] == '\0')
10973 return build_int_cst (TREE_TYPE (TREE_TYPE (fndecl)), 0);
10974
10975 /* If the string has length of 1, call putchar. */
10976 if (str[1] == '\0')
10977 {
10978 /* Given printf("c"), (where c is any one character,)
10979 convert "c"[0] to an int and pass that to the replacement
10980 function. */
10981 arg = build_int_cst (NULL_TREE, str[0]);
10982 arglist = build_tree_list (NULL_TREE, arg);
10983 fn = fn_putchar;
10984 }
10985 else
10986 {
10987 /* If the string was "string\n", call puts("string"). */
10988 size_t len = strlen (str);
10989 if ((unsigned char)str[len - 1] == target_newline)
10990 {
10991 /* Create a NUL-terminated string that's one char shorter
10992 than the original, stripping off the trailing '\n'. */
10993 char *newstr = alloca (len);
10994 memcpy (newstr, str, len - 1);
10995 newstr[len - 1] = 0;
10996
10997 arg = build_string_literal (len, newstr);
10998 arglist = build_tree_list (NULL_TREE, arg);
10999 fn = fn_puts;
11000 }
11001 else
11002 /* We'd like to arrange to call fputs(string,stdout) here,
11003 but we need stdout and don't have a way to get it yet. */
11004 return 0;
11005 }
11006 }
11007
11008 /* The other optimizations can be done only on the non-va_list variants. */
11009 else if (fcode == BUILT_IN_VPRINTF || fcode == BUILT_IN_VPRINTF_CHK)
11010 return 0;
11011
11012 /* If the format specifier was "%s\n", call __builtin_puts(arg). */
11013 else if (strcmp (fmt_str, target_percent_s_newline) == 0)
11014 {
11015 if (! arglist
11016 || ! POINTER_TYPE_P (TREE_TYPE (TREE_VALUE (arglist)))
11017 || TREE_CHAIN (arglist))
11018 return 0;
11019 fn = fn_puts;
11020 }
11021
11022 /* If the format specifier was "%c", call __builtin_putchar(arg). */
11023 else if (strcmp (fmt_str, target_percent_c) == 0)
11024 {
11025 if (! arglist
11026 || TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))) != INTEGER_TYPE
11027 || TREE_CHAIN (arglist))
11028 return 0;
11029 fn = fn_putchar;
11030 }
11031
11032 if (!fn)
11033 return 0;
11034
11035 call = build_function_call_expr (fn, arglist);
11036 return fold_convert (TREE_TYPE (TREE_TYPE (fndecl)), call);
11037}
11038
11039/* Fold a call to the {,v}fprintf{,_unlocked} and __{,v}printf_chk builtins.
11040
11041 Return 0 if no simplification was possible, otherwise return the
11042 simplified form of the call as a tree. FCODE is the BUILT_IN_*
11043 code of the function to be simplified. */
11044
11045static tree
11046fold_builtin_fprintf (tree fndecl, tree arglist, bool ignore,
11047 enum built_in_function fcode)
11048{
11049 tree fp, fmt, fn = NULL_TREE, fn_fputc, fn_fputs, arg, call;
11050 const char *fmt_str = NULL;
11051
11052 /* If the return value is used, don't do the transformation. */
11053 if (! ignore)
11054 return 0;
11055
11056 /* Verify the required arguments in the original call. */
11057 if (! arglist)
11058 return 0;
11059 fp = TREE_VALUE (arglist);
11060 if (! POINTER_TYPE_P (TREE_TYPE (fp)))
11061 return 0;
11062 arglist = TREE_CHAIN (arglist);
11063
11064 if (fcode == BUILT_IN_FPRINTF_CHK || fcode == BUILT_IN_VFPRINTF_CHK)
11065 {
11066 tree flag;
11067
11068 if (! arglist)
11069 return 0;
11070 flag = TREE_VALUE (arglist);
11071 if (TREE_CODE (TREE_TYPE (flag)) != INTEGER_TYPE
11072 || TREE_SIDE_EFFECTS (flag))
11073 return 0;
11074 arglist = TREE_CHAIN (arglist);
11075 }
11076
11077 if (! arglist)
11078 return 0;
11079 fmt = TREE_VALUE (arglist);
11080 if (! POINTER_TYPE_P (TREE_TYPE (fmt)))
11081 return 0;
11082 arglist = TREE_CHAIN (arglist);
11083
11084 /* Check whether the format is a literal string constant. */
11085 fmt_str = c_getstr (fmt);
11086 if (fmt_str == NULL)
11087 return NULL_TREE;
11088
11089 if (fcode == BUILT_IN_FPRINTF_UNLOCKED)
11090 {
11091 /* If we're using an unlocked function, assume the other
11092 unlocked functions exist explicitly. */
11093 fn_fputc = built_in_decls[BUILT_IN_FPUTC_UNLOCKED];
11094 fn_fputs = built_in_decls[BUILT_IN_FPUTS_UNLOCKED];
11095 }
11096 else
11097 {
11098 fn_fputc = implicit_built_in_decls[BUILT_IN_FPUTC];
11099 fn_fputs = implicit_built_in_decls[BUILT_IN_FPUTS];
11100 }
11101
11102 if (!init_target_chars())
11103 return 0;
11104
11105 /* If the format doesn't contain % args or %%, use strcpy. */
11106 if (strchr (fmt_str, target_percent) == NULL)
11107 {
11108 if (fcode != BUILT_IN_VFPRINTF && fcode != BUILT_IN_VFPRINTF_CHK
11109 && arglist)
11110 return 0;
11111
11112 /* If the format specifier was "", fprintf does nothing. */
11113 if (fmt_str[0] == '\0')
11114 {
11115 /* If FP has side-effects, just wait until gimplification is
11116 done. */
11117 if (TREE_SIDE_EFFECTS (fp))
11118 return 0;
11119
11120 return build_int_cst (TREE_TYPE (TREE_TYPE (fndecl)), 0);
11121 }
11122
11123 /* When "string" doesn't contain %, replace all cases of
11124 fprintf (fp, string) with fputs (string, fp). The fputs
11125 builtin will take care of special cases like length == 1. */
11126 arglist = build_tree_list (NULL_TREE, fp);
11127 arglist = tree_cons (NULL_TREE, fmt, arglist);
11128 fn = fn_fputs;
11129 }
11130
11131 /* The other optimizations can be done only on the non-va_list variants. */
11132 else if (fcode == BUILT_IN_VFPRINTF || fcode == BUILT_IN_VFPRINTF_CHK)
11133 return 0;
11134
11135 /* If the format specifier was "%s", call __builtin_fputs (arg, fp). */
11136 else if (strcmp (fmt_str, target_percent_s) == 0)
11137 {
11138 if (! arglist
11139 || ! POINTER_TYPE_P (TREE_TYPE (TREE_VALUE (arglist)))
11140 || TREE_CHAIN (arglist))
11141 return 0;
11142 arg = TREE_VALUE (arglist);
11143 arglist = build_tree_list (NULL_TREE, fp);
11144 arglist = tree_cons (NULL_TREE, arg, arglist);
11145 fn = fn_fputs;
11146 }
11147
11148 /* If the format specifier was "%c", call __builtin_fputc (arg, fp). */
11149 else if (strcmp (fmt_str, target_percent_c) == 0)
11150 {
11151 if (! arglist
11152 || TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))) != INTEGER_TYPE
11153 || TREE_CHAIN (arglist))
11154 return 0;
11155 arg = TREE_VALUE (arglist);
11156 arglist = build_tree_list (NULL_TREE, fp);
11157 arglist = tree_cons (NULL_TREE, arg, arglist);
11158 fn = fn_fputc;
11159 }
11160
11161 if (!fn)
11162 return 0;
11163
11164 call = build_function_call_expr (fn, arglist);
11165 return fold_convert (TREE_TYPE (TREE_TYPE (fndecl)), call);
11166}
11167
11168/* Initialize format string characters in the target charset. */
11169
11170static bool
11171init_target_chars (void)
11172{
11173 static bool init;
11174 if (!init)
11175 {
11176 target_newline = lang_hooks.to_target_charset ('\n');
11177 target_percent = lang_hooks.to_target_charset ('%');
11178 target_c = lang_hooks.to_target_charset ('c');
11179 target_s = lang_hooks.to_target_charset ('s');
11180 if (target_newline == 0 || target_percent == 0 || target_c == 0
11181 || target_s == 0)
11182 return false;
11183
11184 target_percent_c[0] = target_percent;
11185 target_percent_c[1] = target_c;
11186 target_percent_c[2] = '\0';
11187
11188 target_percent_s[0] = target_percent;
11189 target_percent_s[1] = target_s;
11190 target_percent_s[2] = '\0';
11191
11192 target_percent_s_newline[0] = target_percent;
11193 target_percent_s_newline[1] = target_s;
11194 target_percent_s_newline[2] = target_newline;
11195 target_percent_s_newline[3] = '\0';
11196
11197 init = true;
11198 }
11199 return true;
11200}