annotate gcc/gimple-expr.c @ 145:1830386684a0

gcc-9.2.0
author anatofuz
date Thu, 13 Feb 2020 11:34:05 +0900
parents 84e7813d76e9
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
111
kono
parents:
diff changeset
1 /* Gimple decl, type, and expression support functions.
kono
parents:
diff changeset
2
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3 Copyright (C) 2007-2020 Free Software Foundation, Inc.
111
kono
parents:
diff changeset
4 Contributed by Aldy Hernandez <aldyh@redhat.com>
kono
parents:
diff changeset
5
kono
parents:
diff changeset
6 This file is part of GCC.
kono
parents:
diff changeset
7
kono
parents:
diff changeset
8 GCC is free software; you can redistribute it and/or modify it under
kono
parents:
diff changeset
9 the terms of the GNU General Public License as published by the Free
kono
parents:
diff changeset
10 Software Foundation; either version 3, or (at your option) any later
kono
parents:
diff changeset
11 version.
kono
parents:
diff changeset
12
kono
parents:
diff changeset
13 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
kono
parents:
diff changeset
14 WARRANTY; without even the implied warranty of MERCHANTABILITY or
kono
parents:
diff changeset
15 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
kono
parents:
diff changeset
16 for more details.
kono
parents:
diff changeset
17
kono
parents:
diff changeset
18 You should have received a copy of the GNU General Public License
kono
parents:
diff changeset
19 along with GCC; see the file COPYING3. If not see
kono
parents:
diff changeset
20 <http://www.gnu.org/licenses/>. */
kono
parents:
diff changeset
21
kono
parents:
diff changeset
22 #include "config.h"
kono
parents:
diff changeset
23 #include "system.h"
kono
parents:
diff changeset
24 #include "coretypes.h"
kono
parents:
diff changeset
25 #include "backend.h"
kono
parents:
diff changeset
26 #include "tree.h"
kono
parents:
diff changeset
27 #include "gimple.h"
kono
parents:
diff changeset
28 #include "stringpool.h"
kono
parents:
diff changeset
29 #include "gimple-ssa.h"
kono
parents:
diff changeset
30 #include "fold-const.h"
kono
parents:
diff changeset
31 #include "tree-eh.h"
kono
parents:
diff changeset
32 #include "gimplify.h"
kono
parents:
diff changeset
33 #include "stor-layout.h"
kono
parents:
diff changeset
34 #include "demangle.h"
kono
parents:
diff changeset
35 #include "hash-set.h"
kono
parents:
diff changeset
36 #include "rtl.h"
kono
parents:
diff changeset
37 #include "tree-pass.h"
kono
parents:
diff changeset
38 #include "stringpool.h"
kono
parents:
diff changeset
39 #include "attribs.h"
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
40 #include "target.h"
111
kono
parents:
diff changeset
41
kono
parents:
diff changeset
42 /* ----- Type related ----- */
kono
parents:
diff changeset
43
kono
parents:
diff changeset
44 /* Return true if the conversion from INNER_TYPE to OUTER_TYPE is a
kono
parents:
diff changeset
45 useless type conversion, otherwise return false.
kono
parents:
diff changeset
46
kono
parents:
diff changeset
47 This function implicitly defines the middle-end type system. With
kono
parents:
diff changeset
48 the notion of 'a < b' meaning that useless_type_conversion_p (a, b)
kono
parents:
diff changeset
49 holds and 'a > b' meaning that useless_type_conversion_p (b, a) holds,
kono
parents:
diff changeset
50 the following invariants shall be fulfilled:
kono
parents:
diff changeset
51
kono
parents:
diff changeset
52 1) useless_type_conversion_p is transitive.
kono
parents:
diff changeset
53 If a < b and b < c then a < c.
kono
parents:
diff changeset
54
kono
parents:
diff changeset
55 2) useless_type_conversion_p is not symmetric.
kono
parents:
diff changeset
56 From a < b does not follow a > b.
kono
parents:
diff changeset
57
kono
parents:
diff changeset
58 3) Types define the available set of operations applicable to values.
kono
parents:
diff changeset
59 A type conversion is useless if the operations for the target type
kono
parents:
diff changeset
60 is a subset of the operations for the source type. For example
kono
parents:
diff changeset
61 casts to void* are useless, casts from void* are not (void* can't
kono
parents:
diff changeset
62 be dereferenced or offsetted, but copied, hence its set of operations
kono
parents:
diff changeset
63 is a strict subset of that of all other data pointer types). Casts
kono
parents:
diff changeset
64 to const T* are useless (can't be written to), casts from const T*
kono
parents:
diff changeset
65 to T* are not. */
kono
parents:
diff changeset
66
kono
parents:
diff changeset
67 bool
kono
parents:
diff changeset
68 useless_type_conversion_p (tree outer_type, tree inner_type)
kono
parents:
diff changeset
69 {
kono
parents:
diff changeset
70 /* Do the following before stripping toplevel qualifiers. */
kono
parents:
diff changeset
71 if (POINTER_TYPE_P (inner_type)
kono
parents:
diff changeset
72 && POINTER_TYPE_P (outer_type))
kono
parents:
diff changeset
73 {
kono
parents:
diff changeset
74 /* Do not lose casts between pointers to different address spaces. */
kono
parents:
diff changeset
75 if (TYPE_ADDR_SPACE (TREE_TYPE (outer_type))
kono
parents:
diff changeset
76 != TYPE_ADDR_SPACE (TREE_TYPE (inner_type)))
kono
parents:
diff changeset
77 return false;
kono
parents:
diff changeset
78 /* Do not lose casts to function pointer types. */
kono
parents:
diff changeset
79 if ((TREE_CODE (TREE_TYPE (outer_type)) == FUNCTION_TYPE
kono
parents:
diff changeset
80 || TREE_CODE (TREE_TYPE (outer_type)) == METHOD_TYPE)
kono
parents:
diff changeset
81 && !(TREE_CODE (TREE_TYPE (inner_type)) == FUNCTION_TYPE
kono
parents:
diff changeset
82 || TREE_CODE (TREE_TYPE (inner_type)) == METHOD_TYPE))
kono
parents:
diff changeset
83 return false;
kono
parents:
diff changeset
84 }
kono
parents:
diff changeset
85
kono
parents:
diff changeset
86 /* From now on qualifiers on value types do not matter. */
kono
parents:
diff changeset
87 inner_type = TYPE_MAIN_VARIANT (inner_type);
kono
parents:
diff changeset
88 outer_type = TYPE_MAIN_VARIANT (outer_type);
kono
parents:
diff changeset
89
kono
parents:
diff changeset
90 if (inner_type == outer_type)
kono
parents:
diff changeset
91 return true;
kono
parents:
diff changeset
92
kono
parents:
diff changeset
93 /* Changes in machine mode are never useless conversions because the RTL
kono
parents:
diff changeset
94 middle-end expects explicit conversions between modes. */
kono
parents:
diff changeset
95 if (TYPE_MODE (inner_type) != TYPE_MODE (outer_type))
kono
parents:
diff changeset
96 return false;
kono
parents:
diff changeset
97
kono
parents:
diff changeset
98 /* If both the inner and outer types are integral types, then the
kono
parents:
diff changeset
99 conversion is not necessary if they have the same mode and
kono
parents:
diff changeset
100 signedness and precision, and both or neither are boolean. */
kono
parents:
diff changeset
101 if (INTEGRAL_TYPE_P (inner_type)
kono
parents:
diff changeset
102 && INTEGRAL_TYPE_P (outer_type))
kono
parents:
diff changeset
103 {
kono
parents:
diff changeset
104 /* Preserve changes in signedness or precision. */
kono
parents:
diff changeset
105 if (TYPE_UNSIGNED (inner_type) != TYPE_UNSIGNED (outer_type)
kono
parents:
diff changeset
106 || TYPE_PRECISION (inner_type) != TYPE_PRECISION (outer_type))
kono
parents:
diff changeset
107 return false;
kono
parents:
diff changeset
108
kono
parents:
diff changeset
109 /* Preserve conversions to/from BOOLEAN_TYPE if types are not
kono
parents:
diff changeset
110 of precision one. */
kono
parents:
diff changeset
111 if (((TREE_CODE (inner_type) == BOOLEAN_TYPE)
kono
parents:
diff changeset
112 != (TREE_CODE (outer_type) == BOOLEAN_TYPE))
kono
parents:
diff changeset
113 && TYPE_PRECISION (outer_type) != 1)
kono
parents:
diff changeset
114 return false;
kono
parents:
diff changeset
115
kono
parents:
diff changeset
116 /* We don't need to preserve changes in the types minimum or
kono
parents:
diff changeset
117 maximum value in general as these do not generate code
kono
parents:
diff changeset
118 unless the types precisions are different. */
kono
parents:
diff changeset
119 return true;
kono
parents:
diff changeset
120 }
kono
parents:
diff changeset
121
kono
parents:
diff changeset
122 /* Scalar floating point types with the same mode are compatible. */
kono
parents:
diff changeset
123 else if (SCALAR_FLOAT_TYPE_P (inner_type)
kono
parents:
diff changeset
124 && SCALAR_FLOAT_TYPE_P (outer_type))
kono
parents:
diff changeset
125 return true;
kono
parents:
diff changeset
126
kono
parents:
diff changeset
127 /* Fixed point types with the same mode are compatible. */
kono
parents:
diff changeset
128 else if (FIXED_POINT_TYPE_P (inner_type)
kono
parents:
diff changeset
129 && FIXED_POINT_TYPE_P (outer_type))
kono
parents:
diff changeset
130 return TYPE_SATURATING (inner_type) == TYPE_SATURATING (outer_type);
kono
parents:
diff changeset
131
kono
parents:
diff changeset
132 /* We need to take special care recursing to pointed-to types. */
kono
parents:
diff changeset
133 else if (POINTER_TYPE_P (inner_type)
kono
parents:
diff changeset
134 && POINTER_TYPE_P (outer_type))
kono
parents:
diff changeset
135 {
kono
parents:
diff changeset
136 /* We do not care for const qualification of the pointed-to types
kono
parents:
diff changeset
137 as const qualification has no semantic value to the middle-end. */
kono
parents:
diff changeset
138
kono
parents:
diff changeset
139 /* Otherwise pointers/references are equivalent. */
kono
parents:
diff changeset
140 return true;
kono
parents:
diff changeset
141 }
kono
parents:
diff changeset
142
kono
parents:
diff changeset
143 /* Recurse for complex types. */
kono
parents:
diff changeset
144 else if (TREE_CODE (inner_type) == COMPLEX_TYPE
kono
parents:
diff changeset
145 && TREE_CODE (outer_type) == COMPLEX_TYPE)
kono
parents:
diff changeset
146 return useless_type_conversion_p (TREE_TYPE (outer_type),
kono
parents:
diff changeset
147 TREE_TYPE (inner_type));
kono
parents:
diff changeset
148
kono
parents:
diff changeset
149 /* Recurse for vector types with the same number of subparts. */
kono
parents:
diff changeset
150 else if (TREE_CODE (inner_type) == VECTOR_TYPE
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
151 && TREE_CODE (outer_type) == VECTOR_TYPE)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
152 return (known_eq (TYPE_VECTOR_SUBPARTS (inner_type),
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
153 TYPE_VECTOR_SUBPARTS (outer_type))
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
154 && useless_type_conversion_p (TREE_TYPE (outer_type),
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
155 TREE_TYPE (inner_type))
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
156 && targetm.compatible_vector_types_p (inner_type, outer_type));
111
kono
parents:
diff changeset
157
kono
parents:
diff changeset
158 else if (TREE_CODE (inner_type) == ARRAY_TYPE
kono
parents:
diff changeset
159 && TREE_CODE (outer_type) == ARRAY_TYPE)
kono
parents:
diff changeset
160 {
kono
parents:
diff changeset
161 /* Preserve various attributes. */
kono
parents:
diff changeset
162 if (TYPE_REVERSE_STORAGE_ORDER (inner_type)
kono
parents:
diff changeset
163 != TYPE_REVERSE_STORAGE_ORDER (outer_type))
kono
parents:
diff changeset
164 return false;
kono
parents:
diff changeset
165 if (TYPE_STRING_FLAG (inner_type) != TYPE_STRING_FLAG (outer_type))
kono
parents:
diff changeset
166 return false;
kono
parents:
diff changeset
167
kono
parents:
diff changeset
168 /* Conversions from array types with unknown extent to
kono
parents:
diff changeset
169 array types with known extent are not useless. */
kono
parents:
diff changeset
170 if (!TYPE_DOMAIN (inner_type) && TYPE_DOMAIN (outer_type))
kono
parents:
diff changeset
171 return false;
kono
parents:
diff changeset
172
kono
parents:
diff changeset
173 /* Nor are conversions from array types with non-constant size to
kono
parents:
diff changeset
174 array types with constant size or to different size. */
kono
parents:
diff changeset
175 if (TYPE_SIZE (outer_type)
kono
parents:
diff changeset
176 && TREE_CODE (TYPE_SIZE (outer_type)) == INTEGER_CST
kono
parents:
diff changeset
177 && (!TYPE_SIZE (inner_type)
kono
parents:
diff changeset
178 || TREE_CODE (TYPE_SIZE (inner_type)) != INTEGER_CST
kono
parents:
diff changeset
179 || !tree_int_cst_equal (TYPE_SIZE (outer_type),
kono
parents:
diff changeset
180 TYPE_SIZE (inner_type))))
kono
parents:
diff changeset
181 return false;
kono
parents:
diff changeset
182
kono
parents:
diff changeset
183 /* Check conversions between arrays with partially known extents.
kono
parents:
diff changeset
184 If the array min/max values are constant they have to match.
kono
parents:
diff changeset
185 Otherwise allow conversions to unknown and variable extents.
kono
parents:
diff changeset
186 In particular this declares conversions that may change the
kono
parents:
diff changeset
187 mode to BLKmode as useless. */
kono
parents:
diff changeset
188 if (TYPE_DOMAIN (inner_type)
kono
parents:
diff changeset
189 && TYPE_DOMAIN (outer_type)
kono
parents:
diff changeset
190 && TYPE_DOMAIN (inner_type) != TYPE_DOMAIN (outer_type))
kono
parents:
diff changeset
191 {
kono
parents:
diff changeset
192 tree inner_min = TYPE_MIN_VALUE (TYPE_DOMAIN (inner_type));
kono
parents:
diff changeset
193 tree outer_min = TYPE_MIN_VALUE (TYPE_DOMAIN (outer_type));
kono
parents:
diff changeset
194 tree inner_max = TYPE_MAX_VALUE (TYPE_DOMAIN (inner_type));
kono
parents:
diff changeset
195 tree outer_max = TYPE_MAX_VALUE (TYPE_DOMAIN (outer_type));
kono
parents:
diff changeset
196
kono
parents:
diff changeset
197 /* After gimplification a variable min/max value carries no
kono
parents:
diff changeset
198 additional information compared to a NULL value. All that
kono
parents:
diff changeset
199 matters has been lowered to be part of the IL. */
kono
parents:
diff changeset
200 if (inner_min && TREE_CODE (inner_min) != INTEGER_CST)
kono
parents:
diff changeset
201 inner_min = NULL_TREE;
kono
parents:
diff changeset
202 if (outer_min && TREE_CODE (outer_min) != INTEGER_CST)
kono
parents:
diff changeset
203 outer_min = NULL_TREE;
kono
parents:
diff changeset
204 if (inner_max && TREE_CODE (inner_max) != INTEGER_CST)
kono
parents:
diff changeset
205 inner_max = NULL_TREE;
kono
parents:
diff changeset
206 if (outer_max && TREE_CODE (outer_max) != INTEGER_CST)
kono
parents:
diff changeset
207 outer_max = NULL_TREE;
kono
parents:
diff changeset
208
kono
parents:
diff changeset
209 /* Conversions NULL / variable <- cst are useless, but not
kono
parents:
diff changeset
210 the other way around. */
kono
parents:
diff changeset
211 if (outer_min
kono
parents:
diff changeset
212 && (!inner_min
kono
parents:
diff changeset
213 || !tree_int_cst_equal (inner_min, outer_min)))
kono
parents:
diff changeset
214 return false;
kono
parents:
diff changeset
215 if (outer_max
kono
parents:
diff changeset
216 && (!inner_max
kono
parents:
diff changeset
217 || !tree_int_cst_equal (inner_max, outer_max)))
kono
parents:
diff changeset
218 return false;
kono
parents:
diff changeset
219 }
kono
parents:
diff changeset
220
kono
parents:
diff changeset
221 /* Recurse on the element check. */
kono
parents:
diff changeset
222 return useless_type_conversion_p (TREE_TYPE (outer_type),
kono
parents:
diff changeset
223 TREE_TYPE (inner_type));
kono
parents:
diff changeset
224 }
kono
parents:
diff changeset
225
kono
parents:
diff changeset
226 else if ((TREE_CODE (inner_type) == FUNCTION_TYPE
kono
parents:
diff changeset
227 || TREE_CODE (inner_type) == METHOD_TYPE)
kono
parents:
diff changeset
228 && TREE_CODE (inner_type) == TREE_CODE (outer_type))
kono
parents:
diff changeset
229 {
kono
parents:
diff changeset
230 tree outer_parm, inner_parm;
kono
parents:
diff changeset
231
kono
parents:
diff changeset
232 /* If the return types are not compatible bail out. */
kono
parents:
diff changeset
233 if (!useless_type_conversion_p (TREE_TYPE (outer_type),
kono
parents:
diff changeset
234 TREE_TYPE (inner_type)))
kono
parents:
diff changeset
235 return false;
kono
parents:
diff changeset
236
kono
parents:
diff changeset
237 /* Method types should belong to a compatible base class. */
kono
parents:
diff changeset
238 if (TREE_CODE (inner_type) == METHOD_TYPE
kono
parents:
diff changeset
239 && !useless_type_conversion_p (TYPE_METHOD_BASETYPE (outer_type),
kono
parents:
diff changeset
240 TYPE_METHOD_BASETYPE (inner_type)))
kono
parents:
diff changeset
241 return false;
kono
parents:
diff changeset
242
kono
parents:
diff changeset
243 /* A conversion to an unprototyped argument list is ok. */
kono
parents:
diff changeset
244 if (!prototype_p (outer_type))
kono
parents:
diff changeset
245 return true;
kono
parents:
diff changeset
246
kono
parents:
diff changeset
247 /* If the unqualified argument types are compatible the conversion
kono
parents:
diff changeset
248 is useless. */
kono
parents:
diff changeset
249 if (TYPE_ARG_TYPES (outer_type) == TYPE_ARG_TYPES (inner_type))
kono
parents:
diff changeset
250 return true;
kono
parents:
diff changeset
251
kono
parents:
diff changeset
252 for (outer_parm = TYPE_ARG_TYPES (outer_type),
kono
parents:
diff changeset
253 inner_parm = TYPE_ARG_TYPES (inner_type);
kono
parents:
diff changeset
254 outer_parm && inner_parm;
kono
parents:
diff changeset
255 outer_parm = TREE_CHAIN (outer_parm),
kono
parents:
diff changeset
256 inner_parm = TREE_CHAIN (inner_parm))
kono
parents:
diff changeset
257 if (!useless_type_conversion_p
kono
parents:
diff changeset
258 (TYPE_MAIN_VARIANT (TREE_VALUE (outer_parm)),
kono
parents:
diff changeset
259 TYPE_MAIN_VARIANT (TREE_VALUE (inner_parm))))
kono
parents:
diff changeset
260 return false;
kono
parents:
diff changeset
261
kono
parents:
diff changeset
262 /* If there is a mismatch in the number of arguments the functions
kono
parents:
diff changeset
263 are not compatible. */
kono
parents:
diff changeset
264 if (outer_parm || inner_parm)
kono
parents:
diff changeset
265 return false;
kono
parents:
diff changeset
266
kono
parents:
diff changeset
267 /* Defer to the target if necessary. */
kono
parents:
diff changeset
268 if (TYPE_ATTRIBUTES (inner_type) || TYPE_ATTRIBUTES (outer_type))
kono
parents:
diff changeset
269 return comp_type_attributes (outer_type, inner_type) != 0;
kono
parents:
diff changeset
270
kono
parents:
diff changeset
271 return true;
kono
parents:
diff changeset
272 }
kono
parents:
diff changeset
273
kono
parents:
diff changeset
274 /* For aggregates we rely on TYPE_CANONICAL exclusively and require
kono
parents:
diff changeset
275 explicit conversions for types involving to be structurally
kono
parents:
diff changeset
276 compared types. */
kono
parents:
diff changeset
277 else if (AGGREGATE_TYPE_P (inner_type)
kono
parents:
diff changeset
278 && TREE_CODE (inner_type) == TREE_CODE (outer_type))
kono
parents:
diff changeset
279 return TYPE_CANONICAL (inner_type)
kono
parents:
diff changeset
280 && TYPE_CANONICAL (inner_type) == TYPE_CANONICAL (outer_type);
kono
parents:
diff changeset
281
kono
parents:
diff changeset
282 else if (TREE_CODE (inner_type) == OFFSET_TYPE
kono
parents:
diff changeset
283 && TREE_CODE (outer_type) == OFFSET_TYPE)
kono
parents:
diff changeset
284 return useless_type_conversion_p (TREE_TYPE (outer_type),
kono
parents:
diff changeset
285 TREE_TYPE (inner_type))
kono
parents:
diff changeset
286 && useless_type_conversion_p
kono
parents:
diff changeset
287 (TYPE_OFFSET_BASETYPE (outer_type),
kono
parents:
diff changeset
288 TYPE_OFFSET_BASETYPE (inner_type));
kono
parents:
diff changeset
289
kono
parents:
diff changeset
290 return false;
kono
parents:
diff changeset
291 }
kono
parents:
diff changeset
292
kono
parents:
diff changeset
293
kono
parents:
diff changeset
294 /* ----- Decl related ----- */
kono
parents:
diff changeset
295
kono
parents:
diff changeset
296 /* Set sequence SEQ to be the GIMPLE body for function FN. */
kono
parents:
diff changeset
297
kono
parents:
diff changeset
298 void
kono
parents:
diff changeset
299 gimple_set_body (tree fndecl, gimple_seq seq)
kono
parents:
diff changeset
300 {
kono
parents:
diff changeset
301 struct function *fn = DECL_STRUCT_FUNCTION (fndecl);
kono
parents:
diff changeset
302 if (fn == NULL)
kono
parents:
diff changeset
303 {
kono
parents:
diff changeset
304 /* If FNDECL still does not have a function structure associated
kono
parents:
diff changeset
305 with it, then it does not make sense for it to receive a
kono
parents:
diff changeset
306 GIMPLE body. */
kono
parents:
diff changeset
307 gcc_assert (seq == NULL);
kono
parents:
diff changeset
308 }
kono
parents:
diff changeset
309 else
kono
parents:
diff changeset
310 fn->gimple_body = seq;
kono
parents:
diff changeset
311 }
kono
parents:
diff changeset
312
kono
parents:
diff changeset
313
kono
parents:
diff changeset
314 /* Return the body of GIMPLE statements for function FN. After the
kono
parents:
diff changeset
315 CFG pass, the function body doesn't exist anymore because it has
kono
parents:
diff changeset
316 been split up into basic blocks. In this case, it returns
kono
parents:
diff changeset
317 NULL. */
kono
parents:
diff changeset
318
kono
parents:
diff changeset
319 gimple_seq
kono
parents:
diff changeset
320 gimple_body (tree fndecl)
kono
parents:
diff changeset
321 {
kono
parents:
diff changeset
322 struct function *fn = DECL_STRUCT_FUNCTION (fndecl);
kono
parents:
diff changeset
323 return fn ? fn->gimple_body : NULL;
kono
parents:
diff changeset
324 }
kono
parents:
diff changeset
325
kono
parents:
diff changeset
326 /* Return true when FNDECL has Gimple body either in unlowered
kono
parents:
diff changeset
327 or CFG form. */
kono
parents:
diff changeset
328 bool
kono
parents:
diff changeset
329 gimple_has_body_p (tree fndecl)
kono
parents:
diff changeset
330 {
kono
parents:
diff changeset
331 struct function *fn = DECL_STRUCT_FUNCTION (fndecl);
kono
parents:
diff changeset
332 return (gimple_body (fndecl) || (fn && fn->cfg && !(fn->curr_properties & PROP_rtl)));
kono
parents:
diff changeset
333 }
kono
parents:
diff changeset
334
kono
parents:
diff changeset
335 /* Return a printable name for symbol DECL. */
kono
parents:
diff changeset
336
kono
parents:
diff changeset
337 const char *
kono
parents:
diff changeset
338 gimple_decl_printable_name (tree decl, int verbosity)
kono
parents:
diff changeset
339 {
kono
parents:
diff changeset
340 if (!DECL_NAME (decl))
kono
parents:
diff changeset
341 return NULL;
kono
parents:
diff changeset
342
kono
parents:
diff changeset
343 if (HAS_DECL_ASSEMBLER_NAME_P (decl) && DECL_ASSEMBLER_NAME_SET_P (decl))
kono
parents:
diff changeset
344 {
kono
parents:
diff changeset
345 int dmgl_opts = DMGL_NO_OPTS;
kono
parents:
diff changeset
346
kono
parents:
diff changeset
347 if (verbosity >= 2)
kono
parents:
diff changeset
348 {
kono
parents:
diff changeset
349 dmgl_opts = DMGL_VERBOSE
kono
parents:
diff changeset
350 | DMGL_ANSI
kono
parents:
diff changeset
351 | DMGL_GNU_V3
kono
parents:
diff changeset
352 | DMGL_RET_POSTFIX;
kono
parents:
diff changeset
353 if (TREE_CODE (decl) == FUNCTION_DECL)
kono
parents:
diff changeset
354 dmgl_opts |= DMGL_PARAMS;
kono
parents:
diff changeset
355 }
kono
parents:
diff changeset
356
kono
parents:
diff changeset
357 const char *mangled_str
kono
parents:
diff changeset
358 = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME_RAW (decl));
kono
parents:
diff changeset
359 const char *str = cplus_demangle_v3 (mangled_str, dmgl_opts);
kono
parents:
diff changeset
360 return str ? str : mangled_str;
kono
parents:
diff changeset
361 }
kono
parents:
diff changeset
362
kono
parents:
diff changeset
363 return IDENTIFIER_POINTER (DECL_NAME (decl));
kono
parents:
diff changeset
364 }
kono
parents:
diff changeset
365
kono
parents:
diff changeset
366
kono
parents:
diff changeset
367 /* Create a new VAR_DECL and copy information from VAR to it. */
kono
parents:
diff changeset
368
kono
parents:
diff changeset
369 tree
kono
parents:
diff changeset
370 copy_var_decl (tree var, tree name, tree type)
kono
parents:
diff changeset
371 {
kono
parents:
diff changeset
372 tree copy = build_decl (DECL_SOURCE_LOCATION (var), VAR_DECL, name, type);
kono
parents:
diff changeset
373
kono
parents:
diff changeset
374 TREE_ADDRESSABLE (copy) = TREE_ADDRESSABLE (var);
kono
parents:
diff changeset
375 TREE_THIS_VOLATILE (copy) = TREE_THIS_VOLATILE (var);
kono
parents:
diff changeset
376 DECL_GIMPLE_REG_P (copy) = DECL_GIMPLE_REG_P (var);
kono
parents:
diff changeset
377 DECL_ARTIFICIAL (copy) = DECL_ARTIFICIAL (var);
kono
parents:
diff changeset
378 DECL_IGNORED_P (copy) = DECL_IGNORED_P (var);
kono
parents:
diff changeset
379 DECL_CONTEXT (copy) = DECL_CONTEXT (var);
kono
parents:
diff changeset
380 TREE_NO_WARNING (copy) = TREE_NO_WARNING (var);
kono
parents:
diff changeset
381 TREE_USED (copy) = 1;
kono
parents:
diff changeset
382 DECL_SEEN_IN_BIND_EXPR_P (copy) = 1;
kono
parents:
diff changeset
383 DECL_ATTRIBUTES (copy) = DECL_ATTRIBUTES (var);
kono
parents:
diff changeset
384 if (DECL_USER_ALIGN (var))
kono
parents:
diff changeset
385 {
kono
parents:
diff changeset
386 SET_DECL_ALIGN (copy, DECL_ALIGN (var));
kono
parents:
diff changeset
387 DECL_USER_ALIGN (copy) = 1;
kono
parents:
diff changeset
388 }
kono
parents:
diff changeset
389
kono
parents:
diff changeset
390 return copy;
kono
parents:
diff changeset
391 }
kono
parents:
diff changeset
392
kono
parents:
diff changeset
393 /* Strip off a legitimate source ending from the input string NAME of
kono
parents:
diff changeset
394 length LEN. Rather than having to know the names used by all of
kono
parents:
diff changeset
395 our front ends, we strip off an ending of a period followed by
kono
parents:
diff changeset
396 up to four characters. (like ".cpp".) */
kono
parents:
diff changeset
397
kono
parents:
diff changeset
398 static inline void
kono
parents:
diff changeset
399 remove_suffix (char *name, int len)
kono
parents:
diff changeset
400 {
kono
parents:
diff changeset
401 int i;
kono
parents:
diff changeset
402
kono
parents:
diff changeset
403 for (i = 2; i < 7 && len > i; i++)
kono
parents:
diff changeset
404 {
kono
parents:
diff changeset
405 if (name[len - i] == '.')
kono
parents:
diff changeset
406 {
kono
parents:
diff changeset
407 name[len - i] = '\0';
kono
parents:
diff changeset
408 break;
kono
parents:
diff changeset
409 }
kono
parents:
diff changeset
410 }
kono
parents:
diff changeset
411 }
kono
parents:
diff changeset
412
kono
parents:
diff changeset
413 /* Create a new temporary name with PREFIX. Return an identifier. */
kono
parents:
diff changeset
414
kono
parents:
diff changeset
415 static GTY(()) unsigned int tmp_var_id_num;
kono
parents:
diff changeset
416
kono
parents:
diff changeset
417 tree
kono
parents:
diff changeset
418 create_tmp_var_name (const char *prefix)
kono
parents:
diff changeset
419 {
kono
parents:
diff changeset
420 char *tmp_name;
kono
parents:
diff changeset
421
kono
parents:
diff changeset
422 if (prefix)
kono
parents:
diff changeset
423 {
kono
parents:
diff changeset
424 char *preftmp = ASTRDUP (prefix);
kono
parents:
diff changeset
425
kono
parents:
diff changeset
426 remove_suffix (preftmp, strlen (preftmp));
kono
parents:
diff changeset
427 clean_symbol_name (preftmp);
kono
parents:
diff changeset
428
kono
parents:
diff changeset
429 prefix = preftmp;
kono
parents:
diff changeset
430 }
kono
parents:
diff changeset
431
kono
parents:
diff changeset
432 ASM_FORMAT_PRIVATE_NAME (tmp_name, prefix ? prefix : "T", tmp_var_id_num++);
kono
parents:
diff changeset
433 return get_identifier (tmp_name);
kono
parents:
diff changeset
434 }
kono
parents:
diff changeset
435
kono
parents:
diff changeset
436 /* Create a new temporary variable declaration of type TYPE.
kono
parents:
diff changeset
437 Do NOT push it into the current binding. */
kono
parents:
diff changeset
438
kono
parents:
diff changeset
439 tree
kono
parents:
diff changeset
440 create_tmp_var_raw (tree type, const char *prefix)
kono
parents:
diff changeset
441 {
kono
parents:
diff changeset
442 tree tmp_var;
kono
parents:
diff changeset
443
kono
parents:
diff changeset
444 tmp_var = build_decl (input_location,
kono
parents:
diff changeset
445 VAR_DECL, prefix ? create_tmp_var_name (prefix) : NULL,
kono
parents:
diff changeset
446 type);
kono
parents:
diff changeset
447
kono
parents:
diff changeset
448 /* The variable was declared by the compiler. */
kono
parents:
diff changeset
449 DECL_ARTIFICIAL (tmp_var) = 1;
kono
parents:
diff changeset
450 /* And we don't want debug info for it. */
kono
parents:
diff changeset
451 DECL_IGNORED_P (tmp_var) = 1;
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
452 /* And we don't want even the fancy names of those printed in
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
453 -fdump-final-insns= dumps. */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
454 DECL_NAMELESS (tmp_var) = 1;
111
kono
parents:
diff changeset
455
kono
parents:
diff changeset
456 /* Make the variable writable. */
kono
parents:
diff changeset
457 TREE_READONLY (tmp_var) = 0;
kono
parents:
diff changeset
458
kono
parents:
diff changeset
459 DECL_EXTERNAL (tmp_var) = 0;
kono
parents:
diff changeset
460 TREE_STATIC (tmp_var) = 0;
kono
parents:
diff changeset
461 TREE_USED (tmp_var) = 1;
kono
parents:
diff changeset
462
kono
parents:
diff changeset
463 return tmp_var;
kono
parents:
diff changeset
464 }
kono
parents:
diff changeset
465
kono
parents:
diff changeset
466 /* Create a new temporary variable declaration of type TYPE. DO push the
kono
parents:
diff changeset
467 variable into the current binding. Further, assume that this is called
kono
parents:
diff changeset
468 only from gimplification or optimization, at which point the creation of
kono
parents:
diff changeset
469 certain types are bugs. */
kono
parents:
diff changeset
470
kono
parents:
diff changeset
471 tree
kono
parents:
diff changeset
472 create_tmp_var (tree type, const char *prefix)
kono
parents:
diff changeset
473 {
kono
parents:
diff changeset
474 tree tmp_var;
kono
parents:
diff changeset
475
kono
parents:
diff changeset
476 /* We don't allow types that are addressable (meaning we can't make copies),
kono
parents:
diff changeset
477 or incomplete. We also used to reject every variable size objects here,
kono
parents:
diff changeset
478 but now support those for which a constant upper bound can be obtained.
kono
parents:
diff changeset
479 The processing for variable sizes is performed in gimple_add_tmp_var,
kono
parents:
diff changeset
480 point at which it really matters and possibly reached via paths not going
kono
parents:
diff changeset
481 through this function, e.g. after direct calls to create_tmp_var_raw. */
kono
parents:
diff changeset
482 gcc_assert (!TREE_ADDRESSABLE (type) && COMPLETE_TYPE_P (type));
kono
parents:
diff changeset
483
kono
parents:
diff changeset
484 tmp_var = create_tmp_var_raw (type, prefix);
kono
parents:
diff changeset
485 gimple_add_tmp_var (tmp_var);
kono
parents:
diff changeset
486 return tmp_var;
kono
parents:
diff changeset
487 }
kono
parents:
diff changeset
488
kono
parents:
diff changeset
489 /* Create a new temporary variable declaration of type TYPE by calling
kono
parents:
diff changeset
490 create_tmp_var and if TYPE is a vector or a complex number, mark the new
kono
parents:
diff changeset
491 temporary as gimple register. */
kono
parents:
diff changeset
492
kono
parents:
diff changeset
493 tree
kono
parents:
diff changeset
494 create_tmp_reg (tree type, const char *prefix)
kono
parents:
diff changeset
495 {
kono
parents:
diff changeset
496 tree tmp;
kono
parents:
diff changeset
497
kono
parents:
diff changeset
498 tmp = create_tmp_var (type, prefix);
kono
parents:
diff changeset
499 if (TREE_CODE (type) == COMPLEX_TYPE
kono
parents:
diff changeset
500 || TREE_CODE (type) == VECTOR_TYPE)
kono
parents:
diff changeset
501 DECL_GIMPLE_REG_P (tmp) = 1;
kono
parents:
diff changeset
502
kono
parents:
diff changeset
503 return tmp;
kono
parents:
diff changeset
504 }
kono
parents:
diff changeset
505
kono
parents:
diff changeset
506 /* Create a new temporary variable declaration of type TYPE by calling
kono
parents:
diff changeset
507 create_tmp_var and if TYPE is a vector or a complex number, mark the new
kono
parents:
diff changeset
508 temporary as gimple register. */
kono
parents:
diff changeset
509
kono
parents:
diff changeset
510 tree
kono
parents:
diff changeset
511 create_tmp_reg_fn (struct function *fn, tree type, const char *prefix)
kono
parents:
diff changeset
512 {
kono
parents:
diff changeset
513 tree tmp;
kono
parents:
diff changeset
514
kono
parents:
diff changeset
515 tmp = create_tmp_var_raw (type, prefix);
kono
parents:
diff changeset
516 gimple_add_tmp_var_fn (fn, tmp);
kono
parents:
diff changeset
517 if (TREE_CODE (type) == COMPLEX_TYPE
kono
parents:
diff changeset
518 || TREE_CODE (type) == VECTOR_TYPE)
kono
parents:
diff changeset
519 DECL_GIMPLE_REG_P (tmp) = 1;
kono
parents:
diff changeset
520
kono
parents:
diff changeset
521 return tmp;
kono
parents:
diff changeset
522 }
kono
parents:
diff changeset
523
kono
parents:
diff changeset
524
kono
parents:
diff changeset
525 /* ----- Expression related ----- */
kono
parents:
diff changeset
526
kono
parents:
diff changeset
527 /* Extract the operands and code for expression EXPR into *SUBCODE_P,
kono
parents:
diff changeset
528 *OP1_P, *OP2_P and *OP3_P respectively. */
kono
parents:
diff changeset
529
kono
parents:
diff changeset
530 void
kono
parents:
diff changeset
531 extract_ops_from_tree (tree expr, enum tree_code *subcode_p, tree *op1_p,
kono
parents:
diff changeset
532 tree *op2_p, tree *op3_p)
kono
parents:
diff changeset
533 {
kono
parents:
diff changeset
534 *subcode_p = TREE_CODE (expr);
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
535 switch (get_gimple_rhs_class (*subcode_p))
111
kono
parents:
diff changeset
536 {
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
537 case GIMPLE_TERNARY_RHS:
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
538 {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
539 *op1_p = TREE_OPERAND (expr, 0);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
540 *op2_p = TREE_OPERAND (expr, 1);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
541 *op3_p = TREE_OPERAND (expr, 2);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
542 break;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
543 }
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
544 case GIMPLE_BINARY_RHS:
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
545 {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
546 *op1_p = TREE_OPERAND (expr, 0);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
547 *op2_p = TREE_OPERAND (expr, 1);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
548 *op3_p = NULL_TREE;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
549 break;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
550 }
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
551 case GIMPLE_UNARY_RHS:
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
552 {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
553 *op1_p = TREE_OPERAND (expr, 0);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
554 *op2_p = NULL_TREE;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
555 *op3_p = NULL_TREE;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
556 break;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
557 }
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
558 case GIMPLE_SINGLE_RHS:
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
559 {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
560 *op1_p = expr;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
561 *op2_p = NULL_TREE;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
562 *op3_p = NULL_TREE;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
563 break;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
564 }
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
565 default:
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
566 gcc_unreachable ();
111
kono
parents:
diff changeset
567 }
kono
parents:
diff changeset
568 }
kono
parents:
diff changeset
569
kono
parents:
diff changeset
570 /* Extract operands for a GIMPLE_COND statement out of COND_EXPR tree COND. */
kono
parents:
diff changeset
571
kono
parents:
diff changeset
572 void
kono
parents:
diff changeset
573 gimple_cond_get_ops_from_tree (tree cond, enum tree_code *code_p,
kono
parents:
diff changeset
574 tree *lhs_p, tree *rhs_p)
kono
parents:
diff changeset
575 {
kono
parents:
diff changeset
576 gcc_assert (COMPARISON_CLASS_P (cond)
kono
parents:
diff changeset
577 || TREE_CODE (cond) == TRUTH_NOT_EXPR
kono
parents:
diff changeset
578 || is_gimple_min_invariant (cond)
kono
parents:
diff changeset
579 || SSA_VAR_P (cond));
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
580 gcc_checking_assert (!tree_could_throw_p (cond));
111
kono
parents:
diff changeset
581
kono
parents:
diff changeset
582 extract_ops_from_tree (cond, code_p, lhs_p, rhs_p);
kono
parents:
diff changeset
583
kono
parents:
diff changeset
584 /* Canonicalize conditionals of the form 'if (!VAL)'. */
kono
parents:
diff changeset
585 if (*code_p == TRUTH_NOT_EXPR)
kono
parents:
diff changeset
586 {
kono
parents:
diff changeset
587 *code_p = EQ_EXPR;
kono
parents:
diff changeset
588 gcc_assert (*lhs_p && *rhs_p == NULL_TREE);
kono
parents:
diff changeset
589 *rhs_p = build_zero_cst (TREE_TYPE (*lhs_p));
kono
parents:
diff changeset
590 }
kono
parents:
diff changeset
591 /* Canonicalize conditionals of the form 'if (VAL)' */
kono
parents:
diff changeset
592 else if (TREE_CODE_CLASS (*code_p) != tcc_comparison)
kono
parents:
diff changeset
593 {
kono
parents:
diff changeset
594 *code_p = NE_EXPR;
kono
parents:
diff changeset
595 gcc_assert (*lhs_p && *rhs_p == NULL_TREE);
kono
parents:
diff changeset
596 *rhs_p = build_zero_cst (TREE_TYPE (*lhs_p));
kono
parents:
diff changeset
597 }
kono
parents:
diff changeset
598 }
kono
parents:
diff changeset
599
kono
parents:
diff changeset
600 /* Return true if T is a valid LHS for a GIMPLE assignment expression. */
kono
parents:
diff changeset
601
kono
parents:
diff changeset
602 bool
kono
parents:
diff changeset
603 is_gimple_lvalue (tree t)
kono
parents:
diff changeset
604 {
kono
parents:
diff changeset
605 return (is_gimple_addressable (t)
kono
parents:
diff changeset
606 || TREE_CODE (t) == WITH_SIZE_EXPR
kono
parents:
diff changeset
607 /* These are complex lvalues, but don't have addresses, so they
kono
parents:
diff changeset
608 go here. */
kono
parents:
diff changeset
609 || TREE_CODE (t) == BIT_FIELD_REF);
kono
parents:
diff changeset
610 }
kono
parents:
diff changeset
611
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
612 /* Helper for is_gimple_condexpr and is_gimple_condexpr_for_cond. */
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
613
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
614 static bool
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
615 is_gimple_condexpr_1 (tree t, bool allow_traps)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
616 {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
617 return (is_gimple_val (t) || (COMPARISON_CLASS_P (t)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
618 && (allow_traps || !tree_could_throw_p (t))
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
619 && is_gimple_val (TREE_OPERAND (t, 0))
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
620 && is_gimple_val (TREE_OPERAND (t, 1))));
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
621 }
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
622
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
623 /* Return true if T is a GIMPLE condition. */
111
kono
parents:
diff changeset
624
kono
parents:
diff changeset
625 bool
kono
parents:
diff changeset
626 is_gimple_condexpr (tree t)
kono
parents:
diff changeset
627 {
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
628 return is_gimple_condexpr_1 (t, true);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
629 }
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
630
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
631 /* Like is_gimple_condexpr, but does not allow T to trap. */
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
632
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
633 bool
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
634 is_gimple_condexpr_for_cond (tree t)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
635 {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
636 return is_gimple_condexpr_1 (t, false);
111
kono
parents:
diff changeset
637 }
kono
parents:
diff changeset
638
kono
parents:
diff changeset
639 /* Return true if T is a gimple address. */
kono
parents:
diff changeset
640
kono
parents:
diff changeset
641 bool
kono
parents:
diff changeset
642 is_gimple_address (const_tree t)
kono
parents:
diff changeset
643 {
kono
parents:
diff changeset
644 tree op;
kono
parents:
diff changeset
645
kono
parents:
diff changeset
646 if (TREE_CODE (t) != ADDR_EXPR)
kono
parents:
diff changeset
647 return false;
kono
parents:
diff changeset
648
kono
parents:
diff changeset
649 op = TREE_OPERAND (t, 0);
kono
parents:
diff changeset
650 while (handled_component_p (op))
kono
parents:
diff changeset
651 {
kono
parents:
diff changeset
652 if ((TREE_CODE (op) == ARRAY_REF
kono
parents:
diff changeset
653 || TREE_CODE (op) == ARRAY_RANGE_REF)
kono
parents:
diff changeset
654 && !is_gimple_val (TREE_OPERAND (op, 1)))
kono
parents:
diff changeset
655 return false;
kono
parents:
diff changeset
656
kono
parents:
diff changeset
657 op = TREE_OPERAND (op, 0);
kono
parents:
diff changeset
658 }
kono
parents:
diff changeset
659
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
660 if (CONSTANT_CLASS_P (op)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
661 || TREE_CODE (op) == TARGET_MEM_REF
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
662 || TREE_CODE (op) == MEM_REF)
111
kono
parents:
diff changeset
663 return true;
kono
parents:
diff changeset
664
kono
parents:
diff changeset
665 switch (TREE_CODE (op))
kono
parents:
diff changeset
666 {
kono
parents:
diff changeset
667 case PARM_DECL:
kono
parents:
diff changeset
668 case RESULT_DECL:
kono
parents:
diff changeset
669 case LABEL_DECL:
kono
parents:
diff changeset
670 case FUNCTION_DECL:
kono
parents:
diff changeset
671 case VAR_DECL:
kono
parents:
diff changeset
672 case CONST_DECL:
kono
parents:
diff changeset
673 return true;
kono
parents:
diff changeset
674
kono
parents:
diff changeset
675 default:
kono
parents:
diff changeset
676 return false;
kono
parents:
diff changeset
677 }
kono
parents:
diff changeset
678 }
kono
parents:
diff changeset
679
kono
parents:
diff changeset
680 /* Return true if T is a gimple invariant address. */
kono
parents:
diff changeset
681
kono
parents:
diff changeset
682 bool
kono
parents:
diff changeset
683 is_gimple_invariant_address (const_tree t)
kono
parents:
diff changeset
684 {
kono
parents:
diff changeset
685 const_tree op;
kono
parents:
diff changeset
686
kono
parents:
diff changeset
687 if (TREE_CODE (t) != ADDR_EXPR)
kono
parents:
diff changeset
688 return false;
kono
parents:
diff changeset
689
kono
parents:
diff changeset
690 op = strip_invariant_refs (TREE_OPERAND (t, 0));
kono
parents:
diff changeset
691 if (!op)
kono
parents:
diff changeset
692 return false;
kono
parents:
diff changeset
693
kono
parents:
diff changeset
694 if (TREE_CODE (op) == MEM_REF)
kono
parents:
diff changeset
695 {
kono
parents:
diff changeset
696 const_tree op0 = TREE_OPERAND (op, 0);
kono
parents:
diff changeset
697 return (TREE_CODE (op0) == ADDR_EXPR
kono
parents:
diff changeset
698 && (CONSTANT_CLASS_P (TREE_OPERAND (op0, 0))
kono
parents:
diff changeset
699 || decl_address_invariant_p (TREE_OPERAND (op0, 0))));
kono
parents:
diff changeset
700 }
kono
parents:
diff changeset
701
kono
parents:
diff changeset
702 return CONSTANT_CLASS_P (op) || decl_address_invariant_p (op);
kono
parents:
diff changeset
703 }
kono
parents:
diff changeset
704
kono
parents:
diff changeset
705 /* Return true if T is a gimple invariant address at IPA level
kono
parents:
diff changeset
706 (so addresses of variables on stack are not allowed). */
kono
parents:
diff changeset
707
kono
parents:
diff changeset
708 bool
kono
parents:
diff changeset
709 is_gimple_ip_invariant_address (const_tree t)
kono
parents:
diff changeset
710 {
kono
parents:
diff changeset
711 const_tree op;
kono
parents:
diff changeset
712
kono
parents:
diff changeset
713 if (TREE_CODE (t) != ADDR_EXPR)
kono
parents:
diff changeset
714 return false;
kono
parents:
diff changeset
715
kono
parents:
diff changeset
716 op = strip_invariant_refs (TREE_OPERAND (t, 0));
kono
parents:
diff changeset
717 if (!op)
kono
parents:
diff changeset
718 return false;
kono
parents:
diff changeset
719
kono
parents:
diff changeset
720 if (TREE_CODE (op) == MEM_REF)
kono
parents:
diff changeset
721 {
kono
parents:
diff changeset
722 const_tree op0 = TREE_OPERAND (op, 0);
kono
parents:
diff changeset
723 return (TREE_CODE (op0) == ADDR_EXPR
kono
parents:
diff changeset
724 && (CONSTANT_CLASS_P (TREE_OPERAND (op0, 0))
kono
parents:
diff changeset
725 || decl_address_ip_invariant_p (TREE_OPERAND (op0, 0))));
kono
parents:
diff changeset
726 }
kono
parents:
diff changeset
727
kono
parents:
diff changeset
728 return CONSTANT_CLASS_P (op) || decl_address_ip_invariant_p (op);
kono
parents:
diff changeset
729 }
kono
parents:
diff changeset
730
kono
parents:
diff changeset
731 /* Return true if T is a GIMPLE minimal invariant. It's a restricted
kono
parents:
diff changeset
732 form of function invariant. */
kono
parents:
diff changeset
733
kono
parents:
diff changeset
734 bool
kono
parents:
diff changeset
735 is_gimple_min_invariant (const_tree t)
kono
parents:
diff changeset
736 {
kono
parents:
diff changeset
737 if (TREE_CODE (t) == ADDR_EXPR)
kono
parents:
diff changeset
738 return is_gimple_invariant_address (t);
kono
parents:
diff changeset
739
kono
parents:
diff changeset
740 return is_gimple_constant (t);
kono
parents:
diff changeset
741 }
kono
parents:
diff changeset
742
kono
parents:
diff changeset
743 /* Return true if T is a GIMPLE interprocedural invariant. It's a restricted
kono
parents:
diff changeset
744 form of gimple minimal invariant. */
kono
parents:
diff changeset
745
kono
parents:
diff changeset
746 bool
kono
parents:
diff changeset
747 is_gimple_ip_invariant (const_tree t)
kono
parents:
diff changeset
748 {
kono
parents:
diff changeset
749 if (TREE_CODE (t) == ADDR_EXPR)
kono
parents:
diff changeset
750 return is_gimple_ip_invariant_address (t);
kono
parents:
diff changeset
751
kono
parents:
diff changeset
752 return is_gimple_constant (t);
kono
parents:
diff changeset
753 }
kono
parents:
diff changeset
754
kono
parents:
diff changeset
755 /* Return true if T is a non-aggregate register variable. */
kono
parents:
diff changeset
756
kono
parents:
diff changeset
757 bool
kono
parents:
diff changeset
758 is_gimple_reg (tree t)
kono
parents:
diff changeset
759 {
kono
parents:
diff changeset
760 if (virtual_operand_p (t))
kono
parents:
diff changeset
761 return false;
kono
parents:
diff changeset
762
kono
parents:
diff changeset
763 if (TREE_CODE (t) == SSA_NAME)
kono
parents:
diff changeset
764 return true;
kono
parents:
diff changeset
765
kono
parents:
diff changeset
766 if (!is_gimple_variable (t))
kono
parents:
diff changeset
767 return false;
kono
parents:
diff changeset
768
kono
parents:
diff changeset
769 if (!is_gimple_reg_type (TREE_TYPE (t)))
kono
parents:
diff changeset
770 return false;
kono
parents:
diff changeset
771
kono
parents:
diff changeset
772 /* A volatile decl is not acceptable because we can't reuse it as
kono
parents:
diff changeset
773 needed. We need to copy it into a temp first. */
kono
parents:
diff changeset
774 if (TREE_THIS_VOLATILE (t))
kono
parents:
diff changeset
775 return false;
kono
parents:
diff changeset
776
kono
parents:
diff changeset
777 /* We define "registers" as things that can be renamed as needed,
kono
parents:
diff changeset
778 which with our infrastructure does not apply to memory. */
kono
parents:
diff changeset
779 if (needs_to_live_in_memory (t))
kono
parents:
diff changeset
780 return false;
kono
parents:
diff changeset
781
kono
parents:
diff changeset
782 /* Hard register variables are an interesting case. For those that
kono
parents:
diff changeset
783 are call-clobbered, we don't know where all the calls are, since
kono
parents:
diff changeset
784 we don't (want to) take into account which operations will turn
kono
parents:
diff changeset
785 into libcalls at the rtl level. For those that are call-saved,
kono
parents:
diff changeset
786 we don't currently model the fact that calls may in fact change
kono
parents:
diff changeset
787 global hard registers, nor do we examine ASM_CLOBBERS at the tree
kono
parents:
diff changeset
788 level, and so miss variable changes that might imply. All around,
kono
parents:
diff changeset
789 it seems safest to not do too much optimization with these at the
kono
parents:
diff changeset
790 tree level at all. We'll have to rely on the rtl optimizers to
kono
parents:
diff changeset
791 clean this up, as there we've got all the appropriate bits exposed. */
kono
parents:
diff changeset
792 if (TREE_CODE (t) == VAR_DECL && DECL_HARD_REGISTER (t))
kono
parents:
diff changeset
793 return false;
kono
parents:
diff changeset
794
kono
parents:
diff changeset
795 /* Complex and vector values must have been put into SSA-like form.
kono
parents:
diff changeset
796 That is, no assignments to the individual components. */
kono
parents:
diff changeset
797 if (TREE_CODE (TREE_TYPE (t)) == COMPLEX_TYPE
kono
parents:
diff changeset
798 || TREE_CODE (TREE_TYPE (t)) == VECTOR_TYPE)
kono
parents:
diff changeset
799 return DECL_GIMPLE_REG_P (t);
kono
parents:
diff changeset
800
kono
parents:
diff changeset
801 return true;
kono
parents:
diff changeset
802 }
kono
parents:
diff changeset
803
kono
parents:
diff changeset
804
kono
parents:
diff changeset
805 /* Return true if T is a GIMPLE rvalue, i.e. an identifier or a constant. */
kono
parents:
diff changeset
806
kono
parents:
diff changeset
807 bool
kono
parents:
diff changeset
808 is_gimple_val (tree t)
kono
parents:
diff changeset
809 {
kono
parents:
diff changeset
810 /* Make loads from volatiles and memory vars explicit. */
kono
parents:
diff changeset
811 if (is_gimple_variable (t)
kono
parents:
diff changeset
812 && is_gimple_reg_type (TREE_TYPE (t))
kono
parents:
diff changeset
813 && !is_gimple_reg (t))
kono
parents:
diff changeset
814 return false;
kono
parents:
diff changeset
815
kono
parents:
diff changeset
816 return (is_gimple_variable (t) || is_gimple_min_invariant (t));
kono
parents:
diff changeset
817 }
kono
parents:
diff changeset
818
kono
parents:
diff changeset
819 /* Similarly, but accept hard registers as inputs to asm statements. */
kono
parents:
diff changeset
820
kono
parents:
diff changeset
821 bool
kono
parents:
diff changeset
822 is_gimple_asm_val (tree t)
kono
parents:
diff changeset
823 {
kono
parents:
diff changeset
824 if (TREE_CODE (t) == VAR_DECL && DECL_HARD_REGISTER (t))
kono
parents:
diff changeset
825 return true;
kono
parents:
diff changeset
826
kono
parents:
diff changeset
827 return is_gimple_val (t);
kono
parents:
diff changeset
828 }
kono
parents:
diff changeset
829
kono
parents:
diff changeset
830 /* Return true if T is a GIMPLE minimal lvalue. */
kono
parents:
diff changeset
831
kono
parents:
diff changeset
832 bool
kono
parents:
diff changeset
833 is_gimple_min_lval (tree t)
kono
parents:
diff changeset
834 {
kono
parents:
diff changeset
835 if (!(t = CONST_CAST_TREE (strip_invariant_refs (t))))
kono
parents:
diff changeset
836 return false;
kono
parents:
diff changeset
837 return (is_gimple_id (t) || TREE_CODE (t) == MEM_REF);
kono
parents:
diff changeset
838 }
kono
parents:
diff changeset
839
kono
parents:
diff changeset
840 /* Return true if T is a valid function operand of a CALL_EXPR. */
kono
parents:
diff changeset
841
kono
parents:
diff changeset
842 bool
kono
parents:
diff changeset
843 is_gimple_call_addr (tree t)
kono
parents:
diff changeset
844 {
kono
parents:
diff changeset
845 return (TREE_CODE (t) == OBJ_TYPE_REF || is_gimple_val (t));
kono
parents:
diff changeset
846 }
kono
parents:
diff changeset
847
kono
parents:
diff changeset
848 /* Return true if T is a valid address operand of a MEM_REF. */
kono
parents:
diff changeset
849
kono
parents:
diff changeset
850 bool
kono
parents:
diff changeset
851 is_gimple_mem_ref_addr (tree t)
kono
parents:
diff changeset
852 {
kono
parents:
diff changeset
853 return (is_gimple_reg (t)
kono
parents:
diff changeset
854 || TREE_CODE (t) == INTEGER_CST
kono
parents:
diff changeset
855 || (TREE_CODE (t) == ADDR_EXPR
kono
parents:
diff changeset
856 && (CONSTANT_CLASS_P (TREE_OPERAND (t, 0))
kono
parents:
diff changeset
857 || decl_address_invariant_p (TREE_OPERAND (t, 0)))));
kono
parents:
diff changeset
858 }
kono
parents:
diff changeset
859
kono
parents:
diff changeset
860 /* Hold trees marked addressable during expand. */
kono
parents:
diff changeset
861
kono
parents:
diff changeset
862 static hash_set<tree> *mark_addressable_queue;
kono
parents:
diff changeset
863
kono
parents:
diff changeset
864 /* Mark X as addressable or queue it up if called during expand. We
kono
parents:
diff changeset
865 don't want to apply it immediately during expand because decls are
kono
parents:
diff changeset
866 made addressable at that point due to RTL-only concerns, such as
kono
parents:
diff changeset
867 uses of memcpy for block moves, and TREE_ADDRESSABLE changes
kono
parents:
diff changeset
868 is_gimple_reg, which might make it seem like a variable that used
kono
parents:
diff changeset
869 to be a gimple_reg shouldn't have been an SSA name. So we queue up
kono
parents:
diff changeset
870 this flag setting and only apply it when we're done with GIMPLE and
kono
parents:
diff changeset
871 only RTL issues matter. */
kono
parents:
diff changeset
872
kono
parents:
diff changeset
873 static void
kono
parents:
diff changeset
874 mark_addressable_1 (tree x)
kono
parents:
diff changeset
875 {
kono
parents:
diff changeset
876 if (!currently_expanding_to_rtl)
kono
parents:
diff changeset
877 {
kono
parents:
diff changeset
878 TREE_ADDRESSABLE (x) = 1;
kono
parents:
diff changeset
879 return;
kono
parents:
diff changeset
880 }
kono
parents:
diff changeset
881
kono
parents:
diff changeset
882 if (!mark_addressable_queue)
kono
parents:
diff changeset
883 mark_addressable_queue = new hash_set<tree>();
kono
parents:
diff changeset
884 mark_addressable_queue->add (x);
kono
parents:
diff changeset
885 }
kono
parents:
diff changeset
886
kono
parents:
diff changeset
887 /* Adaptor for mark_addressable_1 for use in hash_set traversal. */
kono
parents:
diff changeset
888
kono
parents:
diff changeset
889 bool
kono
parents:
diff changeset
890 mark_addressable_2 (tree const &x, void * ATTRIBUTE_UNUSED = NULL)
kono
parents:
diff changeset
891 {
kono
parents:
diff changeset
892 mark_addressable_1 (x);
kono
parents:
diff changeset
893 return false;
kono
parents:
diff changeset
894 }
kono
parents:
diff changeset
895
kono
parents:
diff changeset
896 /* Mark all queued trees as addressable, and empty the queue. To be
kono
parents:
diff changeset
897 called right after clearing CURRENTLY_EXPANDING_TO_RTL. */
kono
parents:
diff changeset
898
kono
parents:
diff changeset
899 void
kono
parents:
diff changeset
900 flush_mark_addressable_queue ()
kono
parents:
diff changeset
901 {
kono
parents:
diff changeset
902 gcc_assert (!currently_expanding_to_rtl);
kono
parents:
diff changeset
903 if (mark_addressable_queue)
kono
parents:
diff changeset
904 {
kono
parents:
diff changeset
905 mark_addressable_queue->traverse<void*, mark_addressable_2> (NULL);
kono
parents:
diff changeset
906 delete mark_addressable_queue;
kono
parents:
diff changeset
907 mark_addressable_queue = NULL;
kono
parents:
diff changeset
908 }
kono
parents:
diff changeset
909 }
kono
parents:
diff changeset
910
kono
parents:
diff changeset
911 /* Mark X addressable. Unlike the langhook we expect X to be in gimple
kono
parents:
diff changeset
912 form and we don't do any syntax checking. */
kono
parents:
diff changeset
913
kono
parents:
diff changeset
914 void
kono
parents:
diff changeset
915 mark_addressable (tree x)
kono
parents:
diff changeset
916 {
kono
parents:
diff changeset
917 while (handled_component_p (x))
kono
parents:
diff changeset
918 x = TREE_OPERAND (x, 0);
kono
parents:
diff changeset
919 if (TREE_CODE (x) == MEM_REF
kono
parents:
diff changeset
920 && TREE_CODE (TREE_OPERAND (x, 0)) == ADDR_EXPR)
kono
parents:
diff changeset
921 x = TREE_OPERAND (TREE_OPERAND (x, 0), 0);
kono
parents:
diff changeset
922 if (!VAR_P (x)
kono
parents:
diff changeset
923 && TREE_CODE (x) != PARM_DECL
kono
parents:
diff changeset
924 && TREE_CODE (x) != RESULT_DECL)
kono
parents:
diff changeset
925 return;
kono
parents:
diff changeset
926 mark_addressable_1 (x);
kono
parents:
diff changeset
927
kono
parents:
diff changeset
928 /* Also mark the artificial SSA_NAME that points to the partition of X. */
kono
parents:
diff changeset
929 if (TREE_CODE (x) == VAR_DECL
kono
parents:
diff changeset
930 && !DECL_EXTERNAL (x)
kono
parents:
diff changeset
931 && !TREE_STATIC (x)
kono
parents:
diff changeset
932 && cfun->gimple_df != NULL
kono
parents:
diff changeset
933 && cfun->gimple_df->decls_to_pointers != NULL)
kono
parents:
diff changeset
934 {
kono
parents:
diff changeset
935 tree *namep = cfun->gimple_df->decls_to_pointers->get (x);
kono
parents:
diff changeset
936 if (namep)
kono
parents:
diff changeset
937 mark_addressable_1 (*namep);
kono
parents:
diff changeset
938 }
kono
parents:
diff changeset
939 }
kono
parents:
diff changeset
940
kono
parents:
diff changeset
941 /* Returns true iff T is a valid RHS for an assignment to a renamed
kono
parents:
diff changeset
942 user -- or front-end generated artificial -- variable. */
kono
parents:
diff changeset
943
kono
parents:
diff changeset
944 bool
kono
parents:
diff changeset
945 is_gimple_reg_rhs (tree t)
kono
parents:
diff changeset
946 {
kono
parents:
diff changeset
947 return get_gimple_rhs_class (TREE_CODE (t)) != GIMPLE_INVALID_RHS;
kono
parents:
diff changeset
948 }
kono
parents:
diff changeset
949
kono
parents:
diff changeset
950 #include "gt-gimple-expr.h"