Bug Summary

File:build/gcc/var-tracking.c
Warning:line 6937, column 6
Value stored to 'src' is never read

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-unknown-linux-gnu -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name var-tracking.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -analyzer-config-compatibility-mode=true -mrelocation-model static -mframe-pointer=none -fmath-errno -fno-rounding-math -mconstructor-aliases -munwind-tables -target-cpu x86-64 -fno-split-dwarf-inlining -debugger-tuning=gdb -resource-dir /usr/lib64/clang/11.0.0 -D IN_GCC -D HAVE_CONFIG_H -I . -I . -I /home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc -I /home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/. -I /home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/../include -I /home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/../libcpp/include -I /home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/../libcody -I /home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/../libdecnumber -I /home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/../libdecnumber/bid -I ../libdecnumber -I /home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/../libbacktrace -internal-isystem /usr/bin/../lib64/gcc/x86_64-suse-linux/10/../../../../include/c++/10 -internal-isystem /usr/bin/../lib64/gcc/x86_64-suse-linux/10/../../../../include/c++/10/x86_64-suse-linux -internal-isystem /usr/bin/../lib64/gcc/x86_64-suse-linux/10/../../../../include/c++/10/backward -internal-isystem /usr/local/include -internal-isystem /usr/lib64/clang/11.0.0/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-narrowing -Wwrite-strings -Wno-error=format-diag -Wno-long-long -Wno-variadic-macros -Wno-overlength-strings -fdeprecated-macro -fdebug-compilation-dir /home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/objdir/gcc -ferror-limit 19 -fno-rtti -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -analyzer-output=plist-html -analyzer-config silence-checkers=core.NullDereference -faddrsig -o /home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/objdir/clang-static-analyzer/2021-01-16-135054-17580-1/report-LtUefb.plist -x c++ /home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c
1/* Variable tracking routines for the GNU compiler.
2 Copyright (C) 2002-2021 Free Software Foundation, Inc.
3
4 This file is part of GCC.
5
6 GCC is free software; you can redistribute it and/or modify it
7 under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3, or (at your option)
9 any later version.
10
11 GCC is distributed in the hope that it will be useful, but WITHOUT
12 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
14 License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with GCC; see the file COPYING3. If not see
18 <http://www.gnu.org/licenses/>. */
19
20/* This file contains the variable tracking pass. It computes where
21 variables are located (which registers or where in memory) at each position
22 in instruction stream and emits notes describing the locations.
23 Debug information (DWARF2 location lists) is finally generated from
24 these notes.
25 With this debug information, it is possible to show variables
26 even when debugging optimized code.
27
28 How does the variable tracking pass work?
29
30 First, it scans RTL code for uses, stores and clobbers (register/memory
31 references in instructions), for call insns and for stack adjustments
32 separately for each basic block and saves them to an array of micro
33 operations.
34 The micro operations of one instruction are ordered so that
35 pre-modifying stack adjustment < use < use with no var < call insn <
36 < clobber < set < post-modifying stack adjustment
37
38 Then, a forward dataflow analysis is performed to find out how locations
39 of variables change through code and to propagate the variable locations
40 along control flow graph.
41 The IN set for basic block BB is computed as a union of OUT sets of BB's
42 predecessors, the OUT set for BB is copied from the IN set for BB and
43 is changed according to micro operations in BB.
44
45 The IN and OUT sets for basic blocks consist of a current stack adjustment
46 (used for adjusting offset of variables addressed using stack pointer),
47 the table of structures describing the locations of parts of a variable
48 and for each physical register a linked list for each physical register.
49 The linked list is a list of variable parts stored in the register,
50 i.e. it is a list of triplets (reg, decl, offset) where decl is
51 REG_EXPR (reg) and offset is REG_OFFSET (reg). The linked list is used for
52 effective deleting appropriate variable parts when we set or clobber the
53 register.
54
55 There may be more than one variable part in a register. The linked lists
56 should be pretty short so it is a good data structure here.
57 For example in the following code, register allocator may assign same
58 register to variables A and B, and both of them are stored in the same
59 register in CODE:
60
61 if (cond)
62 set A;
63 else
64 set B;
65 CODE;
66 if (cond)
67 use A;
68 else
69 use B;
70
71 Finally, the NOTE_INSN_VAR_LOCATION notes describing the variable locations
72 are emitted to appropriate positions in RTL code. Each such a note describes
73 the location of one variable at the point in instruction stream where the
74 note is. There is no need to emit a note for each variable before each
75 instruction, we only emit these notes where the location of variable changes
76 (this means that we also emit notes for changes between the OUT set of the
77 previous block and the IN set of the current block).
78
79 The notes consist of two parts:
80 1. the declaration (from REG_EXPR or MEM_EXPR)
81 2. the location of a variable - it is either a simple register/memory
82 reference (for simple variables, for example int),
83 or a parallel of register/memory references (for a large variables
84 which consist of several parts, for example long long).
85
86*/
87
88#include "config.h"
89#include "system.h"
90#include "coretypes.h"
91#include "backend.h"
92#include "target.h"
93#include "rtl.h"
94#include "tree.h"
95#include "cfghooks.h"
96#include "alloc-pool.h"
97#include "tree-pass.h"
98#include "memmodel.h"
99#include "tm_p.h"
100#include "insn-config.h"
101#include "regs.h"
102#include "emit-rtl.h"
103#include "recog.h"
104#include "diagnostic.h"
105#include "varasm.h"
106#include "stor-layout.h"
107#include "cfgrtl.h"
108#include "cfganal.h"
109#include "reload.h"
110#include "calls.h"
111#include "tree-dfa.h"
112#include "tree-ssa.h"
113#include "cselib.h"
114#include "tree-pretty-print.h"
115#include "rtl-iter.h"
116#include "fibonacci_heap.h"
117#include "print-rtl.h"
118#include "function-abi.h"
119
120typedef fibonacci_heap <long, basic_block_def> bb_heap_t;
121
122/* var-tracking.c assumes that tree code with the same value as VALUE rtx code
123 has no chance to appear in REG_EXPR/MEM_EXPRs and isn't a decl.
124 Currently the value is the same as IDENTIFIER_NODE, which has such
125 a property. If this compile time assertion ever fails, make sure that
126 the new tree code that equals (int) VALUE has the same property. */
127extern char check_value_val[(int) VALUE == (int) IDENTIFIER_NODE ? 1 : -1];
128
129/* Type of micro operation. */
130enum micro_operation_type
131{
132 MO_USE, /* Use location (REG or MEM). */
133 MO_USE_NO_VAR,/* Use location which is not associated with a variable
134 or the variable is not trackable. */
135 MO_VAL_USE, /* Use location which is associated with a value. */
136 MO_VAL_LOC, /* Use location which appears in a debug insn. */
137 MO_VAL_SET, /* Set location associated with a value. */
138 MO_SET, /* Set location. */
139 MO_COPY, /* Copy the same portion of a variable from one
140 location to another. */
141 MO_CLOBBER, /* Clobber location. */
142 MO_CALL, /* Call insn. */
143 MO_ADJUST /* Adjust stack pointer. */
144
145};
146
147static const char * const ATTRIBUTE_UNUSED__attribute__ ((__unused__))
148micro_operation_type_name[] = {
149 "MO_USE",
150 "MO_USE_NO_VAR",
151 "MO_VAL_USE",
152 "MO_VAL_LOC",
153 "MO_VAL_SET",
154 "MO_SET",
155 "MO_COPY",
156 "MO_CLOBBER",
157 "MO_CALL",
158 "MO_ADJUST"
159};
160
161/* Where shall the note be emitted? BEFORE or AFTER the instruction.
162 Notes emitted as AFTER_CALL are to take effect during the call,
163 rather than after the call. */
164enum emit_note_where
165{
166 EMIT_NOTE_BEFORE_INSN,
167 EMIT_NOTE_AFTER_INSN,
168 EMIT_NOTE_AFTER_CALL_INSN
169};
170
171/* Structure holding information about micro operation. */
172struct micro_operation
173{
174 /* Type of micro operation. */
175 enum micro_operation_type type;
176
177 /* The instruction which the micro operation is in, for MO_USE,
178 MO_USE_NO_VAR, MO_CALL and MO_ADJUST, or the subsequent
179 instruction or note in the original flow (before any var-tracking
180 notes are inserted, to simplify emission of notes), for MO_SET
181 and MO_CLOBBER. */
182 rtx_insn *insn;
183
184 union {
185 /* Location. For MO_SET and MO_COPY, this is the SET that
186 performs the assignment, if known, otherwise it is the target
187 of the assignment. For MO_VAL_USE and MO_VAL_SET, it is a
188 CONCAT of the VALUE and the LOC associated with it. For
189 MO_VAL_LOC, it is a CONCAT of the VALUE and the VAR_LOCATION
190 associated with it. */
191 rtx loc;
192
193 /* Stack adjustment. */
194 HOST_WIDE_INTlong adjust;
195 } u;
196};
197
198
199/* A declaration of a variable, or an RTL value being handled like a
200 declaration. */
201typedef void *decl_or_value;
202
203/* Return true if a decl_or_value DV is a DECL or NULL. */
204static inline bool
205dv_is_decl_p (decl_or_value dv)
206{
207 return !dv || (int) TREE_CODE ((tree) dv)((enum tree_code) ((tree) dv)->base.code) != (int) VALUE;
208}
209
210/* Return true if a decl_or_value is a VALUE rtl. */
211static inline bool
212dv_is_value_p (decl_or_value dv)
213{
214 return dv && !dv_is_decl_p (dv);
215}
216
217/* Return the decl in the decl_or_value. */
218static inline tree
219dv_as_decl (decl_or_value dv)
220{
221 gcc_checking_assert (dv_is_decl_p (dv))((void)(!(dv_is_decl_p (dv)) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 221, __FUNCTION__), 0 : 0))
;
222 return (tree) dv;
223}
224
225/* Return the value in the decl_or_value. */
226static inline rtx
227dv_as_value (decl_or_value dv)
228{
229 gcc_checking_assert (dv_is_value_p (dv))((void)(!(dv_is_value_p (dv)) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 229, __FUNCTION__), 0 : 0))
;
230 return (rtx)dv;
231}
232
233/* Return the opaque pointer in the decl_or_value. */
234static inline void *
235dv_as_opaque (decl_or_value dv)
236{
237 return dv;
238}
239
240
241/* Description of location of a part of a variable. The content of a physical
242 register is described by a chain of these structures.
243 The chains are pretty short (usually 1 or 2 elements) and thus
244 chain is the best data structure. */
245struct attrs
246{
247 /* Pointer to next member of the list. */
248 attrs *next;
249
250 /* The rtx of register. */
251 rtx loc;
252
253 /* The declaration corresponding to LOC. */
254 decl_or_value dv;
255
256 /* Offset from start of DECL. */
257 HOST_WIDE_INTlong offset;
258};
259
260/* Structure for chaining the locations. */
261struct location_chain
262{
263 /* Next element in the chain. */
264 location_chain *next;
265
266 /* The location (REG, MEM or VALUE). */
267 rtx loc;
268
269 /* The "value" stored in this location. */
270 rtx set_src;
271
272 /* Initialized? */
273 enum var_init_status init;
274};
275
276/* A vector of loc_exp_dep holds the active dependencies of a one-part
277 DV on VALUEs, i.e., the VALUEs expanded so as to form the current
278 location of DV. Each entry is also part of VALUE' s linked-list of
279 backlinks back to DV. */
280struct loc_exp_dep
281{
282 /* The dependent DV. */
283 decl_or_value dv;
284 /* The dependency VALUE or DECL_DEBUG. */
285 rtx value;
286 /* The next entry in VALUE's backlinks list. */
287 struct loc_exp_dep *next;
288 /* A pointer to the pointer to this entry (head or prev's next) in
289 the doubly-linked list. */
290 struct loc_exp_dep **pprev;
291};
292
293
294/* This data structure holds information about the depth of a variable
295 expansion. */
296struct expand_depth
297{
298 /* This measures the complexity of the expanded expression. It
299 grows by one for each level of expansion that adds more than one
300 operand. */
301 int complexity;
302 /* This counts the number of ENTRY_VALUE expressions in an
303 expansion. We want to minimize their use. */
304 int entryvals;
305};
306
307/* Type for dependencies actively used when expand FROM into cur_loc. */
308typedef vec<loc_exp_dep, va_heap, vl_embed> deps_vec;
309
310/* This data structure is allocated for one-part variables at the time
311 of emitting notes. */
312struct onepart_aux
313{
314 /* Doubly-linked list of dependent DVs. These are DVs whose cur_loc
315 computation used the expansion of this variable, and that ought
316 to be notified should this variable change. If the DV's cur_loc
317 expanded to NULL, all components of the loc list are regarded as
318 active, so that any changes in them give us a chance to get a
319 location. Otherwise, only components of the loc that expanded to
320 non-NULL are regarded as active dependencies. */
321 loc_exp_dep *backlinks;
322 /* This holds the LOC that was expanded into cur_loc. We need only
323 mark a one-part variable as changed if the FROM loc is removed,
324 or if it has no known location and a loc is added, or if it gets
325 a change notification from any of its active dependencies. */
326 rtx from;
327 /* The depth of the cur_loc expression. */
328 expand_depth depth;
329 /* Dependencies actively used when expand FROM into cur_loc. */
330 deps_vec deps;
331};
332
333/* Structure describing one part of variable. */
334struct variable_part
335{
336 /* Chain of locations of the part. */
337 location_chain *loc_chain;
338
339 /* Location which was last emitted to location list. */
340 rtx cur_loc;
341
342 union variable_aux
343 {
344 /* The offset in the variable, if !var->onepart. */
345 HOST_WIDE_INTlong offset;
346
347 /* Pointer to auxiliary data, if var->onepart and emit_notes. */
348 struct onepart_aux *onepaux;
349 } aux;
350};
351
352/* Maximum number of location parts. */
353#define MAX_VAR_PARTS16 16
354
355/* Enumeration type used to discriminate various types of one-part
356 variables. */
357enum onepart_enum
358{
359 /* Not a one-part variable. */
360 NOT_ONEPART = 0,
361 /* A one-part DECL that is not a DEBUG_EXPR_DECL. */
362 ONEPART_VDECL = 1,
363 /* A DEBUG_EXPR_DECL. */
364 ONEPART_DEXPR = 2,
365 /* A VALUE. */
366 ONEPART_VALUE = 3
367};
368
369/* Structure describing where the variable is located. */
370struct variable
371{
372 /* The declaration of the variable, or an RTL value being handled
373 like a declaration. */
374 decl_or_value dv;
375
376 /* Reference count. */
377 int refcount;
378
379 /* Number of variable parts. */
380 char n_var_parts;
381
382 /* What type of DV this is, according to enum onepart_enum. */
383 ENUM_BITFIELD (onepart_enum)enum onepart_enum onepart : CHAR_BIT8;
384
385 /* True if this variable_def struct is currently in the
386 changed_variables hash table. */
387 bool in_changed_variables;
388
389 /* The variable parts. */
390 variable_part var_part[1];
391};
392
393/* Pointer to the BB's information specific to variable tracking pass. */
394#define VTI(BB)((variable_tracking_info *) (BB)->aux) ((variable_tracking_info *) (BB)->aux)
395
396/* Return MEM_OFFSET (MEM) as a HOST_WIDE_INT, or 0 if we can't. */
397
398static inline HOST_WIDE_INTlong
399int_mem_offset (const_rtx mem)
400{
401 HOST_WIDE_INTlong offset;
402 if (MEM_OFFSET_KNOWN_P (mem)(get_mem_attrs (mem)->offset_known_p) && MEM_OFFSET (mem)(get_mem_attrs (mem)->offset).is_constant (&offset))
403 return offset;
404 return 0;
405}
406
407#if CHECKING_P1 && (GCC_VERSION(4 * 1000 + 2) >= 2007)
408
409/* Access VAR's Ith part's offset, checking that it's not a one-part
410 variable. */
411#define VAR_PART_OFFSET(var, i)__extension__ (*({ variable *const __v = (var); ((void)(!(!__v
->onepart) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 411, __FUNCTION__), 0 : 0)); &__v->var_part[(i)].aux
.offset; }))
__extension__ \
412(*({ variable *const __v = (var); \
413 gcc_checking_assert (!__v->onepart)((void)(!(!__v->onepart) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 413, __FUNCTION__), 0 : 0))
; \
414 &__v->var_part[(i)].aux.offset; }))
415
416/* Access VAR's one-part auxiliary data, checking that it is a
417 one-part variable. */
418#define VAR_LOC_1PAUX(var)__extension__ (*({ variable *const __v = (var); ((void)(!(__v
->onepart) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 418, __FUNCTION__), 0 : 0)); &__v->var_part[0].aux.onepaux
; }))
__extension__ \
419(*({ variable *const __v = (var); \
420 gcc_checking_assert (__v->onepart)((void)(!(__v->onepart) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 420, __FUNCTION__), 0 : 0))
; \
421 &__v->var_part[0].aux.onepaux; }))
422
423#else
424#define VAR_PART_OFFSET(var, i)__extension__ (*({ variable *const __v = (var); ((void)(!(!__v
->onepart) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 424, __FUNCTION__), 0 : 0)); &__v->var_part[(i)].aux
.offset; }))
((var)->var_part[(i)].aux.offset)
425#define VAR_LOC_1PAUX(var)__extension__ (*({ variable *const __v = (var); ((void)(!(__v
->onepart) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 425, __FUNCTION__), 0 : 0)); &__v->var_part[0].aux.onepaux
; }))
((var)->var_part[0].aux.onepaux)
426#endif
427
428/* These are accessor macros for the one-part auxiliary data. When
429 convenient for users, they're guarded by tests that the data was
430 allocated. */
431#define VAR_LOC_DEP_LST(var)(__extension__ (*({ variable *const __v = (var); ((void)(!(__v
->onepart) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 431, __FUNCTION__), 0 : 0)); &__v->var_part[0].aux.onepaux
; })) ? __extension__ (*({ variable *const __v = (var); ((void
)(!(__v->onepart) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 431, __FUNCTION__), 0 : 0)); &__v->var_part[0].aux.onepaux
; }))->backlinks : nullptr)
(VAR_LOC_1PAUX (var)__extension__ (*({ variable *const __v = (var); ((void)(!(__v
->onepart) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 431, __FUNCTION__), 0 : 0)); &__v->var_part[0].aux.onepaux
; }))
\
432 ? VAR_LOC_1PAUX (var)__extension__ (*({ variable *const __v = (var); ((void)(!(__v
->onepart) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 432, __FUNCTION__), 0 : 0)); &__v->var_part[0].aux.onepaux
; }))
->backlinks \
433 : NULLnullptr)
434#define VAR_LOC_DEP_LSTP(var)(__extension__ (*({ variable *const __v = (var); ((void)(!(__v
->onepart) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 434, __FUNCTION__), 0 : 0)); &__v->var_part[0].aux.onepaux
; })) ? &__extension__ (*({ variable *const __v = (var); (
(void)(!(__v->onepart) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 434, __FUNCTION__), 0 : 0)); &__v->var_part[0].aux.onepaux
; }))->backlinks : nullptr)
(VAR_LOC_1PAUX (var)__extension__ (*({ variable *const __v = (var); ((void)(!(__v
->onepart) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 434, __FUNCTION__), 0 : 0)); &__v->var_part[0].aux.onepaux
; }))
\
435 ? &VAR_LOC_1PAUX (var)__extension__ (*({ variable *const __v = (var); ((void)(!(__v
->onepart) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 435, __FUNCTION__), 0 : 0)); &__v->var_part[0].aux.onepaux
; }))
->backlinks \
436 : NULLnullptr)
437#define VAR_LOC_FROM(var)(__extension__ (*({ variable *const __v = (var); ((void)(!(__v
->onepart) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 437, __FUNCTION__), 0 : 0)); &__v->var_part[0].aux.onepaux
; }))->from)
(VAR_LOC_1PAUX (var)__extension__ (*({ variable *const __v = (var); ((void)(!(__v
->onepart) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 437, __FUNCTION__), 0 : 0)); &__v->var_part[0].aux.onepaux
; }))
->from)
438#define VAR_LOC_DEPTH(var)(__extension__ (*({ variable *const __v = (var); ((void)(!(__v
->onepart) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 438, __FUNCTION__), 0 : 0)); &__v->var_part[0].aux.onepaux
; }))->depth)
(VAR_LOC_1PAUX (var)__extension__ (*({ variable *const __v = (var); ((void)(!(__v
->onepart) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 438, __FUNCTION__), 0 : 0)); &__v->var_part[0].aux.onepaux
; }))
->depth)
439#define VAR_LOC_DEP_VEC(var)var_loc_dep_vec (var) var_loc_dep_vec (var)
440
441/* Implements the VAR_LOC_DEP_VEC above as a function to work around
442 a bogus -Wnonnull (PR c/95554). */
443
444static inline deps_vec*
445var_loc_dep_vec (variable *var)
446{
447 return VAR_LOC_1PAUX (var)__extension__ (*({ variable *const __v = (var); ((void)(!(__v
->onepart) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 447, __FUNCTION__), 0 : 0)); &__v->var_part[0].aux.onepaux
; }))
? &VAR_LOC_1PAUX (var)__extension__ (*({ variable *const __v = (var); ((void)(!(__v
->onepart) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 447, __FUNCTION__), 0 : 0)); &__v->var_part[0].aux.onepaux
; }))
->deps : NULLnullptr;
448}
449
450
451typedef unsigned int dvuid;
452
453/* Return the uid of DV. */
454
455static inline dvuid
456dv_uid (decl_or_value dv)
457{
458 if (dv_is_value_p (dv))
459 return CSELIB_VAL_PTR (dv_as_value (dv))(((dv_as_value (dv))->u.fld[0]).rt_cselib)->uid;
460 else
461 return DECL_UID (dv_as_decl (dv))((contains_struct_check ((dv_as_decl (dv)), (TS_DECL_MINIMAL)
, "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 461, __FUNCTION__))->decl_minimal.uid)
;
462}
463
464/* Compute the hash from the uid. */
465
466static inline hashval_t
467dv_uid2hash (dvuid uid)
468{
469 return uid;
470}
471
472/* The hash function for a mask table in a shared_htab chain. */
473
474static inline hashval_t
475dv_htab_hash (decl_or_value dv)
476{
477 return dv_uid2hash (dv_uid (dv));
478}
479
480static void variable_htab_free (void *);
481
482/* Variable hashtable helpers. */
483
484struct variable_hasher : pointer_hash <variable>
485{
486 typedef void *compare_type;
487 static inline hashval_t hash (const variable *);
488 static inline bool equal (const variable *, const void *);
489 static inline void remove (variable *);
490};
491
492/* The hash function for variable_htab, computes the hash value
493 from the declaration of variable X. */
494
495inline hashval_t
496variable_hasher::hash (const variable *v)
497{
498 return dv_htab_hash (v->dv);
499}
500
501/* Compare the declaration of variable X with declaration Y. */
502
503inline bool
504variable_hasher::equal (const variable *v, const void *y)
505{
506 decl_or_value dv = CONST_CAST2 (decl_or_value, const void *, y)(const_cast<decl_or_value> (y));
507
508 return (dv_as_opaque (v->dv) == dv_as_opaque (dv));
509}
510
511/* Free the element of VARIABLE_HTAB (its type is struct variable_def). */
512
513inline void
514variable_hasher::remove (variable *var)
515{
516 variable_htab_free (var);
517}
518
519typedef hash_table<variable_hasher> variable_table_type;
520typedef variable_table_type::iterator variable_iterator_type;
521
522/* Structure for passing some other parameters to function
523 emit_note_insn_var_location. */
524struct emit_note_data
525{
526 /* The instruction which the note will be emitted before/after. */
527 rtx_insn *insn;
528
529 /* Where the note will be emitted (before/after insn)? */
530 enum emit_note_where where;
531
532 /* The variables and values active at this point. */
533 variable_table_type *vars;
534};
535
536/* Structure holding a refcounted hash table. If refcount > 1,
537 it must be first unshared before modified. */
538struct shared_hash
539{
540 /* Reference count. */
541 int refcount;
542
543 /* Actual hash table. */
544 variable_table_type *htab;
545};
546
547/* Structure holding the IN or OUT set for a basic block. */
548struct dataflow_set
549{
550 /* Adjustment of stack offset. */
551 HOST_WIDE_INTlong stack_adjust;
552
553 /* Attributes for registers (lists of attrs). */
554 attrs *regs[FIRST_PSEUDO_REGISTER76];
555
556 /* Variable locations. */
557 shared_hash *vars;
558
559 /* Vars that is being traversed. */
560 shared_hash *traversed_vars;
561};
562
563/* The structure (one for each basic block) containing the information
564 needed for variable tracking. */
565struct variable_tracking_info
566{
567 /* The vector of micro operations. */
568 vec<micro_operation> mos;
569
570 /* The IN and OUT set for dataflow analysis. */
571 dataflow_set in;
572 dataflow_set out;
573
574 /* The permanent-in dataflow set for this block. This is used to
575 hold values for which we had to compute entry values. ??? This
576 should probably be dynamically allocated, to avoid using more
577 memory in non-debug builds. */
578 dataflow_set *permp;
579
580 /* Has the block been visited in DFS? */
581 bool visited;
582
583 /* Has the block been flooded in VTA? */
584 bool flooded;
585
586};
587
588/* Alloc pool for struct attrs_def. */
589object_allocator<attrs> attrs_pool ("attrs pool");
590
591/* Alloc pool for struct variable_def with MAX_VAR_PARTS entries. */
592
593static pool_allocator var_pool
594 ("variable_def pool", sizeof (variable) +
595 (MAX_VAR_PARTS16 - 1) * sizeof (((variable *)NULLnullptr)->var_part[0]));
596
597/* Alloc pool for struct variable_def with a single var_part entry. */
598static pool_allocator valvar_pool
599 ("small variable_def pool", sizeof (variable));
600
601/* Alloc pool for struct location_chain. */
602static object_allocator<location_chain> location_chain_pool
603 ("location_chain pool");
604
605/* Alloc pool for struct shared_hash. */
606static object_allocator<shared_hash> shared_hash_pool ("shared_hash pool");
607
608/* Alloc pool for struct loc_exp_dep_s for NOT_ONEPART variables. */
609object_allocator<loc_exp_dep> loc_exp_dep_pool ("loc_exp_dep pool");
610
611/* Changed variables, notes will be emitted for them. */
612static variable_table_type *changed_variables;
613
614/* Shall notes be emitted? */
615static bool emit_notes;
616
617/* Values whose dynamic location lists have gone empty, but whose
618 cselib location lists are still usable. Use this to hold the
619 current location, the backlinks, etc, during emit_notes. */
620static variable_table_type *dropped_values;
621
622/* Empty shared hashtable. */
623static shared_hash *empty_shared_hash;
624
625/* Scratch register bitmap used by cselib_expand_value_rtx. */
626static bitmap scratch_regs = NULLnullptr;
627
628#ifdef HAVE_window_save
629struct GTY(()) parm_reg {
630 rtx outgoing;
631 rtx incoming;
632};
633
634
635/* Vector of windowed parameter registers, if any. */
636static vec<parm_reg, va_gc> *windowed_parm_regs = NULLnullptr;
637#endif
638
639/* Variable used to tell whether cselib_process_insn called our hook. */
640static bool cselib_hook_called;
641
642/* Local function prototypes. */
643static void stack_adjust_offset_pre_post (rtx, HOST_WIDE_INTlong *,
644 HOST_WIDE_INTlong *);
645static void insn_stack_adjust_offset_pre_post (rtx_insn *, HOST_WIDE_INTlong *,
646 HOST_WIDE_INTlong *);
647static bool vt_stack_adjustments (void);
648
649static void init_attrs_list_set (attrs **);
650static void attrs_list_clear (attrs **);
651static attrs *attrs_list_member (attrs *, decl_or_value, HOST_WIDE_INTlong);
652static void attrs_list_insert (attrs **, decl_or_value, HOST_WIDE_INTlong, rtx);
653static void attrs_list_copy (attrs **, attrs *);
654static void attrs_list_union (attrs **, attrs *);
655
656static variable **unshare_variable (dataflow_set *set, variable **slot,
657 variable *var, enum var_init_status);
658static void vars_copy (variable_table_type *, variable_table_type *);
659static tree var_debug_decl (tree);
660static void var_reg_set (dataflow_set *, rtx, enum var_init_status, rtx);
661static void var_reg_delete_and_set (dataflow_set *, rtx, bool,
662 enum var_init_status, rtx);
663static void var_reg_delete (dataflow_set *, rtx, bool);
664static void var_regno_delete (dataflow_set *, int);
665static void var_mem_set (dataflow_set *, rtx, enum var_init_status, rtx);
666static void var_mem_delete_and_set (dataflow_set *, rtx, bool,
667 enum var_init_status, rtx);
668static void var_mem_delete (dataflow_set *, rtx, bool);
669
670static void dataflow_set_init (dataflow_set *);
671static void dataflow_set_clear (dataflow_set *);
672static void dataflow_set_copy (dataflow_set *, dataflow_set *);
673static int variable_union_info_cmp_pos (const void *, const void *);
674static void dataflow_set_union (dataflow_set *, dataflow_set *);
675static location_chain *find_loc_in_1pdv (rtx, variable *,
676 variable_table_type *);
677static bool canon_value_cmp (rtx, rtx);
678static int loc_cmp (rtx, rtx);
679static bool variable_part_different_p (variable_part *, variable_part *);
680static bool onepart_variable_different_p (variable *, variable *);
681static bool variable_different_p (variable *, variable *);
682static bool dataflow_set_different (dataflow_set *, dataflow_set *);
683static void dataflow_set_destroy (dataflow_set *);
684
685static bool track_expr_p (tree, bool);
686static void add_uses_1 (rtx *, void *);
687static void add_stores (rtx, const_rtx, void *);
688static bool compute_bb_dataflow (basic_block);
689static bool vt_find_locations (void);
690
691static void dump_attrs_list (attrs *);
692static void dump_var (variable *);
693static void dump_vars (variable_table_type *);
694static void dump_dataflow_set (dataflow_set *);
695static void dump_dataflow_sets (void);
696
697static void set_dv_changed (decl_or_value, bool);
698static void variable_was_changed (variable *, dataflow_set *);
699static variable **set_slot_part (dataflow_set *, rtx, variable **,
700 decl_or_value, HOST_WIDE_INTlong,
701 enum var_init_status, rtx);
702static void set_variable_part (dataflow_set *, rtx,
703 decl_or_value, HOST_WIDE_INTlong,
704 enum var_init_status, rtx, enum insert_option);
705static variable **clobber_slot_part (dataflow_set *, rtx,
706 variable **, HOST_WIDE_INTlong, rtx);
707static void clobber_variable_part (dataflow_set *, rtx,
708 decl_or_value, HOST_WIDE_INTlong, rtx);
709static variable **delete_slot_part (dataflow_set *, rtx, variable **,
710 HOST_WIDE_INTlong);
711static void delete_variable_part (dataflow_set *, rtx,
712 decl_or_value, HOST_WIDE_INTlong);
713static void emit_notes_in_bb (basic_block, dataflow_set *);
714static void vt_emit_notes (void);
715
716static void vt_add_function_parameters (void);
717static bool vt_initialize (void);
718static void vt_finalize (void);
719
720/* Callback for stack_adjust_offset_pre_post, called via for_each_inc_dec. */
721
722static int
723stack_adjust_offset_pre_post_cb (rtx, rtx op, rtx dest, rtx src, rtx srcoff,
724 void *arg)
725{
726 if (dest != stack_pointer_rtx((this_target_rtl->x_global_rtl)[GR_STACK_POINTER]))
727 return 0;
728
729 switch (GET_CODE (op)((enum rtx_code) (op)->code))
730 {
731 case PRE_INC:
732 case PRE_DEC:
733 ((HOST_WIDE_INTlong *)arg)[0] -= INTVAL (srcoff)((srcoff)->u.hwint[0]);
734 return 0;
735 case POST_INC:
736 case POST_DEC:
737 ((HOST_WIDE_INTlong *)arg)[1] -= INTVAL (srcoff)((srcoff)->u.hwint[0]);
738 return 0;
739 case PRE_MODIFY:
740 case POST_MODIFY:
741 /* We handle only adjustments by constant amount. */
742 gcc_assert (GET_CODE (src) == PLUS((void)(!(((enum rtx_code) (src)->code) == PLUS &&
(((enum rtx_code) ((((src)->u.fld[1]).rt_rtx))->code) ==
CONST_INT) && (((src)->u.fld[0]).rt_rtx) == ((this_target_rtl
->x_global_rtl)[GR_STACK_POINTER])) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 744, __FUNCTION__), 0 : 0))
743 && CONST_INT_P (XEXP (src, 1))((void)(!(((enum rtx_code) (src)->code) == PLUS &&
(((enum rtx_code) ((((src)->u.fld[1]).rt_rtx))->code) ==
CONST_INT) && (((src)->u.fld[0]).rt_rtx) == ((this_target_rtl
->x_global_rtl)[GR_STACK_POINTER])) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 744, __FUNCTION__), 0 : 0))
744 && XEXP (src, 0) == stack_pointer_rtx)((void)(!(((enum rtx_code) (src)->code) == PLUS &&
(((enum rtx_code) ((((src)->u.fld[1]).rt_rtx))->code) ==
CONST_INT) && (((src)->u.fld[0]).rt_rtx) == ((this_target_rtl
->x_global_rtl)[GR_STACK_POINTER])) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 744, __FUNCTION__), 0 : 0))
;
745 ((HOST_WIDE_INTlong *)arg)[GET_CODE (op)((enum rtx_code) (op)->code) == POST_MODIFY]
746 -= INTVAL (XEXP (src, 1))(((((src)->u.fld[1]).rt_rtx))->u.hwint[0]);
747 return 0;
748 default:
749 gcc_unreachable ()(fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 749, __FUNCTION__))
;
750 }
751}
752
753/* Given a SET, calculate the amount of stack adjustment it contains
754 PRE- and POST-modifying stack pointer.
755 This function is similar to stack_adjust_offset. */
756
757static void
758stack_adjust_offset_pre_post (rtx pattern, HOST_WIDE_INTlong *pre,
759 HOST_WIDE_INTlong *post)
760{
761 rtx src = SET_SRC (pattern)(((pattern)->u.fld[1]).rt_rtx);
762 rtx dest = SET_DEST (pattern)(((pattern)->u.fld[0]).rt_rtx);
763 enum rtx_code code;
764
765 if (dest == stack_pointer_rtx((this_target_rtl->x_global_rtl)[GR_STACK_POINTER]))
766 {
767 /* (set (reg sp) (plus (reg sp) (const_int))) */
768 code = GET_CODE (src)((enum rtx_code) (src)->code);
769 if (! (code == PLUS || code == MINUS)
770 || XEXP (src, 0)(((src)->u.fld[0]).rt_rtx) != stack_pointer_rtx((this_target_rtl->x_global_rtl)[GR_STACK_POINTER])
771 || !CONST_INT_P (XEXP (src, 1))(((enum rtx_code) ((((src)->u.fld[1]).rt_rtx))->code) ==
CONST_INT)
)
772 return;
773
774 if (code == MINUS)
775 *post += INTVAL (XEXP (src, 1))(((((src)->u.fld[1]).rt_rtx))->u.hwint[0]);
776 else
777 *post -= INTVAL (XEXP (src, 1))(((((src)->u.fld[1]).rt_rtx))->u.hwint[0]);
778 return;
779 }
780 HOST_WIDE_INTlong res[2] = { 0, 0 };
781 for_each_inc_dec (pattern, stack_adjust_offset_pre_post_cb, res);
782 *pre += res[0];
783 *post += res[1];
784}
785
786/* Given an INSN, calculate the amount of stack adjustment it contains
787 PRE- and POST-modifying stack pointer. */
788
789static void
790insn_stack_adjust_offset_pre_post (rtx_insn *insn, HOST_WIDE_INTlong *pre,
791 HOST_WIDE_INTlong *post)
792{
793 rtx pattern;
794
795 *pre = 0;
796 *post = 0;
797
798 pattern = PATTERN (insn);
799 if (RTX_FRAME_RELATED_P (insn)(__extension__ ({ __typeof ((insn)) const _rtx = ((insn)); if
(((enum rtx_code) (_rtx)->code) != DEBUG_INSN && (
(enum rtx_code) (_rtx)->code) != INSN && ((enum rtx_code
) (_rtx)->code) != CALL_INSN && ((enum rtx_code) (
_rtx)->code) != JUMP_INSN && ((enum rtx_code) (_rtx
)->code) != BARRIER && ((enum rtx_code) (_rtx)->
code) != SET) rtl_check_failed_flag ("RTX_FRAME_RELATED_P",_rtx
, "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 799, __FUNCTION__); _rtx; })->frame_related)
)
800 {
801 rtx expr = find_reg_note (insn, REG_FRAME_RELATED_EXPR, NULL_RTX(rtx) 0);
802 if (expr)
803 pattern = XEXP (expr, 0)(((expr)->u.fld[0]).rt_rtx);
804 }
805
806 if (GET_CODE (pattern)((enum rtx_code) (pattern)->code) == SET)
807 stack_adjust_offset_pre_post (pattern, pre, post);
808 else if (GET_CODE (pattern)((enum rtx_code) (pattern)->code) == PARALLEL
809 || GET_CODE (pattern)((enum rtx_code) (pattern)->code) == SEQUENCE)
810 {
811 int i;
812
813 /* There may be stack adjustments inside compound insns. Search
814 for them. */
815 for ( i = XVECLEN (pattern, 0)(((((pattern)->u.fld[0]).rt_rtvec))->num_elem) - 1; i >= 0; i--)
816 if (GET_CODE (XVECEXP (pattern, 0, i))((enum rtx_code) ((((((pattern)->u.fld[0]).rt_rtvec))->
elem[i]))->code)
== SET)
817 stack_adjust_offset_pre_post (XVECEXP (pattern, 0, i)(((((pattern)->u.fld[0]).rt_rtvec))->elem[i]), pre, post);
818 }
819}
820
821/* Compute stack adjustments for all blocks by traversing DFS tree.
822 Return true when the adjustments on all incoming edges are consistent.
823 Heavily borrowed from pre_and_rev_post_order_compute. */
824
825static bool
826vt_stack_adjustments (void)
827{
828 edge_iterator *stack;
829 int sp;
830
831 /* Initialize entry block. */
832 VTI (ENTRY_BLOCK_PTR_FOR_FN (cfun))((variable_tracking_info *) ((((cfun + 0))->cfg->x_entry_block_ptr
))->aux)
->visited = true;
833 VTI (ENTRY_BLOCK_PTR_FOR_FN (cfun))((variable_tracking_info *) ((((cfun + 0))->cfg->x_entry_block_ptr
))->aux)
->in.stack_adjust
834 = INCOMING_FRAME_SP_OFFSET((cfun + 0)->machine->func_type == TYPE_EXCEPTION ? 2 *
(((global_options.x_ix86_isa_flags & (1UL << 1)) !=
0) ? 8 : 4) : (((global_options.x_ix86_isa_flags & (1UL <<
1)) != 0) ? 8 : 4))
;
835 VTI (ENTRY_BLOCK_PTR_FOR_FN (cfun))((variable_tracking_info *) ((((cfun + 0))->cfg->x_entry_block_ptr
))->aux)
->out.stack_adjust
836 = INCOMING_FRAME_SP_OFFSET((cfun + 0)->machine->func_type == TYPE_EXCEPTION ? 2 *
(((global_options.x_ix86_isa_flags & (1UL << 1)) !=
0) ? 8 : 4) : (((global_options.x_ix86_isa_flags & (1UL <<
1)) != 0) ? 8 : 4))
;
837
838 /* Allocate stack for back-tracking up CFG. */
839 stack = XNEWVEC (edge_iterator, n_basic_blocks_for_fn (cfun) + 1)((edge_iterator *) xmalloc (sizeof (edge_iterator) * ((((cfun
+ 0))->cfg->x_n_basic_blocks) + 1)))
;
840 sp = 0;
841
842 /* Push the first edge on to the stack. */
843 stack[sp++] = ei_start (ENTRY_BLOCK_PTR_FOR_FN (cfun)->succs)ei_start_1 (&((((cfun + 0))->cfg->x_entry_block_ptr
)->succs))
;
844
845 while (sp)
846 {
847 edge_iterator ei;
848 basic_block src;
849 basic_block dest;
850
851 /* Look at the edge on the top of the stack. */
852 ei = stack[sp - 1];
853 src = ei_edge (ei)->src;
854 dest = ei_edge (ei)->dest;
855
856 /* Check if the edge destination has been visited yet. */
857 if (!VTI (dest)((variable_tracking_info *) (dest)->aux)->visited)
858 {
859 rtx_insn *insn;
860 HOST_WIDE_INTlong pre, post, offset;
861 VTI (dest)((variable_tracking_info *) (dest)->aux)->visited = true;
862 VTI (dest)((variable_tracking_info *) (dest)->aux)->in.stack_adjust = offset = VTI (src)((variable_tracking_info *) (src)->aux)->out.stack_adjust;
863
864 if (dest != EXIT_BLOCK_PTR_FOR_FN (cfun)(((cfun + 0))->cfg->x_exit_block_ptr))
865 for (insn = BB_HEAD (dest)(dest)->il.x.head_;
866 insn != NEXT_INSN (BB_END (dest)(dest)->il.x.rtl->end_);
867 insn = NEXT_INSN (insn))
868 if (INSN_P (insn)(((((enum rtx_code) (insn)->code) == INSN) || (((enum rtx_code
) (insn)->code) == JUMP_INSN) || (((enum rtx_code) (insn)->
code) == CALL_INSN)) || (((enum rtx_code) (insn)->code) ==
DEBUG_INSN))
)
869 {
870 insn_stack_adjust_offset_pre_post (insn, &pre, &post);
871 offset += pre + post;
872 }
873
874 VTI (dest)((variable_tracking_info *) (dest)->aux)->out.stack_adjust = offset;
875
876 if (EDGE_COUNT (dest->succs)vec_safe_length (dest->succs) > 0)
877 /* Since the DEST node has been visited for the first
878 time, check its successors. */
879 stack[sp++] = ei_start (dest->succs)ei_start_1 (&(dest->succs));
880 }
881 else
882 {
883 /* We can end up with different stack adjustments for the exit block
884 of a shrink-wrapped function if stack_adjust_offset_pre_post
885 doesn't understand the rtx pattern used to restore the stack
886 pointer in the epilogue. For example, on s390(x), the stack
887 pointer is often restored via a load-multiple instruction
888 and so no stack_adjust offset is recorded for it. This means
889 that the stack offset at the end of the epilogue block is the
890 same as the offset before the epilogue, whereas other paths
891 to the exit block will have the correct stack_adjust.
892
893 It is safe to ignore these differences because (a) we never
894 use the stack_adjust for the exit block in this pass and
895 (b) dwarf2cfi checks whether the CFA notes in a shrink-wrapped
896 function are correct.
897
898 We must check whether the adjustments on other edges are
899 the same though. */
900 if (dest != EXIT_BLOCK_PTR_FOR_FN (cfun)(((cfun + 0))->cfg->x_exit_block_ptr)
901 && VTI (dest)((variable_tracking_info *) (dest)->aux)->in.stack_adjust != VTI (src)((variable_tracking_info *) (src)->aux)->out.stack_adjust)
902 {
903 free (stack);
904 return false;
905 }
906
907 if (! ei_one_before_end_p (ei))
908 /* Go to the next edge. */
909 ei_next (&stack[sp - 1]);
910 else
911 /* Return to previous level if there are no more edges. */
912 sp--;
913 }
914 }
915
916 free (stack);
917 return true;
918}
919
920/* arg_pointer_rtx resp. frame_pointer_rtx if stack_pointer_rtx or
921 hard_frame_pointer_rtx is being mapped to it and offset for it. */
922static rtx cfa_base_rtx;
923static HOST_WIDE_INTlong cfa_base_offset;
924
925/* Compute a CFA-based value for an ADJUSTMENT made to stack_pointer_rtx
926 or hard_frame_pointer_rtx. */
927
928static inline rtx
929compute_cfa_pointer (poly_int64 adjustment)
930{
931 return plus_constant (Pmode(global_options.x_ix86_pmode == PMODE_DI ? (scalar_int_mode (
(scalar_int_mode::from_int) E_DImode)) : (scalar_int_mode ((scalar_int_mode
::from_int) E_SImode)))
, cfa_base_rtx, adjustment + cfa_base_offset);
932}
933
934/* Adjustment for hard_frame_pointer_rtx to cfa base reg,
935 or -1 if the replacement shouldn't be done. */
936static poly_int64 hard_frame_pointer_adjustment = -1;
937
938/* Data for adjust_mems callback. */
939
940class adjust_mem_data
941{
942public:
943 bool store;
944 machine_mode mem_mode;
945 HOST_WIDE_INTlong stack_adjust;
946 auto_vec<rtx> side_effects;
947};
948
949/* Helper for adjust_mems. Return true if X is suitable for
950 transformation of wider mode arithmetics to narrower mode. */
951
952static bool
953use_narrower_mode_test (rtx x, const_rtx subreg)
954{
955 subrtx_var_iterator::array_type array;
956 FOR_EACH_SUBRTX_VAR (iter, array, x, NONCONST)for (subrtx_var_iterator iter (array, x, rtx_nonconst_subrtx_bounds
); !iter.at_end (); iter.next ())
957 {
958 rtx x = *iter;
959 if (CONSTANT_P (x)((rtx_class[(int) (((enum rtx_code) (x)->code))]) == RTX_CONST_OBJ
)
)
960 iter.skip_subrtxes ();
961 else
962 switch (GET_CODE (x)((enum rtx_code) (x)->code))
963 {
964 case REG:
965 if (cselib_lookup (x, GET_MODE (SUBREG_REG (subreg))((machine_mode) ((((subreg)->u.fld[0]).rt_rtx))->mode), 0, VOIDmode((void) 0, E_VOIDmode)))
966 return false;
967 if (!validate_subreg (GET_MODE (subreg)((machine_mode) (subreg)->mode), GET_MODE (x)((machine_mode) (x)->mode), x,
968 subreg_lowpart_offset (GET_MODE (subreg)((machine_mode) (subreg)->mode),
969 GET_MODE (x)((machine_mode) (x)->mode))))
970 return false;
971 break;
972 case PLUS:
973 case MINUS:
974 case MULT:
975 break;
976 case ASHIFT:
977 if (GET_MODE (XEXP (x, 1))((machine_mode) ((((x)->u.fld[1]).rt_rtx))->mode) != VOIDmode((void) 0, E_VOIDmode))
978 {
979 enum machine_mode mode = GET_MODE (subreg)((machine_mode) (subreg)->mode);
980 rtx op1 = XEXP (x, 1)(((x)->u.fld[1]).rt_rtx);
981 enum machine_mode op1_mode = GET_MODE (op1)((machine_mode) (op1)->mode);
982 if (GET_MODE_PRECISION (as_a <scalar_int_mode> (mode))
983 < GET_MODE_PRECISION (as_a <scalar_int_mode> (op1_mode)))
984 {
985 poly_uint64 byte = subreg_lowpart_offset (mode, op1_mode);
986 if (GET_CODE (op1)((enum rtx_code) (op1)->code) == SUBREG || GET_CODE (op1)((enum rtx_code) (op1)->code) == CONCAT)
987 {
988 if (!simplify_subreg (mode, op1, op1_mode, byte))
989 return false;
990 }
991 else if (!validate_subreg (mode, op1_mode, op1, byte))
992 return false;
993 }
994 }
995 iter.substitute (XEXP (x, 0)(((x)->u.fld[0]).rt_rtx));
996 break;
997 default:
998 return false;
999 }
1000 }
1001 return true;
1002}
1003
1004/* Transform X into narrower mode MODE from wider mode WMODE. */
1005
1006static rtx
1007use_narrower_mode (rtx x, scalar_int_mode mode, scalar_int_mode wmode)
1008{
1009 rtx op0, op1;
1010 if (CONSTANT_P (x)((rtx_class[(int) (((enum rtx_code) (x)->code))]) == RTX_CONST_OBJ
)
)
1011 return lowpart_subreg (mode, x, wmode);
1012 switch (GET_CODE (x)((enum rtx_code) (x)->code))
1013 {
1014 case REG:
1015 return lowpart_subreg (mode, x, wmode);
1016 case PLUS:
1017 case MINUS:
1018 case MULT:
1019 op0 = use_narrower_mode (XEXP (x, 0)(((x)->u.fld[0]).rt_rtx), mode, wmode);
1020 op1 = use_narrower_mode (XEXP (x, 1)(((x)->u.fld[1]).rt_rtx), mode, wmode);
1021 return simplify_gen_binary (GET_CODE (x)((enum rtx_code) (x)->code), mode, op0, op1);
1022 case ASHIFT:
1023 op0 = use_narrower_mode (XEXP (x, 0)(((x)->u.fld[0]).rt_rtx), mode, wmode);
1024 op1 = XEXP (x, 1)(((x)->u.fld[1]).rt_rtx);
1025 /* Ensure shift amount is not wider than mode. */
1026 if (GET_MODE (op1)((machine_mode) (op1)->mode) == VOIDmode((void) 0, E_VOIDmode))
1027 op1 = lowpart_subreg (mode, op1, wmode);
1028 else if (GET_MODE_PRECISION (mode)
1029 < GET_MODE_PRECISION (as_a <scalar_int_mode> (GET_MODE (op1)((machine_mode) (op1)->mode))))
1030 op1 = lowpart_subreg (mode, op1, GET_MODE (op1)((machine_mode) (op1)->mode));
1031 return simplify_gen_binary (ASHIFT, mode, op0, op1);
1032 default:
1033 gcc_unreachable ()(fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 1033, __FUNCTION__))
;
1034 }
1035}
1036
1037/* Helper function for adjusting used MEMs. */
1038
1039static rtx
1040adjust_mems (rtx loc, const_rtx old_rtx, void *data)
1041{
1042 class adjust_mem_data *amd = (class adjust_mem_data *) data;
1043 rtx mem, addr = loc, tem;
1044 machine_mode mem_mode_save;
1045 bool store_save;
1046 scalar_int_mode tem_mode, tem_subreg_mode;
1047 poly_int64 size;
1048 switch (GET_CODE (loc)((enum rtx_code) (loc)->code))
1049 {
1050 case REG:
1051 /* Don't do any sp or fp replacements outside of MEM addresses
1052 on the LHS. */
1053 if (amd->mem_mode == VOIDmode((void) 0, E_VOIDmode) && amd->store)
1054 return loc;
1055 if (loc == stack_pointer_rtx((this_target_rtl->x_global_rtl)[GR_STACK_POINTER])
1056 && !frame_pointer_needed((&x_rtl)->frame_pointer_needed)
1057 && cfa_base_rtx)
1058 return compute_cfa_pointer (amd->stack_adjust);
1059 else if (loc == hard_frame_pointer_rtx((this_target_rtl->x_global_rtl)[GR_HARD_FRAME_POINTER])
1060 && frame_pointer_needed((&x_rtl)->frame_pointer_needed)
1061 && maybe_ne (hard_frame_pointer_adjustment, -1)
1062 && cfa_base_rtx)
1063 return compute_cfa_pointer (hard_frame_pointer_adjustment);
1064 gcc_checking_assert (loc != virtual_incoming_args_rtx)((void)(!(loc != ((this_target_rtl->x_global_rtl)[GR_VIRTUAL_INCOMING_ARGS
])) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 1064, __FUNCTION__), 0 : 0))
;
1065 return loc;
1066 case MEM:
1067 mem = loc;
1068 if (!amd->store)
1069 {
1070 mem = targetm.delegitimize_address (mem);
1071 if (mem != loc && !MEM_P (mem)(((enum rtx_code) (mem)->code) == MEM))
1072 return simplify_replace_fn_rtx (mem, old_rtx, adjust_mems, data);
1073 }
1074
1075 addr = XEXP (mem, 0)(((mem)->u.fld[0]).rt_rtx);
1076 mem_mode_save = amd->mem_mode;
1077 amd->mem_mode = GET_MODE (mem)((machine_mode) (mem)->mode);
1078 store_save = amd->store;
1079 amd->store = false;
1080 addr = simplify_replace_fn_rtx (addr, old_rtx, adjust_mems, data);
1081 amd->store = store_save;
1082 amd->mem_mode = mem_mode_save;
1083 if (mem == loc)
1084 addr = targetm.delegitimize_address (addr);
1085 if (addr != XEXP (mem, 0)(((mem)->u.fld[0]).rt_rtx))
1086 mem = replace_equiv_address_nv (mem, addr);
1087 if (!amd->store)
1088 mem = avoid_constant_pool_reference (mem);
1089 return mem;
1090 case PRE_INC:
1091 case PRE_DEC:
1092 size = GET_MODE_SIZE (amd->mem_mode);
1093 addr = plus_constant (GET_MODE (loc)((machine_mode) (loc)->mode), XEXP (loc, 0)(((loc)->u.fld[0]).rt_rtx),
1094 GET_CODE (loc)((enum rtx_code) (loc)->code) == PRE_INC ? size : -size);
1095 /* FALLTHRU */
1096 case POST_INC:
1097 case POST_DEC:
1098 if (addr == loc)
1099 addr = XEXP (loc, 0)(((loc)->u.fld[0]).rt_rtx);
1100 gcc_assert (amd->mem_mode != VOIDmode && amd->mem_mode != BLKmode)((void)(!(amd->mem_mode != ((void) 0, E_VOIDmode) &&
amd->mem_mode != ((void) 0, E_BLKmode)) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 1100, __FUNCTION__), 0 : 0))
;
1101 addr = simplify_replace_fn_rtx (addr, old_rtx, adjust_mems, data);
1102 size = GET_MODE_SIZE (amd->mem_mode);
1103 tem = plus_constant (GET_MODE (loc)((machine_mode) (loc)->mode), XEXP (loc, 0)(((loc)->u.fld[0]).rt_rtx),
1104 (GET_CODE (loc)((enum rtx_code) (loc)->code) == PRE_INC
1105 || GET_CODE (loc)((enum rtx_code) (loc)->code) == POST_INC) ? size : -size);
1106 store_save = amd->store;
1107 amd->store = false;
1108 tem = simplify_replace_fn_rtx (tem, old_rtx, adjust_mems, data);
1109 amd->store = store_save;
1110 amd->side_effects.safe_push (gen_rtx_SET (XEXP (loc, 0), tem)gen_rtx_fmt_ee_stat ((SET), (((void) 0, E_VOIDmode)), (((((loc
)->u.fld[0]).rt_rtx))), ((tem)) )
);
1111 return addr;
1112 case PRE_MODIFY:
1113 addr = XEXP (loc, 1)(((loc)->u.fld[1]).rt_rtx);
1114 /* FALLTHRU */
1115 case POST_MODIFY:
1116 if (addr == loc)
1117 addr = XEXP (loc, 0)(((loc)->u.fld[0]).rt_rtx);
1118 gcc_assert (amd->mem_mode != VOIDmode)((void)(!(amd->mem_mode != ((void) 0, E_VOIDmode)) ? fancy_abort
("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 1118, __FUNCTION__), 0 : 0))
;
1119 addr = simplify_replace_fn_rtx (addr, old_rtx, adjust_mems, data);
1120 store_save = amd->store;
1121 amd->store = false;
1122 tem = simplify_replace_fn_rtx (XEXP (loc, 1)(((loc)->u.fld[1]).rt_rtx), old_rtx,
1123 adjust_mems, data);
1124 amd->store = store_save;
1125 amd->side_effects.safe_push (gen_rtx_SET (XEXP (loc, 0), tem)gen_rtx_fmt_ee_stat ((SET), (((void) 0, E_VOIDmode)), (((((loc
)->u.fld[0]).rt_rtx))), ((tem)) )
);
1126 return addr;
1127 case SUBREG:
1128 /* First try without delegitimization of whole MEMs and
1129 avoid_constant_pool_reference, which is more likely to succeed. */
1130 store_save = amd->store;
1131 amd->store = true;
1132 addr = simplify_replace_fn_rtx (SUBREG_REG (loc)(((loc)->u.fld[0]).rt_rtx), old_rtx, adjust_mems,
1133 data);
1134 amd->store = store_save;
1135 mem = simplify_replace_fn_rtx (addr, old_rtx, adjust_mems, data);
1136 if (mem == SUBREG_REG (loc)(((loc)->u.fld[0]).rt_rtx))
1137 {
1138 tem = loc;
1139 goto finish_subreg;
1140 }
1141 tem = simplify_gen_subreg (GET_MODE (loc)((machine_mode) (loc)->mode), mem,
1142 GET_MODE (SUBREG_REG (loc))((machine_mode) ((((loc)->u.fld[0]).rt_rtx))->mode),
1143 SUBREG_BYTE (loc)(((loc)->u.fld[1]).rt_subreg));
1144 if (tem)
1145 goto finish_subreg;
1146 tem = simplify_gen_subreg (GET_MODE (loc)((machine_mode) (loc)->mode), addr,
1147 GET_MODE (SUBREG_REG (loc))((machine_mode) ((((loc)->u.fld[0]).rt_rtx))->mode),
1148 SUBREG_BYTE (loc)(((loc)->u.fld[1]).rt_subreg));
1149 if (tem == NULL_RTX(rtx) 0)
1150 tem = gen_rtx_raw_SUBREG (GET_MODE (loc), addr, SUBREG_BYTE (loc))gen_rtx_fmt_ep_stat ((SUBREG), ((((machine_mode) (loc)->mode
))), ((addr)), (((((loc)->u.fld[1]).rt_subreg))) )
;
1151 finish_subreg:
1152 if (MAY_HAVE_DEBUG_BIND_INSNSglobal_options.x_flag_var_tracking_assignments
1153 && GET_CODE (tem)((enum rtx_code) (tem)->code) == SUBREG
1154 && (GET_CODE (SUBREG_REG (tem))((enum rtx_code) ((((tem)->u.fld[0]).rt_rtx))->code) == PLUS
1155 || GET_CODE (SUBREG_REG (tem))((enum rtx_code) ((((tem)->u.fld[0]).rt_rtx))->code) == MINUS
1156 || GET_CODE (SUBREG_REG (tem))((enum rtx_code) ((((tem)->u.fld[0]).rt_rtx))->code) == MULT
1157 || GET_CODE (SUBREG_REG (tem))((enum rtx_code) ((((tem)->u.fld[0]).rt_rtx))->code) == ASHIFT)
1158 && is_a <scalar_int_mode> (GET_MODE (tem)((machine_mode) (tem)->mode), &tem_mode)
1159 && is_a <scalar_int_mode> (GET_MODE (SUBREG_REG (tem))((machine_mode) ((((tem)->u.fld[0]).rt_rtx))->mode),
1160 &tem_subreg_mode)
1161 && (GET_MODE_PRECISION (tem_mode)
1162 < GET_MODE_PRECISION (tem_subreg_mode))
1163 && subreg_lowpart_p (tem)
1164 && use_narrower_mode_test (SUBREG_REG (tem)(((tem)->u.fld[0]).rt_rtx), tem))
1165 return use_narrower_mode (SUBREG_REG (tem)(((tem)->u.fld[0]).rt_rtx), tem_mode, tem_subreg_mode);
1166 return tem;
1167 case ASM_OPERANDS:
1168 /* Don't do any replacements in second and following
1169 ASM_OPERANDS of inline-asm with multiple sets.
1170 ASM_OPERANDS_INPUT_VEC, ASM_OPERANDS_INPUT_CONSTRAINT_VEC
1171 and ASM_OPERANDS_LABEL_VEC need to be equal between
1172 all the ASM_OPERANDs in the insn and adjust_insn will
1173 fix this up. */
1174 if (ASM_OPERANDS_OUTPUT_IDX (loc)(((loc)->u.fld[2]).rt_int) != 0)
1175 return loc;
1176 break;
1177 default:
1178 break;
1179 }
1180 return NULL_RTX(rtx) 0;
1181}
1182
1183/* Helper function for replacement of uses. */
1184
1185static void
1186adjust_mem_uses (rtx *x, void *data)
1187{
1188 rtx new_x = simplify_replace_fn_rtx (*x, NULL_RTX(rtx) 0, adjust_mems, data);
1189 if (new_x != *x)
1190 validate_change (NULL_RTX(rtx) 0, x, new_x, true);
1191}
1192
1193/* Helper function for replacement of stores. */
1194
1195static void
1196adjust_mem_stores (rtx loc, const_rtx expr, void *data)
1197{
1198 if (MEM_P (loc)(((enum rtx_code) (loc)->code) == MEM))
1199 {
1200 rtx new_dest = simplify_replace_fn_rtx (SET_DEST (expr)(((expr)->u.fld[0]).rt_rtx), NULL_RTX(rtx) 0,
1201 adjust_mems, data);
1202 if (new_dest != SET_DEST (expr)(((expr)->u.fld[0]).rt_rtx))
1203 {
1204 rtx xexpr = CONST_CAST_RTX (expr)(const_cast<struct rtx_def *> (((expr))));
1205 validate_change (NULL_RTX(rtx) 0, &SET_DEST (xexpr)(((xexpr)->u.fld[0]).rt_rtx), new_dest, true);
1206 }
1207 }
1208}
1209
1210/* Simplify INSN. Remove all {PRE,POST}_{INC,DEC,MODIFY} rtxes,
1211 replace them with their value in the insn and add the side-effects
1212 as other sets to the insn. */
1213
1214static void
1215adjust_insn (basic_block bb, rtx_insn *insn)
1216{
1217 rtx set;
1218
1219#ifdef HAVE_window_save
1220 /* If the target machine has an explicit window save instruction, the
1221 transformation OUTGOING_REGNO -> INCOMING_REGNO is done there. */
1222 if (RTX_FRAME_RELATED_P (insn)(__extension__ ({ __typeof ((insn)) const _rtx = ((insn)); if
(((enum rtx_code) (_rtx)->code) != DEBUG_INSN && (
(enum rtx_code) (_rtx)->code) != INSN && ((enum rtx_code
) (_rtx)->code) != CALL_INSN && ((enum rtx_code) (
_rtx)->code) != JUMP_INSN && ((enum rtx_code) (_rtx
)->code) != BARRIER && ((enum rtx_code) (_rtx)->
code) != SET) rtl_check_failed_flag ("RTX_FRAME_RELATED_P",_rtx
, "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 1222, __FUNCTION__); _rtx; })->frame_related)
1223 && find_reg_note (insn, REG_CFA_WINDOW_SAVE, NULL_RTX(rtx) 0))
1224 {
1225 unsigned int i, nregs = vec_safe_length (windowed_parm_regs);
1226 rtx rtl = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (nregs * 2))gen_rtx_fmt_E_stat ((PARALLEL), ((((void) 0, E_VOIDmode))), (
(rtvec_alloc (nregs * 2))) )
;
1227 parm_reg *p;
1228
1229 FOR_EACH_VEC_SAFE_ELT (windowed_parm_regs, i, p)for (i = 0; vec_safe_iterate ((windowed_parm_regs), (i), &
(p)); ++(i))
1230 {
1231 XVECEXP (rtl, 0, i * 2)(((((rtl)->u.fld[0]).rt_rtvec))->elem[i * 2])
1232 = gen_rtx_SET (p->incoming, p->outgoing)gen_rtx_fmt_ee_stat ((SET), (((void) 0, E_VOIDmode)), ((p->
incoming)), ((p->outgoing)) )
;
1233 /* Do not clobber the attached DECL, but only the REG. */
1234 XVECEXP (rtl, 0, i * 2 + 1)(((((rtl)->u.fld[0]).rt_rtvec))->elem[i * 2 + 1])
1235 = gen_rtx_CLOBBER (GET_MODE (p->outgoing),gen_rtx_fmt_e_stat ((CLOBBER), ((((machine_mode) (p->outgoing
)->mode))), ((gen_raw_REG (((machine_mode) (p->outgoing
)->mode), (rhs_regno(p->outgoing))))) )
1236 gen_raw_REG (GET_MODE (p->outgoing),gen_rtx_fmt_e_stat ((CLOBBER), ((((machine_mode) (p->outgoing
)->mode))), ((gen_raw_REG (((machine_mode) (p->outgoing
)->mode), (rhs_regno(p->outgoing))))) )
1237 REGNO (p->outgoing)))gen_rtx_fmt_e_stat ((CLOBBER), ((((machine_mode) (p->outgoing
)->mode))), ((gen_raw_REG (((machine_mode) (p->outgoing
)->mode), (rhs_regno(p->outgoing))))) )
;
1238 }
1239
1240 validate_change (NULL_RTX(rtx) 0, &PATTERN (insn), rtl, true);
1241 return;
1242 }
1243#endif
1244
1245 adjust_mem_data amd;
1246 amd.mem_mode = VOIDmode((void) 0, E_VOIDmode);
1247 amd.stack_adjust = -VTI (bb)((variable_tracking_info *) (bb)->aux)->out.stack_adjust;
1248
1249 amd.store = true;
1250 note_stores (insn, adjust_mem_stores, &amd);
1251
1252 amd.store = false;
1253 if (GET_CODE (PATTERN (insn))((enum rtx_code) (PATTERN (insn))->code) == PARALLEL
1254 && asm_noperands (PATTERN (insn)) > 0
1255 && GET_CODE (XVECEXP (PATTERN (insn), 0, 0))((enum rtx_code) ((((((PATTERN (insn))->u.fld[0]).rt_rtvec
))->elem[0]))->code)
== SET)
1256 {
1257 rtx body, set0;
1258 int i;
1259
1260 /* inline-asm with multiple sets is tiny bit more complicated,
1261 because the 3 vectors in ASM_OPERANDS need to be shared between
1262 all ASM_OPERANDS in the instruction. adjust_mems will
1263 not touch ASM_OPERANDS other than the first one, asm_noperands
1264 test above needs to be called before that (otherwise it would fail)
1265 and afterwards this code fixes it up. */
1266 note_uses (&PATTERN (insn), adjust_mem_uses, &amd);
1267 body = PATTERN (insn);
1268 set0 = XVECEXP (body, 0, 0)(((((body)->u.fld[0]).rt_rtvec))->elem[0]);
1269 gcc_checking_assert (GET_CODE (set0) == SET((void)(!(((enum rtx_code) (set0)->code) == SET &&
((enum rtx_code) ((((set0)->u.fld[1]).rt_rtx))->code) ==
ASM_OPERANDS && ((((((set0)->u.fld[1]).rt_rtx))->
u.fld[2]).rt_int) == 0) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 1271, __FUNCTION__), 0 : 0))
1270 && GET_CODE (SET_SRC (set0)) == ASM_OPERANDS((void)(!(((enum rtx_code) (set0)->code) == SET &&
((enum rtx_code) ((((set0)->u.fld[1]).rt_rtx))->code) ==
ASM_OPERANDS && ((((((set0)->u.fld[1]).rt_rtx))->
u.fld[2]).rt_int) == 0) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 1271, __FUNCTION__), 0 : 0))
1271 && ASM_OPERANDS_OUTPUT_IDX (SET_SRC (set0)) == 0)((void)(!(((enum rtx_code) (set0)->code) == SET &&
((enum rtx_code) ((((set0)->u.fld[1]).rt_rtx))->code) ==
ASM_OPERANDS && ((((((set0)->u.fld[1]).rt_rtx))->
u.fld[2]).rt_int) == 0) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 1271, __FUNCTION__), 0 : 0))
;
1272 for (i = 1; i < XVECLEN (body, 0)(((((body)->u.fld[0]).rt_rtvec))->num_elem); i++)
1273 if (GET_CODE (XVECEXP (body, 0, i))((enum rtx_code) ((((((body)->u.fld[0]).rt_rtvec))->elem
[i]))->code)
!= SET)
1274 break;
1275 else
1276 {
1277 set = XVECEXP (body, 0, i)(((((body)->u.fld[0]).rt_rtvec))->elem[i]);
1278 gcc_checking_assert (GET_CODE (SET_SRC (set)) == ASM_OPERANDS((void)(!(((enum rtx_code) ((((set)->u.fld[1]).rt_rtx))->
code) == ASM_OPERANDS && ((((((set)->u.fld[1]).rt_rtx
))->u.fld[2]).rt_int) == i) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 1280, __FUNCTION__), 0 : 0))
1279 && ASM_OPERANDS_OUTPUT_IDX (SET_SRC (set))((void)(!(((enum rtx_code) ((((set)->u.fld[1]).rt_rtx))->
code) == ASM_OPERANDS && ((((((set)->u.fld[1]).rt_rtx
))->u.fld[2]).rt_int) == i) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 1280, __FUNCTION__), 0 : 0))
1280 == i)((void)(!(((enum rtx_code) ((((set)->u.fld[1]).rt_rtx))->
code) == ASM_OPERANDS && ((((((set)->u.fld[1]).rt_rtx
))->u.fld[2]).rt_int) == i) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 1280, __FUNCTION__), 0 : 0))
;
1281 if (ASM_OPERANDS_INPUT_VEC (SET_SRC (set))((((((set)->u.fld[1]).rt_rtx))->u.fld[3]).rt_rtvec)
1282 != ASM_OPERANDS_INPUT_VEC (SET_SRC (set0))((((((set0)->u.fld[1]).rt_rtx))->u.fld[3]).rt_rtvec)
1283 || ASM_OPERANDS_INPUT_CONSTRAINT_VEC (SET_SRC (set))((((((set)->u.fld[1]).rt_rtx))->u.fld[4]).rt_rtvec)
1284 != ASM_OPERANDS_INPUT_CONSTRAINT_VEC (SET_SRC (set0))((((((set0)->u.fld[1]).rt_rtx))->u.fld[4]).rt_rtvec)
1285 || ASM_OPERANDS_LABEL_VEC (SET_SRC (set))((((((set)->u.fld[1]).rt_rtx))->u.fld[5]).rt_rtvec)
1286 != ASM_OPERANDS_LABEL_VEC (SET_SRC (set0))((((((set0)->u.fld[1]).rt_rtx))->u.fld[5]).rt_rtvec))
1287 {
1288 rtx newsrc = shallow_copy_rtx (SET_SRC (set)(((set)->u.fld[1]).rt_rtx));
1289 ASM_OPERANDS_INPUT_VEC (newsrc)(((newsrc)->u.fld[3]).rt_rtvec)
1290 = ASM_OPERANDS_INPUT_VEC (SET_SRC (set0))((((((set0)->u.fld[1]).rt_rtx))->u.fld[3]).rt_rtvec);
1291 ASM_OPERANDS_INPUT_CONSTRAINT_VEC (newsrc)(((newsrc)->u.fld[4]).rt_rtvec)
1292 = ASM_OPERANDS_INPUT_CONSTRAINT_VEC (SET_SRC (set0))((((((set0)->u.fld[1]).rt_rtx))->u.fld[4]).rt_rtvec);
1293 ASM_OPERANDS_LABEL_VEC (newsrc)(((newsrc)->u.fld[5]).rt_rtvec)
1294 = ASM_OPERANDS_LABEL_VEC (SET_SRC (set0))((((((set0)->u.fld[1]).rt_rtx))->u.fld[5]).rt_rtvec);
1295 validate_change (NULL_RTX(rtx) 0, &SET_SRC (set)(((set)->u.fld[1]).rt_rtx), newsrc, true);
1296 }
1297 }
1298 }
1299 else
1300 note_uses (&PATTERN (insn), adjust_mem_uses, &amd);
1301
1302 /* For read-only MEMs containing some constant, prefer those
1303 constants. */
1304 set = single_set (insn);
1305 if (set && MEM_P (SET_SRC (set))(((enum rtx_code) ((((set)->u.fld[1]).rt_rtx))->code) ==
MEM)
&& MEM_READONLY_P (SET_SRC (set))(__extension__ ({ __typeof (((((set)->u.fld[1]).rt_rtx))) const
_rtx = (((((set)->u.fld[1]).rt_rtx))); if (((enum rtx_code
) (_rtx)->code) != MEM) rtl_check_failed_flag ("MEM_READONLY_P"
, _rtx, "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 1305, __FUNCTION__); _rtx; })->unchanging)
)
1306 {
1307 rtx note = find_reg_equal_equiv_note (insn);
1308
1309 if (note && CONSTANT_P (XEXP (note, 0))((rtx_class[(int) (((enum rtx_code) ((((note)->u.fld[0]).rt_rtx
))->code))]) == RTX_CONST_OBJ)
)
1310 validate_change (NULL_RTX(rtx) 0, &SET_SRC (set)(((set)->u.fld[1]).rt_rtx), XEXP (note, 0)(((note)->u.fld[0]).rt_rtx), true);
1311 }
1312
1313 if (!amd.side_effects.is_empty ())
1314 {
1315 rtx *pat, new_pat;
1316 int i, oldn;
1317
1318 pat = &PATTERN (insn);
1319 if (GET_CODE (*pat)((enum rtx_code) (*pat)->code) == COND_EXEC)
1320 pat = &COND_EXEC_CODE (*pat)(((*pat)->u.fld[1]).rt_rtx);
1321 if (GET_CODE (*pat)((enum rtx_code) (*pat)->code) == PARALLEL)
1322 oldn = XVECLEN (*pat, 0)(((((*pat)->u.fld[0]).rt_rtvec))->num_elem);
1323 else
1324 oldn = 1;
1325 unsigned int newn = amd.side_effects.length ();
1326 new_pat = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (oldn + newn))gen_rtx_fmt_E_stat ((PARALLEL), ((((void) 0, E_VOIDmode))), (
(rtvec_alloc (oldn + newn))) )
;
1327 if (GET_CODE (*pat)((enum rtx_code) (*pat)->code) == PARALLEL)
1328 for (i = 0; i < oldn; i++)
1329 XVECEXP (new_pat, 0, i)(((((new_pat)->u.fld[0]).rt_rtvec))->elem[i]) = XVECEXP (*pat, 0, i)(((((*pat)->u.fld[0]).rt_rtvec))->elem[i]);
1330 else
1331 XVECEXP (new_pat, 0, 0)(((((new_pat)->u.fld[0]).rt_rtvec))->elem[0]) = *pat;
1332
1333 rtx effect;
1334 unsigned int j;
1335 FOR_EACH_VEC_ELT_REVERSE (amd.side_effects, j, effect)for (j = (amd.side_effects).length () - 1; (amd.side_effects)
.iterate ((j), &(effect)); (j)--)
1336 XVECEXP (new_pat, 0, j + oldn)(((((new_pat)->u.fld[0]).rt_rtvec))->elem[j + oldn]) = effect;
1337 validate_change (NULL_RTX(rtx) 0, pat, new_pat, true);
1338 }
1339}
1340
1341/* Return the DEBUG_EXPR of a DEBUG_EXPR_DECL or the VALUE in DV. */
1342static inline rtx
1343dv_as_rtx (decl_or_value dv)
1344{
1345 tree decl;
1346
1347 if (dv_is_value_p (dv))
1348 return dv_as_value (dv);
1349
1350 decl = dv_as_decl (dv);
1351
1352 gcc_checking_assert (TREE_CODE (decl) == DEBUG_EXPR_DECL)((void)(!(((enum tree_code) (decl)->base.code) == DEBUG_EXPR_DECL
) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 1352, __FUNCTION__), 0 : 0))
;
1353 return DECL_RTL_KNOWN_SET (decl)__extension__ ({ tree const __d = (decl); ((void)(!((((tree_contains_struct
[(((enum tree_code) (__d)->base.code))][(TS_DECL_WRTL)])) &&
(contains_struct_check ((__d), (TS_DECL_WRTL), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 1353, __FUNCTION__))->decl_with_rtl.rtl != nullptr)) ? fancy_abort
("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 1353, __FUNCTION__), 0 : 0)); &*((((tree_contains_struct
[(((enum tree_code) (__d)->base.code))][(TS_DECL_WRTL)])) &&
(contains_struct_check ((__d), (TS_DECL_WRTL), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 1353, __FUNCTION__))->decl_with_rtl.rtl != nullptr) ? ((
contains_struct_check ((__d), (TS_DECL_WRTL), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 1353, __FUNCTION__))->decl_with_rtl.rtl ? (__d)->decl_with_rtl
.rtl : (make_decl_rtl (__d), (__d)->decl_with_rtl.rtl)) : nullptr
); })
;
1354}
1355
1356/* Return nonzero if a decl_or_value must not have more than one
1357 variable part. The returned value discriminates among various
1358 kinds of one-part DVs ccording to enum onepart_enum. */
1359static inline onepart_enum
1360dv_onepart_p (decl_or_value dv)
1361{
1362 tree decl;
1363
1364 if (!MAY_HAVE_DEBUG_BIND_INSNSglobal_options.x_flag_var_tracking_assignments)
1365 return NOT_ONEPART;
1366
1367 if (dv_is_value_p (dv))
1368 return ONEPART_VALUE;
1369
1370 decl = dv_as_decl (dv);
1371
1372 if (TREE_CODE (decl)((enum tree_code) (decl)->base.code) == DEBUG_EXPR_DECL)
1373 return ONEPART_DEXPR;
1374
1375 if (target_for_debug_bind (decl) != NULL_TREE(tree) nullptr)
1376 return ONEPART_VDECL;
1377
1378 return NOT_ONEPART;
1379}
1380
1381/* Return the variable pool to be used for a dv of type ONEPART. */
1382static inline pool_allocator &
1383onepart_pool (onepart_enum onepart)
1384{
1385 return onepart ? valvar_pool : var_pool;
1386}
1387
1388/* Allocate a variable_def from the corresponding variable pool. */
1389static inline variable *
1390onepart_pool_allocate (onepart_enum onepart)
1391{
1392 return (variable*) onepart_pool (onepart).allocate ();
1393}
1394
1395/* Build a decl_or_value out of a decl. */
1396static inline decl_or_value
1397dv_from_decl (tree decl)
1398{
1399 decl_or_value dv;
1400 dv = decl;
1401 gcc_checking_assert (dv_is_decl_p (dv))((void)(!(dv_is_decl_p (dv)) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 1401, __FUNCTION__), 0 : 0))
;
1402 return dv;
1403}
1404
1405/* Build a decl_or_value out of a value. */
1406static inline decl_or_value
1407dv_from_value (rtx value)
1408{
1409 decl_or_value dv;
1410 dv = value;
1411 gcc_checking_assert (dv_is_value_p (dv))((void)(!(dv_is_value_p (dv)) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 1411, __FUNCTION__), 0 : 0))
;
1412 return dv;
1413}
1414
1415/* Return a value or the decl of a debug_expr as a decl_or_value. */
1416static inline decl_or_value
1417dv_from_rtx (rtx x)
1418{
1419 decl_or_value dv;
1420
1421 switch (GET_CODE (x)((enum rtx_code) (x)->code))
1422 {
1423 case DEBUG_EXPR:
1424 dv = dv_from_decl (DEBUG_EXPR_TREE_DECL (x)(((x)->u.fld[0]).rt_tree));
1425 gcc_checking_assert (DECL_RTL_KNOWN_SET (DEBUG_EXPR_TREE_DECL (x)) == x)((void)(!(__extension__ ({ tree const __d = ((((x)->u.fld[
0]).rt_tree)); ((void)(!((((tree_contains_struct[(((enum tree_code
) (__d)->base.code))][(TS_DECL_WRTL)])) && (contains_struct_check
((__d), (TS_DECL_WRTL), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 1425, __FUNCTION__))->decl_with_rtl.rtl != nullptr)) ? fancy_abort
("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 1425, __FUNCTION__), 0 : 0)); &*((((tree_contains_struct
[(((enum tree_code) (__d)->base.code))][(TS_DECL_WRTL)])) &&
(contains_struct_check ((__d), (TS_DECL_WRTL), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 1425, __FUNCTION__))->decl_with_rtl.rtl != nullptr) ? ((
contains_struct_check ((__d), (TS_DECL_WRTL), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 1425, __FUNCTION__))->decl_with_rtl.rtl ? (__d)->decl_with_rtl
.rtl : (make_decl_rtl (__d), (__d)->decl_with_rtl.rtl)) : nullptr
); }) == x) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 1425, __FUNCTION__), 0 : 0))
;
1426 break;
1427
1428 case VALUE:
1429 dv = dv_from_value (x);
1430 break;
1431
1432 default:
1433 gcc_unreachable ()(fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 1433, __FUNCTION__))
;
1434 }
1435
1436 return dv;
1437}
1438
1439extern void debug_dv (decl_or_value dv);
1440
1441DEBUG_FUNCTION__attribute__ ((__used__)) void
1442debug_dv (decl_or_value dv)
1443{
1444 if (dv_is_value_p (dv))
1445 debug_rtx (dv_as_value (dv));
1446 else
1447 debug_generic_stmt (dv_as_decl (dv));
1448}
1449
1450static void loc_exp_dep_clear (variable *var);
1451
1452/* Free the element of VARIABLE_HTAB (its type is struct variable_def). */
1453
1454static void
1455variable_htab_free (void *elem)
1456{
1457 int i;
1458 variable *var = (variable *) elem;
1459 location_chain *node, *next;
1460
1461 gcc_checking_assert (var->refcount > 0)((void)(!(var->refcount > 0) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 1461, __FUNCTION__), 0 : 0))
;
1462
1463 var->refcount--;
1464 if (var->refcount > 0)
1465 return;
1466
1467 for (i = 0; i < var->n_var_parts; i++)
1468 {
1469 for (node = var->var_part[i].loc_chain; node; node = next)
1470 {
1471 next = node->next;
1472 delete node;
1473 }
1474 var->var_part[i].loc_chain = NULLnullptr;
1475 }
1476 if (var->onepart && VAR_LOC_1PAUX (var)__extension__ (*({ variable *const __v = (var); ((void)(!(__v
->onepart) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 1476, __FUNCTION__), 0 : 0)); &__v->var_part[0].aux.
onepaux; }))
)
1477 {
1478 loc_exp_dep_clear (var);
1479 if (VAR_LOC_DEP_LST (var)(__extension__ (*({ variable *const __v = (var); ((void)(!(__v
->onepart) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 1479, __FUNCTION__), 0 : 0)); &__v->var_part[0].aux.
onepaux; })) ? __extension__ (*({ variable *const __v = (var)
; ((void)(!(__v->onepart) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 1479, __FUNCTION__), 0 : 0)); &__v->var_part[0].aux.
onepaux; }))->backlinks : nullptr)
)
1480 VAR_LOC_DEP_LST (var)(__extension__ (*({ variable *const __v = (var); ((void)(!(__v
->onepart) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 1480, __FUNCTION__), 0 : 0)); &__v->var_part[0].aux.
onepaux; })) ? __extension__ (*({ variable *const __v = (var)
; ((void)(!(__v->onepart) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 1480, __FUNCTION__), 0 : 0)); &__v->var_part[0].aux.
onepaux; }))->backlinks : nullptr)
->pprev = NULLnullptr;
1481 XDELETE (VAR_LOC_1PAUX (var))free ((void*) (__extension__ (*({ variable *const __v = (var)
; ((void)(!(__v->onepart) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 1481, __FUNCTION__), 0 : 0)); &__v->var_part[0].aux.
onepaux; }))))
;
1482 /* These may be reused across functions, so reset
1483 e.g. NO_LOC_P. */
1484 if (var->onepart == ONEPART_DEXPR)
1485 set_dv_changed (var->dv, true);
1486 }
1487 onepart_pool (var->onepart).remove (var);
1488}
1489
1490/* Initialize the set (array) SET of attrs to empty lists. */
1491
1492static void
1493init_attrs_list_set (attrs **set)
1494{
1495 int i;
1496
1497 for (i = 0; i < FIRST_PSEUDO_REGISTER76; i++)
1498 set[i] = NULLnullptr;
1499}
1500
1501/* Make the list *LISTP empty. */
1502
1503static void
1504attrs_list_clear (attrs **listp)
1505{
1506 attrs *list, *next;
1507
1508 for (list = *listp; list; list = next)
1509 {
1510 next = list->next;
1511 delete list;
1512 }
1513 *listp = NULLnullptr;
1514}
1515
1516/* Return true if the pair of DECL and OFFSET is the member of the LIST. */
1517
1518static attrs *
1519attrs_list_member (attrs *list, decl_or_value dv, HOST_WIDE_INTlong offset)
1520{
1521 for (; list; list = list->next)
1522 if (dv_as_opaque (list->dv) == dv_as_opaque (dv) && list->offset == offset)
1523 return list;
1524 return NULLnullptr;
1525}
1526
1527/* Insert the triplet DECL, OFFSET, LOC to the list *LISTP. */
1528
1529static void
1530attrs_list_insert (attrs **listp, decl_or_value dv,
1531 HOST_WIDE_INTlong offset, rtx loc)
1532{
1533 attrs *list = new attrs;
1534 list->loc = loc;
1535 list->dv = dv;
1536 list->offset = offset;
1537 list->next = *listp;
1538 *listp = list;
1539}
1540
1541/* Copy all nodes from SRC and create a list *DSTP of the copies. */
1542
1543static void
1544attrs_list_copy (attrs **dstp, attrs *src)
1545{
1546 attrs_list_clear (dstp);
1547 for (; src; src = src->next)
1548 {
1549 attrs *n = new attrs;
1550 n->loc = src->loc;
1551 n->dv = src->dv;
1552 n->offset = src->offset;
1553 n->next = *dstp;
1554 *dstp = n;
1555 }
1556}
1557
1558/* Add all nodes from SRC which are not in *DSTP to *DSTP. */
1559
1560static void
1561attrs_list_union (attrs **dstp, attrs *src)
1562{
1563 for (; src; src = src->next)
1564 {
1565 if (!attrs_list_member (*dstp, src->dv, src->offset))
1566 attrs_list_insert (dstp, src->dv, src->offset, src->loc);
1567 }
1568}
1569
1570/* Combine nodes that are not onepart nodes from SRC and SRC2 into
1571 *DSTP. */
1572
1573static void
1574attrs_list_mpdv_union (attrs **dstp, attrs *src, attrs *src2)
1575{
1576 gcc_assert (!*dstp)((void)(!(!*dstp) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 1576, __FUNCTION__), 0 : 0))
;
1577 for (; src; src = src->next)
1578 {
1579 if (!dv_onepart_p (src->dv))
1580 attrs_list_insert (dstp, src->dv, src->offset, src->loc);
1581 }
1582 for (src = src2; src; src = src->next)
1583 {
1584 if (!dv_onepart_p (src->dv)
1585 && !attrs_list_member (*dstp, src->dv, src->offset))
1586 attrs_list_insert (dstp, src->dv, src->offset, src->loc);
1587 }
1588}
1589
1590/* Shared hashtable support. */
1591
1592/* Return true if VARS is shared. */
1593
1594static inline bool
1595shared_hash_shared (shared_hash *vars)
1596{
1597 return vars->refcount > 1;
1598}
1599
1600/* Return the hash table for VARS. */
1601
1602static inline variable_table_type *
1603shared_hash_htab (shared_hash *vars)
1604{
1605 return vars->htab;
1606}
1607
1608/* Return true if VAR is shared, or maybe because VARS is shared. */
1609
1610static inline bool
1611shared_var_p (variable *var, shared_hash *vars)
1612{
1613 /* Don't count an entry in the changed_variables table as a duplicate. */
1614 return ((var->refcount > 1 + (int) var->in_changed_variables)
1615 || shared_hash_shared (vars));
1616}
1617
1618/* Copy variables into a new hash table. */
1619
1620static shared_hash *
1621shared_hash_unshare (shared_hash *vars)
1622{
1623 shared_hash *new_vars = new shared_hash;
1624 gcc_assert (vars->refcount > 1)((void)(!(vars->refcount > 1) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 1624, __FUNCTION__), 0 : 0))
;
1625 new_vars->refcount = 1;
1626 new_vars->htab = new variable_table_type (vars->htab->elements () + 3);
1627 vars_copy (new_vars->htab, vars->htab);
1628 vars->refcount--;
1629 return new_vars;
1630}
1631
1632/* Increment reference counter on VARS and return it. */
1633
1634static inline shared_hash *
1635shared_hash_copy (shared_hash *vars)
1636{
1637 vars->refcount++;
1638 return vars;
1639}
1640
1641/* Decrement reference counter and destroy hash table if not shared
1642 anymore. */
1643
1644static void
1645shared_hash_destroy (shared_hash *vars)
1646{
1647 gcc_checking_assert (vars->refcount > 0)((void)(!(vars->refcount > 0) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 1647, __FUNCTION__), 0 : 0))
;
1648 if (--vars->refcount == 0)
1649 {
1650 delete vars->htab;
1651 delete vars;
1652 }
1653}
1654
1655/* Unshare *PVARS if shared and return slot for DV. If INS is
1656 INSERT, insert it if not already present. */
1657
1658static inline variable **
1659shared_hash_find_slot_unshare_1 (shared_hash **pvars, decl_or_value dv,
1660 hashval_t dvhash, enum insert_option ins)
1661{
1662 if (shared_hash_shared (*pvars))
1663 *pvars = shared_hash_unshare (*pvars);
1664 return shared_hash_htab (*pvars)->find_slot_with_hash (dv, dvhash, ins);
1665}
1666
1667static inline variable **
1668shared_hash_find_slot_unshare (shared_hash **pvars, decl_or_value dv,
1669 enum insert_option ins)
1670{
1671 return shared_hash_find_slot_unshare_1 (pvars, dv, dv_htab_hash (dv), ins);
1672}
1673
1674/* Return slot for DV, if it is already present in the hash table.
1675 If it is not present, insert it only VARS is not shared, otherwise
1676 return NULL. */
1677
1678static inline variable **
1679shared_hash_find_slot_1 (shared_hash *vars, decl_or_value dv, hashval_t dvhash)
1680{
1681 return shared_hash_htab (vars)->find_slot_with_hash (dv, dvhash,
1682 shared_hash_shared (vars)
1683 ? NO_INSERT : INSERT);
1684}
1685
1686static inline variable **
1687shared_hash_find_slot (shared_hash *vars, decl_or_value dv)
1688{
1689 return shared_hash_find_slot_1 (vars, dv, dv_htab_hash (dv));
1690}
1691
1692/* Return slot for DV only if it is already present in the hash table. */
1693
1694static inline variable **
1695shared_hash_find_slot_noinsert_1 (shared_hash *vars, decl_or_value dv,
1696 hashval_t dvhash)
1697{
1698 return shared_hash_htab (vars)->find_slot_with_hash (dv, dvhash, NO_INSERT);
1699}
1700
1701static inline variable **
1702shared_hash_find_slot_noinsert (shared_hash *vars, decl_or_value dv)
1703{
1704 return shared_hash_find_slot_noinsert_1 (vars, dv, dv_htab_hash (dv));
1705}
1706
1707/* Return variable for DV or NULL if not already present in the hash
1708 table. */
1709
1710static inline variable *
1711shared_hash_find_1 (shared_hash *vars, decl_or_value dv, hashval_t dvhash)
1712{
1713 return shared_hash_htab (vars)->find_with_hash (dv, dvhash);
1714}
1715
1716static inline variable *
1717shared_hash_find (shared_hash *vars, decl_or_value dv)
1718{
1719 return shared_hash_find_1 (vars, dv, dv_htab_hash (dv));
1720}
1721
1722/* Return true if TVAL is better than CVAL as a canonival value. We
1723 choose lowest-numbered VALUEs, using the RTX address as a
1724 tie-breaker. The idea is to arrange them into a star topology,
1725 such that all of them are at most one step away from the canonical
1726 value, and the canonical value has backlinks to all of them, in
1727 addition to all the actual locations. We don't enforce this
1728 topology throughout the entire dataflow analysis, though.
1729 */
1730
1731static inline bool
1732canon_value_cmp (rtx tval, rtx cval)
1733{
1734 return !cval
1735 || CSELIB_VAL_PTR (tval)(((tval)->u.fld[0]).rt_cselib)->uid < CSELIB_VAL_PTR (cval)(((cval)->u.fld[0]).rt_cselib)->uid;
1736}
1737
1738static bool dst_can_be_shared;
1739
1740/* Return a copy of a variable VAR and insert it to dataflow set SET. */
1741
1742static variable **
1743unshare_variable (dataflow_set *set, variable **slot, variable *var,
1744 enum var_init_status initialized)
1745{
1746 variable *new_var;
1747 int i;
1748
1749 new_var = onepart_pool_allocate (var->onepart);
1750 new_var->dv = var->dv;
1751 new_var->refcount = 1;
1752 var->refcount--;
1753 new_var->n_var_parts = var->n_var_parts;
1754 new_var->onepart = var->onepart;
1755 new_var->in_changed_variables = false;
1756
1757 if (! flag_var_tracking_uninitglobal_options.x_flag_var_tracking_uninit)
1758 initialized = VAR_INIT_STATUS_INITIALIZED;
1759
1760 for (i = 0; i < var->n_var_parts; i++)
1761 {
1762 location_chain *node;
1763 location_chain **nextp;
1764
1765 if (i == 0 && var->onepart)
1766 {
1767 /* One-part auxiliary data is only used while emitting
1768 notes, so propagate it to the new variable in the active
1769 dataflow set. If we're not emitting notes, this will be
1770 a no-op. */
1771 gcc_checking_assert (!VAR_LOC_1PAUX (var) || emit_notes)((void)(!(!__extension__ (*({ variable *const __v = (var); ((
void)(!(__v->onepart) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 1771, __FUNCTION__), 0 : 0)); &__v->var_part[0].aux.
onepaux; })) || emit_notes) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 1771, __FUNCTION__), 0 : 0))
;
1772 VAR_LOC_1PAUX (new_var)__extension__ (*({ variable *const __v = (new_var); ((void)(!
(__v->onepart) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 1772, __FUNCTION__), 0 : 0)); &__v->var_part[0].aux.
onepaux; }))
= VAR_LOC_1PAUX (var)__extension__ (*({ variable *const __v = (var); ((void)(!(__v
->onepart) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 1772, __FUNCTION__), 0 : 0)); &__v->var_part[0].aux.
onepaux; }))
;
1773 VAR_LOC_1PAUX (var)__extension__ (*({ variable *const __v = (var); ((void)(!(__v
->onepart) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 1773, __FUNCTION__), 0 : 0)); &__v->var_part[0].aux.
onepaux; }))
= NULLnullptr;
1774 }
1775 else
1776 VAR_PART_OFFSET (new_var, i)__extension__ (*({ variable *const __v = (new_var); ((void)(!
(!__v->onepart) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 1776, __FUNCTION__), 0 : 0)); &__v->var_part[(i)].aux
.offset; }))
= VAR_PART_OFFSET (var, i)__extension__ (*({ variable *const __v = (var); ((void)(!(!__v
->onepart) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 1776, __FUNCTION__), 0 : 0)); &__v->var_part[(i)].aux
.offset; }))
;
1777 nextp = &new_var->var_part[i].loc_chain;
1778 for (node = var->var_part[i].loc_chain; node; node = node->next)
1779 {
1780 location_chain *new_lc;
1781
1782 new_lc = new location_chain;
1783 new_lc->next = NULLnullptr;
1784 if (node->init > initialized)
1785 new_lc->init = node->init;
1786 else
1787 new_lc->init = initialized;
1788 if (node->set_src && !(MEM_P (node->set_src)(((enum rtx_code) (node->set_src)->code) == MEM)))
1789 new_lc->set_src = node->set_src;
1790 else
1791 new_lc->set_src = NULLnullptr;
1792 new_lc->loc = node->loc;
1793
1794 *nextp = new_lc;
1795 nextp = &new_lc->next;
1796 }
1797
1798 new_var->var_part[i].cur_loc = var->var_part[i].cur_loc;
1799 }
1800
1801 dst_can_be_shared = false;
1802 if (shared_hash_shared (set->vars))
1803 slot = shared_hash_find_slot_unshare (&set->vars, var->dv, NO_INSERT);
1804 else if (set->traversed_vars && set->vars != set->traversed_vars)
1805 slot = shared_hash_find_slot_noinsert (set->vars, var->dv);
1806 *slot = new_var;
1807 if (var->in_changed_variables)
1808 {
1809 variable **cslot
1810 = changed_variables->find_slot_with_hash (var->dv,
1811 dv_htab_hash (var->dv),
1812 NO_INSERT);
1813 gcc_assert (*cslot == (void *) var)((void)(!(*cslot == (void *) var) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 1813, __FUNCTION__), 0 : 0))
;
1814 var->in_changed_variables = false;
1815 variable_htab_free (var);
1816 *cslot = new_var;
1817 new_var->in_changed_variables = true;
1818 }
1819 return slot;
1820}
1821
1822/* Copy all variables from hash table SRC to hash table DST. */
1823
1824static void
1825vars_copy (variable_table_type *dst, variable_table_type *src)
1826{
1827 variable_iterator_type hi;
1828 variable *var;
1829
1830 FOR_EACH_HASH_TABLE_ELEMENT (*src, var, variable, hi)for ((hi) = (*src).begin (); (hi) != (*src).end () ? (var = *
(hi) , true) : false; ++(hi))
1831 {
1832 variable **dstp;
1833 var->refcount++;
1834 dstp = dst->find_slot_with_hash (var->dv, dv_htab_hash (var->dv),
1835 INSERT);
1836 *dstp = var;
1837 }
1838}
1839
1840/* Map a decl to its main debug decl. */
1841
1842static inline tree
1843var_debug_decl (tree decl)
1844{
1845 if (decl && VAR_P (decl)(((enum tree_code) (decl)->base.code) == VAR_DECL) && DECL_HAS_DEBUG_EXPR_P (decl)((tree_check ((decl), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 1845, __FUNCTION__, (VAR_DECL)))->decl_common.debug_expr_is_from
)
)
1846 {
1847 tree debugdecl = DECL_DEBUG_EXPR (decl)(decl_debug_expr_lookup ((tree_check ((decl), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 1847, __FUNCTION__, (VAR_DECL)))))
;
1848 if (DECL_P (debugdecl)(tree_code_type[(int) (((enum tree_code) (debugdecl)->base
.code))] == tcc_declaration)
)
1849 decl = debugdecl;
1850 }
1851
1852 return decl;
1853}
1854
1855/* Set the register LOC to contain DV, OFFSET. */
1856
1857static void
1858var_reg_decl_set (dataflow_set *set, rtx loc, enum var_init_status initialized,
1859 decl_or_value dv, HOST_WIDE_INTlong offset, rtx set_src,
1860 enum insert_option iopt)
1861{
1862 attrs *node;
1863 bool decl_p = dv_is_decl_p (dv);
1864
1865 if (decl_p)
1866 dv = dv_from_decl (var_debug_decl (dv_as_decl (dv)));
1867
1868 for (node = set->regs[REGNO (loc)(rhs_regno(loc))]; node; node = node->next)
1869 if (dv_as_opaque (node->dv) == dv_as_opaque (dv)
1870 && node->offset == offset)
1871 break;
1872 if (!node)
1873 attrs_list_insert (&set->regs[REGNO (loc)(rhs_regno(loc))], dv, offset, loc);
1874 set_variable_part (set, loc, dv, offset, initialized, set_src, iopt);
1875}
1876
1877/* Return true if we should track a location that is OFFSET bytes from
1878 a variable. Store the constant offset in *OFFSET_OUT if so. */
1879
1880static bool
1881track_offset_p (poly_int64 offset, HOST_WIDE_INTlong *offset_out)
1882{
1883 HOST_WIDE_INTlong const_offset;
1884 if (!offset.is_constant (&const_offset)
1885 || !IN_RANGE (const_offset, 0, MAX_VAR_PARTS - 1)((unsigned long) (const_offset) - (unsigned long) (0) <= (
unsigned long) (16 - 1) - (unsigned long) (0))
)
1886 return false;
1887 *offset_out = const_offset;
1888 return true;
1889}
1890
1891/* Return the offset of a register that track_offset_p says we
1892 should track. */
1893
1894static HOST_WIDE_INTlong
1895get_tracked_reg_offset (rtx loc)
1896{
1897 HOST_WIDE_INTlong offset;
1898 if (!track_offset_p (REG_OFFSET (loc)(((&(loc)->u.reg)->attrs) == 0 ? 0 : ((&(loc)->
u.reg)->attrs)->offset)
, &offset))
1899 gcc_unreachable ()(fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 1899, __FUNCTION__))
;
1900 return offset;
1901}
1902
1903/* Set the register to contain REG_EXPR (LOC), REG_OFFSET (LOC). */
1904
1905static void
1906var_reg_set (dataflow_set *set, rtx loc, enum var_init_status initialized,
1907 rtx set_src)
1908{
1909 tree decl = REG_EXPR (loc)(((&(loc)->u.reg)->attrs) == 0 ? 0 : ((&(loc)->
u.reg)->attrs)->decl)
;
1910 HOST_WIDE_INTlong offset = get_tracked_reg_offset (loc);
1911
1912 var_reg_decl_set (set, loc, initialized,
1913 dv_from_decl (decl), offset, set_src, INSERT);
1914}
1915
1916static enum var_init_status
1917get_init_value (dataflow_set *set, rtx loc, decl_or_value dv)
1918{
1919 variable *var;
1920 int i;
1921 enum var_init_status ret_val = VAR_INIT_STATUS_UNKNOWN;
1922
1923 if (! flag_var_tracking_uninitglobal_options.x_flag_var_tracking_uninit)
1924 return VAR_INIT_STATUS_INITIALIZED;
1925
1926 var = shared_hash_find (set->vars, dv);
1927 if (var)
1928 {
1929 for (i = 0; i < var->n_var_parts && ret_val == VAR_INIT_STATUS_UNKNOWN; i++)
1930 {
1931 location_chain *nextp;
1932 for (nextp = var->var_part[i].loc_chain; nextp; nextp = nextp->next)
1933 if (rtx_equal_p (nextp->loc, loc))
1934 {
1935 ret_val = nextp->init;
1936 break;
1937 }
1938 }
1939 }
1940
1941 return ret_val;
1942}
1943
1944/* Delete current content of register LOC in dataflow set SET and set
1945 the register to contain REG_EXPR (LOC), REG_OFFSET (LOC). If
1946 MODIFY is true, any other live copies of the same variable part are
1947 also deleted from the dataflow set, otherwise the variable part is
1948 assumed to be copied from another location holding the same
1949 part. */
1950
1951static void
1952var_reg_delete_and_set (dataflow_set *set, rtx loc, bool modify,
1953 enum var_init_status initialized, rtx set_src)
1954{
1955 tree decl = REG_EXPR (loc)(((&(loc)->u.reg)->attrs) == 0 ? 0 : ((&(loc)->
u.reg)->attrs)->decl)
;
1956 HOST_WIDE_INTlong offset = get_tracked_reg_offset (loc);
1957 attrs *node, *next;
1958 attrs **nextp;
1959
1960 decl = var_debug_decl (decl);
1961
1962 if (initialized == VAR_INIT_STATUS_UNKNOWN)
1963 initialized = get_init_value (set, loc, dv_from_decl (decl));
1964
1965 nextp = &set->regs[REGNO (loc)(rhs_regno(loc))];
1966 for (node = *nextp; node; node = next)
1967 {
1968 next = node->next;
1969 if (dv_as_opaque (node->dv) != decl || node->offset != offset)
1970 {
1971 delete_variable_part (set, node->loc, node->dv, node->offset);
1972 delete node;
1973 *nextp = next;
1974 }
1975 else
1976 {
1977 node->loc = loc;
1978 nextp = &node->next;
1979 }
1980 }
1981 if (modify)
1982 clobber_variable_part (set, loc, dv_from_decl (decl), offset, set_src);
1983 var_reg_set (set, loc, initialized, set_src);
1984}
1985
1986/* Delete the association of register LOC in dataflow set SET with any
1987 variables that aren't onepart. If CLOBBER is true, also delete any
1988 other live copies of the same variable part, and delete the
1989 association with onepart dvs too. */
1990
1991static void
1992var_reg_delete (dataflow_set *set, rtx loc, bool clobber)
1993{
1994 attrs **nextp = &set->regs[REGNO (loc)(rhs_regno(loc))];
1995 attrs *node, *next;
1996
1997 HOST_WIDE_INTlong offset;
1998 if (clobber && track_offset_p (REG_OFFSET (loc)(((&(loc)->u.reg)->attrs) == 0 ? 0 : ((&(loc)->
u.reg)->attrs)->offset)
, &offset))
1999 {
2000 tree decl = REG_EXPR (loc)(((&(loc)->u.reg)->attrs) == 0 ? 0 : ((&(loc)->
u.reg)->attrs)->decl)
;
2001
2002 decl = var_debug_decl (decl);
2003
2004 clobber_variable_part (set, NULLnullptr, dv_from_decl (decl), offset, NULLnullptr);
2005 }
2006
2007 for (node = *nextp; node; node = next)
2008 {
2009 next = node->next;
2010 if (clobber || !dv_onepart_p (node->dv))
2011 {
2012 delete_variable_part (set, node->loc, node->dv, node->offset);
2013 delete node;
2014 *nextp = next;
2015 }
2016 else
2017 nextp = &node->next;
2018 }
2019}
2020
2021/* Delete content of register with number REGNO in dataflow set SET. */
2022
2023static void
2024var_regno_delete (dataflow_set *set, int regno)
2025{
2026 attrs **reg = &set->regs[regno];
2027 attrs *node, *next;
2028
2029 for (node = *reg; node; node = next)
2030 {
2031 next = node->next;
2032 delete_variable_part (set, node->loc, node->dv, node->offset);
2033 delete node;
2034 }
2035 *reg = NULLnullptr;
2036}
2037
2038/* Return true if I is the negated value of a power of two. */
2039static bool
2040negative_power_of_two_p (HOST_WIDE_INTlong i)
2041{
2042 unsigned HOST_WIDE_INTlong x = -(unsigned HOST_WIDE_INTlong)i;
2043 return pow2_or_zerop (x);
2044}
2045
2046/* Strip constant offsets and alignments off of LOC. Return the base
2047 expression. */
2048
2049static rtx
2050vt_get_canonicalize_base (rtx loc)
2051{
2052 while ((GET_CODE (loc)((enum rtx_code) (loc)->code) == PLUS
2053 || GET_CODE (loc)((enum rtx_code) (loc)->code) == AND)
2054 && GET_CODE (XEXP (loc, 1))((enum rtx_code) ((((loc)->u.fld[1]).rt_rtx))->code) == CONST_INT
2055 && (GET_CODE (loc)((enum rtx_code) (loc)->code) != AND
2056 || negative_power_of_two_p (INTVAL (XEXP (loc, 1))(((((loc)->u.fld[1]).rt_rtx))->u.hwint[0]))))
2057 loc = XEXP (loc, 0)(((loc)->u.fld[0]).rt_rtx);
2058
2059 return loc;
2060}
2061
2062/* This caches canonicalized addresses for VALUEs, computed using
2063 information in the global cselib table. */
2064static hash_map<rtx, rtx> *global_get_addr_cache;
2065
2066/* This caches canonicalized addresses for VALUEs, computed using
2067 information from the global cache and information pertaining to a
2068 basic block being analyzed. */
2069static hash_map<rtx, rtx> *local_get_addr_cache;
2070
2071static rtx vt_canonicalize_addr (dataflow_set *, rtx);
2072
2073/* Return the canonical address for LOC, that must be a VALUE, using a
2074 cached global equivalence or computing it and storing it in the
2075 global cache. */
2076
2077static rtx
2078get_addr_from_global_cache (rtx const loc)
2079{
2080 rtx x;
2081
2082 gcc_checking_assert (GET_CODE (loc) == VALUE)((void)(!(((enum rtx_code) (loc)->code) == VALUE) ? fancy_abort
("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 2082, __FUNCTION__), 0 : 0))
;
2083
2084 bool existed;
2085 rtx *slot = &global_get_addr_cache->get_or_insert (loc, &existed);
2086 if (existed)
2087 return *slot;
2088
2089 x = canon_rtx (get_addr (loc));
2090
2091 /* Tentative, avoiding infinite recursion. */
2092 *slot = x;
2093
2094 if (x != loc)
2095 {
2096 rtx nx = vt_canonicalize_addr (NULLnullptr, x);
2097 if (nx != x)
2098 {
2099 /* The table may have moved during recursion, recompute
2100 SLOT. */
2101 *global_get_addr_cache->get (loc) = x = nx;
2102 }
2103 }
2104
2105 return x;
2106}
2107
2108/* Return the canonical address for LOC, that must be a VALUE, using a
2109 cached local equivalence or computing it and storing it in the
2110 local cache. */
2111
2112static rtx
2113get_addr_from_local_cache (dataflow_set *set, rtx const loc)
2114{
2115 rtx x;
2116 decl_or_value dv;
2117 variable *var;
2118 location_chain *l;
2119
2120 gcc_checking_assert (GET_CODE (loc) == VALUE)((void)(!(((enum rtx_code) (loc)->code) == VALUE) ? fancy_abort
("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 2120, __FUNCTION__), 0 : 0))
;
2121
2122 bool existed;
2123 rtx *slot = &local_get_addr_cache->get_or_insert (loc, &existed);
2124 if (existed)
2125 return *slot;
2126
2127 x = get_addr_from_global_cache (loc);
2128
2129 /* Tentative, avoiding infinite recursion. */
2130 *slot = x;
2131
2132 /* Recurse to cache local expansion of X, or if we need to search
2133 for a VALUE in the expansion. */
2134 if (x != loc)
2135 {
2136 rtx nx = vt_canonicalize_addr (set, x);
2137 if (nx != x)
2138 {
2139 slot = local_get_addr_cache->get (loc);
2140 *slot = x = nx;
2141 }
2142 return x;
2143 }
2144
2145 dv = dv_from_rtx (x);
2146 var = shared_hash_find (set->vars, dv);
2147 if (!var)
2148 return x;
2149
2150 /* Look for an improved equivalent expression. */
2151 for (l = var->var_part[0].loc_chain; l; l = l->next)
2152 {
2153 rtx base = vt_get_canonicalize_base (l->loc);
2154 if (GET_CODE (base)((enum rtx_code) (base)->code) == VALUE
2155 && canon_value_cmp (base, loc))
2156 {
2157 rtx nx = vt_canonicalize_addr (set, l->loc);
2158 if (x != nx)
2159 {
2160 slot = local_get_addr_cache->get (loc);
2161 *slot = x = nx;
2162 }
2163 break;
2164 }
2165 }
2166
2167 return x;
2168}
2169
2170/* Canonicalize LOC using equivalences from SET in addition to those
2171 in the cselib static table. It expects a VALUE-based expression,
2172 and it will only substitute VALUEs with other VALUEs or
2173 function-global equivalences, so that, if two addresses have base
2174 VALUEs that are locally or globally related in ways that
2175 memrefs_conflict_p cares about, they will both canonicalize to
2176 expressions that have the same base VALUE.
2177
2178 The use of VALUEs as canonical base addresses enables the canonical
2179 RTXs to remain unchanged globally, if they resolve to a constant,
2180 or throughout a basic block otherwise, so that they can be cached
2181 and the cache needs not be invalidated when REGs, MEMs or such
2182 change. */
2183
2184static rtx
2185vt_canonicalize_addr (dataflow_set *set, rtx oloc)
2186{
2187 poly_int64 ofst = 0, term;
2188 machine_mode mode = GET_MODE (oloc)((machine_mode) (oloc)->mode);
2189 rtx loc = oloc;
2190 rtx x;
2191 bool retry = true;
2192
2193 while (retry)
2194 {
2195 while (GET_CODE (loc)((enum rtx_code) (loc)->code) == PLUS
2196 && poly_int_rtx_p (XEXP (loc, 1)(((loc)->u.fld[1]).rt_rtx), &term))
2197 {
2198 ofst += term;
2199 loc = XEXP (loc, 0)(((loc)->u.fld[0]).rt_rtx);
2200 }
2201
2202 /* Alignment operations can't normally be combined, so just
2203 canonicalize the base and we're done. We'll normally have
2204 only one stack alignment anyway. */
2205 if (GET_CODE (loc)((enum rtx_code) (loc)->code) == AND
2206 && GET_CODE (XEXP (loc, 1))((enum rtx_code) ((((loc)->u.fld[1]).rt_rtx))->code) == CONST_INT
2207 && negative_power_of_two_p (INTVAL (XEXP (loc, 1))(((((loc)->u.fld[1]).rt_rtx))->u.hwint[0])))
2208 {
2209 x = vt_canonicalize_addr (set, XEXP (loc, 0)(((loc)->u.fld[0]).rt_rtx));
2210 if (x != XEXP (loc, 0)(((loc)->u.fld[0]).rt_rtx))
2211 loc = gen_rtx_AND (mode, x, XEXP (loc, 1))gen_rtx_fmt_ee_stat ((AND), ((mode)), ((x)), (((((loc)->u.
fld[1]).rt_rtx))) )
;
2212 retry = false;
2213 }
2214
2215 if (GET_CODE (loc)((enum rtx_code) (loc)->code) == VALUE)
2216 {
2217 if (set)
2218 loc = get_addr_from_local_cache (set, loc);
2219 else
2220 loc = get_addr_from_global_cache (loc);
2221
2222 /* Consolidate plus_constants. */
2223 while (maybe_ne (ofst, 0)
2224 && GET_CODE (loc)((enum rtx_code) (loc)->code) == PLUS
2225 && poly_int_rtx_p (XEXP (loc, 1)(((loc)->u.fld[1]).rt_rtx), &term))
2226 {
2227 ofst += term;
2228 loc = XEXP (loc, 0)(((loc)->u.fld[0]).rt_rtx);
2229 }
2230
2231 retry = false;
2232 }
2233 else
2234 {
2235 x = canon_rtx (loc);
2236 if (retry)
2237 retry = (x != loc);
2238 loc = x;
2239 }
2240 }
2241
2242 /* Add OFST back in. */
2243 if (maybe_ne (ofst, 0))
2244 {
2245 /* Don't build new RTL if we can help it. */
2246 if (strip_offset (oloc, &term) == loc && known_eq (term, ofst)(!maybe_ne (term, ofst)))
2247 return oloc;
2248
2249 loc = plus_constant (mode, loc, ofst);
2250 }
2251
2252 return loc;
2253}
2254
2255/* Return true iff there's a true dependence between MLOC and LOC.
2256 MADDR must be a canonicalized version of MLOC's address. */
2257
2258static inline bool
2259vt_canon_true_dep (dataflow_set *set, rtx mloc, rtx maddr, rtx loc)
2260{
2261 if (GET_CODE (loc)((enum rtx_code) (loc)->code) != MEM)
2262 return false;
2263
2264 rtx addr = vt_canonicalize_addr (set, XEXP (loc, 0)(((loc)->u.fld[0]).rt_rtx));
2265 if (!canon_true_dependence (mloc, GET_MODE (mloc)((machine_mode) (mloc)->mode), maddr, loc, addr))
2266 return false;
2267
2268 return true;
2269}
2270
2271/* Hold parameters for the hashtab traversal function
2272 drop_overlapping_mem_locs, see below. */
2273
2274struct overlapping_mems
2275{
2276 dataflow_set *set;
2277 rtx loc, addr;
2278};
2279
2280/* Remove all MEMs that overlap with COMS->LOC from the location list
2281 of a hash table entry for a onepart variable. COMS->ADDR must be a
2282 canonicalized form of COMS->LOC's address, and COMS->LOC must be
2283 canonicalized itself. */
2284
2285int
2286drop_overlapping_mem_locs (variable **slot, overlapping_mems *coms)
2287{
2288 dataflow_set *set = coms->set;
2289 rtx mloc = coms->loc, addr = coms->addr;
2290 variable *var = *slot;
2291
2292 if (var->onepart != NOT_ONEPART)
2293 {
2294 location_chain *loc, **locp;
2295 bool changed = false;
2296 rtx cur_loc;
2297
2298 gcc_assert (var->n_var_parts == 1)((void)(!(var->n_var_parts == 1) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 2298, __FUNCTION__), 0 : 0))
;
2299
2300 if (shared_var_p (var, set->vars))
2301 {
2302 for (loc = var->var_part[0].loc_chain; loc; loc = loc->next)
2303 if (vt_canon_true_dep (set, mloc, addr, loc->loc))
2304 break;
2305
2306 if (!loc)
2307 return 1;
2308
2309 slot = unshare_variable (set, slot, var, VAR_INIT_STATUS_UNKNOWN);
2310 var = *slot;
2311 gcc_assert (var->n_var_parts == 1)((void)(!(var->n_var_parts == 1) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 2311, __FUNCTION__), 0 : 0))
;
2312 }
2313
2314 if (VAR_LOC_1PAUX (var)__extension__ (*({ variable *const __v = (var); ((void)(!(__v
->onepart) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 2314, __FUNCTION__), 0 : 0)); &__v->var_part[0].aux.
onepaux; }))
)
2315 cur_loc = VAR_LOC_FROM (var)(__extension__ (*({ variable *const __v = (var); ((void)(!(__v
->onepart) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 2315, __FUNCTION__), 0 : 0)); &__v->var_part[0].aux.
onepaux; }))->from)
;
2316 else
2317 cur_loc = var->var_part[0].cur_loc;
2318
2319 for (locp = &var->var_part[0].loc_chain, loc = *locp;
2320 loc; loc = *locp)
2321 {
2322 if (!vt_canon_true_dep (set, mloc, addr, loc->loc))
2323 {
2324 locp = &loc->next;
2325 continue;
2326 }
2327
2328 *locp = loc->next;
2329 /* If we have deleted the location which was last emitted
2330 we have to emit new location so add the variable to set
2331 of changed variables. */
2332 if (cur_loc == loc->loc)
2333 {
2334 changed = true;
2335 var->var_part[0].cur_loc = NULLnullptr;
2336 if (VAR_LOC_1PAUX (var)__extension__ (*({ variable *const __v = (var); ((void)(!(__v
->onepart) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 2336, __FUNCTION__), 0 : 0)); &__v->var_part[0].aux.
onepaux; }))
)
2337 VAR_LOC_FROM (var)(__extension__ (*({ variable *const __v = (var); ((void)(!(__v
->onepart) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 2337, __FUNCTION__), 0 : 0)); &__v->var_part[0].aux.
onepaux; }))->from)
= NULLnullptr;
2338 }
2339 delete loc;
2340 }
2341
2342 if (!var->var_part[0].loc_chain)
2343 {
2344 var->n_var_parts--;
2345 changed = true;
2346 }
2347 if (changed)
2348 variable_was_changed (var, set);
2349 }
2350
2351 return 1;
2352}
2353
2354/* Remove from SET all VALUE bindings to MEMs that overlap with LOC. */
2355
2356static void
2357clobber_overlapping_mems (dataflow_set *set, rtx loc)
2358{
2359 struct overlapping_mems coms;
2360
2361 gcc_checking_assert (GET_CODE (loc) == MEM)((void)(!(((enum rtx_code) (loc)->code) == MEM) ? fancy_abort
("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 2361, __FUNCTION__), 0 : 0))
;
2362
2363 coms.set = set;
2364 coms.loc = canon_rtx (loc);
2365 coms.addr = vt_canonicalize_addr (set, XEXP (loc, 0)(((loc)->u.fld[0]).rt_rtx));
2366
2367 set->traversed_vars = set->vars;
2368 shared_hash_htab (set->vars)
2369 ->traverse <overlapping_mems*, drop_overlapping_mem_locs> (&coms);
2370 set->traversed_vars = NULLnullptr;
2371}
2372
2373/* Set the location of DV, OFFSET as the MEM LOC. */
2374
2375static void
2376var_mem_decl_set (dataflow_set *set, rtx loc, enum var_init_status initialized,
2377 decl_or_value dv, HOST_WIDE_INTlong offset, rtx set_src,
2378 enum insert_option iopt)
2379{
2380 if (dv_is_decl_p (dv))
2381 dv = dv_from_decl (var_debug_decl (dv_as_decl (dv)));
2382
2383 set_variable_part (set, loc, dv, offset, initialized, set_src, iopt);
2384}
2385
2386/* Set the location part of variable MEM_EXPR (LOC) in dataflow set
2387 SET to LOC.
2388 Adjust the address first if it is stack pointer based. */
2389
2390static void
2391var_mem_set (dataflow_set *set, rtx loc, enum var_init_status initialized,
2392 rtx set_src)
2393{
2394 tree decl = MEM_EXPR (loc)(get_mem_attrs (loc)->expr);
2395 HOST_WIDE_INTlong offset = int_mem_offset (loc);
2396
2397 var_mem_decl_set (set, loc, initialized,
2398 dv_from_decl (decl), offset, set_src, INSERT);
2399}
2400
2401/* Delete and set the location part of variable MEM_EXPR (LOC) in
2402 dataflow set SET to LOC. If MODIFY is true, any other live copies
2403 of the same variable part are also deleted from the dataflow set,
2404 otherwise the variable part is assumed to be copied from another
2405 location holding the same part.
2406 Adjust the address first if it is stack pointer based. */
2407
2408static void
2409var_mem_delete_and_set (dataflow_set *set, rtx loc, bool modify,
2410 enum var_init_status initialized, rtx set_src)
2411{
2412 tree decl = MEM_EXPR (loc)(get_mem_attrs (loc)->expr);
2413 HOST_WIDE_INTlong offset = int_mem_offset (loc);
2414
2415 clobber_overlapping_mems (set, loc);
2416 decl = var_debug_decl (decl);
2417
2418 if (initialized == VAR_INIT_STATUS_UNKNOWN)
2419 initialized = get_init_value (set, loc, dv_from_decl (decl));
2420
2421 if (modify)
2422 clobber_variable_part (set, NULLnullptr, dv_from_decl (decl), offset, set_src);
2423 var_mem_set (set, loc, initialized, set_src);
2424}
2425
2426/* Delete the location part LOC from dataflow set SET. If CLOBBER is
2427 true, also delete any other live copies of the same variable part.
2428 Adjust the address first if it is stack pointer based. */
2429
2430static void
2431var_mem_delete (dataflow_set *set, rtx loc, bool clobber)
2432{
2433 tree decl = MEM_EXPR (loc)(get_mem_attrs (loc)->expr);
2434 HOST_WIDE_INTlong offset = int_mem_offset (loc);
2435
2436 clobber_overlapping_mems (set, loc);
2437 decl = var_debug_decl (decl);
2438 if (clobber)
2439 clobber_variable_part (set, NULLnullptr, dv_from_decl (decl), offset, NULLnullptr);
2440 delete_variable_part (set, loc, dv_from_decl (decl), offset);
2441}
2442
2443/* Return true if LOC should not be expanded for location expressions,
2444 or used in them. */
2445
2446static inline bool
2447unsuitable_loc (rtx loc)
2448{
2449 switch (GET_CODE (loc)((enum rtx_code) (loc)->code))
2450 {
2451 case PC:
2452 case SCRATCH:
2453 case CC0:
2454 case ASM_INPUT:
2455 case ASM_OPERANDS:
2456 return true;
2457
2458 default:
2459 return false;
2460 }
2461}
2462
2463/* Bind VAL to LOC in SET. If MODIFIED, detach LOC from any values
2464 bound to it. */
2465
2466static inline void
2467val_bind (dataflow_set *set, rtx val, rtx loc, bool modified)
2468{
2469 if (REG_P (loc)(((enum rtx_code) (loc)->code) == REG))
2470 {
2471 if (modified)
2472 var_regno_delete (set, REGNO (loc)(rhs_regno(loc)));
2473 var_reg_decl_set (set, loc, VAR_INIT_STATUS_INITIALIZED,
2474 dv_from_value (val), 0, NULL_RTX(rtx) 0, INSERT);
2475 }
2476 else if (MEM_P (loc)(((enum rtx_code) (loc)->code) == MEM))
2477 {
2478 struct elt_loc_list *l = CSELIB_VAL_PTR (val)(((val)->u.fld[0]).rt_cselib)->locs;
2479
2480 if (modified)
2481 clobber_overlapping_mems (set, loc);
2482
2483 if (l && GET_CODE (l->loc)((enum rtx_code) (l->loc)->code) == VALUE)
2484 l = canonical_cselib_val (CSELIB_VAL_PTR (l->loc)(((l->loc)->u.fld[0]).rt_cselib))->locs;
2485
2486 /* If this MEM is a global constant, we don't need it in the
2487 dynamic tables. ??? We should test this before emitting the
2488 micro-op in the first place. */
2489 while (l)
2490 if (GET_CODE (l->loc)((enum rtx_code) (l->loc)->code) == MEM && XEXP (l->loc, 0)(((l->loc)->u.fld[0]).rt_rtx) == XEXP (loc, 0)(((loc)->u.fld[0]).rt_rtx))
2491 break;
2492 else
2493 l = l->next;
2494
2495 if (!l)
2496 var_mem_decl_set (set, loc, VAR_INIT_STATUS_INITIALIZED,
2497 dv_from_value (val), 0, NULL_RTX(rtx) 0, INSERT);
2498 }
2499 else
2500 {
2501 /* Other kinds of equivalences are necessarily static, at least
2502 so long as we do not perform substitutions while merging
2503 expressions. */
2504 gcc_unreachable ()(fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 2504, __FUNCTION__))
;
2505 set_variable_part (set, loc, dv_from_value (val), 0,
2506 VAR_INIT_STATUS_INITIALIZED, NULL_RTX(rtx) 0, INSERT);
2507 }
2508}
2509
2510/* Bind a value to a location it was just stored in. If MODIFIED
2511 holds, assume the location was modified, detaching it from any
2512 values bound to it. */
2513
2514static void
2515val_store (dataflow_set *set, rtx val, rtx loc, rtx_insn *insn,
2516 bool modified)
2517{
2518 cselib_val *v = CSELIB_VAL_PTR (val)(((val)->u.fld[0]).rt_cselib);
2519
2520 gcc_assert (cselib_preserved_value_p (v))((void)(!(cselib_preserved_value_p (v)) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 2520, __FUNCTION__), 0 : 0))
;
2521
2522 if (dump_file)
2523 {
2524 fprintf (dump_file, "%i: ", insn ? INSN_UID (insn) : 0);
2525 print_inline_rtx (dump_file, loc, 0);
2526 fprintf (dump_file, " evaluates to ");
2527 print_inline_rtx (dump_file, val, 0);
2528 if (v->locs)
2529 {
2530 struct elt_loc_list *l;
2531 for (l = v->locs; l; l = l->next)
2532 {
2533 fprintf (dump_file, "\n%i: ", INSN_UID (l->setting_insn));
2534 print_inline_rtx (dump_file, l->loc, 0);
2535 }
2536 }
2537 fprintf (dump_file, "\n");
2538 }
2539
2540 gcc_checking_assert (!unsuitable_loc (loc))((void)(!(!unsuitable_loc (loc)) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 2540, __FUNCTION__), 0 : 0))
;
2541
2542 val_bind (set, val, loc, modified);
2543}
2544
2545/* Clear (canonical address) slots that reference X. */
2546
2547bool
2548local_get_addr_clear_given_value (rtx const &, rtx *slot, rtx x)
2549{
2550 if (vt_get_canonicalize_base (*slot) == x)
2551 *slot = NULLnullptr;
2552 return true;
2553}
2554
2555/* Reset this node, detaching all its equivalences. Return the slot
2556 in the variable hash table that holds dv, if there is one. */
2557
2558static void
2559val_reset (dataflow_set *set, decl_or_value dv)
2560{
2561 variable *var = shared_hash_find (set->vars, dv) ;
2562 location_chain *node;
2563 rtx cval;
2564
2565 if (!var || !var->n_var_parts)
2566 return;
2567
2568 gcc_assert (var->n_var_parts == 1)((void)(!(var->n_var_parts == 1) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 2568, __FUNCTION__), 0 : 0))
;
2569
2570 if (var->onepart == ONEPART_VALUE)
2571 {
2572 rtx x = dv_as_value (dv);
2573
2574 /* Relationships in the global cache don't change, so reset the
2575 local cache entry only. */
2576 rtx *slot = local_get_addr_cache->get (x);
2577 if (slot)
2578 {
2579 /* If the value resolved back to itself, odds are that other
2580 values may have cached it too. These entries now refer
2581 to the old X, so detach them too. Entries that used the
2582 old X but resolved to something else remain ok as long as
2583 that something else isn't also reset. */
2584 if (*slot == x)
2585 local_get_addr_cache
2586 ->traverse<rtx, local_get_addr_clear_given_value> (x);
2587 *slot = NULLnullptr;
2588 }
2589 }
2590
2591 cval = NULLnullptr;
2592 for (node = var->var_part[0].loc_chain; node; node = node->next)
2593 if (GET_CODE (node->loc)((enum rtx_code) (node->loc)->code) == VALUE
2594 && canon_value_cmp (node->loc, cval))
2595 cval = node->loc;
2596
2597 for (node = var->var_part[0].loc_chain; node; node = node->next)
2598 if (GET_CODE (node->loc)((enum rtx_code) (node->loc)->code) == VALUE && cval != node->loc)
2599 {
2600 /* Redirect the equivalence link to the new canonical
2601 value, or simply remove it if it would point at
2602 itself. */
2603 if (cval)
2604 set_variable_part (set, cval, dv_from_value (node->loc),
2605 0, node->init, node->set_src, NO_INSERT);
2606 delete_variable_part (set, dv_as_value (dv),
2607 dv_from_value (node->loc), 0);
2608 }
2609
2610 if (cval)
2611 {
2612 decl_or_value cdv = dv_from_value (cval);
2613
2614 /* Keep the remaining values connected, accumulating links
2615 in the canonical value. */
2616 for (node = var->var_part[0].loc_chain; node; node = node->next)
2617 {
2618 if (node->loc == cval)
2619 continue;
2620 else if (GET_CODE (node->loc)((enum rtx_code) (node->loc)->code) == REG)
2621 var_reg_decl_set (set, node->loc, node->init, cdv, 0,
2622 node->set_src, NO_INSERT);
2623 else if (GET_CODE (node->loc)((enum rtx_code) (node->loc)->code) == MEM)
2624 var_mem_decl_set (set, node->loc, node->init, cdv, 0,
2625 node->set_src, NO_INSERT);
2626 else
2627 set_variable_part (set, node->loc, cdv, 0,
2628 node->init, node->set_src, NO_INSERT);
2629 }
2630 }
2631
2632 /* We remove this last, to make sure that the canonical value is not
2633 removed to the point of requiring reinsertion. */
2634 if (cval)
2635 delete_variable_part (set, dv_as_value (dv), dv_from_value (cval), 0);
2636
2637 clobber_variable_part (set, NULLnullptr, dv, 0, NULLnullptr);
2638}
2639
2640/* Find the values in a given location and map the val to another
2641 value, if it is unique, or add the location as one holding the
2642 value. */
2643
2644static void
2645val_resolve (dataflow_set *set, rtx val, rtx loc, rtx_insn *insn)
2646{
2647 decl_or_value dv = dv_from_value (val);
2648
2649 if (dump_file && (dump_flags & TDF_DETAILS))
2650 {
2651 if (insn)
2652 fprintf (dump_file, "%i: ", INSN_UID (insn));
2653 else
2654 fprintf (dump_file, "head: ");
2655 print_inline_rtx (dump_file, val, 0);
2656 fputs (" is at ", dump_file);
2657 print_inline_rtx (dump_file, loc, 0);
2658 fputc ('\n', dump_file);
2659 }
2660
2661 val_reset (set, dv);
2662
2663 gcc_checking_assert (!unsuitable_loc (loc))((void)(!(!unsuitable_loc (loc)) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 2663, __FUNCTION__), 0 : 0))
;
2664
2665 if (REG_P (loc)(((enum rtx_code) (loc)->code) == REG))
2666 {
2667 attrs *node, *found = NULLnullptr;
2668
2669 for (node = set->regs[REGNO (loc)(rhs_regno(loc))]; node; node = node->next)
2670 if (dv_is_value_p (node->dv)
2671 && GET_MODE (dv_as_value (node->dv))((machine_mode) (dv_as_value (node->dv))->mode) == GET_MODE (loc)((machine_mode) (loc)->mode))
2672 {
2673 found = node;
2674
2675 /* Map incoming equivalences. ??? Wouldn't it be nice if
2676 we just started sharing the location lists? Maybe a
2677 circular list ending at the value itself or some
2678 such. */
2679 set_variable_part (set, dv_as_value (node->dv),
2680 dv_from_value (val), node->offset,
2681 VAR_INIT_STATUS_INITIALIZED, NULL_RTX(rtx) 0, INSERT);
2682 set_variable_part (set, val, node->dv, node->offset,
2683 VAR_INIT_STATUS_INITIALIZED, NULL_RTX(rtx) 0, INSERT);
2684 }
2685
2686 /* If we didn't find any equivalence, we need to remember that
2687 this value is held in the named register. */
2688 if (found)
2689 return;
2690 }
2691 /* ??? Attempt to find and merge equivalent MEMs or other
2692 expressions too. */
2693
2694 val_bind (set, val, loc, false);
2695}
2696
2697/* Initialize dataflow set SET to be empty.
2698 VARS_SIZE is the initial size of hash table VARS. */
2699
2700static void
2701dataflow_set_init (dataflow_set *set)
2702{
2703 init_attrs_list_set (set->regs);
2704 set->vars = shared_hash_copy (empty_shared_hash);
2705 set->stack_adjust = 0;
2706 set->traversed_vars = NULLnullptr;
2707}
2708
2709/* Delete the contents of dataflow set SET. */
2710
2711static void
2712dataflow_set_clear (dataflow_set *set)
2713{
2714 int i;
2715
2716 for (i = 0; i < FIRST_PSEUDO_REGISTER76; i++)
2717 attrs_list_clear (&set->regs[i]);
2718
2719 shared_hash_destroy (set->vars);
2720 set->vars = shared_hash_copy (empty_shared_hash);
2721}
2722
2723/* Copy the contents of dataflow set SRC to DST. */
2724
2725static void
2726dataflow_set_copy (dataflow_set *dst, dataflow_set *src)
2727{
2728 int i;
2729
2730 for (i = 0; i < FIRST_PSEUDO_REGISTER76; i++)
2731 attrs_list_copy (&dst->regs[i], src->regs[i]);
2732
2733 shared_hash_destroy (dst->vars);
2734 dst->vars = shared_hash_copy (src->vars);
2735 dst->stack_adjust = src->stack_adjust;
2736}
2737
2738/* Information for merging lists of locations for a given offset of variable.
2739 */
2740struct variable_union_info
2741{
2742 /* Node of the location chain. */
2743 location_chain *lc;
2744
2745 /* The sum of positions in the input chains. */
2746 int pos;
2747
2748 /* The position in the chain of DST dataflow set. */
2749 int pos_dst;
2750};
2751
2752/* Buffer for location list sorting and its allocated size. */
2753static struct variable_union_info *vui_vec;
2754static int vui_allocated;
2755
2756/* Compare function for qsort, order the structures by POS element. */
2757
2758static int
2759variable_union_info_cmp_pos (const void *n1, const void *n2)
2760{
2761 const struct variable_union_info *const i1 =
2762 (const struct variable_union_info *) n1;
2763 const struct variable_union_info *const i2 =
2764 ( const struct variable_union_info *) n2;
2765
2766 if (i1->pos != i2->pos)
2767 return i1->pos - i2->pos;
2768
2769 return (i1->pos_dst - i2->pos_dst);
2770}
2771
2772/* Compute union of location parts of variable *SLOT and the same variable
2773 from hash table DATA. Compute "sorted" union of the location chains
2774 for common offsets, i.e. the locations of a variable part are sorted by
2775 a priority where the priority is the sum of the positions in the 2 chains
2776 (if a location is only in one list the position in the second list is
2777 defined to be larger than the length of the chains).
2778 When we are updating the location parts the newest location is in the
2779 beginning of the chain, so when we do the described "sorted" union
2780 we keep the newest locations in the beginning. */
2781
2782static int
2783variable_union (variable *src, dataflow_set *set)
2784{
2785 variable *dst;
2786 variable **dstp;
2787 int i, j, k;
2788
2789 dstp = shared_hash_find_slot (set->vars, src->dv);
2790 if (!dstp || !*dstp)
2791 {
2792 src->refcount++;
2793
2794 dst_can_be_shared = false;
2795 if (!dstp)
2796 dstp = shared_hash_find_slot_unshare (&set->vars, src->dv, INSERT);
2797
2798 *dstp = src;
2799
2800 /* Continue traversing the hash table. */
2801 return 1;
2802 }
2803 else
2804 dst = *dstp;
2805
2806 gcc_assert (src->n_var_parts)((void)(!(src->n_var_parts) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 2806, __FUNCTION__), 0 : 0))
;
2807 gcc_checking_assert (src->onepart == dst->onepart)((void)(!(src->onepart == dst->onepart) ? fancy_abort (
"/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 2807, __FUNCTION__), 0 : 0))
;
2808
2809 /* We can combine one-part variables very efficiently, because their
2810 entries are in canonical order. */
2811 if (src->onepart)
2812 {
2813 location_chain **nodep, *dnode, *snode;
2814
2815 gcc_assert (src->n_var_parts == 1((void)(!(src->n_var_parts == 1 && dst->n_var_parts
== 1) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 2816, __FUNCTION__), 0 : 0))
2816 && dst->n_var_parts == 1)((void)(!(src->n_var_parts == 1 && dst->n_var_parts
== 1) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 2816, __FUNCTION__), 0 : 0))
;
2817
2818 snode = src->var_part[0].loc_chain;
2819 gcc_assert (snode)((void)(!(snode) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 2819, __FUNCTION__), 0 : 0))
;
2820
2821 restart_onepart_unshared:
2822 nodep = &dst->var_part[0].loc_chain;
2823 dnode = *nodep;
2824 gcc_assert (dnode)((void)(!(dnode) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 2824, __FUNCTION__), 0 : 0))
;
2825
2826 while (snode)
2827 {
2828 int r = dnode ? loc_cmp (dnode->loc, snode->loc) : 1;
2829
2830 if (r > 0)
2831 {
2832 location_chain *nnode;
2833
2834 if (shared_var_p (dst, set->vars))
2835 {
2836 dstp = unshare_variable (set, dstp, dst,
2837 VAR_INIT_STATUS_INITIALIZED);
2838 dst = *dstp;
2839 goto restart_onepart_unshared;
2840 }
2841
2842 *nodep = nnode = new location_chain;
2843 nnode->loc = snode->loc;
2844 nnode->init = snode->init;
2845 if (!snode->set_src || MEM_P (snode->set_src)(((enum rtx_code) (snode->set_src)->code) == MEM))
2846 nnode->set_src = NULLnullptr;
2847 else
2848 nnode->set_src = snode->set_src;
2849 nnode->next = dnode;
2850 dnode = nnode;
2851 }
2852 else if (r == 0)
2853 gcc_checking_assert (rtx_equal_p (dnode->loc, snode->loc))((void)(!(rtx_equal_p (dnode->loc, snode->loc)) ? fancy_abort
("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 2853, __FUNCTION__), 0 : 0))
;
2854
2855 if (r >= 0)
2856 snode = snode->next;
2857
2858 nodep = &dnode->next;
2859 dnode = *nodep;
2860 }
2861
2862 return 1;
2863 }
2864
2865 gcc_checking_assert (!src->onepart)((void)(!(!src->onepart) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 2865, __FUNCTION__), 0 : 0))
;
2866
2867 /* Count the number of location parts, result is K. */
2868 for (i = 0, j = 0, k = 0;
2869 i < src->n_var_parts && j < dst->n_var_parts; k++)
2870 {
2871 if (VAR_PART_OFFSET (src, i)__extension__ (*({ variable *const __v = (src); ((void)(!(!__v
->onepart) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 2871, __FUNCTION__), 0 : 0)); &__v->var_part[(i)].aux
.offset; }))
== VAR_PART_OFFSET (dst, j)__extension__ (*({ variable *const __v = (dst); ((void)(!(!__v
->onepart) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 2871, __FUNCTION__), 0 : 0)); &__v->var_part[(j)].aux
.offset; }))
)
2872 {
2873 i++;
2874 j++;
2875 }
2876 else if (VAR_PART_OFFSET (src, i)__extension__ (*({ variable *const __v = (src); ((void)(!(!__v
->onepart) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 2876, __FUNCTION__), 0 : 0)); &__v->var_part[(i)].aux
.offset; }))
< VAR_PART_OFFSET (dst, j)__extension__ (*({ variable *const __v = (dst); ((void)(!(!__v
->onepart) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 2876, __FUNCTION__), 0 : 0)); &__v->var_part[(j)].aux
.offset; }))
)
2877 i++;
2878 else
2879 j++;
2880 }
2881 k += src->n_var_parts - i;
2882 k += dst->n_var_parts - j;
2883
2884 /* We track only variables whose size is <= MAX_VAR_PARTS bytes
2885 thus there are at most MAX_VAR_PARTS different offsets. */
2886 gcc_checking_assert (dst->onepart ? k == 1 : k <= MAX_VAR_PARTS)((void)(!(dst->onepart ? k == 1 : k <= 16) ? fancy_abort
("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 2886, __FUNCTION__), 0 : 0))
;
2887
2888 if (dst->n_var_parts != k && shared_var_p (dst, set->vars))
2889 {
2890 dstp = unshare_variable (set, dstp, dst, VAR_INIT_STATUS_UNKNOWN);
2891 dst = *dstp;
2892 }
2893
2894 i = src->n_var_parts - 1;
2895 j = dst->n_var_parts - 1;
2896 dst->n_var_parts = k;
2897
2898 for (k--; k >= 0; k--)
2899 {
2900 location_chain *node, *node2;
2901
2902 if (i >= 0 && j >= 0
2903 && VAR_PART_OFFSET (src, i)__extension__ (*({ variable *const __v = (src); ((void)(!(!__v
->onepart) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 2903, __FUNCTION__), 0 : 0)); &__v->var_part[(i)].aux
.offset; }))
== VAR_PART_OFFSET (dst, j)__extension__ (*({ variable *const __v = (dst); ((void)(!(!__v
->onepart) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 2903, __FUNCTION__), 0 : 0)); &__v->var_part[(j)].aux
.offset; }))
)
2904 {
2905 /* Compute the "sorted" union of the chains, i.e. the locations which
2906 are in both chains go first, they are sorted by the sum of
2907 positions in the chains. */
2908 int dst_l, src_l;
2909 int ii, jj, n;
2910 struct variable_union_info *vui;
2911
2912 /* If DST is shared compare the location chains.
2913 If they are different we will modify the chain in DST with
2914 high probability so make a copy of DST. */
2915 if (shared_var_p (dst, set->vars))
2916 {
2917 for (node = src->var_part[i].loc_chain,
2918 node2 = dst->var_part[j].loc_chain; node && node2;
2919 node = node->next, node2 = node2->next)
2920 {
2921 if (!((REG_P (node2->loc)(((enum rtx_code) (node2->loc)->code) == REG)
2922 && REG_P (node->loc)(((enum rtx_code) (node->loc)->code) == REG)
2923 && REGNO (node2->loc)(rhs_regno(node2->loc)) == REGNO (node->loc)(rhs_regno(node->loc)))
2924 || rtx_equal_p (node2->loc, node->loc)))
2925 {
2926 if (node2->init < node->init)
2927 node2->init = node->init;
2928 break;
2929 }
2930 }
2931 if (node || node2)
2932 {
2933 dstp = unshare_variable (set, dstp, dst,
2934 VAR_INIT_STATUS_UNKNOWN);
2935 dst = (variable *)*dstp;
2936 }
2937 }
2938
2939 src_l = 0;
2940 for (node = src->var_part[i].loc_chain; node; node = node->next)
2941 src_l++;
2942 dst_l = 0;
2943 for (node = dst->var_part[j].loc_chain; node; node = node->next)
2944 dst_l++;
2945
2946 if (dst_l == 1)
2947 {
2948 /* The most common case, much simpler, no qsort is needed. */
2949 location_chain *dstnode = dst->var_part[j].loc_chain;
2950 dst->var_part[k].loc_chain = dstnode;
2951 VAR_PART_OFFSET (dst, k)__extension__ (*({ variable *const __v = (dst); ((void)(!(!__v
->onepart) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 2951, __FUNCTION__), 0 : 0)); &__v->var_part[(k)].aux
.offset; }))
= VAR_PART_OFFSET (dst, j)__extension__ (*({ variable *const __v = (dst); ((void)(!(!__v
->onepart) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 2951, __FUNCTION__), 0 : 0)); &__v->var_part[(j)].aux
.offset; }))
;
2952 node2 = dstnode;
2953 for (node = src->var_part[i].loc_chain; node; node = node->next)
2954 if (!((REG_P (dstnode->loc)(((enum rtx_code) (dstnode->loc)->code) == REG)
2955 && REG_P (node->loc)(((enum rtx_code) (node->loc)->code) == REG)
2956 && REGNO (dstnode->loc)(rhs_regno(dstnode->loc)) == REGNO (node->loc)(rhs_regno(node->loc)))
2957 || rtx_equal_p (dstnode->loc, node->loc)))
2958 {
2959 location_chain *new_node;
2960
2961 /* Copy the location from SRC. */
2962 new_node = new location_chain;
2963 new_node->loc = node->loc;
2964 new_node->init = node->init;
2965 if (!node->set_src || MEM_P (node->set_src)(((enum rtx_code) (node->set_src)->code) == MEM))
2966 new_node->set_src = NULLnullptr;
2967 else
2968 new_node->set_src = node->set_src;
2969 node2->next = new_node;
2970 node2 = new_node;
2971 }
2972 node2->next = NULLnullptr;
2973 }
2974 else
2975 {
2976 if (src_l + dst_l > vui_allocated)
2977 {
2978 vui_allocated = MAX (vui_allocated * 2, src_l + dst_l)((vui_allocated * 2) > (src_l + dst_l) ? (vui_allocated * 2
) : (src_l + dst_l))
;
2979 vui_vec = XRESIZEVEC (struct variable_union_info, vui_vec,((struct variable_union_info *) xrealloc ((void *) (vui_vec),
sizeof (struct variable_union_info) * (vui_allocated)))
2980 vui_allocated)((struct variable_union_info *) xrealloc ((void *) (vui_vec),
sizeof (struct variable_union_info) * (vui_allocated)))
;
2981 }
2982 vui = vui_vec;
2983
2984 /* Fill in the locations from DST. */
2985 for (node = dst->var_part[j].loc_chain, jj = 0; node;
2986 node = node->next, jj++)
2987 {
2988 vui[jj].lc = node;
2989 vui[jj].pos_dst = jj;
2990
2991 /* Pos plus value larger than a sum of 2 valid positions. */
2992 vui[jj].pos = jj + src_l + dst_l;
2993 }
2994
2995 /* Fill in the locations from SRC. */
2996 n = dst_l;
2997 for (node = src->var_part[i].loc_chain, ii = 0; node;
2998 node = node->next, ii++)
2999 {
3000 /* Find location from NODE. */
3001 for (jj = 0; jj < dst_l; jj++)
3002 {
3003 if ((REG_P (vui[jj].lc->loc)(((enum rtx_code) (vui[jj].lc->loc)->code) == REG)
3004 && REG_P (node->loc)(((enum rtx_code) (node->loc)->code) == REG)
3005 && REGNO (vui[jj].lc->loc)(rhs_regno(vui[jj].lc->loc)) == REGNO (node->loc)(rhs_regno(node->loc)))
3006 || rtx_equal_p (vui[jj].lc->loc, node->loc))
3007 {
3008 vui[jj].pos = jj + ii;
3009 break;
3010 }
3011 }
3012 if (jj >= dst_l) /* The location has not been found. */
3013 {
3014 location_chain *new_node;
3015
3016 /* Copy the location from SRC. */
3017 new_node = new location_chain;
3018 new_node->loc = node->loc;
3019 new_node->init = node->init;
3020 if (!node->set_src || MEM_P (node->set_src)(((enum rtx_code) (node->set_src)->code) == MEM))
3021 new_node->set_src = NULLnullptr;
3022 else
3023 new_node->set_src = node->set_src;
3024 vui[n].lc = new_node;
3025 vui[n].pos_dst = src_l + dst_l;
3026 vui[n].pos = ii + src_l + dst_l;
3027 n++;
3028 }
3029 }
3030
3031 if (dst_l == 2)
3032 {
3033 /* Special case still very common case. For dst_l == 2
3034 all entries dst_l ... n-1 are sorted, with for i >= dst_l
3035 vui[i].pos == i + src_l + dst_l. */
3036 if (vui[0].pos > vui[1].pos)
3037 {
3038 /* Order should be 1, 0, 2... */
3039 dst->var_part[k].loc_chain = vui[1].lc;
3040 vui[1].lc->next = vui[0].lc;
3041 if (n >= 3)
3042 {
3043 vui[0].lc->next = vui[2].lc;
3044 vui[n - 1].lc->next = NULLnullptr;
3045 }
3046 else
3047 vui[0].lc->next = NULLnullptr;
3048 ii = 3;
3049 }
3050 else
3051 {
3052 dst->var_part[k].loc_chain = vui[0].lc;
3053 if (n >= 3 && vui[2].pos < vui[1].pos)
3054 {
3055 /* Order should be 0, 2, 1, 3... */
3056 vui[0].lc->next = vui[2].lc;
3057 vui[2].lc->next = vui[1].lc;
3058 if (n >= 4)
3059 {
3060 vui[1].lc->next = vui[3].lc;
3061 vui[n - 1].lc->next = NULLnullptr;
3062 }
3063 else
3064 vui[1].lc->next = NULLnullptr;
3065 ii = 4;
3066 }
3067 else
3068 {
3069 /* Order should be 0, 1, 2... */
3070 ii = 1;
3071 vui[n - 1].lc->next = NULLnullptr;
3072 }
3073 }
3074 for (; ii < n; ii++)
3075 vui[ii - 1].lc->next = vui[ii].lc;
3076 }
3077 else
3078 {
3079 qsort (vui, n, sizeof (struct variable_union_info),gcc_qsort (vui, n, sizeof (struct variable_union_info), variable_union_info_cmp_pos
)
3080 variable_union_info_cmp_pos)gcc_qsort (vui, n, sizeof (struct variable_union_info), variable_union_info_cmp_pos
)
;
3081
3082 /* Reconnect the nodes in sorted order. */
3083 for (ii = 1; ii < n; ii++)
3084 vui[ii - 1].lc->next = vui[ii].lc;
3085 vui[n - 1].lc->next = NULLnullptr;
3086 dst->var_part[k].loc_chain = vui[0].lc;
3087 }
3088
3089 VAR_PART_OFFSET (dst, k)__extension__ (*({ variable *const __v = (dst); ((void)(!(!__v
->onepart) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 3089, __FUNCTION__), 0 : 0)); &__v->var_part[(k)].aux
.offset; }))
= VAR_PART_OFFSET (dst, j)__extension__ (*({ variable *const __v = (dst); ((void)(!(!__v
->onepart) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 3089, __FUNCTION__), 0 : 0)); &__v->var_part[(j)].aux
.offset; }))
;
3090 }
3091 i--;
3092 j--;
3093 }
3094 else if ((i >= 0 && j >= 0
3095 && VAR_PART_OFFSET (src, i)__extension__ (*({ variable *const __v = (src); ((void)(!(!__v
->onepart) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 3095, __FUNCTION__), 0 : 0)); &__v->var_part[(i)].aux
.offset; }))
< VAR_PART_OFFSET (dst, j)__extension__ (*({ variable *const __v = (dst); ((void)(!(!__v
->onepart) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 3095, __FUNCTION__), 0 : 0)); &__v->var_part[(j)].aux
.offset; }))
)
3096 || i < 0)
3097 {
3098 dst->var_part[k] = dst->var_part[j];
3099 j--;
3100 }
3101 else if ((i >= 0 && j >= 0
3102 && VAR_PART_OFFSET (src, i)__extension__ (*({ variable *const __v = (src); ((void)(!(!__v
->onepart) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 3102, __FUNCTION__), 0 : 0)); &__v->var_part[(i)].aux
.offset; }))
> VAR_PART_OFFSET (dst, j)__extension__ (*({ variable *const __v = (dst); ((void)(!(!__v
->onepart) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 3102, __FUNCTION__), 0 : 0)); &__v->var_part[(j)].aux
.offset; }))
)
3103 || j < 0)
3104 {
3105 location_chain **nextp;
3106
3107 /* Copy the chain from SRC. */
3108 nextp = &dst->var_part[k].loc_chain;
3109 for (node = src->var_part[i].loc_chain; node; node = node->next)
3110 {
3111 location_chain *new_lc;
3112
3113 new_lc = new location_chain;
3114 new_lc->next = NULLnullptr;
3115 new_lc->init = node->init;
3116 if (!node->set_src || MEM_P (node->set_src)(((enum rtx_code) (node->set_src)->code) == MEM))
3117 new_lc->set_src = NULLnullptr;
3118 else
3119 new_lc->set_src = node->set_src;
3120 new_lc->loc = node->loc;
3121
3122 *nextp = new_lc;
3123 nextp = &new_lc->next;
3124 }
3125
3126 VAR_PART_OFFSET (dst, k)__extension__ (*({ variable *const __v = (dst); ((void)(!(!__v
->onepart) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 3126, __FUNCTION__), 0 : 0)); &__v->var_part[(k)].aux
.offset; }))
= VAR_PART_OFFSET (src, i)__extension__ (*({ variable *const __v = (src); ((void)(!(!__v
->onepart) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 3126, __FUNCTION__), 0 : 0)); &__v->var_part[(i)].aux
.offset; }))
;
3127 i--;
3128 }
3129 dst->var_part[k].cur_loc = NULLnullptr;
3130 }
3131
3132 if (flag_var_tracking_uninitglobal_options.x_flag_var_tracking_uninit)
3133 for (i = 0; i < src->n_var_parts && i < dst->n_var_parts; i++)
3134 {
3135 location_chain *node, *node2;
3136 for (node = src->var_part[i].loc_chain; node; node = node->next)
3137 for (node2 = dst->var_part[i].loc_chain; node2; node2 = node2->next)
3138 if (rtx_equal_p (node->loc, node2->loc))
3139 {
3140 if (node->init > node2->init)
3141 node2->init = node->init;
3142 }
3143 }
3144
3145 /* Continue traversing the hash table. */
3146 return 1;
3147}
3148
3149/* Compute union of dataflow sets SRC and DST and store it to DST. */
3150
3151static void
3152dataflow_set_union (dataflow_set *dst, dataflow_set *src)
3153{
3154 int i;
3155
3156 for (i = 0; i < FIRST_PSEUDO_REGISTER76; i++)
3157 attrs_list_union (&dst->regs[i], src->regs[i]);
3158
3159 if (dst->vars == empty_shared_hash)
3160 {
3161 shared_hash_destroy (dst->vars);
3162 dst->vars = shared_hash_copy (src->vars);
3163 }
3164 else
3165 {
3166 variable_iterator_type hi;
3167 variable *var;
3168
3169 FOR_EACH_HASH_TABLE_ELEMENT (*shared_hash_htab (src->vars),for ((hi) = (*shared_hash_htab (src->vars)).begin (); (hi)
!= (*shared_hash_htab (src->vars)).end () ? (var = *(hi) ,
true) : false; ++(hi))
3170 var, variable, hi)for ((hi) = (*shared_hash_htab (src->vars)).begin (); (hi)
!= (*shared_hash_htab (src->vars)).end () ? (var = *(hi) ,
true) : false; ++(hi))
3171 variable_union (var, dst);
3172 }
3173}
3174
3175/* Whether the value is currently being expanded. */
3176#define VALUE_RECURSED_INTO(x)(__extension__ ({ __typeof ((x)) const _rtx = ((x)); if (((enum
rtx_code) (_rtx)->code) != VALUE && ((enum rtx_code
) (_rtx)->code) != DEBUG_EXPR) rtl_check_failed_flag ("VALUE_RECURSED_INTO"
,_rtx, "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 3176, __FUNCTION__); _rtx; })->used)
\
3177 (RTL_FLAG_CHECK2 ("VALUE_RECURSED_INTO", (x), VALUE, DEBUG_EXPR)__extension__ ({ __typeof ((x)) const _rtx = ((x)); if (((enum
rtx_code) (_rtx)->code) != VALUE && ((enum rtx_code
) (_rtx)->code) != DEBUG_EXPR) rtl_check_failed_flag ("VALUE_RECURSED_INTO"
,_rtx, "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 3177, __FUNCTION__); _rtx; })
->used)
3178
3179/* Whether no expansion was found, saving useless lookups.
3180 It must only be set when VALUE_CHANGED is clear. */
3181#define NO_LOC_P(x)(__extension__ ({ __typeof ((x)) const _rtx = ((x)); if (((enum
rtx_code) (_rtx)->code) != VALUE && ((enum rtx_code
) (_rtx)->code) != DEBUG_EXPR) rtl_check_failed_flag ("NO_LOC_P"
,_rtx, "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 3181, __FUNCTION__); _rtx; })->return_val)
\
3182 (RTL_FLAG_CHECK2 ("NO_LOC_P", (x), VALUE, DEBUG_EXPR)__extension__ ({ __typeof ((x)) const _rtx = ((x)); if (((enum
rtx_code) (_rtx)->code) != VALUE && ((enum rtx_code
) (_rtx)->code) != DEBUG_EXPR) rtl_check_failed_flag ("NO_LOC_P"
,_rtx, "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 3182, __FUNCTION__); _rtx; })
->return_val)
3183
3184/* Whether cur_loc in the value needs to be (re)computed. */
3185#define VALUE_CHANGED(x)(__extension__ ({ __typeof ((x)) const _rtx = ((x)); if (((enum
rtx_code) (_rtx)->code) != VALUE) rtl_check_failed_flag (
"VALUE_CHANGED", _rtx, "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 3185, __FUNCTION__); _rtx; })->frame_related)
\
3186 (RTL_FLAG_CHECK1 ("VALUE_CHANGED", (x), VALUE)__extension__ ({ __typeof ((x)) const _rtx = ((x)); if (((enum
rtx_code) (_rtx)->code) != VALUE) rtl_check_failed_flag (
"VALUE_CHANGED", _rtx, "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 3186, __FUNCTION__); _rtx; })
->frame_related)
3187/* Whether cur_loc in the decl needs to be (re)computed. */
3188#define DECL_CHANGED(x)((x)->base.visited) TREE_VISITED (x)((x)->base.visited)
3189
3190/* Record (if NEWV) that DV needs to have its cur_loc recomputed. For
3191 user DECLs, this means they're in changed_variables. Values and
3192 debug exprs may be left with this flag set if no user variable
3193 requires them to be evaluated. */
3194
3195static inline void
3196set_dv_changed (decl_or_value dv, bool newv)
3197{
3198 switch (dv_onepart_p (dv))
3199 {
3200 case ONEPART_VALUE:
3201 if (newv)
3202 NO_LOC_P (dv_as_value (dv))(__extension__ ({ __typeof ((dv_as_value (dv))) const _rtx = (
(dv_as_value (dv))); if (((enum rtx_code) (_rtx)->code) !=
VALUE && ((enum rtx_code) (_rtx)->code) != DEBUG_EXPR
) rtl_check_failed_flag ("NO_LOC_P",_rtx, "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 3202, __FUNCTION__); _rtx; })->return_val)
= false;
3203 VALUE_CHANGED (dv_as_value (dv))(__extension__ ({ __typeof ((dv_as_value (dv))) const _rtx = (
(dv_as_value (dv))); if (((enum rtx_code) (_rtx)->code) !=
VALUE) rtl_check_failed_flag ("VALUE_CHANGED", _rtx, "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 3203, __FUNCTION__); _rtx; })->frame_related)
= newv;
3204 break;
3205
3206 case ONEPART_DEXPR:
3207 if (newv)
3208 NO_LOC_P (DECL_RTL_KNOWN_SET (dv_as_decl (dv)))(__extension__ ({ __typeof ((__extension__ ({ tree const __d =
(dv_as_decl (dv)); ((void)(!((((tree_contains_struct[(((enum
tree_code) (__d)->base.code))][(TS_DECL_WRTL)])) &&
(contains_struct_check ((__d), (TS_DECL_WRTL), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 3208, __FUNCTION__))->decl_with_rtl.rtl != nullptr)) ? fancy_abort
("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 3208, __FUNCTION__), 0 : 0)); &*((((tree_contains_struct
[(((enum tree_code) (__d)->base.code))][(TS_DECL_WRTL)])) &&
(contains_struct_check ((__d), (TS_DECL_WRTL), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 3208, __FUNCTION__))->decl_with_rtl.rtl != nullptr) ? ((
contains_struct_check ((__d), (TS_DECL_WRTL), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 3208, __FUNCTION__))->decl_with_rtl.rtl ? (__d)->decl_with_rtl
.rtl : (make_decl_rtl (__d), (__d)->decl_with_rtl.rtl)) : nullptr
); }))) const _rtx = ((__extension__ ({ tree const __d = (dv_as_decl
(dv)); ((void)(!((((tree_contains_struct[(((enum tree_code) (
__d)->base.code))][(TS_DECL_WRTL)])) && (contains_struct_check
((__d), (TS_DECL_WRTL), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 3208, __FUNCTION__))->decl_with_rtl.rtl != nullptr)) ? fancy_abort
("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 3208, __FUNCTION__), 0 : 0)); &*((((tree_contains_struct
[(((enum tree_code) (__d)->base.code))][(TS_DECL_WRTL)])) &&
(contains_struct_check ((__d), (TS_DECL_WRTL), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 3208, __FUNCTION__))->decl_with_rtl.rtl != nullptr) ? ((
contains_struct_check ((__d), (TS_DECL_WRTL), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 3208, __FUNCTION__))->decl_with_rtl.rtl ? (__d)->decl_with_rtl
.rtl : (make_decl_rtl (__d), (__d)->decl_with_rtl.rtl)) : nullptr
); }))); if (((enum rtx_code) (_rtx)->code) != VALUE &&
((enum rtx_code) (_rtx)->code) != DEBUG_EXPR) rtl_check_failed_flag
("NO_LOC_P",_rtx, "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 3208, __FUNCTION__); _rtx; })->return_val)
= false;
3209 /* Fall through. */
3210
3211 default:
3212 DECL_CHANGED (dv_as_decl (dv))((dv_as_decl (dv))->base.visited) = newv;
3213 break;
3214 }
3215}
3216
3217/* Return true if DV needs to have its cur_loc recomputed. */
3218
3219static inline bool
3220dv_changed_p (decl_or_value dv)
3221{
3222 return (dv_is_value_p (dv)
3223 ? VALUE_CHANGED (dv_as_value (dv))(__extension__ ({ __typeof ((dv_as_value (dv))) const _rtx = (
(dv_as_value (dv))); if (((enum rtx_code) (_rtx)->code) !=
VALUE) rtl_check_failed_flag ("VALUE_CHANGED", _rtx, "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 3223, __FUNCTION__); _rtx; })->frame_related)
3224 : DECL_CHANGED (dv_as_decl (dv))((dv_as_decl (dv))->base.visited));
3225}
3226
3227/* Return a location list node whose loc is rtx_equal to LOC, in the
3228 location list of a one-part variable or value VAR, or in that of
3229 any values recursively mentioned in the location lists. VARS must
3230 be in star-canonical form. */
3231
3232static location_chain *
3233find_loc_in_1pdv (rtx loc, variable *var, variable_table_type *vars)
3234{
3235 location_chain *node;
3236 enum rtx_code loc_code;
3237
3238 if (!var)
3239 return NULLnullptr;
3240
3241 gcc_checking_assert (var->onepart)((void)(!(var->onepart) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 3241, __FUNCTION__), 0 : 0))
;
3242
3243 if (!var->n_var_parts)
3244 return NULLnullptr;
3245
3246 gcc_checking_assert (loc != dv_as_opaque (var->dv))((void)(!(loc != dv_as_opaque (var->dv)) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 3246, __FUNCTION__), 0 : 0))
;
3247
3248 loc_code = GET_CODE (loc)((enum rtx_code) (loc)->code);
3249 for (node = var->var_part[0].loc_chain; node; node = node->next)
3250 {
3251 decl_or_value dv;
3252 variable *rvar;
3253
3254 if (GET_CODE (node->loc)((enum rtx_code) (node->loc)->code) != loc_code)
3255 {
3256 if (GET_CODE (node->loc)((enum rtx_code) (node->loc)->code) != VALUE)
3257 continue;
3258 }
3259 else if (loc == node->loc)
3260 return node;
3261 else if (loc_code != VALUE)
3262 {
3263 if (rtx_equal_p (loc, node->loc))
3264 return node;
3265 continue;
3266 }
3267
3268 /* Since we're in star-canonical form, we don't need to visit
3269 non-canonical nodes: one-part variables and non-canonical
3270 values would only point back to the canonical node. */
3271 if (dv_is_value_p (var->dv)
3272 && !canon_value_cmp (node->loc, dv_as_value (var->dv)))
3273 {
3274 /* Skip all subsequent VALUEs. */
3275 while (node->next && GET_CODE (node->next->loc)((enum rtx_code) (node->next->loc)->code) == VALUE)
3276 {
3277 node = node->next;
3278 gcc_checking_assert (!canon_value_cmp (node->loc,((void)(!(!canon_value_cmp (node->loc, dv_as_value (var->
dv))) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 3279, __FUNCTION__), 0 : 0))
3279 dv_as_value (var->dv)))((void)(!(!canon_value_cmp (node->loc, dv_as_value (var->
dv))) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 3279, __FUNCTION__), 0 : 0))
;
3280 if (loc == node->loc)
3281 return node;
3282 }
3283 continue;
3284 }
3285
3286 gcc_checking_assert (node == var->var_part[0].loc_chain)((void)(!(node == var->var_part[0].loc_chain) ? fancy_abort
("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 3286, __FUNCTION__), 0 : 0))
;
3287 gcc_checking_assert (!node->next)((void)(!(!node->next) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 3287, __FUNCTION__), 0 : 0))
;
3288
3289 dv = dv_from_value (node->loc);
3290 rvar = vars->find_with_hash (dv, dv_htab_hash (dv));
3291 return find_loc_in_1pdv (loc, rvar, vars);
3292 }
3293
3294 /* ??? Gotta look in cselib_val locations too. */
3295
3296 return NULLnullptr;
3297}
3298
3299/* Hash table iteration argument passed to variable_merge. */
3300struct dfset_merge
3301{
3302 /* The set in which the merge is to be inserted. */
3303 dataflow_set *dst;
3304 /* The set that we're iterating in. */
3305 dataflow_set *cur;
3306 /* The set that may contain the other dv we are to merge with. */
3307 dataflow_set *src;
3308 /* Number of onepart dvs in src. */
3309 int src_onepart_cnt;
3310};
3311
3312/* Insert LOC in *DNODE, if it's not there yet. The list must be in
3313 loc_cmp order, and it is maintained as such. */
3314
3315static void
3316insert_into_intersection (location_chain **nodep, rtx loc,
3317 enum var_init_status status)
3318{
3319 location_chain *node;
3320 int r;
3321
3322 for (node = *nodep; node; nodep = &node->next, node = *nodep)
3323 if ((r = loc_cmp (node->loc, loc)) == 0)
3324 {
3325 node->init = MIN (node->init, status)((node->init) < (status) ? (node->init) : (status));
3326 return;
3327 }
3328 else if (r > 0)
3329 break;
3330
3331 node = new location_chain;
3332
3333 node->loc = loc;
3334 node->set_src = NULLnullptr;
3335 node->init = status;
3336 node->next = *nodep;
3337 *nodep = node;
3338}
3339
3340/* Insert in DEST the intersection of the locations present in both
3341 S1NODE and S2VAR, directly or indirectly. S1NODE is from a
3342 variable in DSM->cur, whereas S2VAR is from DSM->src. dvar is in
3343 DSM->dst. */
3344
3345static void
3346intersect_loc_chains (rtx val, location_chain **dest, struct dfset_merge *dsm,
3347 location_chain *s1node, variable *s2var)
3348{
3349 dataflow_set *s1set = dsm->cur;
3350 dataflow_set *s2set = dsm->src;
3351 location_chain *found;
3352
3353 if (s2var)
3354 {
3355 location_chain *s2node;
3356
3357 gcc_checking_assert (s2var->onepart)((void)(!(s2var->onepart) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 3357, __FUNCTION__), 0 : 0))
;
3358
3359 if (s2var->n_var_parts)
3360 {
3361 s2node = s2var->var_part[0].loc_chain;
3362
3363 for (; s1node && s2node;
3364 s1node = s1node->next, s2node = s2node->next)
3365 if (s1node->loc != s2node->loc)
3366 break;
3367 else if (s1node->loc == val)
3368 continue;
3369 else
3370 insert_into_intersection (dest, s1node->loc,
3371 MIN (s1node->init, s2node->init)((s1node->init) < (s2node->init) ? (s1node->init)
: (s2node->init))
);
3372 }
3373 }
3374
3375 for (; s1node; s1node = s1node->next)
3376 {
3377 if (s1node->loc == val)
3378 continue;
3379
3380 if ((found = find_loc_in_1pdv (s1node->loc, s2var,
3381 shared_hash_htab (s2set->vars))))
3382 {
3383 insert_into_intersection (dest, s1node->loc,
3384 MIN (s1node->init, found->init)((s1node->init) < (found->init) ? (s1node->init) :
(found->init))
);
3385 continue;
3386 }
3387
3388 if (GET_CODE (s1node->loc)((enum rtx_code) (s1node->loc)->code) == VALUE
3389 && !VALUE_RECURSED_INTO (s1node->loc)(__extension__ ({ __typeof ((s1node->loc)) const _rtx = ((
s1node->loc)); if (((enum rtx_code) (_rtx)->code) != VALUE
&& ((enum rtx_code) (_rtx)->code) != DEBUG_EXPR) rtl_check_failed_flag
("VALUE_RECURSED_INTO",_rtx, "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 3389, __FUNCTION__); _rtx; })->used)
)
3390 {
3391 decl_or_value dv = dv_from_value (s1node->loc);
3392 variable *svar = shared_hash_find (s1set->vars, dv);
3393 if (svar)
3394 {
3395 if (svar->n_var_parts == 1)
3396 {
3397 VALUE_RECURSED_INTO (s1node->loc)(__extension__ ({ __typeof ((s1node->loc)) const _rtx = ((
s1node->loc)); if (((enum rtx_code) (_rtx)->code) != VALUE
&& ((enum rtx_code) (_rtx)->code) != DEBUG_EXPR) rtl_check_failed_flag
("VALUE_RECURSED_INTO",_rtx, "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 3397, __FUNCTION__); _rtx; })->used)
= true;
3398 intersect_loc_chains (val, dest, dsm,
3399 svar->var_part[0].loc_chain,
3400 s2var);
3401 VALUE_RECURSED_INTO (s1node->loc)(__extension__ ({ __typeof ((s1node->loc)) const _rtx = ((
s1node->loc)); if (((enum rtx_code) (_rtx)->code) != VALUE
&& ((enum rtx_code) (_rtx)->code) != DEBUG_EXPR) rtl_check_failed_flag
("VALUE_RECURSED_INTO",_rtx, "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 3401, __FUNCTION__); _rtx; })->used)
= false;
3402 }
3403 }
3404 }
3405
3406 /* ??? gotta look in cselib_val locations too. */
3407
3408 /* ??? if the location is equivalent to any location in src,
3409 searched recursively
3410
3411 add to dst the values needed to represent the equivalence
3412
3413 telling whether locations S is equivalent to another dv's
3414 location list:
3415
3416 for each location D in the list
3417
3418 if S and D satisfy rtx_equal_p, then it is present
3419
3420 else if D is a value, recurse without cycles
3421
3422 else if S and D have the same CODE and MODE
3423
3424 for each operand oS and the corresponding oD
3425
3426 if oS and oD are not equivalent, then S an D are not equivalent
3427
3428 else if they are RTX vectors
3429
3430 if any vector oS element is not equivalent to its respective oD,
3431 then S and D are not equivalent
3432
3433 */
3434
3435
3436 }
3437}
3438
3439/* Return -1 if X should be before Y in a location list for a 1-part
3440 variable, 1 if Y should be before X, and 0 if they're equivalent
3441 and should not appear in the list. */
3442
3443static int
3444loc_cmp (rtx x, rtx y)
3445{
3446 int i, j, r;
3447 RTX_CODEenum rtx_code code = GET_CODE (x)((enum rtx_code) (x)->code);
3448 const char *fmt;
3449
3450 if (x == y)
3451 return 0;
3452
3453 if (REG_P (x)(((enum rtx_code) (x)->code) == REG))
3454 {
3455 if (!REG_P (y)(((enum rtx_code) (y)->code) == REG))
3456 return -1;
3457 gcc_assert (GET_MODE (x) == GET_MODE (y))((void)(!(((machine_mode) (x)->mode) == ((machine_mode) (y
)->mode)) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 3457, __FUNCTION__), 0 : 0))
;
3458 if (REGNO (x)(rhs_regno(x)) == REGNO (y)(rhs_regno(y)))
3459 return 0;
3460 else if (REGNO (x)(rhs_regno(x)) < REGNO (y)(rhs_regno(y)))
3461 return -1;
3462 else
3463 return 1;
3464 }
3465
3466 if (REG_P (y)(((enum rtx_code) (y)->code) == REG))
3467 return 1;
3468
3469 if (MEM_P (x)(((enum rtx_code) (x)->code) == MEM))
3470 {
3471 if (!MEM_P (y)(((enum rtx_code) (y)->code) == MEM))
3472 return -1;
3473 gcc_assert (GET_MODE (x) == GET_MODE (y))((void)(!(((machine_mode) (x)->mode) == ((machine_mode) (y
)->mode)) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 3473, __FUNCTION__), 0 : 0))
;
3474 return loc_cmp (XEXP (x, 0)(((x)->u.fld[0]).rt_rtx), XEXP (y, 0)(((y)->u.fld[0]).rt_rtx));
3475 }
3476
3477 if (MEM_P (y)(((enum rtx_code) (y)->code) == MEM))
3478 return 1;
3479
3480 if (GET_CODE (x)((enum rtx_code) (x)->code) == VALUE)
3481 {
3482 if (GET_CODE (y)((enum rtx_code) (y)->code) != VALUE)
3483 return -1;
3484 /* Don't assert the modes are the same, that is true only
3485 when not recursing. (subreg:QI (value:SI 1:1) 0)
3486 and (subreg:QI (value:DI 2:2) 0) can be compared,
3487 even when the modes are different. */
3488 if (canon_value_cmp (x, y))
3489 return -1;
3490 else
3491 return 1;
3492 }
3493
3494 if (GET_CODE (y)((enum rtx_code) (y)->code) == VALUE)
3495 return 1;
3496
3497 /* Entry value is the least preferable kind of expression. */
3498 if (GET_CODE (x)((enum rtx_code) (x)->code) == ENTRY_VALUE)
3499 {
3500 if (GET_CODE (y)((enum rtx_code) (y)->code) != ENTRY_VALUE)
3501 return 1;
3502 gcc_assert (GET_MODE (x) == GET_MODE (y))((void)(!(((machine_mode) (x)->mode) == ((machine_mode) (y
)->mode)) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 3502, __FUNCTION__), 0 : 0))
;
3503 return loc_cmp (ENTRY_VALUE_EXP (x)(((x)->u.fld[0]).rt_rtx), ENTRY_VALUE_EXP (y)(((y)->u.fld[0]).rt_rtx));
3504 }
3505
3506 if (GET_CODE (y)((enum rtx_code) (y)->code) == ENTRY_VALUE)
3507 return -1;
3508
3509 if (GET_CODE (x)((enum rtx_code) (x)->code) == GET_CODE (y)((enum rtx_code) (y)->code))
3510 /* Compare operands below. */;
3511 else if (GET_CODE (x)((enum rtx_code) (x)->code) < GET_CODE (y)((enum rtx_code) (y)->code))
3512 return -1;
3513 else
3514 return 1;
3515
3516 gcc_assert (GET_MODE (x) == GET_MODE (y))((void)(!(((machine_mode) (x)->mode) == ((machine_mode) (y
)->mode)) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 3516, __FUNCTION__), 0 : 0))
;
3517
3518 if (GET_CODE (x)((enum rtx_code) (x)->code) == DEBUG_EXPR)
3519 {
3520 if (DEBUG_TEMP_UID (DEBUG_EXPR_TREE_DECL (x))(-((contains_struct_check (((tree_check ((((((x)->u.fld[0]
).rt_tree))), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 3520, __FUNCTION__, (DEBUG_EXPR_DECL)))), (TS_DECL_MINIMAL)
, "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 3520, __FUNCTION__))->decl_minimal.uid))
3521 < DEBUG_TEMP_UID (DEBUG_EXPR_TREE_DECL (y))(-((contains_struct_check (((tree_check ((((((y)->u.fld[0]
).rt_tree))), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 3521, __FUNCTION__, (DEBUG_EXPR_DECL)))), (TS_DECL_MINIMAL)
, "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 3521, __FUNCTION__))->decl_minimal.uid))
)
3522 return -1;
3523 gcc_checking_assert (DEBUG_TEMP_UID (DEBUG_EXPR_TREE_DECL (x))((void)(!((-((contains_struct_check (((tree_check ((((((x)->
u.fld[0]).rt_tree))), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 3523, __FUNCTION__, (DEBUG_EXPR_DECL)))), (TS_DECL_MINIMAL)
, "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 3523, __FUNCTION__))->decl_minimal.uid)) > (-((contains_struct_check
(((tree_check ((((((y)->u.fld[0]).rt_tree))), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 3524, __FUNCTION__, (DEBUG_EXPR_DECL)))), (TS_DECL_MINIMAL)
, "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 3524, __FUNCTION__))->decl_minimal.uid))) ? fancy_abort (
"/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 3524, __FUNCTION__), 0 : 0))
3524 > DEBUG_TEMP_UID (DEBUG_EXPR_TREE_DECL (y)))((void)(!((-((contains_struct_check (((tree_check ((((((x)->
u.fld[0]).rt_tree))), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 3523, __FUNCTION__, (DEBUG_EXPR_DECL)))), (TS_DECL_MINIMAL)
, "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 3523, __FUNCTION__))->decl_minimal.uid)) > (-((contains_struct_check
(((tree_check ((((((y)->u.fld[0]).rt_tree))), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 3524, __FUNCTION__, (DEBUG_EXPR_DECL)))), (TS_DECL_MINIMAL)
, "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 3524, __FUNCTION__))->decl_minimal.uid))) ? fancy_abort (
"/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 3524, __FUNCTION__), 0 : 0))
;
3525 return 1;
3526 }
3527
3528 fmt = GET_RTX_FORMAT (code)(rtx_format[(int) (code)]);
3529 for (i = 0; i < GET_RTX_LENGTH (code)(rtx_length[(int) (code)]); i++)
3530 switch (fmt[i])
3531 {
3532 case 'w':
3533 if (XWINT (x, i)((x)->u.hwint[i]) == XWINT (y, i)((y)->u.hwint[i]))
3534 break;
3535 else if (XWINT (x, i)((x)->u.hwint[i]) < XWINT (y, i)((y)->u.hwint[i]))
3536 return -1;
3537 else
3538 return 1;
3539
3540 case 'n':
3541 case 'i':
3542 if (XINT (x, i)(((x)->u.fld[i]).rt_int) == XINT (y, i)(((y)->u.fld[i]).rt_int))
3543 break;
3544 else if (XINT (x, i)(((x)->u.fld[i]).rt_int) < XINT (y, i)(((y)->u.fld[i]).rt_int))
3545 return -1;
3546 else
3547 return 1;
3548
3549 case 'p':
3550 r = compare_sizes_for_sort (SUBREG_BYTE (x)(((x)->u.fld[1]).rt_subreg), SUBREG_BYTE (y)(((y)->u.fld[1]).rt_subreg));
3551 if (r != 0)
3552 return r;
3553 break;
3554
3555 case 'V':
3556 case 'E':
3557 /* Compare the vector length first. */
3558 if (XVECLEN (x, i)(((((x)->u.fld[i]).rt_rtvec))->num_elem) == XVECLEN (y, i)(((((y)->u.fld[i]).rt_rtvec))->num_elem))
3559 /* Compare the vectors elements. */;
3560 else if (XVECLEN (x, i)(((((x)->u.fld[i]).rt_rtvec))->num_elem) < XVECLEN (y, i)(((((y)->u.fld[i]).rt_rtvec))->num_elem))
3561 return -1;
3562 else
3563 return 1;
3564
3565 for (j = 0; j < XVECLEN (x, i)(((((x)->u.fld[i]).rt_rtvec))->num_elem); j++)
3566 if ((r = loc_cmp (XVECEXP (x, i, j)(((((x)->u.fld[i]).rt_rtvec))->elem[j]),
3567 XVECEXP (y, i, j)(((((y)->u.fld[i]).rt_rtvec))->elem[j]))))
3568 return r;
3569 break;
3570
3571 case 'e':
3572 if ((r = loc_cmp (XEXP (x, i)(((x)->u.fld[i]).rt_rtx), XEXP (y, i)(((y)->u.fld[i]).rt_rtx))))
3573 return r;
3574 break;
3575
3576 case 'S':
3577 case 's':
3578 if (XSTR (x, i)(((x)->u.fld[i]).rt_str) == XSTR (y, i)(((y)->u.fld[i]).rt_str))
3579 break;
3580 if (!XSTR (x, i)(((x)->u.fld[i]).rt_str))
3581 return -1;
3582 if (!XSTR (y, i)(((y)->u.fld[i]).rt_str))
3583 return 1;
3584 if ((r = strcmp (XSTR (x, i)(((x)->u.fld[i]).rt_str), XSTR (y, i)(((y)->u.fld[i]).rt_str))) == 0)
3585 break;
3586 else if (r < 0)
3587 return -1;
3588 else
3589 return 1;
3590
3591 case 'u':
3592 /* These are just backpointers, so they don't matter. */
3593 break;
3594
3595 case '0':
3596 case 't':
3597 break;
3598
3599 /* It is believed that rtx's at this level will never
3600 contain anything but integers and other rtx's,
3601 except for within LABEL_REFs and SYMBOL_REFs. */
3602 default:
3603 gcc_unreachable ()(fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 3603, __FUNCTION__))
;
3604 }
3605 if (CONST_WIDE_INT_P (x)(((enum rtx_code) (x)->code) == CONST_WIDE_INT))
3606 {
3607 /* Compare the vector length first. */
3608 if (CONST_WIDE_INT_NUNITS (x)((int)__extension__ ({ __typeof ((x)) const _rtx = ((x)); if (
((enum rtx_code) (_rtx)->code) != CONST_WIDE_INT) rtl_check_failed_flag
("CWI_GET_NUM_ELEM", _rtx, "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 3608, __FUNCTION__); _rtx; })->u2.num_elem)
>= CONST_WIDE_INT_NUNITS (y)((int)__extension__ ({ __typeof ((y)) const _rtx = ((y)); if (
((enum rtx_code) (_rtx)->code) != CONST_WIDE_INT) rtl_check_failed_flag
("CWI_GET_NUM_ELEM", _rtx, "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 3608, __FUNCTION__); _rtx; })->u2.num_elem)
)
3609 return 1;
3610 else if (CONST_WIDE_INT_NUNITS (x)((int)__extension__ ({ __typeof ((x)) const _rtx = ((x)); if (
((enum rtx_code) (_rtx)->code) != CONST_WIDE_INT) rtl_check_failed_flag
("CWI_GET_NUM_ELEM", _rtx, "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 3610, __FUNCTION__); _rtx; })->u2.num_elem)
< CONST_WIDE_INT_NUNITS (y)((int)__extension__ ({ __typeof ((y)) const _rtx = ((y)); if (
((enum rtx_code) (_rtx)->code) != CONST_WIDE_INT) rtl_check_failed_flag
("CWI_GET_NUM_ELEM", _rtx, "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 3610, __FUNCTION__); _rtx; })->u2.num_elem)
)
3611 return -1;
3612
3613 /* Compare the vectors elements. */;
3614 for (j = CONST_WIDE_INT_NUNITS (x)((int)__extension__ ({ __typeof ((x)) const _rtx = ((x)); if (
((enum rtx_code) (_rtx)->code) != CONST_WIDE_INT) rtl_check_failed_flag
("CWI_GET_NUM_ELEM", _rtx, "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 3614, __FUNCTION__); _rtx; })->u2.num_elem)
- 1; j >= 0 ; j--)
3615 {
3616 if (CONST_WIDE_INT_ELT (x, j)((x)->u.hwiv.elem[j]) < CONST_WIDE_INT_ELT (y, j)((y)->u.hwiv.elem[j]))
3617 return -1;
3618 if (CONST_WIDE_INT_ELT (x, j)((x)->u.hwiv.elem[j]) > CONST_WIDE_INT_ELT (y, j)((y)->u.hwiv.elem[j]))
3619 return 1;
3620 }
3621 }
3622
3623 return 0;
3624}
3625
3626/* Check the order of entries in one-part variables. */
3627
3628int
3629canonicalize_loc_order_check (variable **slot,
3630 dataflow_set *data ATTRIBUTE_UNUSED__attribute__ ((__unused__)))
3631{
3632 variable *var = *slot;
3633 location_chain *node, *next;
3634
3635#ifdef ENABLE_RTL_CHECKING
3636 int i;
3637 for (i = 0; i < var->n_var_parts; i++)
3638 gcc_assert (var->var_part[0].cur_loc == NULL)((void)(!(var->var_part[0].cur_loc == nullptr) ? fancy_abort
("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 3638, __FUNCTION__), 0 : 0))
;
3639 gcc_assert (!var->in_changed_variables)((void)(!(!var->in_changed_variables) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 3639, __FUNCTION__), 0 : 0))
;
3640#endif
3641
3642 if (!var->onepart)
3643 return 1;
3644
3645 gcc_assert (var->n_var_parts == 1)((void)(!(var->n_var_parts == 1) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 3645, __FUNCTION__), 0 : 0))
;
3646 node = var->var_part[0].loc_chain;
3647 gcc_assert (node)((void)(!(node) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 3647, __FUNCTION__), 0 : 0))
;
3648
3649 while ((next = node->next))
3650 {
3651 gcc_assert (loc_cmp (node->loc, next->loc) < 0)((void)(!(loc_cmp (node->loc, next->loc) < 0) ? fancy_abort
("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 3651, __FUNCTION__), 0 : 0))
;
3652 node = next;
3653 }
3654
3655 return 1;
3656}
3657
3658/* Mark with VALUE_RECURSED_INTO values that have neighbors that are
3659 more likely to be chosen as canonical for an equivalence set.
3660 Ensure less likely values can reach more likely neighbors, making
3661 the connections bidirectional. */
3662
3663int
3664canonicalize_values_mark (variable **slot, dataflow_set *set)
3665{
3666 variable *var = *slot;
3667 decl_or_value dv = var->dv;
3668 rtx val;
3669 location_chain *node;
3670
3671 if (!dv_is_value_p (dv))
3672 return 1;
3673
3674 gcc_checking_assert (var->n_var_parts == 1)((void)(!(var->n_var_parts == 1) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 3674, __FUNCTION__), 0 : 0))
;
3675
3676 val = dv_as_value (dv);
3677
3678 for (node = var->var_part[0].loc_chain; node; node = node->next)
3679 if (GET_CODE (node->loc)((enum rtx_code) (node->loc)->code) == VALUE)
3680 {
3681 if (canon_value_cmp (node->loc, val))
3682 VALUE_RECURSED_INTO (val)(__extension__ ({ __typeof ((val)) const _rtx = ((val)); if (
((enum rtx_code) (_rtx)->code) != VALUE && ((enum rtx_code
) (_rtx)->code) != DEBUG_EXPR) rtl_check_failed_flag ("VALUE_RECURSED_INTO"
,_rtx, "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 3682, __FUNCTION__); _rtx; })->used)
= true;
3683 else
3684 {
3685 decl_or_value odv = dv_from_value (node->loc);
3686 variable **oslot;
3687 oslot = shared_hash_find_slot_noinsert (set->vars, odv);
3688
3689 set_slot_part (set, val, oslot, odv, 0,
3690 node->init, NULL_RTX(rtx) 0);
3691
3692 VALUE_RECURSED_INTO (node->loc)(__extension__ ({ __typeof ((node->loc)) const _rtx = ((node
->loc)); if (((enum rtx_code) (_rtx)->code) != VALUE &&
((enum rtx_code) (_rtx)->code) != DEBUG_EXPR) rtl_check_failed_flag
("VALUE_RECURSED_INTO",_rtx, "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 3692, __FUNCTION__); _rtx; })->used)
= true;
3693 }
3694 }
3695
3696 return 1;
3697}
3698
3699/* Remove redundant entries from equivalence lists in onepart
3700 variables, canonicalizing equivalence sets into star shapes. */
3701
3702int
3703canonicalize_values_star (variable **slot, dataflow_set *set)
3704{
3705 variable *var = *slot;
3706 decl_or_value dv = var->dv;
3707 location_chain *node;
3708 decl_or_value cdv;
3709 rtx val, cval;
3710 variable **cslot;
3711 bool has_value;
3712 bool has_marks;
3713
3714 if (!var->onepart)
3715 return 1;
3716
3717 gcc_checking_assert (var->n_var_parts == 1)((void)(!(var->n_var_parts == 1) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 3717, __FUNCTION__), 0 : 0))
;
3718
3719 if (dv_is_value_p (dv))
3720 {
3721 cval = dv_as_value (dv);
3722 if (!VALUE_RECURSED_INTO (cval)(__extension__ ({ __typeof ((cval)) const _rtx = ((cval)); if
(((enum rtx_code) (_rtx)->code) != VALUE && ((enum
rtx_code) (_rtx)->code) != DEBUG_EXPR) rtl_check_failed_flag
("VALUE_RECURSED_INTO",_rtx, "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 3722, __FUNCTION__); _rtx; })->used)
)
3723 return 1;
3724 VALUE_RECURSED_INTO (cval)(__extension__ ({ __typeof ((cval)) const _rtx = ((cval)); if
(((enum rtx_code) (_rtx)->code) != VALUE && ((enum
rtx_code) (_rtx)->code) != DEBUG_EXPR) rtl_check_failed_flag
("VALUE_RECURSED_INTO",_rtx, "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 3724, __FUNCTION__); _rtx; })->used)
= false;
3725 }
3726 else
3727 cval = NULL_RTX(rtx) 0;
3728
3729 restart:
3730 val = cval;
3731 has_value = false;
3732 has_marks = false;
3733
3734 gcc_assert (var->n_var_parts == 1)((void)(!(var->n_var_parts == 1) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 3734, __FUNCTION__), 0 : 0))
;
3735
3736 for (node = var->var_part[0].loc_chain; node; node = node->next)
3737 if (GET_CODE (node->loc)((enum rtx_code) (node->loc)->code) == VALUE)
3738 {
3739 has_value = true;
3740 if (VALUE_RECURSED_INTO (node->loc)(__extension__ ({ __typeof ((node->loc)) const _rtx = ((node
->loc)); if (((enum rtx_code) (_rtx)->code) != VALUE &&
((enum rtx_code) (_rtx)->code) != DEBUG_EXPR) rtl_check_failed_flag
("VALUE_RECURSED_INTO",_rtx, "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 3740, __FUNCTION__); _rtx; })->used)
)
3741 has_marks = true;
3742 if (canon_value_cmp (node->loc, cval))
3743 cval = node->loc;
3744 }
3745
3746 if (!has_value)
3747 return 1;
3748
3749 if (cval == val)
3750 {
3751 if (!has_marks || dv_is_decl_p (dv))
3752 return 1;
3753
3754 /* Keep it marked so that we revisit it, either after visiting a
3755 child node, or after visiting a new parent that might be
3756 found out. */
3757 VALUE_RECURSED_INTO (val)(__extension__ ({ __typeof ((val)) const _rtx = ((val)); if (
((enum rtx_code) (_rtx)->code) != VALUE && ((enum rtx_code
) (_rtx)->code) != DEBUG_EXPR) rtl_check_failed_flag ("VALUE_RECURSED_INTO"
,_rtx, "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 3757, __FUNCTION__); _rtx; })->used)
= true;
3758
3759 for (node = var->var_part[0].loc_chain; node; node = node->next)
3760 if (GET_CODE (node->loc)((enum rtx_code) (node->loc)->code) == VALUE
3761 && VALUE_RECURSED_INTO (node->loc)(__extension__ ({ __typeof ((node->loc)) const _rtx = ((node
->loc)); if (((enum rtx_code) (_rtx)->code) != VALUE &&
((enum rtx_code) (_rtx)->code) != DEBUG_EXPR) rtl_check_failed_flag
("VALUE_RECURSED_INTO",_rtx, "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 3761, __FUNCTION__); _rtx; })->used)
)
3762 {
3763 cval = node->loc;
3764 restart_with_cval:
3765 VALUE_RECURSED_INTO (cval)(__extension__ ({ __typeof ((cval)) const _rtx = ((cval)); if
(((enum rtx_code) (_rtx)->code) != VALUE && ((enum
rtx_code) (_rtx)->code) != DEBUG_EXPR) rtl_check_failed_flag
("VALUE_RECURSED_INTO",_rtx, "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 3765, __FUNCTION__); _rtx; })->used)
= false;
3766 dv = dv_from_value (cval);
3767 slot = shared_hash_find_slot_noinsert (set->vars, dv);
3768 if (!slot)
3769 {
3770 gcc_assert (dv_is_decl_p (var->dv))((void)(!(dv_is_decl_p (var->dv)) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 3770, __FUNCTION__), 0 : 0))
;
3771 /* The canonical value was reset and dropped.
3772 Remove it. */
3773 clobber_variable_part (set, NULLnullptr, var->dv, 0, NULLnullptr);
3774 return 1;
3775 }
3776 var = *slot;
3777 gcc_assert (dv_is_value_p (var->dv))((void)(!(dv_is_value_p (var->dv)) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 3777, __FUNCTION__), 0 : 0))
;
3778 if (var->n_var_parts == 0)
3779 return 1;
3780 gcc_assert (var->n_var_parts == 1)((void)(!(var->n_var_parts == 1) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 3780, __FUNCTION__), 0 : 0))
;
3781 goto restart;
3782 }
3783
3784 VALUE_RECURSED_INTO (val)(__extension__ ({ __typeof ((val)) const _rtx = ((val)); if (
((enum rtx_code) (_rtx)->code) != VALUE && ((enum rtx_code
) (_rtx)->code) != DEBUG_EXPR) rtl_check_failed_flag ("VALUE_RECURSED_INTO"
,_rtx, "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 3784, __FUNCTION__); _rtx; })->used)
= false;
3785
3786 return 1;
3787 }
3788
3789 /* Push values to the canonical one. */
3790 cdv = dv_from_value (cval);
3791 cslot = shared_hash_find_slot_noinsert (set->vars, cdv);
3792
3793 for (node = var->var_part[0].loc_chain; node; node = node->next)
3794 if (node->loc != cval)
3795 {
3796 cslot = set_slot_part (set, node->loc, cslot, cdv, 0,
3797 node->init, NULL_RTX(rtx) 0);
3798 if (GET_CODE (node->loc)((enum rtx_code) (node->loc)->code) == VALUE)
3799 {
3800 decl_or_value ndv = dv_from_value (node->loc);
3801
3802 set_variable_part (set, cval, ndv, 0, node->init, NULL_RTX(rtx) 0,
3803 NO_INSERT);
3804
3805 if (canon_value_cmp (node->loc, val))
3806 {
3807 /* If it could have been a local minimum, it's not any more,
3808 since it's now neighbor to cval, so it may have to push
3809 to it. Conversely, if it wouldn't have prevailed over
3810 val, then whatever mark it has is fine: if it was to
3811 push, it will now push to a more canonical node, but if
3812 it wasn't, then it has already pushed any values it might
3813 have to. */
3814 VALUE_RECURSED_INTO (node->loc)(__extension__ ({ __typeof ((node->loc)) const _rtx = ((node
->loc)); if (((enum rtx_code) (_rtx)->code) != VALUE &&
((enum rtx_code) (_rtx)->code) != DEBUG_EXPR) rtl_check_failed_flag
("VALUE_RECURSED_INTO",_rtx, "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 3814, __FUNCTION__); _rtx; })->used)
= true;
3815 /* Make sure we visit node->loc by ensuring we cval is
3816 visited too. */
3817 VALUE_RECURSED_INTO (cval)(__extension__ ({ __typeof ((cval)) const _rtx = ((cval)); if
(((enum rtx_code) (_rtx)->code) != VALUE && ((enum
rtx_code) (_rtx)->code) != DEBUG_EXPR) rtl_check_failed_flag
("VALUE_RECURSED_INTO",_rtx, "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 3817, __FUNCTION__); _rtx; })->used)
= true;
3818 }
3819 else if (!VALUE_RECURSED_INTO (node->loc)(__extension__ ({ __typeof ((node->loc)) const _rtx = ((node
->loc)); if (((enum rtx_code) (_rtx)->code) != VALUE &&
((enum rtx_code) (_rtx)->code) != DEBUG_EXPR) rtl_check_failed_flag
("VALUE_RECURSED_INTO",_rtx, "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 3819, __FUNCTION__); _rtx; })->used)
)
3820 /* If we have no need to "recurse" into this node, it's
3821 already "canonicalized", so drop the link to the old
3822 parent. */
3823 clobber_variable_part (set, cval, ndv, 0, NULLnullptr);
3824 }
3825 else if (GET_CODE (node->loc)((enum rtx_code) (node->loc)->code) == REG)
3826 {
3827 attrs *list = set->regs[REGNO (node->loc)(rhs_regno(node->loc))], **listp;
3828
3829 /* Change an existing attribute referring to dv so that it
3830 refers to cdv, removing any duplicate this might
3831 introduce, and checking that no previous duplicates
3832 existed, all in a single pass. */
3833
3834 while (list)
3835 {
3836 if (list->offset == 0
3837 && (dv_as_opaque (list->dv) == dv_as_opaque (dv)
3838 || dv_as_opaque (list->dv) == dv_as_opaque (cdv)))
3839 break;
3840
3841 list = list->next;
3842 }
3843
3844 gcc_assert (list)((void)(!(list) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 3844, __FUNCTION__), 0 : 0))
;
3845 if (dv_as_opaque (list->dv) == dv_as_opaque (dv))
3846 {
3847 list->dv = cdv;
3848 for (listp = &list->next; (list = *listp); listp = &list->next)
3849 {
3850 if (list->offset)
3851 continue;
3852
3853 if (dv_as_opaque (list->dv) == dv_as_opaque (cdv))
3854 {
3855 *listp = list->next;
3856 delete list;
3857 list = *listp;
3858 break;
3859 }
3860
3861 gcc_assert (dv_as_opaque (list->dv) != dv_as_opaque (dv))((void)(!(dv_as_opaque (list->dv) != dv_as_opaque (dv)) ? fancy_abort
("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 3861, __FUNCTION__), 0 : 0))
;
3862 }
3863 }
3864 else if (dv_as_opaque (list->dv) == dv_as_opaque (cdv))
3865 {
3866 for (listp = &list->next; (list = *listp); listp = &list->next)
3867 {
3868 if (list->offset)
3869 continue;
3870
3871 if (dv_as_opaque (list->dv) == dv_as_opaque (dv))
3872 {
3873 *listp = list->next;
3874 delete list;
3875 list = *listp;
3876 break;
3877 }
3878
3879 gcc_assert (dv_as_opaque (list->dv) != dv_as_opaque (cdv))((void)(!(dv_as_opaque (list->dv) != dv_as_opaque (cdv)) ?
fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 3879, __FUNCTION__), 0 : 0))
;
3880 }
3881 }
3882 else
3883 gcc_unreachable ()(fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 3883, __FUNCTION__))
;
3884
3885 if (flag_checkingglobal_options.x_flag_checking)
3886 while (list)
3887 {
3888 if (list->offset == 0
3889 && (dv_as_opaque (list->dv) == dv_as_opaque (dv)
3890 || dv_as_opaque (list->dv) == dv_as_opaque (cdv)))
3891 gcc_unreachable ()(fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 3891, __FUNCTION__))
;
3892
3893 list = list->next;
3894 }
3895 }
3896 }
3897
3898 if (val)
3899 set_slot_part (set, val, cslot, cdv, 0,
3900 VAR_INIT_STATUS_INITIALIZED, NULL_RTX(rtx) 0);
3901
3902 slot = clobber_slot_part (set, cval, slot, 0, NULLnullptr);
3903
3904 /* Variable may have been unshared. */
3905 var = *slot;
3906 gcc_checking_assert (var->n_var_parts && var->var_part[0].loc_chain->loc == cval((void)(!(var->n_var_parts && var->var_part[0].
loc_chain->loc == cval && var->var_part[0].loc_chain
->next == nullptr) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 3907, __FUNCTION__), 0 : 0))
3907 && var->var_part[0].loc_chain->next == NULL)((void)(!(var->n_var_parts && var->var_part[0].
loc_chain->loc == cval && var->var_part[0].loc_chain
->next == nullptr) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 3907, __FUNCTION__), 0 : 0))
;
3908
3909 if (VALUE_RECURSED_INTO (cval)(__extension__ ({ __typeof ((cval)) const _rtx = ((cval)); if
(((enum rtx_code) (_rtx)->code) != VALUE && ((enum
rtx_code) (_rtx)->code) != DEBUG_EXPR) rtl_check_failed_flag
("VALUE_RECURSED_INTO",_rtx, "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 3909, __FUNCTION__); _rtx; })->used)
)
3910 goto restart_with_cval;
3911
3912 return 1;
3913}
3914
3915/* Bind one-part variables to the canonical value in an equivalence
3916 set. Not doing this causes dataflow convergence failure in rare
3917 circumstances, see PR42873. Unfortunately we can't do this
3918 efficiently as part of canonicalize_values_star, since we may not
3919 have determined or even seen the canonical value of a set when we
3920 get to a variable that references another member of the set. */
3921
3922int
3923canonicalize_vars_star (variable **slot, dataflow_set *set)
3924{
3925 variable *var = *slot;
3926 decl_or_value dv = var->dv;
3927 location_chain *node;
3928 rtx cval;
3929 decl_or_value cdv;
3930 variable **cslot;
3931 variable *cvar;
3932 location_chain *cnode;
3933
3934 if (!var->onepart || var->onepart == ONEPART_VALUE)
3935 return 1;
3936
3937 gcc_assert (var->n_var_parts == 1)((void)(!(var->n_var_parts == 1) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 3937, __FUNCTION__), 0 : 0))
;
3938
3939 node = var->var_part[0].loc_chain;
3940
3941 if (GET_CODE (node->loc)((enum rtx_code) (node->loc)->code) != VALUE)
3942 return 1;
3943
3944 gcc_assert (!node->next)((void)(!(!node->next) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 3944, __FUNCTION__), 0 : 0))
;
3945 cval = node->loc;
3946
3947 /* Push values to the canonical one. */
3948 cdv = dv_from_value (cval);
3949 cslot = shared_hash_find_slot_noinsert (set->vars, cdv);
3950 if (!cslot)
3951 return 1;
3952 cvar = *cslot;
3953 gcc_assert (cvar->n_var_parts == 1)((void)(!(cvar->n_var_parts == 1) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 3953, __FUNCTION__), 0 : 0))
;
3954
3955 cnode = cvar->var_part[0].loc_chain;
3956
3957 /* CVAL is canonical if its value list contains non-VALUEs or VALUEs
3958 that are not “more canonical” than it. */
3959 if (GET_CODE (cnode->loc)((enum rtx_code) (cnode->loc)->code) != VALUE
3960 || !canon_value_cmp (cnode->loc, cval))
3961 return 1;
3962
3963 /* CVAL was found to be non-canonical. Change the variable to point
3964 to the canonical VALUE. */
3965 gcc_assert (!cnode->next)((void)(!(!cnode->next) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 3965, __FUNCTION__), 0 : 0))
;
3966 cval = cnode->loc;
3967
3968 slot = set_slot_part (set, cval, slot, dv, 0,
3969 node->init, node->set_src);
3970 clobber_slot_part (set, cval, slot, 0, node->set_src);
3971
3972 return 1;
3973}
3974
3975/* Combine variable or value in *S1SLOT (in DSM->cur) with the
3976 corresponding entry in DSM->src. Multi-part variables are combined
3977 with variable_union, whereas onepart dvs are combined with
3978 intersection. */
3979
3980static int
3981variable_merge_over_cur (variable *s1var, struct dfset_merge *dsm)
3982{
3983 dataflow_set *dst = dsm->dst;
3984 variable **dstslot;
3985 variable *s2var, *dvar = NULLnullptr;
3986 decl_or_value dv = s1var->dv;
3987 onepart_enum onepart = s1var->onepart;
3988 rtx val;
3989 hashval_t dvhash;
3990 location_chain *node, **nodep;
3991
3992 /* If the incoming onepart variable has an empty location list, then
3993 the intersection will be just as empty. For other variables,
3994 it's always union. */
3995 gcc_checking_assert (s1var->n_var_parts((void)(!(s1var->n_var_parts && s1var->var_part
[0].loc_chain) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 3996, __FUNCTION__), 0 : 0))
3996 && s1var->var_part[0].loc_chain)((void)(!(s1var->n_var_parts && s1var->var_part
[0].loc_chain) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 3996, __FUNCTION__), 0 : 0))
;
3997
3998 if (!onepart)
3999 return variable_union (s1var, dst);
4000
4001 gcc_checking_assert (s1var->n_var_parts == 1)((void)(!(s1var->n_var_parts == 1) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 4001, __FUNCTION__), 0 : 0))
;
4002
4003 dvhash = dv_htab_hash (dv);
4004 if (dv_is_value_p (dv))
4005 val = dv_as_value (dv);
4006 else
4007 val = NULLnullptr;
4008
4009 s2var = shared_hash_find_1 (dsm->src->vars, dv, dvhash);
4010 if (!s2var)
4011 {
4012 dst_can_be_shared = false;
4013 return 1;
4014 }
4015
4016 dsm->src_onepart_cnt--;
4017 gcc_assert (s2var->var_part[0].loc_chain((void)(!(s2var->var_part[0].loc_chain && s2var->
onepart == onepart && s2var->n_var_parts == 1) ? fancy_abort
("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 4019, __FUNCTION__), 0 : 0))
4018 && s2var->onepart == onepart((void)(!(s2var->var_part[0].loc_chain && s2var->
onepart == onepart && s2var->n_var_parts == 1) ? fancy_abort
("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 4019, __FUNCTION__), 0 : 0))
4019 && s2var->n_var_parts == 1)((void)(!(s2var->var_part[0].loc_chain && s2var->
onepart == onepart && s2var->n_var_parts == 1) ? fancy_abort
("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 4019, __FUNCTION__), 0 : 0))
;
4020
4021 dstslot = shared_hash_find_slot_noinsert_1 (dst->vars, dv, dvhash);
4022 if (dstslot)
4023 {
4024 dvar = *dstslot;
4025 gcc_assert (dvar->refcount == 1((void)(!(dvar->refcount == 1 && dvar->onepart ==
onepart && dvar->n_var_parts == 1) ? fancy_abort (
"/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 4027, __FUNCTION__), 0 : 0))
4026 && dvar->onepart == onepart((void)(!(dvar->refcount == 1 && dvar->onepart ==
onepart && dvar->n_var_parts == 1) ? fancy_abort (
"/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 4027, __FUNCTION__), 0 : 0))
4027 && dvar->n_var_parts == 1)((void)(!(dvar->refcount == 1 && dvar->onepart ==
onepart && dvar->n_var_parts == 1) ? fancy_abort (
"/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 4027, __FUNCTION__), 0 : 0))
;
4028 nodep = &dvar->var_part[0].loc_chain;
4029 }
4030 else
4031 {
4032 nodep = &node;
4033 node = NULLnullptr;
4034 }
4035
4036 if (!dstslot && !onepart_variable_different_p (s1var, s2var))
4037 {
4038 dstslot = shared_hash_find_slot_unshare_1 (&dst->vars, dv,
4039 dvhash, INSERT);
4040 *dstslot = dvar = s2var;
4041 dvar->refcount++;
4042 }
4043 else
4044 {
4045 dst_can_be_shared = false;
4046
4047 intersect_loc_chains (val, nodep, dsm,
4048 s1var->var_part[0].loc_chain, s2var);
4049
4050 if (!dstslot)
4051 {
4052 if (node)
4053 {
4054 dvar = onepart_pool_allocate (onepart);
4055 dvar->dv = dv;
4056 dvar->refcount = 1;
4057 dvar->n_var_parts = 1;
4058 dvar->onepart = onepart;
4059 dvar->in_changed_variables = false;
4060 dvar->var_part[0].loc_chain = node;
4061 dvar->var_part[0].cur_loc = NULLnullptr;
4062 if (onepart)
4063 VAR_LOC_1PAUX (dvar)__extension__ (*({ variable *const __v = (dvar); ((void)(!(__v
->onepart) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 4063, __FUNCTION__), 0 : 0)); &__v->var_part[0].aux.
onepaux; }))
= NULLnullptr;
4064 else
4065 VAR_PART_OFFSET (dvar, 0)__extension__ (*({ variable *const __v = (dvar); ((void)(!(!__v
->onepart) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 4065, __FUNCTION__), 0 : 0)); &__v->var_part[(0)].aux
.offset; }))
= 0;
4066
4067 dstslot
4068 = shared_hash_find_slot_unshare_1 (&dst->vars, dv, dvhash,
4069 INSERT);
4070 gcc_assert (!*dstslot)((void)(!(!*dstslot) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 4070, __FUNCTION__), 0 : 0))
;
4071 *dstslot = dvar;
4072 }
4073 else
4074 return 1;
4075 }
4076 }
4077
4078 nodep = &dvar->var_part[0].loc_chain;
4079 while ((node = *nodep))
4080 {
4081 location_chain **nextp = &node->next;
4082
4083 if (GET_CODE (node->loc)((enum rtx_code) (node->loc)->code) == REG)
4084 {
4085 attrs *list;
4086
4087 for (list = dst->regs[REGNO (node->loc)(rhs_regno(node->loc))]; list; list = list->next)
4088 if (GET_MODE (node->loc)((machine_mode) (node->loc)->mode) == GET_MODE (list->loc)((machine_mode) (list->loc)->mode)
4089 && dv_is_value_p (list->dv))
4090 break;
4091
4092 if (!list)
4093 attrs_list_insert (&dst->regs[REGNO (node->loc)(rhs_regno(node->loc))],
4094 dv, 0, node->loc);
4095 /* If this value became canonical for another value that had
4096 this register, we want to leave it alone. */
4097 else if (dv_as_value (list->dv) != val)
4098 {
4099 dstslot = set_slot_part (dst, dv_as_value (list->dv),
4100 dstslot, dv, 0,
4101 node->init, NULL_RTX(rtx) 0);
4102 dstslot = delete_slot_part (dst, node->loc, dstslot, 0);
4103
4104 /* Since nextp points into the removed node, we can't
4105 use it. The pointer to the next node moved to nodep.
4106 However, if the variable we're walking is unshared
4107 during our walk, we'll keep walking the location list
4108 of the previously-shared variable, in which case the
4109 node won't have been removed, and we'll want to skip
4110 it. That's why we test *nodep here. */
4111 if (*nodep != node)
4112 nextp = nodep;
4113 }
4114 }
4115 else
4116 /* Canonicalization puts registers first, so we don't have to
4117 walk it all. */
4118 break;
4119 nodep = nextp;
4120 }
4121
4122 if (dvar != *dstslot)
4123 dvar = *dstslot;
4124 nodep = &dvar->var_part[0].loc_chain;
4125
4126 if (val)
4127 {
4128 /* Mark all referenced nodes for canonicalization, and make sure
4129 we have mutual equivalence links. */
4130 VALUE_RECURSED_INTO (val)(__extension__ ({ __typeof ((val)) const _rtx = ((val)); if (
((enum rtx_code) (_rtx)->code) != VALUE && ((enum rtx_code
) (_rtx)->code) != DEBUG_EXPR) rtl_check_failed_flag ("VALUE_RECURSED_INTO"
,_rtx, "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 4130, __FUNCTION__); _rtx; })->used)
= true;
4131 for (node = *nodep; node; node = node->next)
4132 if (GET_CODE (node->loc)((enum rtx_code) (node->loc)->code) == VALUE)
4133 {
4134 VALUE_RECURSED_INTO (node->loc)(__extension__ ({ __typeof ((node->loc)) const _rtx = ((node
->loc)); if (((enum rtx_code) (_rtx)->code) != VALUE &&
((enum rtx_code) (_rtx)->code) != DEBUG_EXPR) rtl_check_failed_flag
("VALUE_RECURSED_INTO",_rtx, "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 4134, __FUNCTION__); _rtx; })->used)
= true;
4135 set_variable_part (dst, val, dv_from_value (node->loc), 0,
4136 node->init, NULLnullptr, INSERT);
4137 }
4138
4139 dstslot = shared_hash_find_slot_noinsert_1 (dst->vars, dv, dvhash);
4140 gcc_assert (*dstslot == dvar)((void)(!(*dstslot == dvar) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 4140, __FUNCTION__), 0 : 0))
;
4141 canonicalize_values_star (dstslot, dst);
4142 gcc_checking_assert (dstslot((void)(!(dstslot == shared_hash_find_slot_noinsert_1 (dst->
vars, dv, dvhash)) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 4144, __FUNCTION__), 0 : 0))
4143 == shared_hash_find_slot_noinsert_1 (dst->vars,((void)(!(dstslot == shared_hash_find_slot_noinsert_1 (dst->
vars, dv, dvhash)) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 4144, __FUNCTION__), 0 : 0))
4144 dv, dvhash))((void)(!(dstslot == shared_hash_find_slot_noinsert_1 (dst->
vars, dv, dvhash)) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 4144, __FUNCTION__), 0 : 0))
;
4145 dvar = *dstslot;
4146 }
4147 else
4148 {
4149 bool has_value = false, has_other = false;
4150
4151 /* If we have one value and anything else, we're going to
4152 canonicalize this, so make sure all values have an entry in
4153 the table and are marked for canonicalization. */
4154 for (node = *nodep; node; node = node->next)
4155 {
4156 if (GET_CODE (node->loc)((enum rtx_code) (node->loc)->code) == VALUE)
4157 {
4158 /* If this was marked during register canonicalization,
4159 we know we have to canonicalize values. */
4160 if (has_value)
4161 has_other = true;
4162 has_value = true;
4163 if (has_other)
4164 break;
4165 }
4166 else
4167 {
4168 has_other = true;
4169 if (has_value)
4170 break;
4171 }
4172 }
4173
4174 if (has_value && has_other)
4175 {
4176 for (node = *nodep; node; node = node->next)
4177 {
4178 if (GET_CODE (node->loc)((enum rtx_code) (node->loc)->code) == VALUE)
4179 {
4180 decl_or_value dv = dv_from_value (node->loc);
4181 variable **slot = NULLnullptr;
4182
4183 if (shared_hash_shared (dst->vars))
4184 slot = shared_hash_find_slot_noinsert (dst->vars, dv);
4185 if (!slot)
4186 slot = shared_hash_find_slot_unshare (&dst->vars, dv,
4187 INSERT);
4188 if (!*slot)
4189 {
4190 variable *var = onepart_pool_allocate (ONEPART_VALUE);
4191 var->dv = dv;
4192 var->refcount = 1;
4193 var->n_var_parts = 1;
4194 var->onepart = ONEPART_VALUE;
4195 var->in_changed_variables = false;
4196 var->var_part[0].loc_chain = NULLnullptr;
4197 var->var_part[0].cur_loc = NULLnullptr;
4198 VAR_LOC_1PAUX (var)__extension__ (*({ variable *const __v = (var); ((void)(!(__v
->onepart) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 4198, __FUNCTION__), 0 : 0)); &__v->var_part[0].aux.
onepaux; }))
= NULLnullptr;
4199 *slot = var;
4200 }
4201
4202 VALUE_RECURSED_INTO (node->loc)(__extension__ ({ __typeof ((node->loc)) const _rtx = ((node
->loc)); if (((enum rtx_code) (_rtx)->code) != VALUE &&
((enum rtx_code) (_rtx)->code) != DEBUG_EXPR) rtl_check_failed_flag
("VALUE_RECURSED_INTO",_rtx, "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 4202, __FUNCTION__); _rtx; })->used)
= true;
4203 }
4204 }
4205
4206 dstslot = shared_hash_find_slot_noinsert_1 (dst->vars, dv, dvhash);
4207 gcc_assert (*dstslot == dvar)((void)(!(*dstslot == dvar) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 4207, __FUNCTION__), 0 : 0))
;
4208 canonicalize_values_star (dstslot, dst);
4209 gcc_checking_assert (dstslot((void)(!(dstslot == shared_hash_find_slot_noinsert_1 (dst->
vars, dv, dvhash)) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 4211, __FUNCTION__), 0 : 0))
4210 == shared_hash_find_slot_noinsert_1 (dst->vars,((void)(!(dstslot == shared_hash_find_slot_noinsert_1 (dst->
vars, dv, dvhash)) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 4211, __FUNCTION__), 0 : 0))
4211 dv, dvhash))((void)(!(dstslot == shared_hash_find_slot_noinsert_1 (dst->
vars, dv, dvhash)) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 4211, __FUNCTION__), 0 : 0))
;
4212 dvar = *dstslot;
4213 }
4214 }
4215
4216 if (!onepart_variable_different_p (dvar, s2var))
4217 {
4218 variable_htab_free (dvar);
4219 *dstslot = dvar = s2var;
4220 dvar->refcount++;
4221 }
4222 else if (s2var != s1var && !onepart_variable_different_p (dvar, s1var))
4223 {
4224 variable_htab_free (dvar);
4225 *dstslot = dvar = s1var;
4226 dvar->refcount++;
4227 dst_can_be_shared = false;
4228 }
4229 else
4230 dst_can_be_shared = false;
4231
4232 return 1;
4233}
4234
4235/* Copy s2slot (in DSM->src) to DSM->dst if the variable is a
4236 multi-part variable. Unions of multi-part variables and
4237 intersections of one-part ones will be handled in
4238 variable_merge_over_cur(). */
4239
4240static int
4241variable_merge_over_src (variable *s2var, struct dfset_merge *dsm)
4242{
4243 dataflow_set *dst = dsm->dst;
4244 decl_or_value dv = s2var->dv;
4245
4246 if (!s2var->onepart)
4247 {
4248 variable **dstp = shared_hash_find_slot (dst->vars, dv);
4249 *dstp = s2var;
4250 s2var->refcount++;
4251 return 1;
4252 }
4253
4254 dsm->src_onepart_cnt++;
4255 return 1;
4256}
4257
4258/* Combine dataflow set information from SRC2 into DST, using PDST
4259 to carry over information across passes. */
4260
4261static void
4262dataflow_set_merge (dataflow_set *dst, dataflow_set *src2)
4263{
4264 dataflow_set cur = *dst;
4265 dataflow_set *src1 = &cur;
4266 struct dfset_merge dsm;
4267 int i;
4268 size_t src1_elems, src2_elems;
4269 variable_iterator_type hi;
4270 variable *var;
4271
4272 src1_elems = shared_hash_htab (src1->vars)->elements ();
4273 src2_elems = shared_hash_htab (src2->vars)->elements ();
4274 dataflow_set_init (dst);
4275 dst->stack_adjust = cur.stack_adjust;
4276 shared_hash_destroy (dst->vars);
4277 dst->vars = new shared_hash;
4278 dst->vars->refcount = 1;
4279 dst->vars->htab = new variable_table_type (MAX (src1_elems, src2_elems)((src1_elems) > (src2_elems) ? (src1_elems) : (src2_elems)
)
);
4280
4281 for (i = 0; i < FIRST_PSEUDO_REGISTER76; i++)
4282 attrs_list_mpdv_union (&dst->regs[i], src1->regs[i], src2->regs[i]);
4283
4284 dsm.dst = dst;
4285 dsm.src = src2;
4286 dsm.cur = src1;
4287 dsm.src_onepart_cnt = 0;
4288
4289 FOR_EACH_HASH_TABLE_ELEMENT (*shared_hash_htab (dsm.src->vars),for ((hi) = (*shared_hash_htab (dsm.src->vars)).begin (); (
hi) != (*shared_hash_htab (dsm.src->vars)).end () ? (var =
*(hi) , true) : false; ++(hi))
4290 var, variable, hi)for ((hi) = (*shared_hash_htab (dsm.src->vars)).begin (); (
hi) != (*shared_hash_htab (dsm.src->vars)).end () ? (var =
*(hi) , true) : false; ++(hi))
4291 variable_merge_over_src (var, &dsm);
4292 FOR_EACH_HASH_TABLE_ELEMENT (*shared_hash_htab (dsm.cur->vars),for ((hi) = (*shared_hash_htab (dsm.cur->vars)).begin (); (
hi) != (*shared_hash_htab (dsm.cur->vars)).end () ? (var =
*(hi) , true) : false; ++(hi))
4293 var, variable, hi)for ((hi) = (*shared_hash_htab (dsm.cur->vars)).begin (); (
hi) != (*shared_hash_htab (dsm.cur->vars)).end () ? (var =
*(hi) , true) : false; ++(hi))
4294 variable_merge_over_cur (var, &dsm);
4295
4296 if (dsm.src_onepart_cnt)
4297 dst_can_be_shared = false;
4298
4299 dataflow_set_destroy (src1);
4300}
4301
4302/* Mark register equivalences. */
4303
4304static void
4305dataflow_set_equiv_regs (dataflow_set *set)
4306{
4307 int i;
4308 attrs *list, **listp;
4309
4310 for (i = 0; i < FIRST_PSEUDO_REGISTER76; i++)
4311 {
4312 rtx canon[NUM_MACHINE_MODES];
4313
4314 /* If the list is empty or one entry, no need to canonicalize
4315 anything. */
4316 if (set->regs[i] == NULLnullptr || set->regs[i]->next == NULLnullptr)
4317 continue;
4318
4319 memset (canon, 0, sizeof (canon));
4320
4321 for (list = set->regs[i]; list; list = list->next)
4322 if (list->offset == 0 && dv_is_value_p (list->dv))
4323 {
4324 rtx val = dv_as_value (list->dv);
4325 rtx *cvalp = &canon[(int)GET_MODE (val)((machine_mode) (val)->mode)];
4326 rtx cval = *cvalp;
4327
4328 if (canon_value_cmp (val, cval))
4329 *cvalp = val;
4330 }
4331
4332 for (list = set->regs[i]; list; list = list->next)
4333 if (list->offset == 0 && dv_onepart_p (list->dv))
4334 {
4335 rtx cval = canon[(int)GET_MODE (list->loc)((machine_mode) (list->loc)->mode)];
4336
4337 if (!cval)
4338 continue;
4339
4340 if (dv_is_value_p (list->dv))
4341 {
4342 rtx val = dv_as_value (list->dv);
4343
4344 if (val == cval)
4345 continue;
4346
4347 VALUE_RECURSED_INTO (val)(__extension__ ({ __typeof ((val)) const _rtx = ((val)); if (
((enum rtx_code) (_rtx)->code) != VALUE && ((enum rtx_code
) (_rtx)->code) != DEBUG_EXPR) rtl_check_failed_flag ("VALUE_RECURSED_INTO"
,_rtx, "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 4347, __FUNCTION__); _rtx; })->used)
= true;
4348 set_variable_part (set, val, dv_from_value (cval), 0,
4349 VAR_INIT_STATUS_INITIALIZED,
4350 NULLnullptr, NO_INSERT);
4351 }
4352
4353 VALUE_RECURSED_INTO (cval)(__extension__ ({ __typeof ((cval)) const _rtx = ((cval)); if
(((enum rtx_code) (_rtx)->code) != VALUE && ((enum
rtx_code) (_rtx)->code) != DEBUG_EXPR) rtl_check_failed_flag
("VALUE_RECURSED_INTO",_rtx, "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 4353, __FUNCTION__); _rtx; })->used)
= true;
4354 set_variable_part (set, cval, list->dv, 0,
4355 VAR_INIT_STATUS_INITIALIZED, NULLnullptr, NO_INSERT);
4356 }
4357
4358 for (listp = &set->regs[i]; (list = *listp);
4359 listp = list ? &list->next : listp)
4360 if (list->offset == 0 && dv_onepart_p (list->dv))
4361 {
4362 rtx cval = canon[(int)GET_MODE (list->loc)((machine_mode) (list->loc)->mode)];
4363 variable **slot;
4364
4365 if (!cval)
4366 continue;
4367
4368 if (dv_is_value_p (list->dv))
4369 {
4370 rtx val = dv_as_value (list->dv);
4371 if (!VALUE_RECURSED_INTO (val)(__extension__ ({ __typeof ((val)) const _rtx = ((val)); if (
((enum rtx_code) (_rtx)->code) != VALUE && ((enum rtx_code
) (_rtx)->code) != DEBUG_EXPR) rtl_check_failed_flag ("VALUE_RECURSED_INTO"
,_rtx, "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 4371, __FUNCTION__); _rtx; })->used)
)
4372 continue;
4373 }
4374
4375 slot = shared_hash_find_slot_noinsert (set->vars, list->dv);
4376 canonicalize_values_star (slot, set);
4377 if (*listp != list)
4378 list = NULLnullptr;
4379 }
4380 }
4381}
4382
4383/* Remove any redundant values in the location list of VAR, which must
4384 be unshared and 1-part. */
4385
4386static void
4387remove_duplicate_values (variable *var)
4388{
4389 location_chain *node, **nodep;
4390
4391 gcc_assert (var->onepart)((void)(!(var->onepart) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 4391, __FUNCTION__), 0 : 0))
;
4392 gcc_assert (var->n_var_parts == 1)((void)(!(var->n_var_parts == 1) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 4392, __FUNCTION__), 0 : 0))
;
4393 gcc_assert (var->refcount == 1)((void)(!(var->refcount == 1) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 4393, __FUNCTION__), 0 : 0))
;
4394
4395 for (nodep = &var->var_part[0].loc_chain; (node = *nodep); )
4396 {
4397 if (GET_CODE (node->loc)((enum rtx_code) (node->loc)->code) == VALUE)
4398 {
4399 if (VALUE_RECURSED_INTO (node->loc)(__extension__ ({ __typeof ((node->loc)) const _rtx = ((node
->loc)); if (((enum rtx_code) (_rtx)->code) != VALUE &&
((enum rtx_code) (_rtx)->code) != DEBUG_EXPR) rtl_check_failed_flag
("VALUE_RECURSED_INTO",_rtx, "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 4399, __FUNCTION__); _rtx; })->used)
)
4400 {
4401 /* Remove duplicate value node. */
4402 *nodep = node->next;
4403 delete node;
4404 continue;
4405 }
4406 else
4407 VALUE_RECURSED_INTO (node->loc)(__extension__ ({ __typeof ((node->loc)) const _rtx = ((node
->loc)); if (((enum rtx_code) (_rtx)->code) != VALUE &&
((enum rtx_code) (_rtx)->code) != DEBUG_EXPR) rtl_check_failed_flag
("VALUE_RECURSED_INTO",_rtx, "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 4407, __FUNCTION__); _rtx; })->used)
= true;
4408 }
4409 nodep = &node->next;
4410 }
4411
4412 for (node = var->var_part[0].loc_chain; node; node = node->next)
4413 if (GET_CODE (node->loc)((enum rtx_code) (node->loc)->code) == VALUE)
4414 {
4415 gcc_assert (VALUE_RECURSED_INTO (node->loc))((void)(!((__extension__ ({ __typeof ((node->loc)) const _rtx
= ((node->loc)); if (((enum rtx_code) (_rtx)->code) !=
VALUE && ((enum rtx_code) (_rtx)->code) != DEBUG_EXPR
) rtl_check_failed_flag ("VALUE_RECURSED_INTO",_rtx, "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 4415, __FUNCTION__); _rtx; })->used)) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 4415, __FUNCTION__), 0 : 0))
;
4416 VALUE_RECURSED_INTO (node->loc)(__extension__ ({ __typeof ((node->loc)) const _rtx = ((node
->loc)); if (((enum rtx_code) (_rtx)->code) != VALUE &&
((enum rtx_code) (_rtx)->code) != DEBUG_EXPR) rtl_check_failed_flag
("VALUE_RECURSED_INTO",_rtx, "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 4416, __FUNCTION__); _rtx; })->used)
= false;
4417 }
4418}
4419
4420
4421/* Hash table iteration argument passed to variable_post_merge. */
4422struct dfset_post_merge
4423{
4424 /* The new input set for the current block. */
4425 dataflow_set *set;
4426 /* Pointer to the permanent input set for the current block, or
4427 NULL. */
4428 dataflow_set **permp;
4429};
4430
4431/* Create values for incoming expressions associated with one-part
4432 variables that don't have value numbers for them. */
4433
4434int
4435variable_post_merge_new_vals (variable **slot, dfset_post_merge *dfpm)
4436{
4437 dataflow_set *set = dfpm->set;
4438 variable *var = *slot;
4439 location_chain *node;
4440
4441 if (!var->onepart || !var->n_var_parts)
4442 return 1;
4443
4444 gcc_assert (var->n_var_parts == 1)((void)(!(var->n_var_parts == 1) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 4444, __FUNCTION__), 0 : 0))
;
4445
4446 if (dv_is_decl_p (var->dv))
4447 {
4448 bool check_dupes = false;
4449
4450 restart:
4451 for (node = var->var_part[0].loc_chain; node; node = node->next)
4452 {
4453 if (GET_CODE (node->loc)((enum rtx_code) (node->loc)->code) == VALUE)
4454 gcc_assert (!VALUE_RECURSED_INTO (node->loc))((void)(!(!(__extension__ ({ __typeof ((node->loc)) const _rtx
= ((node->loc)); if (((enum rtx_code) (_rtx)->code) !=
VALUE && ((enum rtx_code) (_rtx)->code) != DEBUG_EXPR
) rtl_check_failed_flag ("VALUE_RECURSED_INTO",_rtx, "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 4454, __FUNCTION__); _rtx; })->used)) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 4454, __FUNCTION__), 0 : 0))
;
4455 else if (GET_CODE (node->loc)((enum rtx_code) (node->loc)->code) == REG)
4456 {
4457 attrs *att, **attp, **curp = NULLnullptr;
4458
4459 if (var->refcount != 1)
4460 {
4461 slot = unshare_variable (set, slot, var,
4462 VAR_INIT_STATUS_INITIALIZED);
4463 var = *slot;
4464 goto restart;
4465 }
4466
4467 for (attp = &set->regs[REGNO (node->loc)(rhs_regno(node->loc))]; (att = *attp);
4468 attp = &att->next)
4469 if (att->offset == 0
4470 && GET_MODE (att->loc)((machine_mode) (att->loc)->mode) == GET_MODE (node->loc)((machine_mode) (node->loc)->mode))
4471 {
4472 if (dv_is_value_p (att->dv))
4473 {
4474 rtx cval = dv_as_value (att->dv);
4475 node->loc = cval;
4476 check_dupes = true;
4477 break;
4478 }
4479 else if (dv_as_opaque (att->dv) == dv_as_opaque (var->dv))
4480 curp = attp;
4481 }
4482
4483 if (!curp)
4484 {
4485 curp = attp;
4486 while (*curp)
4487 if ((*curp)->offset == 0
4488 && GET_MODE ((*curp)->loc)((machine_mode) ((*curp)->loc)->mode) == GET_MODE (node->loc)((machine_mode) (node->loc)->mode)
4489 && dv_as_opaque ((*curp)->dv) == dv_as_opaque (var->dv))
4490 break;
4491 else
4492 curp = &(*curp)->next;
4493 gcc_assert (*curp)((void)(!(*curp) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 4493, __FUNCTION__), 0 : 0))
;
4494 }
4495
4496 if (!att)
4497 {
4498 decl_or_value cdv;
4499 rtx cval;
4500
4501 if (!*dfpm->permp)
4502 {
4503 *dfpm->permp = XNEW (dataflow_set)((dataflow_set *) xmalloc (sizeof (dataflow_set)));
4504 dataflow_set_init (*dfpm->permp);
4505 }
4506
4507 for (att = (*dfpm->permp)->regs[REGNO (node->loc)(rhs_regno(node->loc))];
4508 att; att = att->next)
4509 if (GET_MODE (att->loc)((machine_mode) (att->loc)->mode) == GET_MODE (node->loc)((machine_mode) (node->loc)->mode))
4510 {
4511 gcc_assert (att->offset == 0((void)(!(att->offset == 0 && dv_is_value_p (att->
dv)) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 4512, __FUNCTION__), 0 : 0))
4512 && dv_is_value_p (att->dv))((void)(!(att->offset == 0 && dv_is_value_p (att->
dv)) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 4512, __FUNCTION__), 0 : 0))
;
4513 val_reset (set, att->dv);
4514 break;
4515 }
4516
4517 if (att)
4518 {
4519 cdv = att->dv;
4520 cval = dv_as_value (cdv);
4521 }
4522 else
4523 {
4524 /* Create a unique value to hold this register,
4525 that ought to be found and reused in
4526 subsequent rounds. */
4527 cselib_val *v;
4528 gcc_assert (!cselib_lookup (node->loc,((void)(!(!cselib_lookup (node->loc, ((machine_mode) (node
->loc)->mode), 0, ((void) 0, E_VOIDmode))) ? fancy_abort
("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 4530, __FUNCTION__), 0 : 0))
4529 GET_MODE (node->loc), 0,((void)(!(!cselib_lookup (node->loc, ((machine_mode) (node
->loc)->mode), 0, ((void) 0, E_VOIDmode))) ? fancy_abort
("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 4530, __FUNCTION__), 0 : 0))
4530 VOIDmode))((void)(!(!cselib_lookup (node->loc, ((machine_mode) (node
->loc)->mode), 0, ((void) 0, E_VOIDmode))) ? fancy_abort
("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 4530, __FUNCTION__), 0 : 0))
;
4531 v = cselib_lookup (node->loc, GET_MODE (node->loc)((machine_mode) (node->loc)->mode), 1,
4532 VOIDmode((void) 0, E_VOIDmode));
4533 cselib_preserve_value (v);
4534 cselib_invalidate_rtx (node->loc);
4535 cval = v->val_rtx;
4536 cdv = dv_from_value (cval);
4537 if (dump_file)
4538 fprintf (dump_file,
4539 "Created new value %u:%u for reg %i\n",
4540 v->uid, v->hash, REGNO (node->loc)(rhs_regno(node->loc)));
4541 }
4542
4543 var_reg_decl_set (*dfpm->permp, node->loc,
4544 VAR_INIT_STATUS_INITIALIZED,
4545 cdv, 0, NULLnullptr, INSERT);
4546
4547 node->loc = cval;
4548 check_dupes = true;
4549 }
4550
4551 /* Remove attribute referring to the decl, which now
4552 uses the value for the register, already existing or
4553 to be added when we bring perm in. */
4554 att = *curp;
4555 *curp = att->next;
4556 delete att;
4557 }
4558 }
4559
4560 if (check_dupes)
4561 remove_duplicate_values (var);
4562 }
4563
4564 return 1;
4565}
4566
4567/* Reset values in the permanent set that are not associated with the
4568 chosen expression. */
4569
4570int
4571variable_post_merge_perm_vals (variable **pslot, dfset_post_merge *dfpm)
4572{
4573 dataflow_set *set = dfpm->set;
4574 variable *pvar = *pslot, *var;
4575 location_chain *pnode;
4576 decl_or_value dv;
4577 attrs *att;
4578
4579 gcc_assert (dv_is_value_p (pvar->dv)((void)(!(dv_is_value_p (pvar->dv) && pvar->n_var_parts
== 1) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 4580, __FUNCTION__), 0 : 0))
4580 && pvar->n_var_parts == 1)((void)(!(dv_is_value_p (pvar->dv) && pvar->n_var_parts
== 1) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 4580, __FUNCTION__), 0 : 0))
;
4581 pnode = pvar->var_part[0].loc_chain;
4582 gcc_assert (pnode((void)(!(pnode && !pnode->next && (((enum
rtx_code) (pnode->loc)->code) == REG)) ? fancy_abort (
"/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 4584, __FUNCTION__), 0 : 0))
4583 && !pnode->next((void)(!(pnode && !pnode->next && (((enum
rtx_code) (pnode->loc)->code) == REG)) ? fancy_abort (
"/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 4584, __FUNCTION__), 0 : 0))
4584 && REG_P (pnode->loc))((void)(!(pnode && !pnode->next && (((enum
rtx_code) (pnode->loc)->code) == REG)) ? fancy_abort (
"/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 4584, __FUNCTION__), 0 : 0))
;
4585
4586 dv = pvar->dv;
4587
4588 var = shared_hash_find (set->vars, dv);
4589 if (var)
4590 {
4591 /* Although variable_post_merge_new_vals may have made decls
4592 non-star-canonical, values that pre-existed in canonical form
4593 remain canonical, and newly-created values reference a single
4594 REG, so they are canonical as well. Since VAR has the
4595 location list for a VALUE, using find_loc_in_1pdv for it is
4596 fine, since VALUEs don't map back to DECLs. */
4597 if (find_loc_in_1pdv (pnode->loc, var, shared_hash_htab (set->vars)))
4598 return 1;
4599 val_reset (set, dv);
4600 }
4601
4602 for (att = set->regs[REGNO (pnode->loc)(rhs_regno(pnode->loc))]; att; att = att->next)
4603 if (att->offset == 0
4604 && GET_MODE (att->loc)((machine_mode) (att->loc)->mode) == GET_MODE (pnode->loc)((machine_mode) (pnode->loc)->mode)
4605 && dv_is_value_p (att->dv))
4606 break;
4607
4608 /* If there is a value associated with this register already, create
4609 an equivalence. */
4610 if (att && dv_as_value (att->dv) != dv_as_value (dv))
4611 {
4612 rtx cval = dv_as_value (att->dv);
4613 set_variable_part (set, cval, dv, 0, pnode->init, NULLnullptr, INSERT);
4614 set_variable_part (set, dv_as_value (dv), att->dv, 0, pnode->init,
4615 NULLnullptr, INSERT);
4616 }
4617 else if (!att)
4618 {
4619 attrs_list_insert (&set->regs[REGNO (pnode->loc)(rhs_regno(pnode->loc))],
4620 dv, 0, pnode->loc);
4621 variable_union (pvar, set);
4622 }
4623
4624 return 1;
4625}
4626
4627/* Just checking stuff and registering register attributes for
4628 now. */
4629
4630static void
4631dataflow_post_merge_adjust (dataflow_set *set, dataflow_set **permp)
4632{
4633 struct dfset_post_merge dfpm;
4634
4635 dfpm.set = set;
4636 dfpm.permp = permp;
4637
4638 shared_hash_htab (set->vars)
4639 ->traverse <dfset_post_merge*, variable_post_merge_new_vals> (&dfpm);
4640 if (*permp)
4641 shared_hash_htab ((*permp)->vars)
4642 ->traverse <dfset_post_merge*, variable_post_merge_perm_vals> (&dfpm);
4643 shared_hash_htab (set->vars)
4644 ->traverse <dataflow_set *, canonicalize_values_star> (set);
4645 shared_hash_htab (set->vars)
4646 ->traverse <dataflow_set *, canonicalize_vars_star> (set);
4647}
4648
4649/* Return a node whose loc is a MEM that refers to EXPR in the
4650 location list of a one-part variable or value VAR, or in that of
4651 any values recursively mentioned in the location lists. */
4652
4653static location_chain *
4654find_mem_expr_in_1pdv (tree expr, rtx val, variable_table_type *vars)
4655{
4656 location_chain *node;
4657 decl_or_value dv;
4658 variable *var;
4659 location_chain *where = NULLnullptr;
4660
4661 if (!val)
4662 return NULLnullptr;
4663
4664 gcc_assert (GET_CODE (val) == VALUE((void)(!(((enum rtx_code) (val)->code) == VALUE &&
!(__extension__ ({ __typeof ((val)) const _rtx = ((val)); if
(((enum rtx_code) (_rtx)->code) != VALUE && ((enum
rtx_code) (_rtx)->code) != DEBUG_EXPR) rtl_check_failed_flag
("VALUE_RECURSED_INTO",_rtx, "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 4665, __FUNCTION__); _rtx; })->used)) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 4665, __FUNCTION__), 0 : 0))
4665 && !VALUE_RECURSED_INTO (val))((void)(!(((enum rtx_code) (val)->code) == VALUE &&
!(__extension__ ({ __typeof ((val)) const _rtx = ((val)); if
(((enum rtx_code) (_rtx)->code) != VALUE && ((enum
rtx_code) (_rtx)->code) != DEBUG_EXPR) rtl_check_failed_flag
("VALUE_RECURSED_INTO",_rtx, "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 4665, __FUNCTION__); _rtx; })->used)) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 4665, __FUNCTION__), 0 : 0))
;
4666
4667 dv = dv_from_value (val);
4668 var = vars->find_with_hash (dv, dv_htab_hash (dv));
4669
4670 if (!var)
4671 return NULLnullptr;
4672
4673 gcc_assert (var->onepart)((void)(!(var->onepart) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 4673, __FUNCTION__), 0 : 0))
;
4674
4675 if (!var->n_var_parts)
4676 return NULLnullptr;
4677
4678 VALUE_RECURSED_INTO (val)(__extension__ ({ __typeof ((val)) const _rtx = ((val)); if (
((enum rtx_code) (_rtx)->code) != VALUE && ((enum rtx_code
) (_rtx)->code) != DEBUG_EXPR) rtl_check_failed_flag ("VALUE_RECURSED_INTO"
,_rtx, "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 4678, __FUNCTION__); _rtx; })->used)
= true;
4679
4680 for (node = var->var_part[0].loc_chain; node; node = node->next)
4681 if (MEM_P (node->loc)(((enum rtx_code) (node->loc)->code) == MEM)
4682 && MEM_EXPR (node->loc)(get_mem_attrs (node->loc)->expr) == expr
4683 && int_mem_offset (node->loc) == 0)
4684 {
4685 where = node;
4686 break;
4687 }
4688 else if (GET_CODE (node->loc)((enum rtx_code) (node->loc)->code) == VALUE
4689 && !VALUE_RECURSED_INTO (node->loc)(__extension__ ({ __typeof ((node->loc)) const _rtx = ((node
->loc)); if (((enum rtx_code) (_rtx)->code) != VALUE &&
((enum rtx_code) (_rtx)->code) != DEBUG_EXPR) rtl_check_failed_flag
("VALUE_RECURSED_INTO",_rtx, "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 4689, __FUNCTION__); _rtx; })->used)
4690 && (where = find_mem_expr_in_1pdv (expr, node->loc, vars)))
4691 break;
4692
4693 VALUE_RECURSED_INTO (val)(__extension__ ({ __typeof ((val)) const _rtx = ((val)); if (
((enum rtx_code) (_rtx)->code) != VALUE && ((enum rtx_code
) (_rtx)->code) != DEBUG_EXPR) rtl_check_failed_flag ("VALUE_RECURSED_INTO"
,_rtx, "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 4693, __FUNCTION__); _rtx; })->used)
= false;
4694
4695 return where;
4696}
4697
4698/* Return TRUE if the value of MEM may vary across a call. */
4699
4700static bool
4701mem_dies_at_call (rtx mem)
4702{
4703 tree expr = MEM_EXPR (mem)(get_mem_attrs (mem)->expr);
4704 tree decl;
4705
4706 if (!expr)
4707 return true;
4708
4709 decl = get_base_address (expr);
4710
4711 if (!decl)
4712 return true;
4713
4714 if (!DECL_P (decl)(tree_code_type[(int) (((enum tree_code) (decl)->base.code
))] == tcc_declaration)
)
4715 return true;
4716
4717 return (may_be_aliased (decl)
4718 || (!TREE_READONLY (decl)((non_type_check ((decl), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 4718, __FUNCTION__))->base.readonly_flag)
&& is_global_var (decl)));
4719}
4720
4721/* Remove all MEMs from the location list of a hash table entry for a
4722 one-part variable, except those whose MEM attributes map back to
4723 the variable itself, directly or within a VALUE. */
4724
4725int
4726dataflow_set_preserve_mem_locs (variable **slot, dataflow_set *set)
4727{
4728 variable *var = *slot;
4729
4730 if (var->onepart == ONEPART_VDECL || var->onepart == ONEPART_DEXPR)
4731 {
4732 tree decl = dv_as_decl (var->dv);
4733 location_chain *loc, **locp;
4734 bool changed = false;
4735
4736 if (!var->n_var_parts)
4737 return 1;
4738
4739 gcc_assert (var->n_var_parts == 1)((void)(!(var->n_var_parts == 1) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 4739, __FUNCTION__), 0 : 0))
;
4740
4741 if (shared_var_p (var, set->vars))
4742 {
4743 for (loc = var->var_part[0].loc_chain; loc; loc = loc->next)
4744 {
4745 /* We want to remove dying MEMs that don't refer to DECL. */
4746 if (GET_CODE (loc->loc)((enum rtx_code) (loc->loc)->code) == MEM
4747 && (MEM_EXPR (loc->loc)(get_mem_attrs (loc->loc)->expr) != decl
4748 || int_mem_offset (loc->loc) != 0)
4749 && mem_dies_at_call (loc->loc))
4750 break;
4751 /* We want to move here MEMs that do refer to DECL. */
4752 else if (GET_CODE (loc->loc)((enum rtx_code) (loc->loc)->code) == VALUE
4753 && find_mem_expr_in_1pdv (decl, loc->loc,
4754 shared_hash_htab (set->vars)))
4755 break;
4756 }
4757
4758 if (!loc)
4759 return 1;
4760
4761 slot = unshare_variable (set, slot, var, VAR_INIT_STATUS_UNKNOWN);
4762 var = *slot;
4763 gcc_assert (var->n_var_parts == 1)((void)(!(var->n_var_parts == 1) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 4763, __FUNCTION__), 0 : 0))
;
4764 }
4765
4766 for (locp = &var->var_part[0].loc_chain, loc = *locp;
4767 loc; loc = *locp)
4768 {
4769 rtx old_loc = loc->loc;
4770 if (GET_CODE (old_loc)((enum rtx_code) (old_loc)->code) == VALUE)
4771 {
4772 location_chain *mem_node
4773 = find_mem_expr_in_1pdv (decl, loc->loc,
4774 shared_hash_htab (set->vars));
4775
4776 /* ??? This picks up only one out of multiple MEMs that
4777 refer to the same variable. Do we ever need to be
4778 concerned about dealing with more than one, or, given
4779 that they should all map to the same variable
4780 location, their addresses will have been merged and
4781 they will be regarded as equivalent? */
4782 if (mem_node)
4783 {
4784 loc->loc = mem_node->loc;
4785 loc->set_src = mem_node->set_src;
4786 loc->init = MIN (loc->init, mem_node->init)((loc->init) < (mem_node->init) ? (loc->init) : (
mem_node->init))
;
4787 }
4788 }
4789
4790 if (GET_CODE (loc->loc)((enum rtx_code) (loc->loc)->code) != MEM
4791 || (MEM_EXPR (loc->loc)(get_mem_attrs (loc->loc)->expr) == decl
4792 && int_mem_offset (loc->loc) == 0)
4793 || !mem_dies_at_call (loc->loc))
4794 {
4795 if (old_loc != loc->loc && emit_notes)
4796 {
4797 if (old_loc == var->var_part[0].cur_loc)
4798 {
4799 changed = true;
4800 var->var_part[0].cur_loc = NULLnullptr;
4801 }
4802 }
4803 locp = &loc->next;
4804 continue;
4805 }
4806
4807 if (emit_notes)
4808 {
4809 if (old_loc == var->var_part[0].cur_loc)
4810 {
4811 changed = true;
4812 var->var_part[0].cur_loc = NULLnullptr;
4813 }
4814 }
4815 *locp = loc->next;
4816 delete loc;
4817 }
4818
4819 if (!var->var_part[0].loc_chain)
4820 {
4821 var->n_var_parts--;
4822 changed = true;
4823 }
4824 if (changed)
4825 variable_was_changed (var, set);
4826 }
4827
4828 return 1;
4829}
4830
4831/* Remove all MEMs from the location list of a hash table entry for a
4832 onepart variable. */
4833
4834int
4835dataflow_set_remove_mem_locs (variable **slot, dataflow_set *set)
4836{
4837 variable *var = *slot;
4838
4839 if (var->onepart != NOT_ONEPART)
4840 {
4841 location_chain *loc, **locp;
4842 bool changed = false;
4843 rtx cur_loc;
4844
4845 gcc_assert (var->n_var_parts == 1)((void)(!(var->n_var_parts == 1) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 4845, __FUNCTION__), 0 : 0))
;
4846
4847 if (shared_var_p (var, set->vars))
4848 {
4849 for (loc = var->var_part[0].loc_chain; loc; loc = loc->next)
4850 if (GET_CODE (loc->loc)((enum rtx_code) (loc->loc)->code) == MEM
4851 && mem_dies_at_call (loc->loc))
4852 break;
4853
4854 if (!loc)
4855 return 1;
4856
4857 slot = unshare_variable (set, slot, var, VAR_INIT_STATUS_UNKNOWN);
4858 var = *slot;
4859 gcc_assert (var->n_var_parts == 1)((void)(!(var->n_var_parts == 1) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 4859, __FUNCTION__), 0 : 0))
;
4860 }
4861
4862 if (VAR_LOC_1PAUX (var)__extension__ (*({ variable *const __v = (var); ((void)(!(__v
->onepart) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 4862, __FUNCTION__), 0 : 0)); &__v->var_part[0].aux.
onepaux; }))
)
4863 cur_loc = VAR_LOC_FROM (var)(__extension__ (*({ variable *const __v = (var); ((void)(!(__v
->onepart) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 4863, __FUNCTION__), 0 : 0)); &__v->var_part[0].aux.
onepaux; }))->from)
;
4864 else
4865 cur_loc = var->var_part[0].cur_loc;
4866
4867 for (locp = &var->var_part[0].loc_chain, loc = *locp;
4868 loc; loc = *locp)
4869 {
4870 if (GET_CODE (loc->loc)((enum rtx_code) (loc->loc)->code) != MEM
4871 || !mem_dies_at_call (loc->loc))
4872 {
4873 locp = &loc->next;
4874 continue;
4875 }
4876
4877 *locp = loc->next;
4878 /* If we have deleted the location which was last emitted
4879 we have to emit new location so add the variable to set
4880 of changed variables. */
4881 if (cur_loc == loc->loc)
4882 {
4883 changed = true;
4884 var->var_part[0].cur_loc = NULLnullptr;
4885 if (VAR_LOC_1PAUX (var)__extension__ (*({ variable *const __v = (var); ((void)(!(__v
->onepart) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 4885, __FUNCTION__), 0 : 0)); &__v->var_part[0].aux.
onepaux; }))
)
4886 VAR_LOC_FROM (var)(__extension__ (*({ variable *const __v = (var); ((void)(!(__v
->onepart) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 4886, __FUNCTION__), 0 : 0)); &__v->var_part[0].aux.
onepaux; }))->from)
= NULLnullptr;
4887 }
4888 delete loc;
4889 }
4890
4891 if (!var->var_part[0].loc_chain)
4892 {
4893 var->n_var_parts--;
4894 changed = true;
4895 }
4896 if (changed)
4897 variable_was_changed (var, set);
4898 }
4899
4900 return 1;
4901}
4902
4903/* Remove all variable-location information about call-clobbered
4904 registers, as well as associations between MEMs and VALUEs. */
4905
4906static void
4907dataflow_set_clear_at_call (dataflow_set *set, rtx_insn *call_insn)
4908{
4909 unsigned int r;
4910 hard_reg_set_iterator hrsi;
4911
4912 HARD_REG_SET callee_clobbers
4913 = insn_callee_abi (call_insn).full_reg_clobbers ();
4914
4915 EXECUTE_IF_SET_IN_HARD_REG_SET (callee_clobbers, 0, r, hrsi)for (hard_reg_set_iter_init (&(hrsi), (callee_clobbers), (
0), &(r)); hard_reg_set_iter_set (&(hrsi), &(r));
hard_reg_set_iter_next (&(hrsi), &(r)))
4916 var_regno_delete (set, r);
4917
4918 if (MAY_HAVE_DEBUG_BIND_INSNSglobal_options.x_flag_var_tracking_assignments)
4919 {
4920 set->traversed_vars = set->vars;
4921 shared_hash_htab (set->vars)
4922 ->traverse <dataflow_set *, dataflow_set_preserve_mem_locs> (set);
4923 set->traversed_vars = set->vars;
4924 shared_hash_htab (set->vars)
4925 ->traverse <dataflow_set *, dataflow_set_remove_mem_locs> (set);
4926 set->traversed_vars = NULLnullptr;
4927 }
4928}
4929
4930static bool
4931variable_part_different_p (variable_part *vp1, variable_part *vp2)
4932{
4933 location_chain *lc1, *lc2;
4934
4935 for (lc1 = vp1->loc_chain; lc1; lc1 = lc1->next)
4936 {
4937 for (lc2 = vp2->loc_chain; lc2; lc2 = lc2->next)
4938 {
4939 if (REG_P (lc1->loc)(((enum rtx_code) (lc1->loc)->code) == REG) && REG_P (lc2->loc)(((enum rtx_code) (lc2->loc)->code) == REG))
4940 {
4941 if (REGNO (lc1->loc)(rhs_regno(lc1->loc)) == REGNO (lc2->loc)(rhs_regno(lc2->loc)))
4942 break;
4943 }
4944 if (rtx_equal_p (lc1->loc, lc2->loc))
4945 break;
4946 }
4947 if (!lc2)
4948 return true;
4949 }
4950 return false;
4951}
4952
4953/* Return true if one-part variables VAR1 and VAR2 are different.
4954 They must be in canonical order. */
4955
4956static bool
4957onepart_variable_different_p (variable *var1, variable *var2)
4958{
4959 location_chain *lc1, *lc2;
4960
4961 if (var1 == var2)
4962 return false;
4963
4964 gcc_assert (var1->n_var_parts == 1((void)(!(var1->n_var_parts == 1 && var2->n_var_parts
== 1) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 4965, __FUNCTION__), 0 : 0))
4965 && var2->n_var_parts == 1)((void)(!(var1->n_var_parts == 1 && var2->n_var_parts
== 1) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 4965, __FUNCTION__), 0 : 0))
;
4966
4967 lc1 = var1->var_part[0].loc_chain;
4968 lc2 = var2->var_part[0].loc_chain;
4969
4970 gcc_assert (lc1 && lc2)((void)(!(lc1 && lc2) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 4970, __FUNCTION__), 0 : 0))
;
4971
4972 while (lc1 && lc2)
4973 {
4974 if (loc_cmp (lc1->loc, lc2->loc))
4975 return true;
4976 lc1 = lc1->next;
4977 lc2 = lc2->next;
4978 }
4979
4980 return lc1 != lc2;
4981}
4982
4983/* Return true if one-part variables VAR1 and VAR2 are different.
4984 They must be in canonical order. */
4985
4986static void
4987dump_onepart_variable_differences (variable *var1, variable *var2)
4988{
4989 location_chain *lc1, *lc2;
4990
4991 gcc_assert (var1 != var2)((void)(!(var1 != var2) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 4991, __FUNCTION__), 0 : 0))
;
4992 gcc_assert (dump_file)((void)(!(dump_file) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 4992, __FUNCTION__), 0 : 0))
;
4993 gcc_assert (dv_as_opaque (var1->dv) == dv_as_opaque (var2->dv))((void)(!(dv_as_opaque (var1->dv) == dv_as_opaque (var2->
dv)) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 4993, __FUNCTION__), 0 : 0))
;
4994 gcc_assert (var1->n_var_parts == 1((void)(!(var1->n_var_parts == 1 && var2->n_var_parts
== 1) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 4995, __FUNCTION__), 0 : 0))
4995 && var2->n_var_parts == 1)((void)(!(var1->n_var_parts == 1 && var2->n_var_parts
== 1) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 4995, __FUNCTION__), 0 : 0))
;
4996
4997 lc1 = var1->var_part[0].loc_chain;
4998 lc2 = var2->var_part[0].loc_chain;
4999
5000 gcc_assert (lc1 && lc2)((void)(!(lc1 && lc2) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 5000, __FUNCTION__), 0 : 0))
;
5001
5002 while (lc1 && lc2)
5003 {
5004 switch (loc_cmp (lc1->loc, lc2->loc))
5005 {
5006 case -1:
5007 fprintf (dump_file, "removed: ");
5008 print_rtl_single (dump_file, lc1->loc);
5009 lc1 = lc1->next;
5010 continue;
5011 case 0:
5012 break;
5013 case 1:
5014 fprintf (dump_file, "added: ");
5015 print_rtl_single (dump_file, lc2->loc);
5016 lc2 = lc2->next;
5017 continue;
5018 default:
5019 gcc_unreachable ()(fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 5019, __FUNCTION__))
;
5020 }
5021 lc1 = lc1->next;
5022 lc2 = lc2->next;
5023 }
5024
5025 while (lc1)
5026 {
5027 fprintf (dump_file, "removed: ");
5028 print_rtl_single (dump_file, lc1->loc);
5029 lc1 = lc1->next;
5030 }
5031
5032 while (lc2)
5033 {
5034 fprintf (dump_file, "added: ");
5035 print_rtl_single (dump_file, lc2->loc);
5036 lc2 = lc2->next;
5037 }
5038}
5039
5040/* Return true if variables VAR1 and VAR2 are different. */
5041
5042static bool
5043variable_different_p (variable *var1, variable *var2)
5044{
5045 int i;
5046
5047 if (var1 == var2)
5048 return false;
5049
5050 if (var1->onepart != var2->onepart)
5051 return true;
5052
5053 if (var1->n_var_parts != var2->n_var_parts)
5054 return true;
5055
5056 if (var1->onepart && var1->n_var_parts)
5057 {
5058 gcc_checking_assert (dv_as_opaque (var1->dv) == dv_as_opaque (var2->dv)((void)(!(dv_as_opaque (var1->dv) == dv_as_opaque (var2->
dv) && var1->n_var_parts == 1) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 5059, __FUNCTION__), 0 : 0))
5059 && var1->n_var_parts == 1)((void)(!(dv_as_opaque (var1->dv) == dv_as_opaque (var2->
dv) && var1->n_var_parts == 1) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 5059, __FUNCTION__), 0 : 0))
;
5060 /* One-part values have locations in a canonical order. */
5061 return onepart_variable_different_p (var1, var2);
5062 }
5063
5064 for (i = 0; i < var1->n_var_parts; i++)
5065 {
5066 if (VAR_PART_OFFSET (var1, i)__extension__ (*({ variable *const __v = (var1); ((void)(!(!__v
->onepart) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 5066, __FUNCTION__), 0 : 0)); &__v->var_part[(i)].aux
.offset; }))
!= VAR_PART_OFFSET (var2, i)__extension__ (*({ variable *const __v = (var2); ((void)(!(!__v
->onepart) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 5066, __FUNCTION__), 0 : 0)); &__v->var_part[(i)].aux
.offset; }))
)
5067 return true;
5068 if (variable_part_different_p (&var1->var_part[i], &var2->var_part[i]))
5069 return true;
5070 if (variable_part_different_p (&var2->var_part[i], &var1->var_part[i]))
5071 return true;
5072 }
5073 return false;
5074}
5075
5076/* Return true if dataflow sets OLD_SET and NEW_SET differ. */
5077
5078static bool
5079dataflow_set_different (dataflow_set *old_set, dataflow_set *new_set)
5080{
5081 variable_iterator_type hi;
5082 variable *var1;
5083 bool diffound = false;
5084 bool details = (dump_file && (dump_flags & TDF_DETAILS));
5085
5086#define RETRUE \
5087 do \
5088 { \
5089 if (!details) \
5090 return true; \
5091 else \
5092 diffound = true; \
5093 } \
5094 while (0)
5095
5096 if (old_set->vars == new_set->vars)
5097 return false;
5098
5099 if (shared_hash_htab (old_set->vars)->elements ()
5100 != shared_hash_htab (new_set->vars)->elements ())
5101 RETRUE;
5102
5103 FOR_EACH_HASH_TABLE_ELEMENT (*shared_hash_htab (old_set->vars),for ((hi) = (*shared_hash_htab (old_set->vars)).begin (); (
hi) != (*shared_hash_htab (old_set->vars)).end () ? (var1 =
*(hi) , true) : false; ++(hi))
5104 var1, variable, hi)for ((hi) = (*shared_hash_htab (old_set->vars)).begin (); (
hi) != (*shared_hash_htab (old_set->vars)).end () ? (var1 =
*(hi) , true) : false; ++(hi))
5105 {
5106 variable_table_type *htab = shared_hash_htab (new_set->vars);
5107 variable *var2 = htab->find_with_hash (var1->dv, dv_htab_hash (var1->dv));
5108
5109 if (!var2)
5110 {
5111 if (dump_file && (dump_flags & TDF_DETAILS))
5112 {
5113 fprintf (dump_file, "dataflow difference found: removal of:\n");
5114 dump_var (var1);
5115 }
5116 RETRUE;
5117 }
5118 else if (variable_different_p (var1, var2))
5119 {
5120 if (details)
5121 {
5122 fprintf (dump_file, "dataflow difference found: "
5123 "old and new follow:\n");
5124 dump_var (var1);
5125 if (dv_onepart_p (var1->dv))
5126 dump_onepart_variable_differences (var1, var2);
5127 dump_var (var2);
5128 }
5129 RETRUE;
5130 }
5131 }
5132
5133 /* There's no need to traverse the second hashtab unless we want to
5134 print the details. If both have the same number of elements and
5135 the second one had all entries found in the first one, then the
5136 second can't have any extra entries. */
5137 if (!details)
5138 return diffound;
5139
5140 FOR_EACH_HASH_TABLE_ELEMENT (*shared_hash_htab (new_set->vars),for ((hi) = (*shared_hash_htab (new_set->vars)).begin (); (
hi) != (*shared_hash_htab (new_set->vars)).end () ? (var1 =
*(hi) , true) : false; ++(hi))
5141 var1, variable, hi)for ((hi) = (*shared_hash_htab (new_set->vars)).begin (); (
hi) != (*shared_hash_htab (new_set->vars)).end () ? (var1 =
*(hi) , true) : false; ++(hi))
5142 {
5143 variable_table_type *htab = shared_hash_htab (old_set->vars);
5144 variable *var2 = htab->find_with_hash (var1->dv, dv_htab_hash (var1->dv));
5145 if (!var2)
5146 {
5147 if (details)
5148 {
5149 fprintf (dump_file, "dataflow difference found: addition of:\n");
5150 dump_var (var1);
5151 }
5152 RETRUE;
5153 }
5154 }
5155
5156#undef RETRUE
5157
5158 return diffound;
5159}
5160
5161/* Free the contents of dataflow set SET. */
5162
5163static void
5164dataflow_set_destroy (dataflow_set *set)
5165{
5166 int i;
5167
5168 for (i = 0; i < FIRST_PSEUDO_REGISTER76; i++)
5169 attrs_list_clear (&set->regs[i]);
5170
5171 shared_hash_destroy (set->vars);
5172 set->vars = NULLnullptr;
5173}
5174
5175/* Return true if T is a tracked parameter with non-degenerate record type. */
5176
5177static bool
5178tracked_record_parameter_p (tree t)
5179{
5180 if (TREE_CODE (t)((enum tree_code) (t)->base.code) != PARM_DECL)
5181 return false;
5182
5183 if (DECL_MODE (t)((contains_struct_check ((t), (TS_DECL_COMMON), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 5183, __FUNCTION__))->decl_common.mode)
== BLKmode((void) 0, E_BLKmode))
5184 return false;
5185
5186 tree type = TREE_TYPE (t)((contains_struct_check ((t), (TS_TYPED), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 5186, __FUNCTION__))->typed.type)
;
5187 if (TREE_CODE (type)((enum tree_code) (type)->base.code) != RECORD_TYPE)
5188 return false;
5189
5190 if (TYPE_FIELDS (type)((tree_check3 ((type), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 5190, __FUNCTION__, (RECORD_TYPE), (UNION_TYPE), (QUAL_UNION_TYPE
)))->type_non_common.values)
== NULL_TREE(tree) nullptr
5191 || DECL_CHAIN (TYPE_FIELDS (type))(((contains_struct_check (((contains_struct_check ((((tree_check3
((type), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 5191, __FUNCTION__, (RECORD_TYPE), (UNION_TYPE), (QUAL_UNION_TYPE
)))->type_non_common.values)), (TS_DECL_MINIMAL), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 5191, __FUNCTION__))), (TS_COMMON), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 5191, __FUNCTION__))->common.chain))
== NULL_TREE(tree) nullptr)
5192 return false;
5193
5194 return true;
5195}
5196
5197/* Shall EXPR be tracked? */
5198
5199static bool
5200track_expr_p (tree expr, bool need_rtl)
5201{
5202 rtx decl_rtl;
5203 tree realdecl;
5204
5205 if (TREE_CODE (expr)((enum tree_code) (expr)->base.code) == DEBUG_EXPR_DECL)
5206 return DECL_RTL_SET_P (expr)(((tree_contains_struct[(((enum tree_code) (expr)->base.code
))][(TS_DECL_WRTL)])) && (contains_struct_check ((expr
), (TS_DECL_WRTL), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 5206, __FUNCTION__))->decl_with_rtl.rtl != nullptr)
;
5207
5208 /* If EXPR is not a parameter or a variable do not track it. */
5209 if (!VAR_P (expr)(((enum tree_code) (expr)->base.code) == VAR_DECL) && TREE_CODE (expr)((enum tree_code) (expr)->base.code) != PARM_DECL)
5210 return 0;
5211
5212 /* It also must have a name... */
5213 if (!DECL_NAME (expr)((contains_struct_check ((expr), (TS_DECL_MINIMAL), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 5213, __FUNCTION__))->decl_minimal.name)
&& need_rtl)
5214 return 0;
5215
5216 /* ... and a RTL assigned to it. */
5217 decl_rtl = DECL_RTL_IF_SET (expr)((((tree_contains_struct[(((enum tree_code) (expr)->base.code
))][(TS_DECL_WRTL)])) && (contains_struct_check ((expr
), (TS_DECL_WRTL), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 5217, __FUNCTION__))->decl_with_rtl.rtl != nullptr) ? ((
contains_struct_check ((expr), (TS_DECL_WRTL), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 5217, __FUNCTION__))->decl_with_rtl.rtl ? (expr)->decl_with_rtl
.rtl : (make_decl_rtl (expr), (expr)->decl_with_rtl.rtl)) :
nullptr)
;
5218 if (!decl_rtl && need_rtl)
5219 return 0;
5220
5221 /* If this expression is really a debug alias of some other declaration, we
5222 don't need to track this expression if the ultimate declaration is
5223 ignored. */
5224 realdecl = expr;
5225 if (VAR_P (realdecl)(((enum tree_code) (realdecl)->base.code) == VAR_DECL) && DECL_HAS_DEBUG_EXPR_P (realdecl)((tree_check ((realdecl), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 5225, __FUNCTION__, (VAR_DECL)))->decl_common.debug_expr_is_from
)
)
5226 {
5227 realdecl = DECL_DEBUG_EXPR (realdecl)(decl_debug_expr_lookup ((tree_check ((realdecl), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 5227, __FUNCTION__, (VAR_DECL)))))
;
5228 if (!DECL_P (realdecl)(tree_code_type[(int) (((enum tree_code) (realdecl)->base.
code))] == tcc_declaration)
)
5229 {
5230 if (handled_component_p (realdecl)
5231 || (TREE_CODE (realdecl)((enum tree_code) (realdecl)->base.code) == MEM_REF
5232 && TREE_CODE (TREE_OPERAND (realdecl, 0))((enum tree_code) ((*((const_cast<tree*> (tree_operand_check
((realdecl), (0), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 5232, __FUNCTION__))))))->base.code)
== ADDR_EXPR))
5233 {
5234 HOST_WIDE_INTlong bitsize, bitpos;
5235 bool reverse;
5236 tree innerdecl
5237 = get_ref_base_and_extent_hwi (realdecl, &bitpos,
5238 &bitsize, &reverse);
5239 if (!innerdecl
5240 || !DECL_P (innerdecl)(tree_code_type[(int) (((enum tree_code) (innerdecl)->base
.code))] == tcc_declaration)
5241 || DECL_IGNORED_P (innerdecl)((contains_struct_check ((innerdecl), (TS_DECL_COMMON), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 5241, __FUNCTION__))->decl_common.ignored_flag)
5242 /* Do not track declarations for parts of tracked record
5243 parameters since we want to track them as a whole. */
5244 || tracked_record_parameter_p (innerdecl)
5245 || TREE_STATIC (innerdecl)((innerdecl)->base.static_flag)
5246 || bitsize == 0
5247 || bitpos + bitsize > 256)
5248 return 0;
5249 else
5250 realdecl = expr;
5251 }
5252 else
5253 return 0;
5254 }
5255 }
5256
5257 /* Do not track EXPR if REALDECL it should be ignored for debugging
5258 purposes. */
5259 if (DECL_IGNORED_P (realdecl)((contains_struct_check ((realdecl), (TS_DECL_COMMON), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 5259, __FUNCTION__))->decl_common.ignored_flag)
)
5260 return 0;
5261
5262 /* Do not track global variables until we are able to emit correct location
5263 list for them. */
5264 if (TREE_STATIC (realdecl)((realdecl)->base.static_flag))
5265 return 0;
5266
5267 /* When the EXPR is a DECL for alias of some variable (see example)
5268 the TREE_STATIC flag is not used. Disable tracking all DECLs whose
5269 DECL_RTL contains SYMBOL_REF.
5270
5271 Example:
5272 extern char **_dl_argv_internal __attribute__ ((alias ("_dl_argv")));
5273 char **_dl_argv;
5274 */
5275 if (decl_rtl && MEM_P (decl_rtl)(((enum rtx_code) (decl_rtl)->code) == MEM)
5276 && contains_symbol_ref_p (XEXP (decl_rtl, 0)(((decl_rtl)->u.fld[0]).rt_rtx)))
5277 return 0;
5278
5279 /* If RTX is a memory it should not be very large (because it would be
5280 an array or struct). */
5281 if (decl_rtl && MEM_P (decl_rtl)(((enum rtx_code) (decl_rtl)->code) == MEM))
5282 {
5283 /* Do not track structures and arrays. */
5284 if ((GET_MODE (decl_rtl)((machine_mode) (decl_rtl)->mode) == BLKmode((void) 0, E_BLKmode)
5285 || AGGREGATE_TYPE_P (TREE_TYPE (realdecl))(((enum tree_code) (((contains_struct_check ((realdecl), (TS_TYPED
), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 5285, __FUNCTION__))->typed.type))->base.code) == ARRAY_TYPE
|| (((enum tree_code) (((contains_struct_check ((realdecl), (
TS_TYPED), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 5285, __FUNCTION__))->typed.type))->base.code) == RECORD_TYPE
|| ((enum tree_code) (((contains_struct_check ((realdecl), (
TS_TYPED), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 5285, __FUNCTION__))->typed.type))->base.code) == UNION_TYPE
|| ((enum tree_code) (((contains_struct_check ((realdecl), (
TS_TYPED), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 5285, __FUNCTION__))->typed.type))->base.code) == QUAL_UNION_TYPE
))
)
5286 && !tracked_record_parameter_p (realdecl))
5287 return 0;
5288 if (MEM_SIZE_KNOWN_P (decl_rtl)(get_mem_attrs (decl_rtl)->size_known_p)
5289 && maybe_gt (MEM_SIZE (decl_rtl), MAX_VAR_PARTS)maybe_lt (16, (get_mem_attrs (decl_rtl)->size)))
5290 return 0;
5291 }
5292
5293 DECL_CHANGED (expr)((expr)->base.visited) = 0;
5294 DECL_CHANGED (realdecl)((realdecl)->base.visited) = 0;
5295 return 1;
5296}
5297
5298/* Determine whether a given LOC refers to the same variable part as
5299 EXPR+OFFSET. */
5300
5301static bool
5302same_variable_part_p (rtx loc, tree expr, poly_int64 offset)
5303{
5304 tree expr2;
5305 poly_int64 offset2;
5306
5307 if (! DECL_P (expr)(tree_code_type[(int) (((enum tree_code) (expr)->base.code
))] == tcc_declaration)
)
5308 return false;
5309
5310 if (REG_P (loc)(((enum rtx_code) (loc)->code) == REG))
5311 {
5312 expr2 = REG_EXPR (loc)(((&(loc)->u.reg)->attrs) == 0 ? 0 : ((&(loc)->
u.reg)->attrs)->decl)
;
5313 offset2 = REG_OFFSET (loc)(((&(loc)->u.reg)->attrs) == 0 ? 0 : ((&(loc)->
u.reg)->attrs)->offset)
;
5314 }
5315 else if (MEM_P (loc)(((enum rtx_code) (loc)->code) == MEM))
5316 {
5317 expr2 = MEM_EXPR (loc)(get_mem_attrs (loc)->expr);
5318 offset2 = int_mem_offset (loc);
5319 }
5320 else
5321 return false;
5322
5323 if (! expr2 || ! DECL_P (expr2)(tree_code_type[(int) (((enum tree_code) (expr2)->base.code
))] == tcc_declaration)
)
5324 return false;
5325
5326 expr = var_debug_decl (expr);
5327 expr2 = var_debug_decl (expr2);
5328
5329 return (expr == expr2 && known_eq (offset, offset2)(!maybe_ne (offset, offset2)));
5330}
5331
5332/* LOC is a REG or MEM that we would like to track if possible.
5333 If EXPR is null, we don't know what expression LOC refers to,
5334 otherwise it refers to EXPR + OFFSET. STORE_REG_P is true if
5335 LOC is an lvalue register.
5336
5337 Return true if EXPR is nonnull and if LOC, or some lowpart of it,
5338 is something we can track. When returning true, store the mode of
5339 the lowpart we can track in *MODE_OUT (if nonnull) and its offset
5340 from EXPR in *OFFSET_OUT (if nonnull). */
5341
5342static bool
5343track_loc_p (rtx loc, tree expr, poly_int64 offset, bool store_reg_p,
5344 machine_mode *mode_out, HOST_WIDE_INTlong *offset_out)
5345{
5346 machine_mode mode;
5347
5348 if (expr == NULLnullptr || !track_expr_p (expr, true))
5349 return false;
5350
5351 /* If REG was a paradoxical subreg, its REG_ATTRS will describe the
5352 whole subreg, but only the old inner part is really relevant. */
5353 mode = GET_MODE (loc)((machine_mode) (loc)->mode);
5354 if (REG_P (loc)(((enum rtx_code) (loc)->code) == REG) && !HARD_REGISTER_NUM_P (ORIGINAL_REGNO (loc))(((__extension__ ({ __typeof ((loc)) const _rtx = ((loc)); if
(((enum rtx_code) (_rtx)->code) != REG) rtl_check_failed_flag
("ORIGINAL_REGNO", _rtx, "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 5354, __FUNCTION__); _rtx; })->u2.original_regno)) < 76
)
)
5355 {
5356 machine_mode pseudo_mode;
5357
5358 pseudo_mode = PSEUDO_REGNO_MODE (ORIGINAL_REGNO (loc))((machine_mode) (regno_reg_rtx[(__extension__ ({ __typeof ((loc
)) const _rtx = ((loc)); if (((enum rtx_code) (_rtx)->code
) != REG) rtl_check_failed_flag ("ORIGINAL_REGNO", _rtx, "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 5358, __FUNCTION__); _rtx; })->u2.original_regno)])->
mode)
;
5359 if (paradoxical_subreg_p (mode, pseudo_mode))
5360 {
5361 offset += byte_lowpart_offset (pseudo_mode, mode);
5362 mode = pseudo_mode;
5363 }
5364 }
5365
5366 /* If LOC is a paradoxical lowpart of EXPR, refer to EXPR itself.
5367 Do the same if we are storing to a register and EXPR occupies
5368 the whole of register LOC; in that case, the whole of EXPR is
5369 being changed. We exclude complex modes from the second case
5370 because the real and imaginary parts are represented as separate
5371 pseudo registers, even if the whole complex value fits into one
5372 hard register. */
5373 if ((paradoxical_subreg_p (mode, DECL_MODE (expr)((contains_struct_check ((expr), (TS_DECL_COMMON), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 5373, __FUNCTION__))->decl_common.mode)
)
5374 || (store_reg_p
5375 && !COMPLEX_MODE_P (DECL_MODE (expr))(((enum mode_class) mode_class[((contains_struct_check ((expr
), (TS_DECL_COMMON), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 5375, __FUNCTION__))->decl_common.mode)]) == MODE_COMPLEX_INT
|| ((enum mode_class) mode_class[((contains_struct_check ((expr
), (TS_DECL_COMMON), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 5375, __FUNCTION__))->decl_common.mode)]) == MODE_COMPLEX_FLOAT
)
5376 && hard_regno_nregs (REGNO (loc)(rhs_regno(loc)), DECL_MODE (expr)((contains_struct_check ((expr), (TS_DECL_COMMON), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 5376, __FUNCTION__))->decl_common.mode)
) == 1))
5377 && known_eq (offset + byte_lowpart_offset (DECL_MODE (expr), mode), 0)(!maybe_ne (offset + byte_lowpart_offset (((contains_struct_check
((expr), (TS_DECL_COMMON), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 5377, __FUNCTION__))->decl_common.mode), mode), 0))
)
5378 {
5379 mode = DECL_MODE (expr)((contains_struct_check ((expr), (TS_DECL_COMMON), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 5379, __FUNCTION__))->decl_common.mode)
;
5380 offset = 0;
5381 }
5382
5383 HOST_WIDE_INTlong const_offset;
5384 if (!track_offset_p (offset, &const_offset))
5385 return false;
5386
5387 if (mode_out)
5388 *mode_out = mode;
5389 if (offset_out)
5390 *offset_out = const_offset;
5391 return true;
5392}
5393
5394/* Return the MODE lowpart of LOC, or null if LOC is not something we
5395 want to track. When returning nonnull, make sure that the attributes
5396 on the returned value are updated. */
5397
5398static rtx
5399var_lowpart (machine_mode mode, rtx loc)
5400{
5401 unsigned int regno;
5402
5403 if (GET_MODE (loc)((machine_mode) (loc)->mode) == mode)
5404 return loc;
5405
5406 if (!REG_P (loc)(((enum rtx_code) (loc)->code) == REG) && !MEM_P (loc)(((enum rtx_code) (loc)->code) == MEM))
5407 return NULLnullptr;
5408
5409 poly_uint64 offset = byte_lowpart_offset (mode, GET_MODE (loc)((machine_mode) (loc)->mode));
5410
5411 if (MEM_P (loc)(((enum rtx_code) (loc)->code) == MEM))
5412 return adjust_address_nv (loc, mode, offset)adjust_address_1 (loc, mode, offset, 0, 1, 0, 0);
5413
5414 poly_uint64 reg_offset = subreg_lowpart_offset (mode, GET_MODE (loc)((machine_mode) (loc)->mode));
5415 regno = REGNO (loc)(rhs_regno(loc)) + subreg_regno_offset (REGNO (loc)(rhs_regno(loc)), GET_MODE (loc)((machine_mode) (loc)->mode),
5416 reg_offset, mode);
5417 return gen_rtx_REG_offset (loc, mode, regno, offset);
5418}
5419
5420/* Carry information about uses and stores while walking rtx. */
5421
5422struct count_use_info
5423{
5424 /* The insn where the RTX is. */
5425 rtx_insn *insn;
5426
5427 /* The basic block where insn is. */
5428 basic_block bb;
5429
5430 /* The array of n_sets sets in the insn, as determined by cselib. */
5431 struct cselib_set *sets;
5432 int n_sets;
5433
5434 /* True if we're counting stores, false otherwise. */
5435 bool store_p;
5436};
5437
5438/* Find a VALUE corresponding to X. */
5439
5440static inline cselib_val *
5441find_use_val (rtx x, machine_mode mode, struct count_use_info *cui)
5442{
5443 int i;
5444
5445 if (cui->sets)
5446 {
5447 /* This is called after uses are set up and before stores are
5448 processed by cselib, so it's safe to look up srcs, but not
5449 dsts. So we look up expressions that appear in srcs or in
5450 dest expressions, but we search the sets array for dests of
5451 stores. */
5452 if (cui->store_p)
5453 {
5454 /* Some targets represent memset and memcpy patterns
5455 by (set (mem:BLK ...) (reg:[QHSD]I ...)) or
5456 (set (mem:BLK ...) (const_int ...)) or
5457 (set (mem:BLK ...) (mem:BLK ...)). Don't return anything
5458 in that case, otherwise we end up with mode mismatches. */
5459 if (mode == BLKmode((void) 0, E_BLKmode) && MEM_P (x)(((enum rtx_code) (x)->code) == MEM))
5460 return NULLnullptr;
5461 for (i = 0; i < cui->n_sets; i++)
5462 if (cui->sets[i].dest == x)
5463 return cui->sets[i].src_elt;
5464 }
5465 else
5466 return cselib_lookup (x, mode, 0, VOIDmode((void) 0, E_VOIDmode));
5467 }
5468
5469 return NULLnullptr;
5470}
5471
5472/* Replace all registers and addresses in an expression with VALUE
5473 expressions that map back to them, unless the expression is a
5474 register. If no mapping is or can be performed, returns NULL. */
5475
5476static rtx
5477replace_expr_with_values (rtx loc)
5478{
5479 if (REG_P (loc)(((enum rtx_code) (loc)->code) == REG) || GET_CODE (loc)((enum rtx_code) (loc)->code) == ENTRY_VALUE)
5480 return NULLnullptr;
5481 else if (MEM_P (loc)(((enum rtx_code) (loc)->code) == MEM))
5482 {
5483 cselib_val *addr = cselib_lookup (XEXP (loc, 0)(((loc)->u.fld[0]).rt_rtx),
5484 get_address_mode (loc), 0,
5485 GET_MODE (loc)((machine_mode) (loc)->mode));
5486 if (addr)
5487 return replace_equiv_address_nv (loc, addr->val_rtx);
5488 else
5489 return NULLnullptr;
5490 }
5491 else
5492 return cselib_subst_to_values (loc, VOIDmode((void) 0, E_VOIDmode));
5493}
5494
5495/* Return true if X contains a DEBUG_EXPR. */
5496
5497static bool
5498rtx_debug_expr_p (const_rtx x)
5499{
5500 subrtx_iterator::array_type array;
5501 FOR_EACH_SUBRTX (iter, array, x, ALL)for (subrtx_iterator iter (array, x, rtx_all_subrtx_bounds); !
iter.at_end (); iter.next ())
5502 if (GET_CODE (*iter)((enum rtx_code) (*iter)->code) == DEBUG_EXPR)
5503 return true;
5504 return false;
5505}
5506
5507/* Determine what kind of micro operation to choose for a USE. Return
5508 MO_CLOBBER if no micro operation is to be generated. */
5509
5510static enum micro_operation_type
5511use_type (rtx loc, struct count_use_info *cui, machine_mode *modep)
5512{
5513 tree expr;
5514
5515 if (cui && cui->sets)
5516 {
5517 if (GET_CODE (loc)((enum rtx_code) (loc)->code) == VAR_LOCATION)
5518 {
5519 if (track_expr_p (PAT_VAR_LOCATION_DECL (loc)(((((loc))->u.fld[0]).rt_tree)), false))
5520 {
5521 rtx ploc = PAT_VAR_LOCATION_LOC (loc)(((((loc))->u.fld[1]).rt_rtx));
5522 if (! VAR_LOC_UNKNOWN_P (ploc)(((enum rtx_code) (ploc)->code) == CLOBBER && ((((
ploc))->u.fld[0]).rt_rtx) == (const_int_rtx[64]))
)
5523 {
5524 cselib_val *val = cselib_lookup (ploc, GET_MODE (loc)((machine_mode) (loc)->mode), 1,
5525 VOIDmode((void) 0, E_VOIDmode));
5526
5527 /* ??? flag_float_store and volatile mems are never
5528 given values, but we could in theory use them for
5529 locations. */
5530 gcc_assert (val || 1)((void)(!(val || 1) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 5530, __FUNCTION__), 0 : 0))
;
5531 }
5532 return MO_VAL_LOC;
5533 }
5534 else
5535 return MO_CLOBBER;
5536 }
5537
5538 if (REG_P (loc)(((enum rtx_code) (loc)->code) == REG) || MEM_P (loc)(((enum rtx_code) (loc)->code) == MEM))
5539 {
5540 if (modep)
5541 *modep = GET_MODE (loc)((machine_mode) (loc)->mode);
5542 if (cui->store_p)
5543 {
5544 if (REG_P (loc)(((enum rtx_code) (loc)->code) == REG)
5545 || (find_use_val (loc, GET_MODE (loc)((machine_mode) (loc)->mode), cui)
5546 && cselib_lookup (XEXP (loc, 0)(((loc)->u.fld[0]).rt_rtx),
5547 get_address_mode (loc), 0,
5548 GET_MODE (loc)((machine_mode) (loc)->mode))))
5549 return MO_VAL_SET;
5550 }
5551 else
5552 {
5553 cselib_val *val = find_use_val (loc, GET_MODE (loc)((machine_mode) (loc)->mode), cui);
5554
5555 if (val && !cselib_preserved_value_p (val))
5556 return MO_VAL_USE;
5557 }
5558 }
5559 }
5560
5561 if (REG_P (loc)(((enum rtx_code) (loc)->code) == REG))
5562 {
5563 gcc_assert (REGNO (loc) < FIRST_PSEUDO_REGISTER)((void)(!((rhs_regno(loc)) < 76) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 5563, __FUNCTION__), 0 : 0))
;
5564
5565 if (loc == cfa_base_rtx)
5566 return MO_CLOBBER;
5567 expr = REG_EXPR (loc)(((&(loc)->u.reg)->attrs) == 0 ? 0 : ((&(loc)->
u.reg)->attrs)->decl)
;
5568
5569 if (!expr)
5570 return MO_USE_NO_VAR;
5571 else if (target_for_debug_bind (var_debug_decl (expr)))
5572 return MO_CLOBBER;
5573 else if (track_loc_p (loc, expr, REG_OFFSET (loc)(((&(loc)->u.reg)->attrs) == 0 ? 0 : ((&(loc)->
u.reg)->attrs)->offset)
,
5574 false, modep, NULLnullptr))
5575 return MO_USE;
5576 else
5577 return MO_USE_NO_VAR;
5578 }
5579 else if (MEM_P (loc)(((enum rtx_code) (loc)->code) == MEM))
5580 {
5581 expr = MEM_EXPR (loc)(get_mem_attrs (loc)->expr);
5582
5583 if (!expr)
5584 return MO_CLOBBER;
5585 else if (target_for_debug_bind (var_debug_decl (expr)))
5586 return MO_CLOBBER;
5587 else if (track_loc_p (loc, expr, int_mem_offset (loc),
5588 false, modep, NULLnullptr)
5589 /* Multi-part variables shouldn't refer to one-part
5590 variable names such as VALUEs (never happens) or
5591 DEBUG_EXPRs (only happens in the presence of debug
5592 insns). */
5593 && (!MAY_HAVE_DEBUG_BIND_INSNSglobal_options.x_flag_var_tracking_assignments
5594 || !rtx_debug_expr_p (XEXP (loc, 0)(((loc)->u.fld[0]).rt_rtx))))
5595 return MO_USE;
5596 else
5597 return MO_CLOBBER;
5598 }
5599
5600 return MO_CLOBBER;
5601}
5602
5603/* Log to OUT information about micro-operation MOPT involving X in
5604 INSN of BB. */
5605
5606static inline void
5607log_op_type (rtx x, basic_block bb, rtx_insn *insn,
5608 enum micro_operation_type mopt, FILE *out)
5609{
5610 fprintf (out, "bb %i op %i insn %i %s ",
5611 bb->index, VTI (bb)((variable_tracking_info *) (bb)->aux)->mos.length (),
5612 INSN_UID (insn), micro_operation_type_name[mopt]);
5613 print_inline_rtx (out, x, 2);
5614 fputc ('\n', out);
5615}
5616
5617/* Tell whether the CONCAT used to holds a VALUE and its location
5618 needs value resolution, i.e., an attempt of mapping the location
5619 back to other incoming values. */
5620#define VAL_NEEDS_RESOLUTION(x)(__extension__ ({ __typeof ((x)) const _rtx = ((x)); if (((enum
rtx_code) (_rtx)->code) != CONCAT) rtl_check_failed_flag (
"VAL_NEEDS_RESOLUTION", _rtx, "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 5620, __FUNCTION__); _rtx; })->volatil)
\
5621 (RTL_FLAG_CHECK1 ("VAL_NEEDS_RESOLUTION", (x), CONCAT)__extension__ ({ __typeof ((x)) const _rtx = ((x)); if (((enum
rtx_code) (_rtx)->code) != CONCAT) rtl_check_failed_flag (
"VAL_NEEDS_RESOLUTION", _rtx, "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 5621, __FUNCTION__); _rtx; })
->volatil)
5622/* Whether the location in the CONCAT is a tracked expression, that
5623 should also be handled like a MO_USE. */
5624#define VAL_HOLDS_TRACK_EXPR(x)(__extension__ ({ __typeof ((x)) const _rtx = ((x)); if (((enum
rtx_code) (_rtx)->code) != CONCAT) rtl_check_failed_flag (
"VAL_HOLDS_TRACK_EXPR", _rtx, "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 5624, __FUNCTION__); _rtx; })->used)
\
5625 (RTL_FLAG_CHECK1 ("VAL_HOLDS_TRACK_EXPR", (x), CONCAT)__extension__ ({ __typeof ((x)) const _rtx = ((x)); if (((enum
rtx_code) (_rtx)->code) != CONCAT) rtl_check_failed_flag (
"VAL_HOLDS_TRACK_EXPR", _rtx, "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 5625, __FUNCTION__); _rtx; })
->used)
5626/* Whether the location in the CONCAT should be handled like a MO_COPY
5627 as well. */
5628#define VAL_EXPR_IS_COPIED(x)(__extension__ ({ __typeof ((x)) const _rtx = ((x)); if (((enum
rtx_code) (_rtx)->code) != CONCAT) rtl_check_failed_flag (
"VAL_EXPR_IS_COPIED", _rtx, "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 5628, __FUNCTION__); _rtx; })->jump)
\
5629 (RTL_FLAG_CHECK1 ("VAL_EXPR_IS_COPIED", (x), CONCAT)__extension__ ({ __typeof ((x)) const _rtx = ((x)); if (((enum
rtx_code) (_rtx)->code) != CONCAT) rtl_check_failed_flag (
"VAL_EXPR_IS_COPIED", _rtx, "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 5629, __FUNCTION__); _rtx; })
->jump)
5630/* Whether the location in the CONCAT should be handled like a
5631 MO_CLOBBER as well. */
5632#define VAL_EXPR_IS_CLOBBERED(x)(__extension__ ({ __typeof ((x)) const _rtx = ((x)); if (((enum
rtx_code) (_rtx)->code) != CONCAT) rtl_check_failed_flag (
"VAL_EXPR_IS_CLOBBERED", _rtx, "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 5632, __FUNCTION__); _rtx; })->unchanging)
\
5633 (RTL_FLAG_CHECK1 ("VAL_EXPR_IS_CLOBBERED", (x), CONCAT)__extension__ ({ __typeof ((x)) const _rtx = ((x)); if (((enum
rtx_code) (_rtx)->code) != CONCAT) rtl_check_failed_flag (
"VAL_EXPR_IS_CLOBBERED", _rtx, "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 5633, __FUNCTION__); _rtx; })
->unchanging)
5634
5635/* All preserved VALUEs. */
5636static vec<rtx> preserved_values;
5637
5638/* Ensure VAL is preserved and remember it in a vector for vt_emit_notes. */
5639
5640static void
5641preserve_value (cselib_val *val)
5642{
5643 cselib_preserve_value (val);
5644 preserved_values.safe_push (val->val_rtx);
5645}
5646
5647/* Helper function for MO_VAL_LOC handling. Return non-zero if
5648 any rtxes not suitable for CONST use not replaced by VALUEs
5649 are discovered. */
5650
5651static bool
5652non_suitable_const (const_rtx x)
5653{
5654 subrtx_iterator::array_type array;
5655 FOR_EACH_SUBRTX (iter, array, x, ALL)for (subrtx_iterator iter (array, x, rtx_all_subrtx_bounds); !
iter.at_end (); iter.next ())
5656 {
5657 const_rtx x = *iter;
5658 switch (GET_CODE (x)((enum rtx_code) (x)->code))
5659 {
5660 case REG:
5661 case DEBUG_EXPR:
5662 case PC:
5663 case SCRATCH:
5664 case CC0:
5665 case ASM_INPUT:
5666 case ASM_OPERANDS:
5667 return true;
5668 case MEM:
5669 if (!MEM_READONLY_P (x)(__extension__ ({ __typeof ((x)) const _rtx = ((x)); if (((enum
rtx_code) (_rtx)->code) != MEM) rtl_check_failed_flag ("MEM_READONLY_P"
, _rtx, "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 5669, __FUNCTION__); _rtx; })->unchanging)
)
5670 return true;
5671 break;
5672 default:
5673 break;
5674 }
5675 }
5676 return false;
5677}
5678
5679/* Add uses (register and memory references) LOC which will be tracked
5680 to VTI (bb)->mos. */
5681
5682static void
5683add_uses (rtx loc, struct count_use_info *cui)
5684{
5685 machine_mode mode = VOIDmode((void) 0, E_VOIDmode);
5686 enum micro_operation_type type = use_type (loc, cui, &mode);
5687
5688 if (type != MO_CLOBBER)
5689 {
5690 basic_block bb = cui->bb;
5691 micro_operation mo;
5692
5693 mo.type = type;
5694 mo.u.loc = type == MO_USE ? var_lowpart (mode, loc) : loc;
5695 mo.insn = cui->insn;
5696
5697 if (type == MO_VAL_LOC)
5698 {
5699 rtx oloc = loc;
5700 rtx vloc = PAT_VAR_LOCATION_LOC (oloc)(((((oloc))->u.fld[1]).rt_rtx));
5701 cselib_val *val;
5702
5703 gcc_assert (cui->sets)((void)(!(cui->sets) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 5703, __FUNCTION__), 0 : 0))
;
5704
5705 if (MEM_P (vloc)(((enum rtx_code) (vloc)->code) == MEM)
5706 && !REG_P (XEXP (vloc, 0))(((enum rtx_code) ((((vloc)->u.fld[0]).rt_rtx))->code) ==
REG)
5707 && !MEM_P (XEXP (vloc, 0))(((enum rtx_code) ((((vloc)->u.fld[0]).rt_rtx))->code) ==
MEM)
)
5708 {
5709 rtx mloc = vloc;
5710 machine_mode address_mode = get_address_mode (mloc);
5711 cselib_val *val
5712 = cselib_lookup (XEXP (mloc, 0)(((mloc)->u.fld[0]).rt_rtx), address_mode, 0,
5713 GET_MODE (mloc)((machine_mode) (mloc)->mode));
5714
5715 if (val && !cselib_preserved_value_p (val))
5716 preserve_value (val);
5717 }
5718
5719 if (CONSTANT_P (vloc)((rtx_class[(int) (((enum rtx_code) (vloc)->code))]) == RTX_CONST_OBJ
)
5720 && (GET_CODE (vloc)((enum rtx_code) (vloc)->code) != CONST || non_suitable_const (vloc)))
5721 /* For constants don't look up any value. */;
5722 else if (!VAR_LOC_UNKNOWN_P (vloc)(((enum rtx_code) (vloc)->code) == CLOBBER && ((((
vloc))->u.fld[0]).rt_rtx) == (const_int_rtx[64]))
&& !unsuitable_loc (vloc)
5723 && (val = find_use_val (vloc, GET_MODE (oloc)((machine_mode) (oloc)->mode), cui)))
5724 {
5725 machine_mode mode2;
5726 enum micro_operation_type type2;
5727 rtx nloc = NULLnullptr;
5728 bool resolvable = REG_P (vloc)(((enum rtx_code) (vloc)->code) == REG) || MEM_P (vloc)(((enum rtx_code) (vloc)->code) == MEM);
5729
5730 if (resolvable)
5731 nloc = replace_expr_with_values (vloc);
5732
5733 if (nloc)
5734 {
5735 oloc = shallow_copy_rtx (oloc);
5736 PAT_VAR_LOCATION_LOC (oloc)(((((oloc))->u.fld[1]).rt_rtx)) = nloc;
5737 }
5738
5739 oloc = gen_rtx_CONCAT (mode, val->val_rtx, oloc)gen_rtx_fmt_ee_stat ((CONCAT), ((mode)), ((val->val_rtx)),
((oloc)) )
;
5740
5741 type2 = use_type (vloc, 0, &mode2);
5742
5743 gcc_assert (type2 == MO_USE || type2 == MO_USE_NO_VAR((void)(!(type2 == MO_USE || type2 == MO_USE_NO_VAR || type2 ==
MO_CLOBBER) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 5744, __FUNCTION__), 0 : 0))
5744 || type2 == MO_CLOBBER)((void)(!(type2 == MO_USE || type2 == MO_USE_NO_VAR || type2 ==
MO_CLOBBER) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 5744, __FUNCTION__), 0 : 0))
;
5745
5746 if (type2 == MO_CLOBBER
5747 && !cselib_preserved_value_p (val))
5748 {
5749 VAL_NEEDS_RESOLUTION (oloc)(__extension__ ({ __typeof ((oloc)) const _rtx = ((oloc)); if
(((enum rtx_code) (_rtx)->code) != CONCAT) rtl_check_failed_flag
("VAL_NEEDS_RESOLUTION", _rtx, "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 5749, __FUNCTION__); _rtx; })->volatil)
= resolvable;
5750 preserve_value (val);
5751 }
5752 }
5753 else if (!VAR_LOC_UNKNOWN_P (vloc)(((enum rtx_code) (vloc)->code) == CLOBBER && ((((
vloc))->u.fld[0]).rt_rtx) == (const_int_rtx[64]))
)
5754 {
5755 oloc = shallow_copy_rtx (oloc);
5756 PAT_VAR_LOCATION_LOC (oloc)(((((oloc))->u.fld[1]).rt_rtx)) = gen_rtx_UNKNOWN_VAR_LOC ()(gen_rtx_fmt_e_stat ((CLOBBER), ((((void) 0, E_VOIDmode))), (
((const_int_rtx[64]))) ))
;
5757 }
5758
5759 mo.u.loc = oloc;
5760 }
5761 else if (type == MO_VAL_USE)
5762 {
5763 machine_mode mode2 = VOIDmode((void) 0, E_VOIDmode);
5764 enum micro_operation_type type2;
5765 cselib_val *val = find_use_val (loc, GET_MODE (loc)((machine_mode) (loc)->mode), cui);
5766 rtx vloc, oloc = loc, nloc;
5767
5768 gcc_assert (cui->sets)((void)(!(cui->sets) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 5768, __FUNCTION__), 0 : 0))
;
5769
5770 if (MEM_P (oloc)(((enum rtx_code) (oloc)->code) == MEM)
5771 && !REG_P (XEXP (oloc, 0))(((enum rtx_code) ((((oloc)->u.fld[0]).rt_rtx))->code) ==
REG)
5772 && !MEM_P (XEXP (oloc, 0))(((enum rtx_code) ((((oloc)->u.fld[0]).rt_rtx))->code) ==
MEM)
)
5773 {
5774 rtx mloc = oloc;
5775 machine_mode address_mode = get_address_mode (mloc);
5776 cselib_val *val
5777 = cselib_lookup (XEXP (mloc, 0)(((mloc)->u.fld[0]).rt_rtx), address_mode, 0,
5778 GET_MODE (mloc)((machine_mode) (mloc)->mode));
5779
5780 if (val && !cselib_preserved_value_p (val))
5781 preserve_value (val);
5782 }
5783
5784 type2 = use_type (loc, 0, &mode2);
5785
5786 gcc_assert (type2 == MO_USE || type2 == MO_USE_NO_VAR((void)(!(type2 == MO_USE || type2 == MO_USE_NO_VAR || type2 ==
MO_CLOBBER) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 5787, __FUNCTION__), 0 : 0))
5787 || type2 == MO_CLOBBER)((void)(!(type2 == MO_USE || type2 == MO_USE_NO_VAR || type2 ==
MO_CLOBBER) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/var-tracking.c"
, 5787, __FUNCTION__), 0 : 0))
;
5788
5789 if (type2 == MO_USE)
5790 vloc = var_lowpart (mode2, loc);
5791 else
5792 vloc = oloc;
5793
5794 /* The loc of a MO_VAL_USE may have two forms:
5795
5796 (concat val src): val is at src, a value-based
5797 representation.
5798
5799 (concat (concat val use) src): same as above, with use as
5800 the MO_USE tracked value, if it differs from src.
5801