annotate gcc/tree-ssa-loop-im.c @ 158:494b0b89df80 default tip

...
author Shinji KONO <kono@ie.u-ryukyu.ac.jp>
date Mon, 25 May 2020 18:13:55 +0900
parents 1830386684a0
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1 /* Loop invariant motion.
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2 Copyright (C) 2003-2020 Free Software Foundation, Inc.
55
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 47
diff changeset
3
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
4 This file is part of GCC.
55
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 47
diff changeset
5
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
6 GCC is free software; you can redistribute it and/or modify it
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
7 under the terms of the GNU General Public License as published by the
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
8 Free Software Foundation; either version 3, or (at your option) any
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
9 later version.
55
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 47
diff changeset
10
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
11 GCC is distributed in the hope that it will be useful, but WITHOUT
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
12 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
13 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
14 for more details.
55
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 47
diff changeset
15
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
16 You should have received a copy of the GNU General Public License
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
17 along with GCC; see the file COPYING3. If not see
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
18 <http://www.gnu.org/licenses/>. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
19
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
20 #include "config.h"
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
21 #include "system.h"
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
22 #include "coretypes.h"
111
kono
parents: 67
diff changeset
23 #include "backend.h"
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
24 #include "tree.h"
111
kono
parents: 67
diff changeset
25 #include "gimple.h"
kono
parents: 67
diff changeset
26 #include "cfghooks.h"
kono
parents: 67
diff changeset
27 #include "tree-pass.h"
kono
parents: 67
diff changeset
28 #include "ssa.h"
63
b7f97abdc517 update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
29 #include "gimple-pretty-print.h"
111
kono
parents: 67
diff changeset
30 #include "fold-const.h"
kono
parents: 67
diff changeset
31 #include "cfganal.h"
kono
parents: 67
diff changeset
32 #include "tree-eh.h"
kono
parents: 67
diff changeset
33 #include "gimplify.h"
kono
parents: 67
diff changeset
34 #include "gimple-iterator.h"
kono
parents: 67
diff changeset
35 #include "tree-cfg.h"
kono
parents: 67
diff changeset
36 #include "tree-ssa-loop-manip.h"
kono
parents: 67
diff changeset
37 #include "tree-ssa-loop.h"
kono
parents: 67
diff changeset
38 #include "tree-into-ssa.h"
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
39 #include "cfgloop.h"
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
40 #include "domwalk.h"
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
41 #include "tree-affine.h"
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
42 #include "tree-ssa-propagate.h"
111
kono
parents: 67
diff changeset
43 #include "trans-mem.h"
kono
parents: 67
diff changeset
44 #include "gimple-fold.h"
kono
parents: 67
diff changeset
45 #include "tree-scalar-evolution.h"
kono
parents: 67
diff changeset
46 #include "tree-ssa-loop-niter.h"
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
47 #include "alias.h"
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
48 #include "builtins.h"
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
49 #include "tree-dfa.h"
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
50
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
51 /* TODO: Support for predicated code motion. I.e.
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
52
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
53 while (1)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
54 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
55 if (cond)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
56 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
57 a = inv;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
58 something;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
59 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
60 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
61
111
kono
parents: 67
diff changeset
62 Where COND and INV are invariants, but evaluating INV may trap or be
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
63 invalid from some other reason if !COND. This may be transformed to
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
64
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
65 if (cond)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
66 a = inv;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
67 while (1)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
68 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
69 if (cond)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
70 something;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
71 } */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
72
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
73 /* The auxiliary data kept for each statement. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
74
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
75 struct lim_aux_data
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
76 {
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
77 class loop *max_loop; /* The outermost loop in that the statement
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
78 is invariant. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
79
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
80 class loop *tgt_loop; /* The loop out of that we want to move the
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
81 invariant. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
82
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
83 class loop *always_executed_in;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
84 /* The outermost loop for that we are sure
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
85 the statement is executed if the loop
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
86 is entered. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
87
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
88 unsigned cost; /* Cost of the computation performed by the
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
89 statement. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
90
111
kono
parents: 67
diff changeset
91 unsigned ref; /* The simple_mem_ref in this stmt or 0. */
kono
parents: 67
diff changeset
92
kono
parents: 67
diff changeset
93 vec<gimple *> depends; /* Vector of statements that must be also
kono
parents: 67
diff changeset
94 hoisted out of the loop when this statement
kono
parents: 67
diff changeset
95 is hoisted; i.e. those that define the
kono
parents: 67
diff changeset
96 operands of the statement and are inside of
kono
parents: 67
diff changeset
97 the MAX_LOOP loop. */
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
98 };
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
99
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
100 /* Maps statements to their lim_aux_data. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
101
111
kono
parents: 67
diff changeset
102 static hash_map<gimple *, lim_aux_data *> *lim_aux_data_map;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
103
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
104 /* Description of a memory reference location. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
105
111
kono
parents: 67
diff changeset
106 struct mem_ref_loc
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
107 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
108 tree *ref; /* The reference itself. */
111
kono
parents: 67
diff changeset
109 gimple *stmt; /* The statement in that it occurs. */
kono
parents: 67
diff changeset
110 };
kono
parents: 67
diff changeset
111
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
112
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
113 /* Description of a memory reference. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
114
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
115 class im_mem_ref
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
116 {
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
117 public:
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
118 unsigned id : 30; /* ID assigned to the memory reference
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
119 (its index in memory_accesses.refs_list) */
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
120 unsigned ref_canonical : 1; /* Whether mem.ref was canonicalized. */
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
121 unsigned ref_decomposed : 1; /* Whether the ref was hashed from mem. */
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
122 hashval_t hash; /* Its hash value. */
111
kono
parents: 67
diff changeset
123
kono
parents: 67
diff changeset
124 /* The memory access itself and associated caching of alias-oracle
kono
parents: 67
diff changeset
125 query meta-data. */
kono
parents: 67
diff changeset
126 ao_ref mem;
kono
parents: 67
diff changeset
127
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
128 bitmap stored; /* The set of loops in that this memory location
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
129 is stored to. */
111
kono
parents: 67
diff changeset
130 vec<mem_ref_loc> accesses_in_loop;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
131 /* The locations of the accesses. Vector
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
132 indexed by the loop number. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
133
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
134 /* The following sets are computed on demand. We keep both set and
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
135 its complement, so that we know whether the information was
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
136 already computed or not. */
111
kono
parents: 67
diff changeset
137 bitmap_head indep_loop; /* The set of loops in that the memory
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
138 reference is independent, meaning:
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
139 If it is stored in the loop, this store
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
140 is independent on all other loads and
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
141 stores.
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
142 If it is only loaded, then it is independent
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
143 on all stores in the loop. */
111
kono
parents: 67
diff changeset
144 bitmap_head dep_loop; /* The complement of INDEP_LOOP. */
kono
parents: 67
diff changeset
145 };
kono
parents: 67
diff changeset
146
kono
parents: 67
diff changeset
147 /* We use two bits per loop in the ref->{in,}dep_loop bitmaps, the first
kono
parents: 67
diff changeset
148 to record (in)dependence against stores in the loop and its subloops, the
kono
parents: 67
diff changeset
149 second to record (in)dependence against all references in the loop
kono
parents: 67
diff changeset
150 and its subloops. */
kono
parents: 67
diff changeset
151 #define LOOP_DEP_BIT(loopnum, storedp) (2 * (loopnum) + (storedp ? 1 : 0))
kono
parents: 67
diff changeset
152
kono
parents: 67
diff changeset
153 /* Mem_ref hashtable helpers. */
kono
parents: 67
diff changeset
154
kono
parents: 67
diff changeset
155 struct mem_ref_hasher : nofree_ptr_hash <im_mem_ref>
kono
parents: 67
diff changeset
156 {
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
157 typedef ao_ref *compare_type;
111
kono
parents: 67
diff changeset
158 static inline hashval_t hash (const im_mem_ref *);
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
159 static inline bool equal (const im_mem_ref *, const ao_ref *);
111
kono
parents: 67
diff changeset
160 };
kono
parents: 67
diff changeset
161
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
162 /* A hash function for class im_mem_ref object OBJ. */
111
kono
parents: 67
diff changeset
163
kono
parents: 67
diff changeset
164 inline hashval_t
kono
parents: 67
diff changeset
165 mem_ref_hasher::hash (const im_mem_ref *mem)
kono
parents: 67
diff changeset
166 {
kono
parents: 67
diff changeset
167 return mem->hash;
kono
parents: 67
diff changeset
168 }
kono
parents: 67
diff changeset
169
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
170 /* An equality function for class im_mem_ref object MEM1 with
111
kono
parents: 67
diff changeset
171 memory reference OBJ2. */
kono
parents: 67
diff changeset
172
kono
parents: 67
diff changeset
173 inline bool
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
174 mem_ref_hasher::equal (const im_mem_ref *mem1, const ao_ref *obj2)
111
kono
parents: 67
diff changeset
175 {
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
176 if (obj2->max_size_known_p ())
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
177 return (mem1->ref_decomposed
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
178 && operand_equal_p (mem1->mem.base, obj2->base, 0)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
179 && known_eq (mem1->mem.offset, obj2->offset)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
180 && known_eq (mem1->mem.size, obj2->size)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
181 && known_eq (mem1->mem.max_size, obj2->max_size)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
182 && mem1->mem.volatile_p == obj2->volatile_p
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
183 && (mem1->mem.ref_alias_set == obj2->ref_alias_set
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
184 /* We are not canonicalizing alias-sets but for the
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
185 special-case we didn't canonicalize yet and the
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
186 incoming ref is a alias-set zero MEM we pick
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
187 the correct one already. */
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
188 || (!mem1->ref_canonical
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
189 && (TREE_CODE (obj2->ref) == MEM_REF
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
190 || TREE_CODE (obj2->ref) == TARGET_MEM_REF)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
191 && obj2->ref_alias_set == 0)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
192 /* Likewise if there's a canonical ref with alias-set zero. */
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
193 || (mem1->ref_canonical && mem1->mem.ref_alias_set == 0))
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
194 && types_compatible_p (TREE_TYPE (mem1->mem.ref),
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
195 TREE_TYPE (obj2->ref)));
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
196 else
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
197 return operand_equal_p (mem1->mem.ref, obj2->ref, 0);
111
kono
parents: 67
diff changeset
198 }
kono
parents: 67
diff changeset
199
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
200
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
201 /* Description of memory accesses in loops. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
202
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
203 static struct
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
204 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
205 /* The hash table of memory references accessed in loops. */
111
kono
parents: 67
diff changeset
206 hash_table<mem_ref_hasher> *refs;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
207
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
208 /* The list of memory references. */
111
kono
parents: 67
diff changeset
209 vec<im_mem_ref *> refs_list;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
210
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
211 /* The set of memory references accessed in each loop. */
111
kono
parents: 67
diff changeset
212 vec<bitmap_head> refs_in_loop;
kono
parents: 67
diff changeset
213
kono
parents: 67
diff changeset
214 /* The set of memory references stored in each loop. */
kono
parents: 67
diff changeset
215 vec<bitmap_head> refs_stored_in_loop;
kono
parents: 67
diff changeset
216
kono
parents: 67
diff changeset
217 /* The set of memory references stored in each loop, including subloops . */
kono
parents: 67
diff changeset
218 vec<bitmap_head> all_refs_stored_in_loop;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
219
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
220 /* Cache for expanding memory addresses. */
111
kono
parents: 67
diff changeset
221 hash_map<tree, name_expansion *> *ttae_cache;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
222 } memory_accesses;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
223
111
kono
parents: 67
diff changeset
224 /* Obstack for the bitmaps in the above data structures. */
kono
parents: 67
diff changeset
225 static bitmap_obstack lim_bitmap_obstack;
kono
parents: 67
diff changeset
226 static obstack mem_ref_obstack;
kono
parents: 67
diff changeset
227
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
228 static bool ref_indep_loop_p (class loop *, im_mem_ref *);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
229 static bool ref_always_accessed_p (class loop *, im_mem_ref *, bool);
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
230
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
231 /* Minimum cost of an expensive expression. */
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
232 #define LIM_EXPENSIVE ((unsigned) param_lim_expensive)
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
233
111
kono
parents: 67
diff changeset
234 /* The outermost loop for which execution of the header guarantees that the
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
235 block will be executed. */
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
236 #define ALWAYS_EXECUTED_IN(BB) ((class loop *) (BB)->aux)
111
kono
parents: 67
diff changeset
237 #define SET_ALWAYS_EXECUTED_IN(BB, VAL) ((BB)->aux = (void *) (VAL))
kono
parents: 67
diff changeset
238
kono
parents: 67
diff changeset
239 /* ID of the shared unanalyzable mem. */
kono
parents: 67
diff changeset
240 #define UNANALYZABLE_MEM_ID 0
kono
parents: 67
diff changeset
241
kono
parents: 67
diff changeset
242 /* Whether the reference was analyzable. */
kono
parents: 67
diff changeset
243 #define MEM_ANALYZABLE(REF) ((REF)->id != UNANALYZABLE_MEM_ID)
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
244
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
245 static struct lim_aux_data *
111
kono
parents: 67
diff changeset
246 init_lim_data (gimple *stmt)
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
247 {
111
kono
parents: 67
diff changeset
248 lim_aux_data *p = XCNEW (struct lim_aux_data);
kono
parents: 67
diff changeset
249 lim_aux_data_map->put (stmt, p);
kono
parents: 67
diff changeset
250
kono
parents: 67
diff changeset
251 return p;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
252 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
253
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
254 static struct lim_aux_data *
111
kono
parents: 67
diff changeset
255 get_lim_data (gimple *stmt)
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
256 {
111
kono
parents: 67
diff changeset
257 lim_aux_data **p = lim_aux_data_map->get (stmt);
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
258 if (!p)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
259 return NULL;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
260
111
kono
parents: 67
diff changeset
261 return *p;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
262 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
263
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
264 /* Releases the memory occupied by DATA. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
265
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
266 static void
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
267 free_lim_aux_data (struct lim_aux_data *data)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
268 {
111
kono
parents: 67
diff changeset
269 data->depends.release ();
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
270 free (data);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
271 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
272
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
273 static void
111
kono
parents: 67
diff changeset
274 clear_lim_data (gimple *stmt)
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
275 {
111
kono
parents: 67
diff changeset
276 lim_aux_data **p = lim_aux_data_map->get (stmt);
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
277 if (!p)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
278 return;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
279
111
kono
parents: 67
diff changeset
280 free_lim_aux_data (*p);
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
281 *p = NULL;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
282 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
283
111
kono
parents: 67
diff changeset
284
kono
parents: 67
diff changeset
285 /* The possibilities of statement movement. */
kono
parents: 67
diff changeset
286 enum move_pos
kono
parents: 67
diff changeset
287 {
kono
parents: 67
diff changeset
288 MOVE_IMPOSSIBLE, /* No movement -- side effect expression. */
kono
parents: 67
diff changeset
289 MOVE_PRESERVE_EXECUTION, /* Must not cause the non-executed statement
kono
parents: 67
diff changeset
290 become executed -- memory accesses, ... */
kono
parents: 67
diff changeset
291 MOVE_POSSIBLE /* Unlimited movement. */
kono
parents: 67
diff changeset
292 };
kono
parents: 67
diff changeset
293
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
294
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
295 /* If it is possible to hoist the statement STMT unconditionally,
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
296 returns MOVE_POSSIBLE.
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
297 If it is possible to hoist the statement STMT, but we must avoid making
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
298 it executed if it would not be executed in the original program (e.g.
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
299 because it may trap), return MOVE_PRESERVE_EXECUTION.
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
300 Otherwise return MOVE_IMPOSSIBLE. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
301
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
302 enum move_pos
111
kono
parents: 67
diff changeset
303 movement_possibility (gimple *stmt)
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
304 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
305 tree lhs;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
306 enum move_pos ret = MOVE_POSSIBLE;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
307
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
308 if (flag_unswitch_loops
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
309 && gimple_code (stmt) == GIMPLE_COND)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
310 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
311 /* If we perform unswitching, force the operands of the invariant
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
312 condition to be moved out of the loop. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
313 return MOVE_POSSIBLE;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
314 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
315
63
b7f97abdc517 update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
316 if (gimple_code (stmt) == GIMPLE_PHI
b7f97abdc517 update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
317 && gimple_phi_num_args (stmt) <= 2
111
kono
parents: 67
diff changeset
318 && !virtual_operand_p (gimple_phi_result (stmt))
63
b7f97abdc517 update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
319 && !SSA_NAME_OCCURS_IN_ABNORMAL_PHI (gimple_phi_result (stmt)))
b7f97abdc517 update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
320 return MOVE_POSSIBLE;
b7f97abdc517 update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
321
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
322 if (gimple_get_lhs (stmt) == NULL_TREE)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
323 return MOVE_IMPOSSIBLE;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
324
55
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 47
diff changeset
325 if (gimple_vdef (stmt))
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
326 return MOVE_IMPOSSIBLE;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
327
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
328 if (stmt_ends_bb_p (stmt)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
329 || gimple_has_volatile_ops (stmt)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
330 || gimple_has_side_effects (stmt)
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
331 || stmt_could_throw_p (cfun, stmt))
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
332 return MOVE_IMPOSSIBLE;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
333
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
334 if (is_gimple_call (stmt))
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
335 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
336 /* While pure or const call is guaranteed to have no side effects, we
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
337 cannot move it arbitrarily. Consider code like
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
338
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
339 char *s = something ();
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
340
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
341 while (1)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
342 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
343 if (s)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
344 t = strlen (s);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
345 else
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
346 t = 0;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
347 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
348
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
349 Here the strlen call cannot be moved out of the loop, even though
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
350 s is invariant. In addition to possibly creating a call with
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
351 invalid arguments, moving out a function call that is not executed
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
352 may cause performance regressions in case the call is costly and
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
353 not executed at all. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
354 ret = MOVE_PRESERVE_EXECUTION;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
355 lhs = gimple_call_lhs (stmt);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
356 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
357 else if (is_gimple_assign (stmt))
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
358 lhs = gimple_assign_lhs (stmt);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
359 else
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
360 return MOVE_IMPOSSIBLE;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
361
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
362 if (TREE_CODE (lhs) == SSA_NAME
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
363 && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (lhs))
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
364 return MOVE_IMPOSSIBLE;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
365
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
366 if (TREE_CODE (lhs) != SSA_NAME
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
367 || gimple_could_trap_p (stmt))
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
368 return MOVE_PRESERVE_EXECUTION;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
369
111
kono
parents: 67
diff changeset
370 /* Non local loads in a transaction cannot be hoisted out. Well,
kono
parents: 67
diff changeset
371 unless the load happens on every path out of the loop, but we
kono
parents: 67
diff changeset
372 don't take this into account yet. */
kono
parents: 67
diff changeset
373 if (flag_tm
kono
parents: 67
diff changeset
374 && gimple_in_transaction (stmt)
kono
parents: 67
diff changeset
375 && gimple_assign_single_p (stmt))
kono
parents: 67
diff changeset
376 {
kono
parents: 67
diff changeset
377 tree rhs = gimple_assign_rhs1 (stmt);
kono
parents: 67
diff changeset
378 if (DECL_P (rhs) && is_global_var (rhs))
kono
parents: 67
diff changeset
379 {
kono
parents: 67
diff changeset
380 if (dump_file)
kono
parents: 67
diff changeset
381 {
kono
parents: 67
diff changeset
382 fprintf (dump_file, "Cannot hoist conditional load of ");
kono
parents: 67
diff changeset
383 print_generic_expr (dump_file, rhs, TDF_SLIM);
kono
parents: 67
diff changeset
384 fprintf (dump_file, " because it is in a transaction.\n");
kono
parents: 67
diff changeset
385 }
kono
parents: 67
diff changeset
386 return MOVE_IMPOSSIBLE;
kono
parents: 67
diff changeset
387 }
kono
parents: 67
diff changeset
388 }
kono
parents: 67
diff changeset
389
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
390 return ret;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
391 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
392
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
393 /* Suppose that operand DEF is used inside the LOOP. Returns the outermost
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
394 loop to that we could move the expression using DEF if it did not have
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
395 other operands, i.e. the outermost loop enclosing LOOP in that the value
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
396 of DEF is invariant. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
397
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
398 static class loop *
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
399 outermost_invariant_loop (tree def, class loop *loop)
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
400 {
111
kono
parents: 67
diff changeset
401 gimple *def_stmt;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
402 basic_block def_bb;
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
403 class loop *max_loop;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
404 struct lim_aux_data *lim_data;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
405
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
406 if (!def)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
407 return superloop_at_depth (loop, 1);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
408
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
409 if (TREE_CODE (def) != SSA_NAME)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
410 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
411 gcc_assert (is_gimple_min_invariant (def));
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
412 return superloop_at_depth (loop, 1);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
413 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
414
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
415 def_stmt = SSA_NAME_DEF_STMT (def);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
416 def_bb = gimple_bb (def_stmt);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
417 if (!def_bb)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
418 return superloop_at_depth (loop, 1);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
419
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
420 max_loop = find_common_loop (loop, def_bb->loop_father);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
421
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
422 lim_data = get_lim_data (def_stmt);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
423 if (lim_data != NULL && lim_data->max_loop != NULL)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
424 max_loop = find_common_loop (max_loop,
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
425 loop_outer (lim_data->max_loop));
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
426 if (max_loop == loop)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
427 return NULL;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
428 max_loop = superloop_at_depth (loop, loop_depth (max_loop) + 1);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
429
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
430 return max_loop;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
431 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
432
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
433 /* DATA is a structure containing information associated with a statement
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
434 inside LOOP. DEF is one of the operands of this statement.
55
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 47
diff changeset
435
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
436 Find the outermost loop enclosing LOOP in that value of DEF is invariant
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
437 and record this in DATA->max_loop field. If DEF itself is defined inside
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
438 this loop as well (i.e. we need to hoist it out of the loop if we want
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
439 to hoist the statement represented by DATA), record the statement in that
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
440 DEF is defined to the DATA->depends list. Additionally if ADD_COST is true,
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
441 add the cost of the computation of DEF to the DATA->cost.
55
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 47
diff changeset
442
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
443 If DEF is not invariant in LOOP, return false. Otherwise return TRUE. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
444
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
445 static bool
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
446 add_dependency (tree def, struct lim_aux_data *data, class loop *loop,
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
447 bool add_cost)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
448 {
111
kono
parents: 67
diff changeset
449 gimple *def_stmt = SSA_NAME_DEF_STMT (def);
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
450 basic_block def_bb = gimple_bb (def_stmt);
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
451 class loop *max_loop;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
452 struct lim_aux_data *def_data;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
453
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
454 if (!def_bb)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
455 return true;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
456
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
457 max_loop = outermost_invariant_loop (def, loop);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
458 if (!max_loop)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
459 return false;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
460
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
461 if (flow_loop_nested_p (data->max_loop, max_loop))
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
462 data->max_loop = max_loop;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
463
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
464 def_data = get_lim_data (def_stmt);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
465 if (!def_data)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
466 return true;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
467
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
468 if (add_cost
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
469 /* Only add the cost if the statement defining DEF is inside LOOP,
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
470 i.e. if it is likely that by moving the invariants dependent
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
471 on it, we will be able to avoid creating a new register for
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
472 it (since it will be only used in these dependent invariants). */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
473 && def_bb->loop_father == loop)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
474 data->cost += def_data->cost;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
475
111
kono
parents: 67
diff changeset
476 data->depends.safe_push (def_stmt);
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
477
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
478 return true;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
479 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
480
111
kono
parents: 67
diff changeset
481 /* Returns an estimate for a cost of statement STMT. The values here
kono
parents: 67
diff changeset
482 are just ad-hoc constants, similar to costs for inlining. */
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
483
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
484 static unsigned
111
kono
parents: 67
diff changeset
485 stmt_cost (gimple *stmt)
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
486 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
487 /* Always try to create possibilities for unswitching. */
63
b7f97abdc517 update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
488 if (gimple_code (stmt) == GIMPLE_COND
b7f97abdc517 update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
489 || gimple_code (stmt) == GIMPLE_PHI)
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
490 return LIM_EXPENSIVE;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
491
111
kono
parents: 67
diff changeset
492 /* We should be hoisting calls if possible. */
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
493 if (is_gimple_call (stmt))
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
494 {
111
kono
parents: 67
diff changeset
495 tree fndecl;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
496
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
497 /* Unless the call is a builtin_constant_p; this always folds to a
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
498 constant, so moving it is useless. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
499 fndecl = gimple_call_fndecl (stmt);
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
500 if (fndecl && fndecl_built_in_p (fndecl, BUILT_IN_CONSTANT_P))
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
501 return 0;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
502
111
kono
parents: 67
diff changeset
503 return LIM_EXPENSIVE;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
504 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
505
111
kono
parents: 67
diff changeset
506 /* Hoisting memory references out should almost surely be a win. */
kono
parents: 67
diff changeset
507 if (gimple_references_memory_p (stmt))
kono
parents: 67
diff changeset
508 return LIM_EXPENSIVE;
kono
parents: 67
diff changeset
509
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
510 if (gimple_code (stmt) != GIMPLE_ASSIGN)
111
kono
parents: 67
diff changeset
511 return 1;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
512
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
513 switch (gimple_assign_rhs_code (stmt))
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
514 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
515 case MULT_EXPR:
111
kono
parents: 67
diff changeset
516 case WIDEN_MULT_EXPR:
kono
parents: 67
diff changeset
517 case WIDEN_MULT_PLUS_EXPR:
kono
parents: 67
diff changeset
518 case WIDEN_MULT_MINUS_EXPR:
kono
parents: 67
diff changeset
519 case DOT_PROD_EXPR:
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
520 case TRUNC_DIV_EXPR:
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
521 case CEIL_DIV_EXPR:
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
522 case FLOOR_DIV_EXPR:
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
523 case ROUND_DIV_EXPR:
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
524 case EXACT_DIV_EXPR:
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
525 case CEIL_MOD_EXPR:
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
526 case FLOOR_MOD_EXPR:
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
527 case ROUND_MOD_EXPR:
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
528 case TRUNC_MOD_EXPR:
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
529 case RDIV_EXPR:
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
530 /* Division and multiplication are usually expensive. */
111
kono
parents: 67
diff changeset
531 return LIM_EXPENSIVE;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
532
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
533 case LSHIFT_EXPR:
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
534 case RSHIFT_EXPR:
111
kono
parents: 67
diff changeset
535 case WIDEN_LSHIFT_EXPR:
kono
parents: 67
diff changeset
536 case LROTATE_EXPR:
kono
parents: 67
diff changeset
537 case RROTATE_EXPR:
kono
parents: 67
diff changeset
538 /* Shifts and rotates are usually expensive. */
kono
parents: 67
diff changeset
539 return LIM_EXPENSIVE;
kono
parents: 67
diff changeset
540
kono
parents: 67
diff changeset
541 case CONSTRUCTOR:
kono
parents: 67
diff changeset
542 /* Make vector construction cost proportional to the number
kono
parents: 67
diff changeset
543 of elements. */
kono
parents: 67
diff changeset
544 return CONSTRUCTOR_NELTS (gimple_assign_rhs1 (stmt));
kono
parents: 67
diff changeset
545
kono
parents: 67
diff changeset
546 case SSA_NAME:
kono
parents: 67
diff changeset
547 case PAREN_EXPR:
kono
parents: 67
diff changeset
548 /* Whether or not something is wrapped inside a PAREN_EXPR
kono
parents: 67
diff changeset
549 should not change move cost. Nor should an intermediate
kono
parents: 67
diff changeset
550 unpropagated SSA name copy. */
kono
parents: 67
diff changeset
551 return 0;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
552
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
553 default:
111
kono
parents: 67
diff changeset
554 return 1;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
555 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
556 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
557
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
558 /* Finds the outermost loop between OUTER and LOOP in that the memory reference
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
559 REF is independent. If REF is not independent in LOOP, NULL is returned
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
560 instead. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
561
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
562 static class loop *
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
563 outermost_indep_loop (class loop *outer, class loop *loop, im_mem_ref *ref)
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
564 {
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
565 class loop *aloop;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
566
111
kono
parents: 67
diff changeset
567 if (ref->stored && bitmap_bit_p (ref->stored, loop->num))
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
568 return NULL;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
569
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
570 for (aloop = outer;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
571 aloop != loop;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
572 aloop = superloop_at_depth (loop, loop_depth (aloop) + 1))
111
kono
parents: 67
diff changeset
573 if ((!ref->stored || !bitmap_bit_p (ref->stored, aloop->num))
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
574 && ref_indep_loop_p (aloop, ref))
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
575 return aloop;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
576
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
577 if (ref_indep_loop_p (loop, ref))
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
578 return loop;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
579 else
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
580 return NULL;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
581 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
582
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
583 /* If there is a simple load or store to a memory reference in STMT, returns
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
584 the location of the memory reference, and sets IS_STORE according to whether
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
585 it is a store or load. Otherwise, returns NULL. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
586
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
587 static tree *
111
kono
parents: 67
diff changeset
588 simple_mem_ref_in_stmt (gimple *stmt, bool *is_store)
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
589 {
111
kono
parents: 67
diff changeset
590 tree *lhs, *rhs;
kono
parents: 67
diff changeset
591
kono
parents: 67
diff changeset
592 /* Recognize SSA_NAME = MEM and MEM = (SSA_NAME | invariant) patterns. */
kono
parents: 67
diff changeset
593 if (!gimple_assign_single_p (stmt))
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
594 return NULL;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
595
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
596 lhs = gimple_assign_lhs_ptr (stmt);
111
kono
parents: 67
diff changeset
597 rhs = gimple_assign_rhs1_ptr (stmt);
kono
parents: 67
diff changeset
598
kono
parents: 67
diff changeset
599 if (TREE_CODE (*lhs) == SSA_NAME && gimple_vuse (stmt))
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
600 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
601 *is_store = false;
111
kono
parents: 67
diff changeset
602 return rhs;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
603 }
111
kono
parents: 67
diff changeset
604 else if (gimple_vdef (stmt)
kono
parents: 67
diff changeset
605 && (TREE_CODE (*rhs) == SSA_NAME || is_gimple_min_invariant (*rhs)))
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
606 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
607 *is_store = true;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
608 return lhs;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
609 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
610 else
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
611 return NULL;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
612 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
613
63
b7f97abdc517 update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
614 /* From a controlling predicate in DOM determine the arguments from
b7f97abdc517 update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
615 the PHI node PHI that are chosen if the predicate evaluates to
b7f97abdc517 update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
616 true and false and store them to *TRUE_ARG_P and *FALSE_ARG_P if
b7f97abdc517 update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
617 they are non-NULL. Returns true if the arguments can be determined,
b7f97abdc517 update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
618 else return false. */
b7f97abdc517 update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
619
b7f97abdc517 update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
620 static bool
111
kono
parents: 67
diff changeset
621 extract_true_false_args_from_phi (basic_block dom, gphi *phi,
63
b7f97abdc517 update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
622 tree *true_arg_p, tree *false_arg_p)
b7f97abdc517 update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
623 {
111
kono
parents: 67
diff changeset
624 edge te, fe;
kono
parents: 67
diff changeset
625 if (! extract_true_false_controlled_edges (dom, gimple_bb (phi),
kono
parents: 67
diff changeset
626 &te, &fe))
63
b7f97abdc517 update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
627 return false;
b7f97abdc517 update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
628
b7f97abdc517 update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
629 if (true_arg_p)
111
kono
parents: 67
diff changeset
630 *true_arg_p = PHI_ARG_DEF (phi, te->dest_idx);
63
b7f97abdc517 update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
631 if (false_arg_p)
111
kono
parents: 67
diff changeset
632 *false_arg_p = PHI_ARG_DEF (phi, fe->dest_idx);
63
b7f97abdc517 update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
633
b7f97abdc517 update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
634 return true;
b7f97abdc517 update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
635 }
b7f97abdc517 update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
636
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
637 /* Determine the outermost loop to that it is possible to hoist a statement
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
638 STMT and store it to LIM_DATA (STMT)->max_loop. To do this we determine
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
639 the outermost loop in that the value computed by STMT is invariant.
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
640 If MUST_PRESERVE_EXEC is true, additionally choose such a loop that
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
641 we preserve the fact whether STMT is executed. It also fills other related
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
642 information to LIM_DATA (STMT).
55
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 47
diff changeset
643
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
644 The function returns false if STMT cannot be hoisted outside of the loop it
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
645 is defined in, and true otherwise. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
646
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
647 static bool
111
kono
parents: 67
diff changeset
648 determine_max_movement (gimple *stmt, bool must_preserve_exec)
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
649 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
650 basic_block bb = gimple_bb (stmt);
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
651 class loop *loop = bb->loop_father;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
652 class loop *level;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
653 struct lim_aux_data *lim_data = get_lim_data (stmt);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
654 tree val;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
655 ssa_op_iter iter;
55
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 47
diff changeset
656
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
657 if (must_preserve_exec)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
658 level = ALWAYS_EXECUTED_IN (bb);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
659 else
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
660 level = superloop_at_depth (loop, 1);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
661 lim_data->max_loop = level;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
662
111
kono
parents: 67
diff changeset
663 if (gphi *phi = dyn_cast <gphi *> (stmt))
63
b7f97abdc517 update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
664 {
b7f97abdc517 update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
665 use_operand_p use_p;
b7f97abdc517 update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
666 unsigned min_cost = UINT_MAX;
b7f97abdc517 update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
667 unsigned total_cost = 0;
b7f97abdc517 update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
668 struct lim_aux_data *def_data;
b7f97abdc517 update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
669
b7f97abdc517 update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
670 /* We will end up promoting dependencies to be unconditionally
b7f97abdc517 update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
671 evaluated. For this reason the PHI cost (and thus the
b7f97abdc517 update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
672 cost we remove from the loop by doing the invariant motion)
b7f97abdc517 update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
673 is that of the cheapest PHI argument dependency chain. */
111
kono
parents: 67
diff changeset
674 FOR_EACH_PHI_ARG (use_p, phi, iter, SSA_OP_USE)
63
b7f97abdc517 update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
675 {
b7f97abdc517 update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
676 val = USE_FROM_PTR (use_p);
111
kono
parents: 67
diff changeset
677
63
b7f97abdc517 update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
678 if (TREE_CODE (val) != SSA_NAME)
111
kono
parents: 67
diff changeset
679 {
kono
parents: 67
diff changeset
680 /* Assign const 1 to constants. */
kono
parents: 67
diff changeset
681 min_cost = MIN (min_cost, 1);
kono
parents: 67
diff changeset
682 total_cost += 1;
kono
parents: 67
diff changeset
683 continue;
kono
parents: 67
diff changeset
684 }
63
b7f97abdc517 update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
685 if (!add_dependency (val, lim_data, loop, false))
b7f97abdc517 update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
686 return false;
111
kono
parents: 67
diff changeset
687
kono
parents: 67
diff changeset
688 gimple *def_stmt = SSA_NAME_DEF_STMT (val);
kono
parents: 67
diff changeset
689 if (gimple_bb (def_stmt)
kono
parents: 67
diff changeset
690 && gimple_bb (def_stmt)->loop_father == loop)
63
b7f97abdc517 update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
691 {
111
kono
parents: 67
diff changeset
692 def_data = get_lim_data (def_stmt);
kono
parents: 67
diff changeset
693 if (def_data)
kono
parents: 67
diff changeset
694 {
kono
parents: 67
diff changeset
695 min_cost = MIN (min_cost, def_data->cost);
kono
parents: 67
diff changeset
696 total_cost += def_data->cost;
kono
parents: 67
diff changeset
697 }
63
b7f97abdc517 update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
698 }
b7f97abdc517 update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
699 }
b7f97abdc517 update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
700
111
kono
parents: 67
diff changeset
701 min_cost = MIN (min_cost, total_cost);
63
b7f97abdc517 update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
702 lim_data->cost += min_cost;
b7f97abdc517 update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
703
111
kono
parents: 67
diff changeset
704 if (gimple_phi_num_args (phi) > 1)
63
b7f97abdc517 update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
705 {
b7f97abdc517 update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
706 basic_block dom = get_immediate_dominator (CDI_DOMINATORS, bb);
111
kono
parents: 67
diff changeset
707 gimple *cond;
63
b7f97abdc517 update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
708 if (gsi_end_p (gsi_last_bb (dom)))
b7f97abdc517 update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
709 return false;
b7f97abdc517 update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
710 cond = gsi_stmt (gsi_last_bb (dom));
b7f97abdc517 update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
711 if (gimple_code (cond) != GIMPLE_COND)
b7f97abdc517 update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
712 return false;
b7f97abdc517 update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
713 /* Verify that this is an extended form of a diamond and
b7f97abdc517 update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
714 the PHI arguments are completely controlled by the
b7f97abdc517 update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
715 predicate in DOM. */
111
kono
parents: 67
diff changeset
716 if (!extract_true_false_args_from_phi (dom, phi, NULL, NULL))
63
b7f97abdc517 update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
717 return false;
b7f97abdc517 update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
718
b7f97abdc517 update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
719 /* Fold in dependencies and cost of the condition. */
b7f97abdc517 update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
720 FOR_EACH_SSA_TREE_OPERAND (val, cond, iter, SSA_OP_USE)
b7f97abdc517 update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
721 {
b7f97abdc517 update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
722 if (!add_dependency (val, lim_data, loop, false))
b7f97abdc517 update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
723 return false;
b7f97abdc517 update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
724 def_data = get_lim_data (SSA_NAME_DEF_STMT (val));
b7f97abdc517 update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
725 if (def_data)
111
kono
parents: 67
diff changeset
726 lim_data->cost += def_data->cost;
63
b7f97abdc517 update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
727 }
b7f97abdc517 update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
728
b7f97abdc517 update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
729 /* We want to avoid unconditionally executing very expensive
b7f97abdc517 update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
730 operations. As costs for our dependencies cannot be
b7f97abdc517 update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
731 negative just claim we are not invariand for this case.
b7f97abdc517 update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
732 We also are not sure whether the control-flow inside the
b7f97abdc517 update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
733 loop will vanish. */
b7f97abdc517 update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
734 if (total_cost - min_cost >= 2 * LIM_EXPENSIVE
b7f97abdc517 update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
735 && !(min_cost != 0
b7f97abdc517 update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
736 && total_cost / min_cost <= 2))
b7f97abdc517 update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
737 return false;
b7f97abdc517 update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
738
b7f97abdc517 update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
739 /* Assume that the control-flow in the loop will vanish.
b7f97abdc517 update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
740 ??? We should verify this and not artificially increase
b7f97abdc517 update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
741 the cost if that is not the case. */
b7f97abdc517 update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
742 lim_data->cost += stmt_cost (stmt);
b7f97abdc517 update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
743 }
b7f97abdc517 update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
744
b7f97abdc517 update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
745 return true;
b7f97abdc517 update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
746 }
b7f97abdc517 update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
747 else
b7f97abdc517 update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
748 FOR_EACH_SSA_TREE_OPERAND (val, stmt, iter, SSA_OP_USE)
b7f97abdc517 update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
749 if (!add_dependency (val, lim_data, loop, true))
b7f97abdc517 update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
750 return false;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
751
55
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 47
diff changeset
752 if (gimple_vuse (stmt))
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
753 {
111
kono
parents: 67
diff changeset
754 im_mem_ref *ref
kono
parents: 67
diff changeset
755 = lim_data ? memory_accesses.refs_list[lim_data->ref] : NULL;
kono
parents: 67
diff changeset
756 if (ref
kono
parents: 67
diff changeset
757 && MEM_ANALYZABLE (ref))
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
758 {
111
kono
parents: 67
diff changeset
759 lim_data->max_loop = outermost_indep_loop (lim_data->max_loop,
kono
parents: 67
diff changeset
760 loop, ref);
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
761 if (!lim_data->max_loop)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
762 return false;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
763 }
111
kono
parents: 67
diff changeset
764 else if (! add_dependency (gimple_vuse (stmt), lim_data, loop, false))
kono
parents: 67
diff changeset
765 return false;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
766 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
767
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
768 lim_data->cost += stmt_cost (stmt);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
769
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
770 return true;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
771 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
772
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
773 /* Suppose that some statement in ORIG_LOOP is hoisted to the loop LEVEL,
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
774 and that one of the operands of this statement is computed by STMT.
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
775 Ensure that STMT (together with all the statements that define its
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
776 operands) is hoisted at least out of the loop LEVEL. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
777
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
778 static void
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
779 set_level (gimple *stmt, class loop *orig_loop, class loop *level)
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
780 {
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
781 class loop *stmt_loop = gimple_bb (stmt)->loop_father;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
782 struct lim_aux_data *lim_data;
111
kono
parents: 67
diff changeset
783 gimple *dep_stmt;
kono
parents: 67
diff changeset
784 unsigned i;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
785
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
786 stmt_loop = find_common_loop (orig_loop, stmt_loop);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
787 lim_data = get_lim_data (stmt);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
788 if (lim_data != NULL && lim_data->tgt_loop != NULL)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
789 stmt_loop = find_common_loop (stmt_loop,
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
790 loop_outer (lim_data->tgt_loop));
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
791 if (flow_loop_nested_p (stmt_loop, level))
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
792 return;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
793
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
794 gcc_assert (level == lim_data->max_loop
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
795 || flow_loop_nested_p (lim_data->max_loop, level));
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
796
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
797 lim_data->tgt_loop = level;
111
kono
parents: 67
diff changeset
798 FOR_EACH_VEC_ELT (lim_data->depends, i, dep_stmt)
kono
parents: 67
diff changeset
799 set_level (dep_stmt, orig_loop, level);
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
800 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
801
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
802 /* Determines an outermost loop from that we want to hoist the statement STMT.
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
803 For now we chose the outermost possible loop. TODO -- use profiling
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
804 information to set it more sanely. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
805
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
806 static void
111
kono
parents: 67
diff changeset
807 set_profitable_level (gimple *stmt)
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
808 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
809 set_level (stmt, gimple_bb (stmt)->loop_father, get_lim_data (stmt)->max_loop);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
810 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
811
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
812 /* Returns true if STMT is a call that has side effects. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
813
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
814 static bool
111
kono
parents: 67
diff changeset
815 nonpure_call_p (gimple *stmt)
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
816 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
817 if (gimple_code (stmt) != GIMPLE_CALL)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
818 return false;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
819
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
820 return gimple_has_side_effects (stmt);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
821 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
822
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
823 /* Rewrite a/b to a*(1/b). Return the invariant stmt to process. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
824
111
kono
parents: 67
diff changeset
825 static gimple *
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
826 rewrite_reciprocal (gimple_stmt_iterator *bsi)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
827 {
111
kono
parents: 67
diff changeset
828 gassign *stmt, *stmt1, *stmt2;
kono
parents: 67
diff changeset
829 tree name, lhs, type;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
830 tree real_one;
55
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 47
diff changeset
831 gimple_stmt_iterator gsi;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
832
111
kono
parents: 67
diff changeset
833 stmt = as_a <gassign *> (gsi_stmt (*bsi));
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
834 lhs = gimple_assign_lhs (stmt);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
835 type = TREE_TYPE (lhs);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
836
67
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 63
diff changeset
837 real_one = build_one_cst (type);
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
838
111
kono
parents: 67
diff changeset
839 name = make_temp_ssa_name (type, NULL, "reciptmp");
kono
parents: 67
diff changeset
840 stmt1 = gimple_build_assign (name, RDIV_EXPR, real_one,
kono
parents: 67
diff changeset
841 gimple_assign_rhs2 (stmt));
kono
parents: 67
diff changeset
842 stmt2 = gimple_build_assign (lhs, MULT_EXPR, name,
kono
parents: 67
diff changeset
843 gimple_assign_rhs1 (stmt));
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
844
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
845 /* Replace division stmt with reciprocal and multiply stmts.
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
846 The multiply stmt is not invariant, so update iterator
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
847 and avoid rescanning. */
55
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 47
diff changeset
848 gsi = *bsi;
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 47
diff changeset
849 gsi_insert_before (bsi, stmt1, GSI_NEW_STMT);
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 47
diff changeset
850 gsi_replace (&gsi, stmt2, true);
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
851
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
852 /* Continue processing with invariant reciprocal statement. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
853 return stmt1;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
854 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
855
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
856 /* Check if the pattern at *BSI is a bittest of the form
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
857 (A >> B) & 1 != 0 and in this case rewrite it to A & (1 << B) != 0. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
858
111
kono
parents: 67
diff changeset
859 static gimple *
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
860 rewrite_bittest (gimple_stmt_iterator *bsi)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
861 {
111
kono
parents: 67
diff changeset
862 gassign *stmt;
kono
parents: 67
diff changeset
863 gimple *stmt1;
kono
parents: 67
diff changeset
864 gassign *stmt2;
kono
parents: 67
diff changeset
865 gimple *use_stmt;
kono
parents: 67
diff changeset
866 gcond *cond_stmt;
kono
parents: 67
diff changeset
867 tree lhs, name, t, a, b;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
868 use_operand_p use;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
869
111
kono
parents: 67
diff changeset
870 stmt = as_a <gassign *> (gsi_stmt (*bsi));
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
871 lhs = gimple_assign_lhs (stmt);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
872
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
873 /* Verify that the single use of lhs is a comparison against zero. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
874 if (TREE_CODE (lhs) != SSA_NAME
111
kono
parents: 67
diff changeset
875 || !single_imm_use (lhs, &use, &use_stmt))
kono
parents: 67
diff changeset
876 return stmt;
kono
parents: 67
diff changeset
877 cond_stmt = dyn_cast <gcond *> (use_stmt);
kono
parents: 67
diff changeset
878 if (!cond_stmt)
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
879 return stmt;
111
kono
parents: 67
diff changeset
880 if (gimple_cond_lhs (cond_stmt) != lhs
kono
parents: 67
diff changeset
881 || (gimple_cond_code (cond_stmt) != NE_EXPR
kono
parents: 67
diff changeset
882 && gimple_cond_code (cond_stmt) != EQ_EXPR)
kono
parents: 67
diff changeset
883 || !integer_zerop (gimple_cond_rhs (cond_stmt)))
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
884 return stmt;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
885
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
886 /* Get at the operands of the shift. The rhs is TMP1 & 1. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
887 stmt1 = SSA_NAME_DEF_STMT (gimple_assign_rhs1 (stmt));
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
888 if (gimple_code (stmt1) != GIMPLE_ASSIGN)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
889 return stmt;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
890
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
891 /* There is a conversion in between possibly inserted by fold. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
892 if (CONVERT_EXPR_CODE_P (gimple_assign_rhs_code (stmt1)))
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
893 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
894 t = gimple_assign_rhs1 (stmt1);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
895 if (TREE_CODE (t) != SSA_NAME
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
896 || !has_single_use (t))
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
897 return stmt;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
898 stmt1 = SSA_NAME_DEF_STMT (t);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
899 if (gimple_code (stmt1) != GIMPLE_ASSIGN)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
900 return stmt;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
901 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
902
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
903 /* Verify that B is loop invariant but A is not. Verify that with
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
904 all the stmt walking we are still in the same loop. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
905 if (gimple_assign_rhs_code (stmt1) != RSHIFT_EXPR
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
906 || loop_containing_stmt (stmt1) != loop_containing_stmt (stmt))
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
907 return stmt;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
908
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
909 a = gimple_assign_rhs1 (stmt1);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
910 b = gimple_assign_rhs2 (stmt1);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
911
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
912 if (outermost_invariant_loop (b, loop_containing_stmt (stmt1)) != NULL
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
913 && outermost_invariant_loop (a, loop_containing_stmt (stmt1)) == NULL)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
914 {
55
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 47
diff changeset
915 gimple_stmt_iterator rsi;
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 47
diff changeset
916
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
917 /* 1 << B */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
918 t = fold_build2 (LSHIFT_EXPR, TREE_TYPE (a),
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
919 build_int_cst (TREE_TYPE (a), 1), b);
111
kono
parents: 67
diff changeset
920 name = make_temp_ssa_name (TREE_TYPE (a), NULL, "shifttmp");
kono
parents: 67
diff changeset
921 stmt1 = gimple_build_assign (name, t);
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
922
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
923 /* A & (1 << B) */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
924 t = fold_build2 (BIT_AND_EXPR, TREE_TYPE (a), a, name);
111
kono
parents: 67
diff changeset
925 name = make_temp_ssa_name (TREE_TYPE (a), NULL, "shifttmp");
kono
parents: 67
diff changeset
926 stmt2 = gimple_build_assign (name, t);
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
927
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
928 /* Replace the SSA_NAME we compare against zero. Adjust
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
929 the type of zero accordingly. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
930 SET_USE (use, name);
111
kono
parents: 67
diff changeset
931 gimple_cond_set_rhs (cond_stmt,
kono
parents: 67
diff changeset
932 build_int_cst_type (TREE_TYPE (name),
kono
parents: 67
diff changeset
933 0));
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
934
55
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 47
diff changeset
935 /* Don't use gsi_replace here, none of the new assignments sets
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 47
diff changeset
936 the variable originally set in stmt. Move bsi to stmt1, and
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 47
diff changeset
937 then remove the original stmt, so that we get a chance to
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 47
diff changeset
938 retain debug info for it. */
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 47
diff changeset
939 rsi = *bsi;
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 47
diff changeset
940 gsi_insert_before (bsi, stmt1, GSI_NEW_STMT);
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 47
diff changeset
941 gsi_insert_before (&rsi, stmt2, GSI_SAME_STMT);
111
kono
parents: 67
diff changeset
942 gimple *to_release = gsi_stmt (rsi);
55
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 47
diff changeset
943 gsi_remove (&rsi, true);
111
kono
parents: 67
diff changeset
944 release_defs (to_release);
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
945
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
946 return stmt1;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
947 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
948
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
949 return stmt;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
950 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
951
111
kono
parents: 67
diff changeset
952 /* For each statement determines the outermost loop in that it is invariant,
kono
parents: 67
diff changeset
953 - statements on whose motion it depends and the cost of the computation.
kono
parents: 67
diff changeset
954 - This information is stored to the LIM_DATA structure associated with
kono
parents: 67
diff changeset
955 - each statement. */
kono
parents: 67
diff changeset
956 class invariantness_dom_walker : public dom_walker
kono
parents: 67
diff changeset
957 {
kono
parents: 67
diff changeset
958 public:
kono
parents: 67
diff changeset
959 invariantness_dom_walker (cdi_direction direction)
kono
parents: 67
diff changeset
960 : dom_walker (direction) {}
kono
parents: 67
diff changeset
961
kono
parents: 67
diff changeset
962 virtual edge before_dom_children (basic_block);
kono
parents: 67
diff changeset
963 };
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
964
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
965 /* Determine the outermost loops in that statements in basic block BB are
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
966 invariant, and record them to the LIM_DATA associated with the statements.
111
kono
parents: 67
diff changeset
967 Callback for dom_walker. */
kono
parents: 67
diff changeset
968
kono
parents: 67
diff changeset
969 edge
kono
parents: 67
diff changeset
970 invariantness_dom_walker::before_dom_children (basic_block bb)
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
971 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
972 enum move_pos pos;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
973 gimple_stmt_iterator bsi;
111
kono
parents: 67
diff changeset
974 gimple *stmt;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
975 bool maybe_never = ALWAYS_EXECUTED_IN (bb) == NULL;
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
976 class loop *outermost = ALWAYS_EXECUTED_IN (bb);
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
977 struct lim_aux_data *lim_data;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
978
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
979 if (!loop_outer (bb->loop_father))
111
kono
parents: 67
diff changeset
980 return NULL;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
981
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
982 if (dump_file && (dump_flags & TDF_DETAILS))
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
983 fprintf (dump_file, "Basic block %d (loop %d -- depth %d):\n\n",
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
984 bb->index, bb->loop_father->num, loop_depth (bb->loop_father));
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
985
63
b7f97abdc517 update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
986 /* Look at PHI nodes, but only if there is at most two.
b7f97abdc517 update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
987 ??? We could relax this further by post-processing the inserted
b7f97abdc517 update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
988 code and transforming adjacent cond-exprs with the same predicate
b7f97abdc517 update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
989 to control flow again. */
b7f97abdc517 update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
990 bsi = gsi_start_phis (bb);
b7f97abdc517 update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
991 if (!gsi_end_p (bsi)
b7f97abdc517 update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
992 && ((gsi_next (&bsi), gsi_end_p (bsi))
b7f97abdc517 update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
993 || (gsi_next (&bsi), gsi_end_p (bsi))))
b7f97abdc517 update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
994 for (bsi = gsi_start_phis (bb); !gsi_end_p (bsi); gsi_next (&bsi))
b7f97abdc517 update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
995 {
b7f97abdc517 update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
996 stmt = gsi_stmt (bsi);
b7f97abdc517 update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
997
b7f97abdc517 update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
998 pos = movement_possibility (stmt);
b7f97abdc517 update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
999 if (pos == MOVE_IMPOSSIBLE)
b7f97abdc517 update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
1000 continue;
b7f97abdc517 update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
1001
111
kono
parents: 67
diff changeset
1002 lim_data = get_lim_data (stmt);
kono
parents: 67
diff changeset
1003 if (! lim_data)
kono
parents: 67
diff changeset
1004 lim_data = init_lim_data (stmt);
63
b7f97abdc517 update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
1005 lim_data->always_executed_in = outermost;
b7f97abdc517 update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
1006
b7f97abdc517 update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
1007 if (!determine_max_movement (stmt, false))
b7f97abdc517 update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
1008 {
b7f97abdc517 update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
1009 lim_data->max_loop = NULL;
b7f97abdc517 update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
1010 continue;
b7f97abdc517 update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
1011 }
b7f97abdc517 update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
1012
b7f97abdc517 update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
1013 if (dump_file && (dump_flags & TDF_DETAILS))
b7f97abdc517 update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
1014 {
111
kono
parents: 67
diff changeset
1015 print_gimple_stmt (dump_file, stmt, 2);
63
b7f97abdc517 update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
1016 fprintf (dump_file, " invariant up to level %d, cost %d.\n\n",
b7f97abdc517 update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
1017 loop_depth (lim_data->max_loop),
b7f97abdc517 update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
1018 lim_data->cost);
b7f97abdc517 update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
1019 }
b7f97abdc517 update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
1020
b7f97abdc517 update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
1021 if (lim_data->cost >= LIM_EXPENSIVE)
b7f97abdc517 update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
1022 set_profitable_level (stmt);
b7f97abdc517 update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
1023 }
b7f97abdc517 update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
1024
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1025 for (bsi = gsi_start_bb (bb); !gsi_end_p (bsi); gsi_next (&bsi))
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1026 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1027 stmt = gsi_stmt (bsi);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1028
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1029 pos = movement_possibility (stmt);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1030 if (pos == MOVE_IMPOSSIBLE)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1031 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1032 if (nonpure_call_p (stmt))
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1033 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1034 maybe_never = true;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1035 outermost = NULL;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1036 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1037 /* Make sure to note always_executed_in for stores to make
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1038 store-motion work. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1039 else if (stmt_makes_single_store (stmt))
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1040 {
111
kono
parents: 67
diff changeset
1041 struct lim_aux_data *lim_data = get_lim_data (stmt);
kono
parents: 67
diff changeset
1042 if (! lim_data)
kono
parents: 67
diff changeset
1043 lim_data = init_lim_data (stmt);
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1044 lim_data->always_executed_in = outermost;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1045 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1046 continue;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1047 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1048
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1049 if (is_gimple_assign (stmt)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1050 && (get_gimple_rhs_class (gimple_assign_rhs_code (stmt))
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1051 == GIMPLE_BINARY_RHS))
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1052 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1053 tree op0 = gimple_assign_rhs1 (stmt);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1054 tree op1 = gimple_assign_rhs2 (stmt);
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1055 class loop *ol1 = outermost_invariant_loop (op1,
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1056 loop_containing_stmt (stmt));
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1057
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1058 /* If divisor is invariant, convert a/b to a*(1/b), allowing reciprocal
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1059 to be hoisted out of loop, saving expensive divide. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1060 if (pos == MOVE_POSSIBLE
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1061 && gimple_assign_rhs_code (stmt) == RDIV_EXPR
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1062 && flag_unsafe_math_optimizations
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1063 && !flag_trapping_math
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1064 && ol1 != NULL
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1065 && outermost_invariant_loop (op0, ol1) == NULL)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1066 stmt = rewrite_reciprocal (&bsi);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1067
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1068 /* If the shift count is invariant, convert (A >> B) & 1 to
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1069 A & (1 << B) allowing the bit mask to be hoisted out of the loop
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1070 saving an expensive shift. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1071 if (pos == MOVE_POSSIBLE
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1072 && gimple_assign_rhs_code (stmt) == BIT_AND_EXPR
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1073 && integer_onep (op1)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1074 && TREE_CODE (op0) == SSA_NAME
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1075 && has_single_use (op0))
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1076 stmt = rewrite_bittest (&bsi);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1077 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1078
111
kono
parents: 67
diff changeset
1079 lim_data = get_lim_data (stmt);
kono
parents: 67
diff changeset
1080 if (! lim_data)
kono
parents: 67
diff changeset
1081 lim_data = init_lim_data (stmt);
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1082 lim_data->always_executed_in = outermost;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1083
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1084 if (maybe_never && pos == MOVE_PRESERVE_EXECUTION)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1085 continue;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1086
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1087 if (!determine_max_movement (stmt, pos == MOVE_PRESERVE_EXECUTION))
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1088 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1089 lim_data->max_loop = NULL;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1090 continue;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1091 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1092
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1093 if (dump_file && (dump_flags & TDF_DETAILS))
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1094 {
111
kono
parents: 67
diff changeset
1095 print_gimple_stmt (dump_file, stmt, 2);
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1096 fprintf (dump_file, " invariant up to level %d, cost %d.\n\n",
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1097 loop_depth (lim_data->max_loop),
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1098 lim_data->cost);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1099 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1100
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1101 if (lim_data->cost >= LIM_EXPENSIVE)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1102 set_profitable_level (stmt);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1103 }
111
kono
parents: 67
diff changeset
1104 return NULL;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1105 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1106
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1107 /* Hoist the statements in basic block BB out of the loops prescribed by
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1108 data stored in LIM_DATA structures associated with each statement. Callback
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1109 for walk_dominator_tree. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1110
111
kono
parents: 67
diff changeset
1111 unsigned int
kono
parents: 67
diff changeset
1112 move_computations_worker (basic_block bb)
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1113 {
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1114 class loop *level;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1115 unsigned cost = 0;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1116 struct lim_aux_data *lim_data;
111
kono
parents: 67
diff changeset
1117 unsigned int todo = 0;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1118
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1119 if (!loop_outer (bb->loop_father))
111
kono
parents: 67
diff changeset
1120 return todo;
kono
parents: 67
diff changeset
1121
kono
parents: 67
diff changeset
1122 for (gphi_iterator bsi = gsi_start_phis (bb); !gsi_end_p (bsi); )
63
b7f97abdc517 update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
1123 {
111
kono
parents: 67
diff changeset
1124 gassign *new_stmt;
kono
parents: 67
diff changeset
1125 gphi *stmt = bsi.phi ();
63
b7f97abdc517 update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
1126
b7f97abdc517 update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
1127 lim_data = get_lim_data (stmt);
b7f97abdc517 update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
1128 if (lim_data == NULL)
b7f97abdc517 update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
1129 {
b7f97abdc517 update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
1130 gsi_next (&bsi);
b7f97abdc517 update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
1131 continue;
b7f97abdc517 update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
1132 }
b7f97abdc517 update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
1133
b7f97abdc517 update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
1134 cost = lim_data->cost;
b7f97abdc517 update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
1135 level = lim_data->tgt_loop;
b7f97abdc517 update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
1136 clear_lim_data (stmt);
b7f97abdc517 update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
1137
b7f97abdc517 update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
1138 if (!level)
b7f97abdc517 update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
1139 {
b7f97abdc517 update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
1140 gsi_next (&bsi);
b7f97abdc517 update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
1141 continue;
b7f97abdc517 update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
1142 }
b7f97abdc517 update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
1143
b7f97abdc517 update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
1144 if (dump_file && (dump_flags & TDF_DETAILS))
b7f97abdc517 update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
1145 {
b7f97abdc517 update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
1146 fprintf (dump_file, "Moving PHI node\n");
111
kono
parents: 67
diff changeset
1147 print_gimple_stmt (dump_file, stmt, 0);
63
b7f97abdc517 update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
1148 fprintf (dump_file, "(cost %u) out of loop %d.\n\n",
b7f97abdc517 update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
1149 cost, level->num);
b7f97abdc517 update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
1150 }
b7f97abdc517 update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
1151
b7f97abdc517 update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
1152 if (gimple_phi_num_args (stmt) == 1)
b7f97abdc517 update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
1153 {
b7f97abdc517 update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
1154 tree arg = PHI_ARG_DEF (stmt, 0);
111
kono
parents: 67
diff changeset
1155 new_stmt = gimple_build_assign (gimple_phi_result (stmt),
kono
parents: 67
diff changeset
1156 TREE_CODE (arg), arg);
63
b7f97abdc517 update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
1157 }
b7f97abdc517 update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
1158 else
b7f97abdc517 update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
1159 {
b7f97abdc517 update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
1160 basic_block dom = get_immediate_dominator (CDI_DOMINATORS, bb);
111
kono
parents: 67
diff changeset
1161 gimple *cond = gsi_stmt (gsi_last_bb (dom));
63
b7f97abdc517 update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
1162 tree arg0 = NULL_TREE, arg1 = NULL_TREE, t;
b7f97abdc517 update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
1163 /* Get the PHI arguments corresponding to the true and false
b7f97abdc517 update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
1164 edges of COND. */
b7f97abdc517 update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
1165 extract_true_false_args_from_phi (dom, stmt, &arg0, &arg1);
b7f97abdc517 update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
1166 gcc_assert (arg0 && arg1);
b7f97abdc517 update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
1167 t = build2 (gimple_cond_code (cond), boolean_type_node,
b7f97abdc517 update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
1168 gimple_cond_lhs (cond), gimple_cond_rhs (cond));
111
kono
parents: 67
diff changeset
1169 new_stmt = gimple_build_assign (gimple_phi_result (stmt),
kono
parents: 67
diff changeset
1170 COND_EXPR, t, arg0, arg1);
kono
parents: 67
diff changeset
1171 todo |= TODO_cleanup_cfg;
kono
parents: 67
diff changeset
1172 }
kono
parents: 67
diff changeset
1173 if (INTEGRAL_TYPE_P (TREE_TYPE (gimple_assign_lhs (new_stmt)))
kono
parents: 67
diff changeset
1174 && (!ALWAYS_EXECUTED_IN (bb)
kono
parents: 67
diff changeset
1175 || (ALWAYS_EXECUTED_IN (bb) != level
kono
parents: 67
diff changeset
1176 && !flow_loop_nested_p (ALWAYS_EXECUTED_IN (bb), level))))
kono
parents: 67
diff changeset
1177 {
kono
parents: 67
diff changeset
1178 tree lhs = gimple_assign_lhs (new_stmt);
kono
parents: 67
diff changeset
1179 SSA_NAME_RANGE_INFO (lhs) = NULL;
63
b7f97abdc517 update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
1180 }
b7f97abdc517 update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
1181 gsi_insert_on_edge (loop_preheader_edge (level), new_stmt);
b7f97abdc517 update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
1182 remove_phi_node (&bsi, false);
b7f97abdc517 update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
1183 }
b7f97abdc517 update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
1184
111
kono
parents: 67
diff changeset
1185 for (gimple_stmt_iterator bsi = gsi_start_bb (bb); !gsi_end_p (bsi); )
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1186 {
111
kono
parents: 67
diff changeset
1187 edge e;
kono
parents: 67
diff changeset
1188
kono
parents: 67
diff changeset
1189 gimple *stmt = gsi_stmt (bsi);
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1190
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1191 lim_data = get_lim_data (stmt);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1192 if (lim_data == NULL)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1193 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1194 gsi_next (&bsi);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1195 continue;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1196 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1197
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1198 cost = lim_data->cost;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1199 level = lim_data->tgt_loop;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1200 clear_lim_data (stmt);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1201
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1202 if (!level)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1203 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1204 gsi_next (&bsi);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1205 continue;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1206 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1207
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1208 /* We do not really want to move conditionals out of the loop; we just
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1209 placed it here to force its operands to be moved if necessary. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1210 if (gimple_code (stmt) == GIMPLE_COND)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1211 continue;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1212
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1213 if (dump_file && (dump_flags & TDF_DETAILS))
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1214 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1215 fprintf (dump_file, "Moving statement\n");
111
kono
parents: 67
diff changeset
1216 print_gimple_stmt (dump_file, stmt, 0);
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1217 fprintf (dump_file, "(cost %u) out of loop %d.\n\n",
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1218 cost, level->num);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1219 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1220
111
kono
parents: 67
diff changeset
1221 e = loop_preheader_edge (level);
kono
parents: 67
diff changeset
1222 gcc_assert (!gimple_vdef (stmt));
kono
parents: 67
diff changeset
1223 if (gimple_vuse (stmt))
kono
parents: 67
diff changeset
1224 {
kono
parents: 67
diff changeset
1225 /* The new VUSE is the one from the virtual PHI in the loop
kono
parents: 67
diff changeset
1226 header or the one already present. */
kono
parents: 67
diff changeset
1227 gphi_iterator gsi2;
kono
parents: 67
diff changeset
1228 for (gsi2 = gsi_start_phis (e->dest);
kono
parents: 67
diff changeset
1229 !gsi_end_p (gsi2); gsi_next (&gsi2))
kono
parents: 67
diff changeset
1230 {
kono
parents: 67
diff changeset
1231 gphi *phi = gsi2.phi ();
kono
parents: 67
diff changeset
1232 if (virtual_operand_p (gimple_phi_result (phi)))
kono
parents: 67
diff changeset
1233 {
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1234 SET_USE (gimple_vuse_op (stmt),
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1235 PHI_ARG_DEF_FROM_EDGE (phi, e));
111
kono
parents: 67
diff changeset
1236 break;
kono
parents: 67
diff changeset
1237 }
kono
parents: 67
diff changeset
1238 }
kono
parents: 67
diff changeset
1239 }
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1240 gsi_remove (&bsi, false);
111
kono
parents: 67
diff changeset
1241 if (gimple_has_lhs (stmt)
kono
parents: 67
diff changeset
1242 && TREE_CODE (gimple_get_lhs (stmt)) == SSA_NAME
kono
parents: 67
diff changeset
1243 && INTEGRAL_TYPE_P (TREE_TYPE (gimple_get_lhs (stmt)))
kono
parents: 67
diff changeset
1244 && (!ALWAYS_EXECUTED_IN (bb)
kono
parents: 67
diff changeset
1245 || !(ALWAYS_EXECUTED_IN (bb) == level
kono
parents: 67
diff changeset
1246 || flow_loop_nested_p (ALWAYS_EXECUTED_IN (bb), level))))
kono
parents: 67
diff changeset
1247 {
kono
parents: 67
diff changeset
1248 tree lhs = gimple_get_lhs (stmt);
kono
parents: 67
diff changeset
1249 SSA_NAME_RANGE_INFO (lhs) = NULL;
kono
parents: 67
diff changeset
1250 }
kono
parents: 67
diff changeset
1251 /* In case this is a stmt that is not unconditionally executed
kono
parents: 67
diff changeset
1252 when the target loop header is executed and the stmt may
kono
parents: 67
diff changeset
1253 invoke undefined integer or pointer overflow rewrite it to
kono
parents: 67
diff changeset
1254 unsigned arithmetic. */
kono
parents: 67
diff changeset
1255 if (is_gimple_assign (stmt)
kono
parents: 67
diff changeset
1256 && INTEGRAL_TYPE_P (TREE_TYPE (gimple_assign_lhs (stmt)))
kono
parents: 67
diff changeset
1257 && TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (gimple_assign_lhs (stmt)))
kono
parents: 67
diff changeset
1258 && arith_code_with_undefined_signed_overflow
kono
parents: 67
diff changeset
1259 (gimple_assign_rhs_code (stmt))
kono
parents: 67
diff changeset
1260 && (!ALWAYS_EXECUTED_IN (bb)
kono
parents: 67
diff changeset
1261 || !(ALWAYS_EXECUTED_IN (bb) == level
kono
parents: 67
diff changeset
1262 || flow_loop_nested_p (ALWAYS_EXECUTED_IN (bb), level))))
kono
parents: 67
diff changeset
1263 gsi_insert_seq_on_edge (e, rewrite_to_defined_overflow (stmt));
kono
parents: 67
diff changeset
1264 else
kono
parents: 67
diff changeset
1265 gsi_insert_on_edge (e, stmt);
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1266 }
111
kono
parents: 67
diff changeset
1267
kono
parents: 67
diff changeset
1268 return todo;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1269 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1270
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1271 /* Hoist the statements out of the loops prescribed by data stored in
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1272 LIM_DATA structures associated with each statement.*/
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1273
63
b7f97abdc517 update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
1274 static unsigned int
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1275 move_computations (void)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1276 {
111
kono
parents: 67
diff changeset
1277 int *rpo = XNEWVEC (int, last_basic_block_for_fn (cfun));
kono
parents: 67
diff changeset
1278 int n = pre_and_rev_post_order_compute_fn (cfun, NULL, rpo, false);
kono
parents: 67
diff changeset
1279 unsigned todo = 0;
kono
parents: 67
diff changeset
1280
kono
parents: 67
diff changeset
1281 for (int i = 0; i < n; ++i)
kono
parents: 67
diff changeset
1282 todo |= move_computations_worker (BASIC_BLOCK_FOR_FN (cfun, rpo[i]));
kono
parents: 67
diff changeset
1283
kono
parents: 67
diff changeset
1284 free (rpo);
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1285
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1286 gsi_commit_edge_inserts ();
55
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 47
diff changeset
1287 if (need_ssa_update_p (cfun))
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1288 rewrite_into_loop_closed_ssa (NULL, TODO_update_ssa);
63
b7f97abdc517 update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
1289
b7f97abdc517 update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
1290 return todo;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1291 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1292
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1293 /* Checks whether the statement defining variable *INDEX can be hoisted
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1294 out of the loop passed in DATA. Callback for for_each_index. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1295
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1296 static bool
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1297 may_move_till (tree ref, tree *index, void *data)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1298 {
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1299 class loop *loop = (class loop *) data, *max_loop;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1300
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1301 /* If REF is an array reference, check also that the step and the lower
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1302 bound is invariant in LOOP. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1303 if (TREE_CODE (ref) == ARRAY_REF)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1304 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1305 tree step = TREE_OPERAND (ref, 3);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1306 tree lbound = TREE_OPERAND (ref, 2);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1307
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1308 max_loop = outermost_invariant_loop (step, loop);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1309 if (!max_loop)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1310 return false;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1311
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1312 max_loop = outermost_invariant_loop (lbound, loop);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1313 if (!max_loop)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1314 return false;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1315 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1316
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1317 max_loop = outermost_invariant_loop (*index, loop);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1318 if (!max_loop)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1319 return false;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1320
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1321 return true;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1322 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1323
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1324 /* If OP is SSA NAME, force the statement that defines it to be
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1325 moved out of the LOOP. ORIG_LOOP is the loop in that EXPR is used. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1326
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1327 static void
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1328 force_move_till_op (tree op, class loop *orig_loop, class loop *loop)
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1329 {
111
kono
parents: 67
diff changeset
1330 gimple *stmt;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1331
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1332 if (!op
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1333 || is_gimple_min_invariant (op))
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1334 return;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1335
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1336 gcc_assert (TREE_CODE (op) == SSA_NAME);
55
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 47
diff changeset
1337
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1338 stmt = SSA_NAME_DEF_STMT (op);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1339 if (gimple_nop_p (stmt))
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1340 return;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1341
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1342 set_level (stmt, orig_loop, loop);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1343 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1344
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1345 /* Forces statement defining invariants in REF (and *INDEX) to be moved out of
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1346 the LOOP. The reference REF is used in the loop ORIG_LOOP. Callback for
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1347 for_each_index. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1348
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1349 struct fmt_data
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1350 {
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1351 class loop *loop;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1352 class loop *orig_loop;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1353 };
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1354
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1355 static bool
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1356 force_move_till (tree ref, tree *index, void *data)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1357 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1358 struct fmt_data *fmt_data = (struct fmt_data *) data;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1359
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1360 if (TREE_CODE (ref) == ARRAY_REF)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1361 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1362 tree step = TREE_OPERAND (ref, 3);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1363 tree lbound = TREE_OPERAND (ref, 2);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1364
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1365 force_move_till_op (step, fmt_data->orig_loop, fmt_data->loop);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1366 force_move_till_op (lbound, fmt_data->orig_loop, fmt_data->loop);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1367 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1368
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1369 force_move_till_op (*index, fmt_data->orig_loop, fmt_data->loop);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1370
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1371 return true;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1372 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1373
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1374 /* A function to free the mem_ref object OBJ. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1375
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1376 static void
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1377 memref_free (class im_mem_ref *mem)
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1378 {
111
kono
parents: 67
diff changeset
1379 mem->accesses_in_loop.release ();
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1380 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1381
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1382 /* Allocates and returns a memory reference description for MEM whose hash
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1383 value is HASH and id is ID. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1384
111
kono
parents: 67
diff changeset
1385 static im_mem_ref *
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1386 mem_ref_alloc (ao_ref *mem, unsigned hash, unsigned id)
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1387 {
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1388 im_mem_ref *ref = XOBNEW (&mem_ref_obstack, class im_mem_ref);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1389 if (mem)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1390 ref->mem = *mem;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1391 else
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1392 ao_ref_init (&ref->mem, error_mark_node);
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1393 ref->id = id;
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1394 ref->ref_canonical = false;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1395 ref->ref_decomposed = false;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1396 ref->hash = hash;
111
kono
parents: 67
diff changeset
1397 ref->stored = NULL;
kono
parents: 67
diff changeset
1398 bitmap_initialize (&ref->indep_loop, &lim_bitmap_obstack);
kono
parents: 67
diff changeset
1399 bitmap_initialize (&ref->dep_loop, &lim_bitmap_obstack);
kono
parents: 67
diff changeset
1400 ref->accesses_in_loop.create (1);
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1401
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1402 return ref;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1403 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1404
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1405 /* Records memory reference location *LOC in LOOP to the memory reference
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1406 description REF. The reference occurs in statement STMT. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1407
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1408 static void
111
kono
parents: 67
diff changeset
1409 record_mem_ref_loc (im_mem_ref *ref, gimple *stmt, tree *loc)
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1410 {
111
kono
parents: 67
diff changeset
1411 mem_ref_loc aref;
kono
parents: 67
diff changeset
1412 aref.stmt = stmt;
kono
parents: 67
diff changeset
1413 aref.ref = loc;
kono
parents: 67
diff changeset
1414 ref->accesses_in_loop.safe_push (aref);
kono
parents: 67
diff changeset
1415 }
kono
parents: 67
diff changeset
1416
kono
parents: 67
diff changeset
1417 /* Set the LOOP bit in REF stored bitmap and allocate that if
kono
parents: 67
diff changeset
1418 necessary. Return whether a bit was changed. */
kono
parents: 67
diff changeset
1419
kono
parents: 67
diff changeset
1420 static bool
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1421 set_ref_stored_in_loop (im_mem_ref *ref, class loop *loop)
111
kono
parents: 67
diff changeset
1422 {
kono
parents: 67
diff changeset
1423 if (!ref->stored)
kono
parents: 67
diff changeset
1424 ref->stored = BITMAP_ALLOC (&lim_bitmap_obstack);
kono
parents: 67
diff changeset
1425 return bitmap_set_bit (ref->stored, loop->num);
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1426 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1427
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1428 /* Marks reference REF as stored in LOOP. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1429
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1430 static void
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1431 mark_ref_stored (im_mem_ref *ref, class loop *loop)
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1432 {
111
kono
parents: 67
diff changeset
1433 while (loop != current_loops->tree_root
kono
parents: 67
diff changeset
1434 && set_ref_stored_in_loop (ref, loop))
kono
parents: 67
diff changeset
1435 loop = loop_outer (loop);
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1436 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1437
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1438 /* Gathers memory references in statement STMT in LOOP, storing the
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1439 information about them in the memory_accesses structure. Marks
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1440 the vops accessed through unrecognized statements there as
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1441 well. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1442
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1443 static void
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1444 gather_mem_refs_stmt (class loop *loop, gimple *stmt)
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1445 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1446 tree *mem = NULL;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1447 hashval_t hash;
111
kono
parents: 67
diff changeset
1448 im_mem_ref **slot;
kono
parents: 67
diff changeset
1449 im_mem_ref *ref;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1450 bool is_stored;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1451 unsigned id;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1452
55
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 47
diff changeset
1453 if (!gimple_vuse (stmt))
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1454 return;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1455
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1456 mem = simple_mem_ref_in_stmt (stmt, &is_stored);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1457 if (!mem)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1458 {
111
kono
parents: 67
diff changeset
1459 /* We use the shared mem_ref for all unanalyzable refs. */
kono
parents: 67
diff changeset
1460 id = UNANALYZABLE_MEM_ID;
kono
parents: 67
diff changeset
1461 ref = memory_accesses.refs_list[id];
kono
parents: 67
diff changeset
1462 if (dump_file && (dump_flags & TDF_DETAILS))
kono
parents: 67
diff changeset
1463 {
kono
parents: 67
diff changeset
1464 fprintf (dump_file, "Unanalyzed memory reference %u: ", id);
kono
parents: 67
diff changeset
1465 print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM);
kono
parents: 67
diff changeset
1466 }
kono
parents: 67
diff changeset
1467 is_stored = gimple_vdef (stmt);
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1468 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1469 else
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1470 {
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1471 /* We are looking for equal refs that might differ in structure
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1472 such as a.b vs. MEM[&a + 4]. So we key off the ao_ref but
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1473 make sure we can canonicalize the ref in the hashtable if
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1474 non-operand_equal_p refs are found. For the lookup we mark
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1475 the case we want strict equality with aor.max_size == -1. */
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1476 ao_ref aor;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1477 ao_ref_init (&aor, *mem);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1478 ao_ref_base (&aor);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1479 ao_ref_alias_set (&aor);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1480 HOST_WIDE_INT offset, size, max_size;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1481 poly_int64 saved_maxsize = aor.max_size, mem_off;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1482 tree mem_base;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1483 bool ref_decomposed;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1484 if (aor.max_size_known_p ()
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1485 && aor.offset.is_constant (&offset)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1486 && aor.size.is_constant (&size)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1487 && aor.max_size.is_constant (&max_size)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1488 && size == max_size
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1489 && (size % BITS_PER_UNIT) == 0
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1490 /* We're canonicalizing to a MEM where TYPE_SIZE specifies the
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1491 size. Make sure this is consistent with the extraction. */
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1492 && poly_int_tree_p (TYPE_SIZE (TREE_TYPE (*mem)))
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1493 && known_eq (wi::to_poly_offset (TYPE_SIZE (TREE_TYPE (*mem))),
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1494 aor.size)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1495 && (mem_base = get_addr_base_and_unit_offset (aor.ref, &mem_off)))
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1496 {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1497 ref_decomposed = true;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1498 hash = iterative_hash_expr (ao_ref_base (&aor), 0);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1499 hash = iterative_hash_host_wide_int (offset, hash);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1500 hash = iterative_hash_host_wide_int (size, hash);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1501 }
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1502 else
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1503 {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1504 ref_decomposed = false;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1505 hash = iterative_hash_expr (aor.ref, 0);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1506 aor.max_size = -1;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1507 }
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1508 slot = memory_accesses.refs->find_slot_with_hash (&aor, hash, INSERT);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1509 aor.max_size = saved_maxsize;
111
kono
parents: 67
diff changeset
1510 if (*slot)
kono
parents: 67
diff changeset
1511 {
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1512 if (!(*slot)->ref_canonical
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1513 && !operand_equal_p (*mem, (*slot)->mem.ref, 0))
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1514 {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1515 /* If we didn't yet canonicalize the hashtable ref (which
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1516 we'll end up using for code insertion) and hit a second
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1517 equal ref that is not structurally equivalent create
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1518 a canonical ref which is a bare MEM_REF. */
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1519 if (TREE_CODE (*mem) == MEM_REF
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1520 || TREE_CODE (*mem) == TARGET_MEM_REF)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1521 {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1522 (*slot)->mem.ref = *mem;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1523 (*slot)->mem.base_alias_set = ao_ref_base_alias_set (&aor);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1524 }
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1525 else
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1526 {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1527 tree ref_alias_type = reference_alias_ptr_type (*mem);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1528 unsigned int ref_align = get_object_alignment (*mem);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1529 tree ref_type = TREE_TYPE (*mem);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1530 tree tmp = build_fold_addr_expr (unshare_expr (mem_base));
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1531 if (TYPE_ALIGN (ref_type) != ref_align)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1532 ref_type = build_aligned_type (ref_type, ref_align);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1533 (*slot)->mem.ref
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1534 = fold_build2 (MEM_REF, ref_type, tmp,
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1535 build_int_cst (ref_alias_type, mem_off));
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1536 if ((*slot)->mem.volatile_p)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1537 TREE_THIS_VOLATILE ((*slot)->mem.ref) = 1;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1538 gcc_checking_assert (TREE_CODE ((*slot)->mem.ref) == MEM_REF
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1539 && is_gimple_mem_ref_addr
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1540 (TREE_OPERAND ((*slot)->mem.ref,
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1541 0)));
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1542 (*slot)->mem.base_alias_set = (*slot)->mem.ref_alias_set;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1543 }
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1544 (*slot)->ref_canonical = true;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1545 }
111
kono
parents: 67
diff changeset
1546 ref = *slot;
kono
parents: 67
diff changeset
1547 id = ref->id;
kono
parents: 67
diff changeset
1548 }
kono
parents: 67
diff changeset
1549 else
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1550 {
111
kono
parents: 67
diff changeset
1551 id = memory_accesses.refs_list.length ();
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1552 ref = mem_ref_alloc (&aor, hash, id);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1553 ref->ref_decomposed = ref_decomposed;
111
kono
parents: 67
diff changeset
1554 memory_accesses.refs_list.safe_push (ref);
kono
parents: 67
diff changeset
1555 *slot = ref;
kono
parents: 67
diff changeset
1556
kono
parents: 67
diff changeset
1557 if (dump_file && (dump_flags & TDF_DETAILS))
kono
parents: 67
diff changeset
1558 {
kono
parents: 67
diff changeset
1559 fprintf (dump_file, "Memory reference %u: ", id);
kono
parents: 67
diff changeset
1560 print_generic_expr (dump_file, ref->mem.ref, TDF_SLIM);
kono
parents: 67
diff changeset
1561 fprintf (dump_file, "\n");
kono
parents: 67
diff changeset
1562 }
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1563 }
111
kono
parents: 67
diff changeset
1564
kono
parents: 67
diff changeset
1565 record_mem_ref_loc (ref, stmt, mem);
kono
parents: 67
diff changeset
1566 }
kono
parents: 67
diff changeset
1567 bitmap_set_bit (&memory_accesses.refs_in_loop[loop->num], ref->id);
kono
parents: 67
diff changeset
1568 if (is_stored)
kono
parents: 67
diff changeset
1569 {
kono
parents: 67
diff changeset
1570 bitmap_set_bit (&memory_accesses.refs_stored_in_loop[loop->num], ref->id);
kono
parents: 67
diff changeset
1571 mark_ref_stored (ref, loop);
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1572 }
111
kono
parents: 67
diff changeset
1573 init_lim_data (stmt)->ref = ref->id;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1574 return;
111
kono
parents: 67
diff changeset
1575 }
kono
parents: 67
diff changeset
1576
kono
parents: 67
diff changeset
1577 static unsigned *bb_loop_postorder;
kono
parents: 67
diff changeset
1578
kono
parents: 67
diff changeset
1579 /* qsort sort function to sort blocks after their loop fathers postorder. */
kono
parents: 67
diff changeset
1580
kono
parents: 67
diff changeset
1581 static int
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1582 sort_bbs_in_loop_postorder_cmp (const void *bb1_, const void *bb2_,
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1583 void *bb_loop_postorder_)
111
kono
parents: 67
diff changeset
1584 {
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1585 unsigned *bb_loop_postorder = (unsigned *)bb_loop_postorder_;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1586 basic_block bb1 = *(const basic_block *)bb1_;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1587 basic_block bb2 = *(const basic_block *)bb2_;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1588 class loop *loop1 = bb1->loop_father;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1589 class loop *loop2 = bb2->loop_father;
111
kono
parents: 67
diff changeset
1590 if (loop1->num == loop2->num)
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1591 return bb1->index - bb2->index;
111
kono
parents: 67
diff changeset
1592 return bb_loop_postorder[loop1->num] < bb_loop_postorder[loop2->num] ? -1 : 1;
kono
parents: 67
diff changeset
1593 }
kono
parents: 67
diff changeset
1594
kono
parents: 67
diff changeset
1595 /* qsort sort function to sort ref locs after their loop fathers postorder. */
kono
parents: 67
diff changeset
1596
kono
parents: 67
diff changeset
1597 static int
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1598 sort_locs_in_loop_postorder_cmp (const void *loc1_, const void *loc2_,
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1599 void *bb_loop_postorder_)
111
kono
parents: 67
diff changeset
1600 {
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1601 unsigned *bb_loop_postorder = (unsigned *)bb_loop_postorder_;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1602 const mem_ref_loc *loc1 = (const mem_ref_loc *)loc1_;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1603 const mem_ref_loc *loc2 = (const mem_ref_loc *)loc2_;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1604 class loop *loop1 = gimple_bb (loc1->stmt)->loop_father;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1605 class loop *loop2 = gimple_bb (loc2->stmt)->loop_father;
111
kono
parents: 67
diff changeset
1606 if (loop1->num == loop2->num)
kono
parents: 67
diff changeset
1607 return 0;
kono
parents: 67
diff changeset
1608 return bb_loop_postorder[loop1->num] < bb_loop_postorder[loop2->num] ? -1 : 1;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1609 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1610
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1611 /* Gathers memory references in loops. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1612
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1613 static void
111
kono
parents: 67
diff changeset
1614 analyze_memory_references (void)
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1615 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1616 gimple_stmt_iterator bsi;
111
kono
parents: 67
diff changeset
1617 basic_block bb, *bbs;
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1618 class loop *loop, *outer;
111
kono
parents: 67
diff changeset
1619 unsigned i, n;
kono
parents: 67
diff changeset
1620
kono
parents: 67
diff changeset
1621 /* Collect all basic-blocks in loops and sort them after their
kono
parents: 67
diff changeset
1622 loops postorder. */
kono
parents: 67
diff changeset
1623 i = 0;
kono
parents: 67
diff changeset
1624 bbs = XNEWVEC (basic_block, n_basic_blocks_for_fn (cfun) - NUM_FIXED_BLOCKS);
kono
parents: 67
diff changeset
1625 FOR_EACH_BB_FN (bb, cfun)
kono
parents: 67
diff changeset
1626 if (bb->loop_father != current_loops->tree_root)
kono
parents: 67
diff changeset
1627 bbs[i++] = bb;
kono
parents: 67
diff changeset
1628 n = i;
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1629 gcc_sort_r (bbs, n, sizeof (basic_block), sort_bbs_in_loop_postorder_cmp,
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1630 bb_loop_postorder);
111
kono
parents: 67
diff changeset
1631
kono
parents: 67
diff changeset
1632 /* Visit blocks in loop postorder and assign mem-ref IDs in that order.
kono
parents: 67
diff changeset
1633 That results in better locality for all the bitmaps. */
kono
parents: 67
diff changeset
1634 for (i = 0; i < n; ++i)
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1635 {
111
kono
parents: 67
diff changeset
1636 basic_block bb = bbs[i];
kono
parents: 67
diff changeset
1637 for (bsi = gsi_start_bb (bb); !gsi_end_p (bsi); gsi_next (&bsi))
kono
parents: 67
diff changeset
1638 gather_mem_refs_stmt (bb->loop_father, gsi_stmt (bsi));
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1639 }
111
kono
parents: 67
diff changeset
1640
kono
parents: 67
diff changeset
1641 /* Sort the location list of gathered memory references after their
kono
parents: 67
diff changeset
1642 loop postorder number. */
kono
parents: 67
diff changeset
1643 im_mem_ref *ref;
kono
parents: 67
diff changeset
1644 FOR_EACH_VEC_ELT (memory_accesses.refs_list, i, ref)
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1645 ref->accesses_in_loop.sort (sort_locs_in_loop_postorder_cmp,
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1646 bb_loop_postorder);
111
kono
parents: 67
diff changeset
1647
kono
parents: 67
diff changeset
1648 free (bbs);
kono
parents: 67
diff changeset
1649
kono
parents: 67
diff changeset
1650 /* Propagate the information about accessed memory references up
kono
parents: 67
diff changeset
1651 the loop hierarchy. */
kono
parents: 67
diff changeset
1652 FOR_EACH_LOOP (loop, LI_FROM_INNERMOST)
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1653 {
111
kono
parents: 67
diff changeset
1654 /* Finalize the overall touched references (including subloops). */
kono
parents: 67
diff changeset
1655 bitmap_ior_into (&memory_accesses.all_refs_stored_in_loop[loop->num],
kono
parents: 67
diff changeset
1656 &memory_accesses.refs_stored_in_loop[loop->num]);
kono
parents: 67
diff changeset
1657
kono
parents: 67
diff changeset
1658 /* Propagate the information about accessed memory references up
kono
parents: 67
diff changeset
1659 the loop hierarchy. */
kono
parents: 67
diff changeset
1660 outer = loop_outer (loop);
kono
parents: 67
diff changeset
1661 if (outer == current_loops->tree_root)
kono
parents: 67
diff changeset
1662 continue;
kono
parents: 67
diff changeset
1663
kono
parents: 67
diff changeset
1664 bitmap_ior_into (&memory_accesses.all_refs_stored_in_loop[outer->num],
kono
parents: 67
diff changeset
1665 &memory_accesses.all_refs_stored_in_loop[loop->num]);
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1666 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1667 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1668
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1669 /* Returns true if MEM1 and MEM2 may alias. TTAE_CACHE is used as a cache in
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1670 tree_to_aff_combination_expand. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1671
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1672 static bool
111
kono
parents: 67
diff changeset
1673 mem_refs_may_alias_p (im_mem_ref *mem1, im_mem_ref *mem2,
kono
parents: 67
diff changeset
1674 hash_map<tree, name_expansion *> **ttae_cache)
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1675 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1676 /* Perform BASE + OFFSET analysis -- if MEM1 and MEM2 are based on the same
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1677 object and their offset differ in such a way that the locations cannot
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1678 overlap, then they cannot alias. */
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1679 poly_widest_int size1, size2;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1680 aff_tree off1, off2;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1681
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1682 /* Perform basic offset and type-based disambiguation. */
111
kono
parents: 67
diff changeset
1683 if (!refs_may_alias_p_1 (&mem1->mem, &mem2->mem, true))
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1684 return false;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1685
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1686 /* The expansion of addresses may be a bit expensive, thus we only do
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1687 the check at -O2 and higher optimization levels. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1688 if (optimize < 2)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1689 return true;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1690
111
kono
parents: 67
diff changeset
1691 get_inner_reference_aff (mem1->mem.ref, &off1, &size1);
kono
parents: 67
diff changeset
1692 get_inner_reference_aff (mem2->mem.ref, &off2, &size2);
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1693 aff_combination_expand (&off1, ttae_cache);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1694 aff_combination_expand (&off2, ttae_cache);
111
kono
parents: 67
diff changeset
1695 aff_combination_scale (&off1, -1);
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1696 aff_combination_add (&off2, &off1);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1697
111
kono
parents: 67
diff changeset
1698 if (aff_comb_cannot_overlap_p (&off2, size1, size2))
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1699 return false;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1700
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1701 return true;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1702 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1703
111
kono
parents: 67
diff changeset
1704 /* Compare function for bsearch searching for reference locations
kono
parents: 67
diff changeset
1705 in a loop. */
kono
parents: 67
diff changeset
1706
kono
parents: 67
diff changeset
1707 static int
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1708 find_ref_loc_in_loop_cmp (const void *loop_, const void *loc_,
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1709 void *bb_loop_postorder_)
111
kono
parents: 67
diff changeset
1710 {
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1711 unsigned *bb_loop_postorder = (unsigned *)bb_loop_postorder_;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1712 class loop *loop = (class loop *)const_cast<void *>(loop_);
111
kono
parents: 67
diff changeset
1713 mem_ref_loc *loc = (mem_ref_loc *)const_cast<void *>(loc_);
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1714 class loop *loc_loop = gimple_bb (loc->stmt)->loop_father;
111
kono
parents: 67
diff changeset
1715 if (loop->num == loc_loop->num
kono
parents: 67
diff changeset
1716 || flow_loop_nested_p (loop, loc_loop))
kono
parents: 67
diff changeset
1717 return 0;
kono
parents: 67
diff changeset
1718 return (bb_loop_postorder[loop->num] < bb_loop_postorder[loc_loop->num]
kono
parents: 67
diff changeset
1719 ? -1 : 1);
kono
parents: 67
diff changeset
1720 }
kono
parents: 67
diff changeset
1721
kono
parents: 67
diff changeset
1722 /* Iterates over all locations of REF in LOOP and its subloops calling
kono
parents: 67
diff changeset
1723 fn.operator() with the location as argument. When that operator
kono
parents: 67
diff changeset
1724 returns true the iteration is stopped and true is returned.
kono
parents: 67
diff changeset
1725 Otherwise false is returned. */
kono
parents: 67
diff changeset
1726
kono
parents: 67
diff changeset
1727 template <typename FN>
kono
parents: 67
diff changeset
1728 static bool
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1729 for_all_locs_in_loop (class loop *loop, im_mem_ref *ref, FN fn)
111
kono
parents: 67
diff changeset
1730 {
kono
parents: 67
diff changeset
1731 unsigned i;
kono
parents: 67
diff changeset
1732 mem_ref_loc *loc;
kono
parents: 67
diff changeset
1733
kono
parents: 67
diff changeset
1734 /* Search for the cluster of locs in the accesses_in_loop vector
kono
parents: 67
diff changeset
1735 which is sorted after postorder index of the loop father. */
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1736 loc = ref->accesses_in_loop.bsearch (loop, find_ref_loc_in_loop_cmp,
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1737 bb_loop_postorder);
111
kono
parents: 67
diff changeset
1738 if (!loc)
kono
parents: 67
diff changeset
1739 return false;
kono
parents: 67
diff changeset
1740
kono
parents: 67
diff changeset
1741 /* We have found one location inside loop or its sub-loops. Iterate
kono
parents: 67
diff changeset
1742 both forward and backward to cover the whole cluster. */
kono
parents: 67
diff changeset
1743 i = loc - ref->accesses_in_loop.address ();
kono
parents: 67
diff changeset
1744 while (i > 0)
kono
parents: 67
diff changeset
1745 {
kono
parents: 67
diff changeset
1746 --i;
kono
parents: 67
diff changeset
1747 mem_ref_loc *l = &ref->accesses_in_loop[i];
kono
parents: 67
diff changeset
1748 if (!flow_bb_inside_loop_p (loop, gimple_bb (l->stmt)))
kono
parents: 67
diff changeset
1749 break;
kono
parents: 67
diff changeset
1750 if (fn (l))
kono
parents: 67
diff changeset
1751 return true;
kono
parents: 67
diff changeset
1752 }
kono
parents: 67
diff changeset
1753 for (i = loc - ref->accesses_in_loop.address ();
kono
parents: 67
diff changeset
1754 i < ref->accesses_in_loop.length (); ++i)
kono
parents: 67
diff changeset
1755 {
kono
parents: 67
diff changeset
1756 mem_ref_loc *l = &ref->accesses_in_loop[i];
kono
parents: 67
diff changeset
1757 if (!flow_bb_inside_loop_p (loop, gimple_bb (l->stmt)))
kono
parents: 67
diff changeset
1758 break;
kono
parents: 67
diff changeset
1759 if (fn (l))
kono
parents: 67
diff changeset
1760 return true;
kono
parents: 67
diff changeset
1761 }
kono
parents: 67
diff changeset
1762
kono
parents: 67
diff changeset
1763 return false;
kono
parents: 67
diff changeset
1764 }
kono
parents: 67
diff changeset
1765
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1766 /* Rewrites location LOC by TMP_VAR. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1767
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1768 class rewrite_mem_ref_loc
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1769 {
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1770 public:
111
kono
parents: 67
diff changeset
1771 rewrite_mem_ref_loc (tree tmp_var_) : tmp_var (tmp_var_) {}
kono
parents: 67
diff changeset
1772 bool operator () (mem_ref_loc *loc);
kono
parents: 67
diff changeset
1773 tree tmp_var;
kono
parents: 67
diff changeset
1774 };
kono
parents: 67
diff changeset
1775
kono
parents: 67
diff changeset
1776 bool
kono
parents: 67
diff changeset
1777 rewrite_mem_ref_loc::operator () (mem_ref_loc *loc)
kono
parents: 67
diff changeset
1778 {
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1779 *loc->ref = tmp_var;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1780 update_stmt (loc->stmt);
111
kono
parents: 67
diff changeset
1781 return false;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1782 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1783
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1784 /* Rewrites all references to REF in LOOP by variable TMP_VAR. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1785
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1786 static void
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1787 rewrite_mem_refs (class loop *loop, im_mem_ref *ref, tree tmp_var)
111
kono
parents: 67
diff changeset
1788 {
kono
parents: 67
diff changeset
1789 for_all_locs_in_loop (loop, ref, rewrite_mem_ref_loc (tmp_var));
kono
parents: 67
diff changeset
1790 }
kono
parents: 67
diff changeset
1791
kono
parents: 67
diff changeset
1792 /* Stores the first reference location in LOCP. */
kono
parents: 67
diff changeset
1793
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1794 class first_mem_ref_loc_1
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1795 {
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1796 public:
111
kono
parents: 67
diff changeset
1797 first_mem_ref_loc_1 (mem_ref_loc **locp_) : locp (locp_) {}
kono
parents: 67
diff changeset
1798 bool operator () (mem_ref_loc *loc);
kono
parents: 67
diff changeset
1799 mem_ref_loc **locp;
kono
parents: 67
diff changeset
1800 };
kono
parents: 67
diff changeset
1801
kono
parents: 67
diff changeset
1802 bool
kono
parents: 67
diff changeset
1803 first_mem_ref_loc_1::operator () (mem_ref_loc *loc)
kono
parents: 67
diff changeset
1804 {
kono
parents: 67
diff changeset
1805 *locp = loc;
kono
parents: 67
diff changeset
1806 return true;
kono
parents: 67
diff changeset
1807 }
kono
parents: 67
diff changeset
1808
kono
parents: 67
diff changeset
1809 /* Returns the first reference location to REF in LOOP. */
kono
parents: 67
diff changeset
1810
kono
parents: 67
diff changeset
1811 static mem_ref_loc *
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1812 first_mem_ref_loc (class loop *loop, im_mem_ref *ref)
111
kono
parents: 67
diff changeset
1813 {
kono
parents: 67
diff changeset
1814 mem_ref_loc *locp = NULL;
kono
parents: 67
diff changeset
1815 for_all_locs_in_loop (loop, ref, first_mem_ref_loc_1 (&locp));
kono
parents: 67
diff changeset
1816 return locp;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1817 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1818
111
kono
parents: 67
diff changeset
1819 struct prev_flag_edges {
kono
parents: 67
diff changeset
1820 /* Edge to insert new flag comparison code. */
kono
parents: 67
diff changeset
1821 edge append_cond_position;
kono
parents: 67
diff changeset
1822
kono
parents: 67
diff changeset
1823 /* Edge for fall through from previous flag comparison. */
kono
parents: 67
diff changeset
1824 edge last_cond_fallthru;
kono
parents: 67
diff changeset
1825 };
kono
parents: 67
diff changeset
1826
kono
parents: 67
diff changeset
1827 /* Helper function for execute_sm. Emit code to store TMP_VAR into
kono
parents: 67
diff changeset
1828 MEM along edge EX.
kono
parents: 67
diff changeset
1829
kono
parents: 67
diff changeset
1830 The store is only done if MEM has changed. We do this so no
kono
parents: 67
diff changeset
1831 changes to MEM occur on code paths that did not originally store
kono
parents: 67
diff changeset
1832 into it.
kono
parents: 67
diff changeset
1833
kono
parents: 67
diff changeset
1834 The common case for execute_sm will transform:
kono
parents: 67
diff changeset
1835
kono
parents: 67
diff changeset
1836 for (...) {
kono
parents: 67
diff changeset
1837 if (foo)
kono
parents: 67
diff changeset
1838 stuff;
kono
parents: 67
diff changeset
1839 else
kono
parents: 67
diff changeset
1840 MEM = TMP_VAR;
kono
parents: 67
diff changeset
1841 }
kono
parents: 67
diff changeset
1842
kono
parents: 67
diff changeset
1843 into:
kono
parents: 67
diff changeset
1844
kono
parents: 67
diff changeset
1845 lsm = MEM;
kono
parents: 67
diff changeset
1846 for (...) {
kono
parents: 67
diff changeset
1847 if (foo)
kono
parents: 67
diff changeset
1848 stuff;
kono
parents: 67
diff changeset
1849 else
kono
parents: 67
diff changeset
1850 lsm = TMP_VAR;
kono
parents: 67
diff changeset
1851 }
kono
parents: 67
diff changeset
1852 MEM = lsm;
kono
parents: 67
diff changeset
1853
kono
parents: 67
diff changeset
1854 This function will generate:
kono
parents: 67
diff changeset
1855
kono
parents: 67
diff changeset
1856 lsm = MEM;
kono
parents: 67
diff changeset
1857
kono
parents: 67
diff changeset
1858 lsm_flag = false;
kono
parents: 67
diff changeset
1859 ...
kono
parents: 67
diff changeset
1860 for (...) {
kono
parents: 67
diff changeset
1861 if (foo)
kono
parents: 67
diff changeset
1862 stuff;
kono
parents: 67
diff changeset
1863 else {
kono
parents: 67
diff changeset
1864 lsm = TMP_VAR;
kono
parents: 67
diff changeset
1865 lsm_flag = true;
kono
parents: 67
diff changeset
1866 }
kono
parents: 67
diff changeset
1867 }
kono
parents: 67
diff changeset
1868 if (lsm_flag) <--
kono
parents: 67
diff changeset
1869 MEM = lsm; <--
kono
parents: 67
diff changeset
1870 */
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1871
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1872 static void
111
kono
parents: 67
diff changeset
1873 execute_sm_if_changed (edge ex, tree mem, tree tmp_var, tree flag,
kono
parents: 67
diff changeset
1874 edge preheader, hash_set <basic_block> *flag_bbs)
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1875 {
111
kono
parents: 67
diff changeset
1876 basic_block new_bb, then_bb, old_dest;
kono
parents: 67
diff changeset
1877 bool loop_has_only_one_exit;
kono
parents: 67
diff changeset
1878 edge then_old_edge, orig_ex = ex;
kono
parents: 67
diff changeset
1879 gimple_stmt_iterator gsi;
kono
parents: 67
diff changeset
1880 gimple *stmt;
kono
parents: 67
diff changeset
1881 struct prev_flag_edges *prev_edges = (struct prev_flag_edges *) ex->aux;
kono
parents: 67
diff changeset
1882 bool irr = ex->flags & EDGE_IRREDUCIBLE_LOOP;
kono
parents: 67
diff changeset
1883
kono
parents: 67
diff changeset
1884 profile_count count_sum = profile_count::zero ();
kono
parents: 67
diff changeset
1885 int nbbs = 0, ncount = 0;
kono
parents: 67
diff changeset
1886 profile_probability flag_probability = profile_probability::uninitialized ();
kono
parents: 67
diff changeset
1887
kono
parents: 67
diff changeset
1888 /* Flag is set in FLAG_BBS. Determine probability that flag will be true
kono
parents: 67
diff changeset
1889 at loop exit.
kono
parents: 67
diff changeset
1890
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1891 This code may look fancy, but it cannot update profile very realistically
111
kono
parents: 67
diff changeset
1892 because we do not know the probability that flag will be true at given
kono
parents: 67
diff changeset
1893 loop exit.
kono
parents: 67
diff changeset
1894
kono
parents: 67
diff changeset
1895 We look for two interesting extremes
kono
parents: 67
diff changeset
1896 - when exit is dominated by block setting the flag, we know it will
kono
parents: 67
diff changeset
1897 always be true. This is a common case.
kono
parents: 67
diff changeset
1898 - when all blocks setting the flag have very low frequency we know
kono
parents: 67
diff changeset
1899 it will likely be false.
kono
parents: 67
diff changeset
1900 In all other cases we default to 2/3 for flag being true. */
kono
parents: 67
diff changeset
1901
kono
parents: 67
diff changeset
1902 for (hash_set<basic_block>::iterator it = flag_bbs->begin ();
kono
parents: 67
diff changeset
1903 it != flag_bbs->end (); ++it)
kono
parents: 67
diff changeset
1904 {
kono
parents: 67
diff changeset
1905 if ((*it)->count.initialized_p ())
kono
parents: 67
diff changeset
1906 count_sum += (*it)->count, ncount ++;
kono
parents: 67
diff changeset
1907 if (dominated_by_p (CDI_DOMINATORS, ex->src, *it))
kono
parents: 67
diff changeset
1908 flag_probability = profile_probability::always ();
kono
parents: 67
diff changeset
1909 nbbs++;
kono
parents: 67
diff changeset
1910 }
kono
parents: 67
diff changeset
1911
kono
parents: 67
diff changeset
1912 profile_probability cap = profile_probability::always ().apply_scale (2, 3);
kono
parents: 67
diff changeset
1913
kono
parents: 67
diff changeset
1914 if (flag_probability.initialized_p ())
kono
parents: 67
diff changeset
1915 ;
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1916 else if (ncount == nbbs
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1917 && preheader->count () >= count_sum && preheader->count ().nonzero_p ())
111
kono
parents: 67
diff changeset
1918 {
kono
parents: 67
diff changeset
1919 flag_probability = count_sum.probability_in (preheader->count ());
kono
parents: 67
diff changeset
1920 if (flag_probability > cap)
kono
parents: 67
diff changeset
1921 flag_probability = cap;
kono
parents: 67
diff changeset
1922 }
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1923
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1924 if (!flag_probability.initialized_p ())
111
kono
parents: 67
diff changeset
1925 flag_probability = cap;
kono
parents: 67
diff changeset
1926
kono
parents: 67
diff changeset
1927 /* ?? Insert store after previous store if applicable. See note
kono
parents: 67
diff changeset
1928 below. */
kono
parents: 67
diff changeset
1929 if (prev_edges)
kono
parents: 67
diff changeset
1930 ex = prev_edges->append_cond_position;
kono
parents: 67
diff changeset
1931
kono
parents: 67
diff changeset
1932 loop_has_only_one_exit = single_pred_p (ex->dest);
kono
parents: 67
diff changeset
1933
kono
parents: 67
diff changeset
1934 if (loop_has_only_one_exit)
kono
parents: 67
diff changeset
1935 ex = split_block_after_labels (ex->dest);
kono
parents: 67
diff changeset
1936 else
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1937 {
111
kono
parents: 67
diff changeset
1938 for (gphi_iterator gpi = gsi_start_phis (ex->dest);
kono
parents: 67
diff changeset
1939 !gsi_end_p (gpi); gsi_next (&gpi))
kono
parents: 67
diff changeset
1940 {
kono
parents: 67
diff changeset
1941 gphi *phi = gpi.phi ();
kono
parents: 67
diff changeset
1942 if (virtual_operand_p (gimple_phi_result (phi)))
kono
parents: 67
diff changeset
1943 continue;
kono
parents: 67
diff changeset
1944
kono
parents: 67
diff changeset
1945 /* When the destination has a non-virtual PHI node with multiple
kono
parents: 67
diff changeset
1946 predecessors make sure we preserve the PHI structure by
kono
parents: 67
diff changeset
1947 forcing a forwarder block so that hoisting of that PHI will
kono
parents: 67
diff changeset
1948 still work. */
kono
parents: 67
diff changeset
1949 split_edge (ex);
kono
parents: 67
diff changeset
1950 break;
kono
parents: 67
diff changeset
1951 }
kono
parents: 67
diff changeset
1952 }
kono
parents: 67
diff changeset
1953
kono
parents: 67
diff changeset
1954 old_dest = ex->dest;
kono
parents: 67
diff changeset
1955 new_bb = split_edge (ex);
kono
parents: 67
diff changeset
1956 then_bb = create_empty_bb (new_bb);
kono
parents: 67
diff changeset
1957 then_bb->count = new_bb->count.apply_probability (flag_probability);
kono
parents: 67
diff changeset
1958 if (irr)
kono
parents: 67
diff changeset
1959 then_bb->flags = BB_IRREDUCIBLE_LOOP;
kono
parents: 67
diff changeset
1960 add_bb_to_loop (then_bb, new_bb->loop_father);
kono
parents: 67
diff changeset
1961
kono
parents: 67
diff changeset
1962 gsi = gsi_start_bb (new_bb);
kono
parents: 67
diff changeset
1963 stmt = gimple_build_cond (NE_EXPR, flag, boolean_false_node,
kono
parents: 67
diff changeset
1964 NULL_TREE, NULL_TREE);
kono
parents: 67
diff changeset
1965 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
kono
parents: 67
diff changeset
1966
kono
parents: 67
diff changeset
1967 gsi = gsi_start_bb (then_bb);
kono
parents: 67
diff changeset
1968 /* Insert actual store. */
kono
parents: 67
diff changeset
1969 stmt = gimple_build_assign (unshare_expr (mem), tmp_var);
kono
parents: 67
diff changeset
1970 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
kono
parents: 67
diff changeset
1971
kono
parents: 67
diff changeset
1972 edge e1 = single_succ_edge (new_bb);
kono
parents: 67
diff changeset
1973 edge e2 = make_edge (new_bb, then_bb,
kono
parents: 67
diff changeset
1974 EDGE_TRUE_VALUE | (irr ? EDGE_IRREDUCIBLE_LOOP : 0));
kono
parents: 67
diff changeset
1975 e2->probability = flag_probability;
kono
parents: 67
diff changeset
1976
kono
parents: 67
diff changeset
1977 e1->flags |= EDGE_FALSE_VALUE | (irr ? EDGE_IRREDUCIBLE_LOOP : 0);
kono
parents: 67
diff changeset
1978 e1->flags &= ~EDGE_FALLTHRU;
kono
parents: 67
diff changeset
1979
kono
parents: 67
diff changeset
1980 e1->probability = flag_probability.invert ();
kono
parents: 67
diff changeset
1981
kono
parents: 67
diff changeset
1982 then_old_edge = make_single_succ_edge (then_bb, old_dest,
kono
parents: 67
diff changeset
1983 EDGE_FALLTHRU | (irr ? EDGE_IRREDUCIBLE_LOOP : 0));
kono
parents: 67
diff changeset
1984
kono
parents: 67
diff changeset
1985 set_immediate_dominator (CDI_DOMINATORS, then_bb, new_bb);
kono
parents: 67
diff changeset
1986
kono
parents: 67
diff changeset
1987 if (prev_edges)
kono
parents: 67
diff changeset
1988 {
kono
parents: 67
diff changeset
1989 basic_block prevbb = prev_edges->last_cond_fallthru->src;
kono
parents: 67
diff changeset
1990 redirect_edge_succ (prev_edges->last_cond_fallthru, new_bb);
kono
parents: 67
diff changeset
1991 set_immediate_dominator (CDI_DOMINATORS, new_bb, prevbb);
kono
parents: 67
diff changeset
1992 set_immediate_dominator (CDI_DOMINATORS, old_dest,
kono
parents: 67
diff changeset
1993 recompute_dominator (CDI_DOMINATORS, old_dest));
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1994 }
111
kono
parents: 67
diff changeset
1995
kono
parents: 67
diff changeset
1996 /* ?? Because stores may alias, they must happen in the exact
kono
parents: 67
diff changeset
1997 sequence they originally happened. Save the position right after
kono
parents: 67
diff changeset
1998 the (_lsm) store we just created so we can continue appending after
kono
parents: 67
diff changeset
1999 it and maintain the original order. */
kono
parents: 67
diff changeset
2000 {
kono
parents: 67
diff changeset
2001 struct prev_flag_edges *p;
kono
parents: 67
diff changeset
2002
kono
parents: 67
diff changeset
2003 if (orig_ex->aux)
kono
parents: 67
diff changeset
2004 orig_ex->aux = NULL;
kono
parents: 67
diff changeset
2005 alloc_aux_for_edge (orig_ex, sizeof (struct prev_flag_edges));
kono
parents: 67
diff changeset
2006 p = (struct prev_flag_edges *) orig_ex->aux;
kono
parents: 67
diff changeset
2007 p->append_cond_position = then_old_edge;
kono
parents: 67
diff changeset
2008 p->last_cond_fallthru = find_edge (new_bb, old_dest);
kono
parents: 67
diff changeset
2009 orig_ex->aux = (void *) p;
kono
parents: 67
diff changeset
2010 }
kono
parents: 67
diff changeset
2011
kono
parents: 67
diff changeset
2012 if (!loop_has_only_one_exit)
kono
parents: 67
diff changeset
2013 for (gphi_iterator gpi = gsi_start_phis (old_dest);
kono
parents: 67
diff changeset
2014 !gsi_end_p (gpi); gsi_next (&gpi))
kono
parents: 67
diff changeset
2015 {
kono
parents: 67
diff changeset
2016 gphi *phi = gpi.phi ();
kono
parents: 67
diff changeset
2017 unsigned i;
kono
parents: 67
diff changeset
2018
kono
parents: 67
diff changeset
2019 for (i = 0; i < gimple_phi_num_args (phi); i++)
kono
parents: 67
diff changeset
2020 if (gimple_phi_arg_edge (phi, i)->src == new_bb)
kono
parents: 67
diff changeset
2021 {
kono
parents: 67
diff changeset
2022 tree arg = gimple_phi_arg_def (phi, i);
kono
parents: 67
diff changeset
2023 add_phi_arg (phi, arg, then_old_edge, UNKNOWN_LOCATION);
kono
parents: 67
diff changeset
2024 update_stmt (phi);
kono
parents: 67
diff changeset
2025 }
kono
parents: 67
diff changeset
2026 }
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2027 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2028
111
kono
parents: 67
diff changeset
2029 /* When REF is set on the location, set flag indicating the store. */
kono
parents: 67
diff changeset
2030
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2031 class sm_set_flag_if_changed
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2032 {
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2033 public:
111
kono
parents: 67
diff changeset
2034 sm_set_flag_if_changed (tree flag_, hash_set <basic_block> *bbs_)
kono
parents: 67
diff changeset
2035 : flag (flag_), bbs (bbs_) {}
kono
parents: 67
diff changeset
2036 bool operator () (mem_ref_loc *loc);
kono
parents: 67
diff changeset
2037 tree flag;
kono
parents: 67
diff changeset
2038 hash_set <basic_block> *bbs;
kono
parents: 67
diff changeset
2039 };
kono
parents: 67
diff changeset
2040
kono
parents: 67
diff changeset
2041 bool
kono
parents: 67
diff changeset
2042 sm_set_flag_if_changed::operator () (mem_ref_loc *loc)
kono
parents: 67
diff changeset
2043 {
kono
parents: 67
diff changeset
2044 /* Only set the flag for writes. */
kono
parents: 67
diff changeset
2045 if (is_gimple_assign (loc->stmt)
kono
parents: 67
diff changeset
2046 && gimple_assign_lhs_ptr (loc->stmt) == loc->ref)
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2047 {
111
kono
parents: 67
diff changeset
2048 gimple_stmt_iterator gsi = gsi_for_stmt (loc->stmt);
kono
parents: 67
diff changeset
2049 gimple *stmt = gimple_build_assign (flag, boolean_true_node);
kono
parents: 67
diff changeset
2050 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
kono
parents: 67
diff changeset
2051 bbs->add (gimple_bb (stmt));
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2052 }
111
kono
parents: 67
diff changeset
2053 return false;
kono
parents: 67
diff changeset
2054 }
kono
parents: 67
diff changeset
2055
kono
parents: 67
diff changeset
2056 /* Helper function for execute_sm. On every location where REF is
kono
parents: 67
diff changeset
2057 set, set an appropriate flag indicating the store. */
kono
parents: 67
diff changeset
2058
kono
parents: 67
diff changeset
2059 static tree
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2060 execute_sm_if_changed_flag_set (class loop *loop, im_mem_ref *ref,
111
kono
parents: 67
diff changeset
2061 hash_set <basic_block> *bbs)
kono
parents: 67
diff changeset
2062 {
kono
parents: 67
diff changeset
2063 tree flag;
kono
parents: 67
diff changeset
2064 char *str = get_lsm_tmp_name (ref->mem.ref, ~0, "_flag");
kono
parents: 67
diff changeset
2065 flag = create_tmp_reg (boolean_type_node, str);
kono
parents: 67
diff changeset
2066 for_all_locs_in_loop (loop, ref, sm_set_flag_if_changed (flag, bbs));
kono
parents: 67
diff changeset
2067 return flag;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2068 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2069
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2070 /* Executes store motion of memory reference REF from LOOP.
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2071 Exits from the LOOP are stored in EXITS. The initialization of the
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2072 temporary variable is put to the preheader of the loop, and assignments
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2073 to the reference from the temporary variable are emitted to exits. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2074
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2075 static void
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2076 execute_sm (class loop *loop, vec<edge> exits, im_mem_ref *ref)
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2077 {
111
kono
parents: 67
diff changeset
2078 tree tmp_var, store_flag = NULL_TREE;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2079 unsigned i;
111
kono
parents: 67
diff changeset
2080 gassign *load;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2081 struct fmt_data fmt_data;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2082 edge ex;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2083 struct lim_aux_data *lim_data;
111
kono
parents: 67
diff changeset
2084 bool multi_threaded_model_p = false;
kono
parents: 67
diff changeset
2085 gimple_stmt_iterator gsi;
kono
parents: 67
diff changeset
2086 hash_set<basic_block> flag_bbs;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2087
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2088 if (dump_file && (dump_flags & TDF_DETAILS))
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2089 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2090 fprintf (dump_file, "Executing store motion of ");
111
kono
parents: 67
diff changeset
2091 print_generic_expr (dump_file, ref->mem.ref);
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2092 fprintf (dump_file, " from loop %d\n", loop->num);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2093 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2094
111
kono
parents: 67
diff changeset
2095 tmp_var = create_tmp_reg (TREE_TYPE (ref->mem.ref),
kono
parents: 67
diff changeset
2096 get_lsm_tmp_name (ref->mem.ref, ~0));
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2097
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2098 fmt_data.loop = loop;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2099 fmt_data.orig_loop = loop;
111
kono
parents: 67
diff changeset
2100 for_each_index (&ref->mem.ref, force_move_till, &fmt_data);
kono
parents: 67
diff changeset
2101
kono
parents: 67
diff changeset
2102 if (bb_in_transaction (loop_preheader_edge (loop)->src)
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2103 || (! flag_store_data_races
111
kono
parents: 67
diff changeset
2104 && ! ref_always_accessed_p (loop, ref, true)))
kono
parents: 67
diff changeset
2105 multi_threaded_model_p = true;
kono
parents: 67
diff changeset
2106
kono
parents: 67
diff changeset
2107 if (multi_threaded_model_p)
kono
parents: 67
diff changeset
2108 store_flag = execute_sm_if_changed_flag_set (loop, ref, &flag_bbs);
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2109
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2110 rewrite_mem_refs (loop, ref, tmp_var);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2111
111
kono
parents: 67
diff changeset
2112 /* Emit the load code on a random exit edge or into the latch if
kono
parents: 67
diff changeset
2113 the loop does not exit, so that we are sure it will be processed
kono
parents: 67
diff changeset
2114 by move_computations after all dependencies. */
kono
parents: 67
diff changeset
2115 gsi = gsi_for_stmt (first_mem_ref_loc (loop, ref)->stmt);
kono
parents: 67
diff changeset
2116
kono
parents: 67
diff changeset
2117 /* FIXME/TODO: For the multi-threaded variant, we could avoid this
kono
parents: 67
diff changeset
2118 load altogether, since the store is predicated by a flag. We
kono
parents: 67
diff changeset
2119 could, do the load only if it was originally in the loop. */
kono
parents: 67
diff changeset
2120 load = gimple_build_assign (tmp_var, unshare_expr (ref->mem.ref));
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2121 lim_data = init_lim_data (load);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2122 lim_data->max_loop = loop;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2123 lim_data->tgt_loop = loop;
111
kono
parents: 67
diff changeset
2124 gsi_insert_before (&gsi, load, GSI_SAME_STMT);
kono
parents: 67
diff changeset
2125
kono
parents: 67
diff changeset
2126 if (multi_threaded_model_p)
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2127 {
111
kono
parents: 67
diff changeset
2128 load = gimple_build_assign (store_flag, boolean_false_node);
kono
parents: 67
diff changeset
2129 lim_data = init_lim_data (load);
kono
parents: 67
diff changeset
2130 lim_data->max_loop = loop;
kono
parents: 67
diff changeset
2131 lim_data->tgt_loop = loop;
kono
parents: 67
diff changeset
2132 gsi_insert_before (&gsi, load, GSI_SAME_STMT);
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2133 }
111
kono
parents: 67
diff changeset
2134
kono
parents: 67
diff changeset
2135 /* Sink the store to every exit from the loop. */
kono
parents: 67
diff changeset
2136 FOR_EACH_VEC_ELT (exits, i, ex)
kono
parents: 67
diff changeset
2137 if (!multi_threaded_model_p)
kono
parents: 67
diff changeset
2138 {
kono
parents: 67
diff changeset
2139 gassign *store;
kono
parents: 67
diff changeset
2140 store = gimple_build_assign (unshare_expr (ref->mem.ref), tmp_var);
kono
parents: 67
diff changeset
2141 gsi_insert_on_edge (ex, store);
kono
parents: 67
diff changeset
2142 }
kono
parents: 67
diff changeset
2143 else
kono
parents: 67
diff changeset
2144 execute_sm_if_changed (ex, ref->mem.ref, tmp_var, store_flag,
kono
parents: 67
diff changeset
2145 loop_preheader_edge (loop), &flag_bbs);
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2146 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2147
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2148 /* Hoists memory references MEM_REFS out of LOOP. EXITS is the list of exit
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2149 edges of the LOOP. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2150
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2151 static void
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2152 hoist_memory_references (class loop *loop, bitmap mem_refs,
111
kono
parents: 67
diff changeset
2153 vec<edge> exits)
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2154 {
111
kono
parents: 67
diff changeset
2155 im_mem_ref *ref;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2156 unsigned i;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2157 bitmap_iterator bi;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2158
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2159 EXECUTE_IF_SET_IN_BITMAP (mem_refs, 0, i, bi)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2160 {
111
kono
parents: 67
diff changeset
2161 ref = memory_accesses.refs_list[i];
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2162 execute_sm (loop, exits, ref);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2163 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2164 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2165
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2166 class ref_always_accessed
111
kono
parents: 67
diff changeset
2167 {
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2168 public:
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2169 ref_always_accessed (class loop *loop_, bool stored_p_)
111
kono
parents: 67
diff changeset
2170 : loop (loop_), stored_p (stored_p_) {}
kono
parents: 67
diff changeset
2171 bool operator () (mem_ref_loc *loc);
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2172 class loop *loop;
111
kono
parents: 67
diff changeset
2173 bool stored_p;
kono
parents: 67
diff changeset
2174 };
kono
parents: 67
diff changeset
2175
kono
parents: 67
diff changeset
2176 bool
kono
parents: 67
diff changeset
2177 ref_always_accessed::operator () (mem_ref_loc *loc)
kono
parents: 67
diff changeset
2178 {
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2179 class loop *must_exec;
111
kono
parents: 67
diff changeset
2180
kono
parents: 67
diff changeset
2181 if (!get_lim_data (loc->stmt))
kono
parents: 67
diff changeset
2182 return false;
kono
parents: 67
diff changeset
2183
kono
parents: 67
diff changeset
2184 /* If we require an always executed store make sure the statement
kono
parents: 67
diff changeset
2185 stores to the reference. */
kono
parents: 67
diff changeset
2186 if (stored_p)
kono
parents: 67
diff changeset
2187 {
kono
parents: 67
diff changeset
2188 tree lhs = gimple_get_lhs (loc->stmt);
kono
parents: 67
diff changeset
2189 if (!lhs
kono
parents: 67
diff changeset
2190 || lhs != *loc->ref)
kono
parents: 67
diff changeset
2191 return false;
kono
parents: 67
diff changeset
2192 }
kono
parents: 67
diff changeset
2193
kono
parents: 67
diff changeset
2194 must_exec = get_lim_data (loc->stmt)->always_executed_in;
kono
parents: 67
diff changeset
2195 if (!must_exec)
kono
parents: 67
diff changeset
2196 return false;
kono
parents: 67
diff changeset
2197
kono
parents: 67
diff changeset
2198 if (must_exec == loop
kono
parents: 67
diff changeset
2199 || flow_loop_nested_p (must_exec, loop))
kono
parents: 67
diff changeset
2200 return true;
kono
parents: 67
diff changeset
2201
kono
parents: 67
diff changeset
2202 return false;
kono
parents: 67
diff changeset
2203 }
kono
parents: 67
diff changeset
2204
63
b7f97abdc517 update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
2205 /* Returns true if REF is always accessed in LOOP. If STORED_P is true
b7f97abdc517 update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
2206 make sure REF is always stored to in LOOP. */
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2207
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2208 static bool
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2209 ref_always_accessed_p (class loop *loop, im_mem_ref *ref, bool stored_p)
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2210 {
111
kono
parents: 67
diff changeset
2211 return for_all_locs_in_loop (loop, ref,
kono
parents: 67
diff changeset
2212 ref_always_accessed (loop, stored_p));
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2213 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2214
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2215 /* Returns true if REF1 and REF2 are independent. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2216
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2217 static bool
111
kono
parents: 67
diff changeset
2218 refs_independent_p (im_mem_ref *ref1, im_mem_ref *ref2)
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2219 {
111
kono
parents: 67
diff changeset
2220 if (ref1 == ref2)
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2221 return true;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2222
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2223 if (dump_file && (dump_flags & TDF_DETAILS))
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2224 fprintf (dump_file, "Querying dependency of refs %u and %u: ",
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2225 ref1->id, ref2->id);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2226
111
kono
parents: 67
diff changeset
2227 if (mem_refs_may_alias_p (ref1, ref2, &memory_accesses.ttae_cache))
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2228 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2229 if (dump_file && (dump_flags & TDF_DETAILS))
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2230 fprintf (dump_file, "dependent.\n");
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2231 return false;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2232 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2233 else
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2234 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2235 if (dump_file && (dump_flags & TDF_DETAILS))
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2236 fprintf (dump_file, "independent.\n");
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2237 return true;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2238 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2239 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2240
111
kono
parents: 67
diff changeset
2241 /* Mark REF dependent on stores or loads (according to STORED_P) in LOOP
kono
parents: 67
diff changeset
2242 and its super-loops. */
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2243
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2244 static void
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2245 record_dep_loop (class loop *loop, im_mem_ref *ref, bool stored_p)
111
kono
parents: 67
diff changeset
2246 {
kono
parents: 67
diff changeset
2247 /* We can propagate dependent-in-loop bits up the loop
kono
parents: 67
diff changeset
2248 hierarchy to all outer loops. */
kono
parents: 67
diff changeset
2249 while (loop != current_loops->tree_root
kono
parents: 67
diff changeset
2250 && bitmap_set_bit (&ref->dep_loop, LOOP_DEP_BIT (loop->num, stored_p)))
kono
parents: 67
diff changeset
2251 loop = loop_outer (loop);
kono
parents: 67
diff changeset
2252 }
kono
parents: 67
diff changeset
2253
kono
parents: 67
diff changeset
2254 /* Returns true if REF is independent on all other memory
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2255 references in LOOP. */
111
kono
parents: 67
diff changeset
2256
kono
parents: 67
diff changeset
2257 static bool
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2258 ref_indep_loop_p_1 (class loop *loop, im_mem_ref *ref, bool stored_p)
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2259 {
111
kono
parents: 67
diff changeset
2260 stored_p |= (ref->stored && bitmap_bit_p (ref->stored, loop->num));
kono
parents: 67
diff changeset
2261
kono
parents: 67
diff changeset
2262 bool indep_p = true;
kono
parents: 67
diff changeset
2263 bitmap refs_to_check;
kono
parents: 67
diff changeset
2264
kono
parents: 67
diff changeset
2265 if (stored_p)
kono
parents: 67
diff changeset
2266 refs_to_check = &memory_accesses.refs_in_loop[loop->num];
kono
parents: 67
diff changeset
2267 else
kono
parents: 67
diff changeset
2268 refs_to_check = &memory_accesses.refs_stored_in_loop[loop->num];
kono
parents: 67
diff changeset
2269
kono
parents: 67
diff changeset
2270 if (bitmap_bit_p (refs_to_check, UNANALYZABLE_MEM_ID))
kono
parents: 67
diff changeset
2271 indep_p = false;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2272 else
111
kono
parents: 67
diff changeset
2273 {
kono
parents: 67
diff changeset
2274 if (bitmap_bit_p (&ref->indep_loop, LOOP_DEP_BIT (loop->num, stored_p)))
kono
parents: 67
diff changeset
2275 return true;
kono
parents: 67
diff changeset
2276 if (bitmap_bit_p (&ref->dep_loop, LOOP_DEP_BIT (loop->num, stored_p)))
kono
parents: 67
diff changeset
2277 return false;
kono
parents: 67
diff changeset
2278
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2279 class loop *inner = loop->inner;
111
kono
parents: 67
diff changeset
2280 while (inner)
kono
parents: 67
diff changeset
2281 {
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2282 if (!ref_indep_loop_p_1 (inner, ref, stored_p))
111
kono
parents: 67
diff changeset
2283 {
kono
parents: 67
diff changeset
2284 indep_p = false;
kono
parents: 67
diff changeset
2285 break;
kono
parents: 67
diff changeset
2286 }
kono
parents: 67
diff changeset
2287 inner = inner->next;
kono
parents: 67
diff changeset
2288 }
kono
parents: 67
diff changeset
2289
kono
parents: 67
diff changeset
2290 if (indep_p)
kono
parents: 67
diff changeset
2291 {
kono
parents: 67
diff changeset
2292 unsigned i;
kono
parents: 67
diff changeset
2293 bitmap_iterator bi;
kono
parents: 67
diff changeset
2294 EXECUTE_IF_SET_IN_BITMAP (refs_to_check, 0, i, bi)
kono
parents: 67
diff changeset
2295 {
kono
parents: 67
diff changeset
2296 im_mem_ref *aref = memory_accesses.refs_list[i];
kono
parents: 67
diff changeset
2297 if (!refs_independent_p (ref, aref))
kono
parents: 67
diff changeset
2298 {
kono
parents: 67
diff changeset
2299 indep_p = false;
kono
parents: 67
diff changeset
2300 break;
kono
parents: 67
diff changeset
2301 }
kono
parents: 67
diff changeset
2302 }
kono
parents: 67
diff changeset
2303 }
kono
parents: 67
diff changeset
2304 }
kono
parents: 67
diff changeset
2305
kono
parents: 67
diff changeset
2306 if (dump_file && (dump_flags & TDF_DETAILS))
kono
parents: 67
diff changeset
2307 fprintf (dump_file, "Querying dependencies of ref %u in loop %d: %s\n",
kono
parents: 67
diff changeset
2308 ref->id, loop->num, indep_p ? "independent" : "dependent");
kono
parents: 67
diff changeset
2309
kono
parents: 67
diff changeset
2310 /* Record the computed result in the cache. */
kono
parents: 67
diff changeset
2311 if (indep_p)
kono
parents: 67
diff changeset
2312 {
kono
parents: 67
diff changeset
2313 if (bitmap_set_bit (&ref->indep_loop, LOOP_DEP_BIT (loop->num, stored_p))
kono
parents: 67
diff changeset
2314 && stored_p)
kono
parents: 67
diff changeset
2315 {
kono
parents: 67
diff changeset
2316 /* If it's independend against all refs then it's independent
kono
parents: 67
diff changeset
2317 against stores, too. */
kono
parents: 67
diff changeset
2318 bitmap_set_bit (&ref->indep_loop, LOOP_DEP_BIT (loop->num, false));
kono
parents: 67
diff changeset
2319 }
kono
parents: 67
diff changeset
2320 }
kono
parents: 67
diff changeset
2321 else
kono
parents: 67
diff changeset
2322 {
kono
parents: 67
diff changeset
2323 record_dep_loop (loop, ref, stored_p);
kono
parents: 67
diff changeset
2324 if (!stored_p)
kono
parents: 67
diff changeset
2325 {
kono
parents: 67
diff changeset
2326 /* If it's dependent against stores it's dependent against
kono
parents: 67
diff changeset
2327 all refs, too. */
kono
parents: 67
diff changeset
2328 record_dep_loop (loop, ref, true);
kono
parents: 67
diff changeset
2329 }
kono
parents: 67
diff changeset
2330 }
kono
parents: 67
diff changeset
2331
kono
parents: 67
diff changeset
2332 return indep_p;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2333 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2334
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2335 /* Returns true if REF is independent on all other memory references in
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2336 LOOP. */
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2337
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2338 static bool
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2339 ref_indep_loop_p (class loop *loop, im_mem_ref *ref)
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2340 {
111
kono
parents: 67
diff changeset
2341 gcc_checking_assert (MEM_ANALYZABLE (ref));
kono
parents: 67
diff changeset
2342
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2343 return ref_indep_loop_p_1 (loop, ref, false);
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2344 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2345
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2346 /* Returns true if we can perform store motion of REF from LOOP. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2347
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2348 static bool
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2349 can_sm_ref_p (class loop *loop, im_mem_ref *ref)
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2350 {
63
b7f97abdc517 update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
2351 tree base;
b7f97abdc517 update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
2352
111
kono
parents: 67
diff changeset
2353 /* Can't hoist unanalyzable refs. */
kono
parents: 67
diff changeset
2354 if (!MEM_ANALYZABLE (ref))
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2355 return false;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2356
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2357 /* It should be movable. */
111
kono
parents: 67
diff changeset
2358 if (!is_gimple_reg_type (TREE_TYPE (ref->mem.ref))
kono
parents: 67
diff changeset
2359 || TREE_THIS_VOLATILE (ref->mem.ref)
kono
parents: 67
diff changeset
2360 || !for_each_index (&ref->mem.ref, may_move_till, loop))
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2361 return false;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2362
67
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 63
diff changeset
2363 /* If it can throw fail, we do not properly update EH info. */
111
kono
parents: 67
diff changeset
2364 if (tree_could_throw_p (ref->mem.ref))
67
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 63
diff changeset
2365 return false;
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 63
diff changeset
2366
63
b7f97abdc517 update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
2367 /* If it can trap, it must be always executed in LOOP.
b7f97abdc517 update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
2368 Readonly memory locations may trap when storing to them, but
b7f97abdc517 update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
2369 tree_could_trap_p is a predicate for rvalues, so check that
b7f97abdc517 update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
2370 explicitly. */
111
kono
parents: 67
diff changeset
2371 base = get_base_address (ref->mem.ref);
kono
parents: 67
diff changeset
2372 if ((tree_could_trap_p (ref->mem.ref)
63
b7f97abdc517 update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
2373 || (DECL_P (base) && TREE_READONLY (base)))
b7f97abdc517 update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
2374 && !ref_always_accessed_p (loop, ref, true))
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2375 return false;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2376
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2377 /* And it must be independent on all other memory references
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2378 in LOOP. */
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2379 if (!ref_indep_loop_p (loop, ref))
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2380 return false;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2381
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2382 return true;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2383 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2384
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2385 /* Marks the references in LOOP for that store motion should be performed
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2386 in REFS_TO_SM. SM_EXECUTED is the set of references for that store
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2387 motion was performed in one of the outer loops. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2388
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2389 static void
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2390 find_refs_for_sm (class loop *loop, bitmap sm_executed, bitmap refs_to_sm)
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2391 {
111
kono
parents: 67
diff changeset
2392 bitmap refs = &memory_accesses.all_refs_stored_in_loop[loop->num];
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2393 unsigned i;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2394 bitmap_iterator bi;
111
kono
parents: 67
diff changeset
2395 im_mem_ref *ref;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2396
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2397 EXECUTE_IF_AND_COMPL_IN_BITMAP (refs, sm_executed, 0, i, bi)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2398 {
111
kono
parents: 67
diff changeset
2399 ref = memory_accesses.refs_list[i];
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2400 if (can_sm_ref_p (loop, ref))
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2401 bitmap_set_bit (refs_to_sm, i);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2402 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2403 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2404
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2405 /* Checks whether LOOP (with exits stored in EXITS array) is suitable
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2406 for a store motion optimization (i.e. whether we can insert statement
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2407 on its exits). */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2408
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2409 static bool
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2410 loop_suitable_for_sm (class loop *loop ATTRIBUTE_UNUSED,
111
kono
parents: 67
diff changeset
2411 vec<edge> exits)
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2412 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2413 unsigned i;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2414 edge ex;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2415
111
kono
parents: 67
diff changeset
2416 FOR_EACH_VEC_ELT (exits, i, ex)
67
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 63
diff changeset
2417 if (ex->flags & (EDGE_ABNORMAL | EDGE_EH))
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2418 return false;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2419
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2420 return true;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2421 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2422
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2423 /* Try to perform store motion for all memory references modified inside
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2424 LOOP. SM_EXECUTED is the bitmap of the memory references for that
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2425 store motion was executed in one of the outer loops. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2426
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2427 static void
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2428 store_motion_loop (class loop *loop, bitmap sm_executed)
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2429 {
111
kono
parents: 67
diff changeset
2430 vec<edge> exits = get_loop_exit_edges (loop);
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2431 class loop *subloop;
111
kono
parents: 67
diff changeset
2432 bitmap sm_in_loop = BITMAP_ALLOC (&lim_bitmap_obstack);
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2433
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2434 if (loop_suitable_for_sm (loop, exits))
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2435 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2436 find_refs_for_sm (loop, sm_executed, sm_in_loop);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2437 hoist_memory_references (loop, sm_in_loop, exits);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2438 }
111
kono
parents: 67
diff changeset
2439 exits.release ();
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2440
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2441 bitmap_ior_into (sm_executed, sm_in_loop);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2442 for (subloop = loop->inner; subloop != NULL; subloop = subloop->next)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2443 store_motion_loop (subloop, sm_executed);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2444 bitmap_and_compl_into (sm_executed, sm_in_loop);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2445 BITMAP_FREE (sm_in_loop);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2446 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2447
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2448 /* Try to perform store motion for all memory references modified inside
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2449 loops. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2450
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2451 static void
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2452 store_motion (void)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2453 {
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2454 class loop *loop;
111
kono
parents: 67
diff changeset
2455 bitmap sm_executed = BITMAP_ALLOC (&lim_bitmap_obstack);
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2456
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2457 for (loop = current_loops->tree_root->inner; loop != NULL; loop = loop->next)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2458 store_motion_loop (loop, sm_executed);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2459
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2460 BITMAP_FREE (sm_executed);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2461 gsi_commit_edge_inserts ();
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2462 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2463
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2464 /* Fills ALWAYS_EXECUTED_IN information for basic blocks of LOOP, i.e.
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2465 for each such basic block bb records the outermost loop for that execution
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2466 of its header implies execution of bb. CONTAINS_CALL is the bitmap of
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2467 blocks that contain a nonpure call. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2468
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2469 static void
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2470 fill_always_executed_in_1 (class loop *loop, sbitmap contains_call)
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2471 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2472 basic_block bb = NULL, *bbs, last = NULL;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2473 unsigned i;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2474 edge e;
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2475 class loop *inn_loop = loop;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2476
111
kono
parents: 67
diff changeset
2477 if (ALWAYS_EXECUTED_IN (loop->header) == NULL)
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2478 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2479 bbs = get_loop_body_in_dom_order (loop);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2480
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2481 for (i = 0; i < loop->num_nodes; i++)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2482 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2483 edge_iterator ei;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2484 bb = bbs[i];
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2485
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2486 if (dominated_by_p (CDI_DOMINATORS, loop->latch, bb))
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2487 last = bb;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2488
111
kono
parents: 67
diff changeset
2489 if (bitmap_bit_p (contains_call, bb->index))
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2490 break;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2491
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2492 FOR_EACH_EDGE (e, ei, bb->succs)
111
kono
parents: 67
diff changeset
2493 {
kono
parents: 67
diff changeset
2494 /* If there is an exit from this BB. */
kono
parents: 67
diff changeset
2495 if (!flow_bb_inside_loop_p (loop, e->dest))
kono
parents: 67
diff changeset
2496 break;
kono
parents: 67
diff changeset
2497 /* Or we enter a possibly non-finite loop. */
kono
parents: 67
diff changeset
2498 if (flow_loop_nested_p (bb->loop_father,
kono
parents: 67
diff changeset
2499 e->dest->loop_father)
kono
parents: 67
diff changeset
2500 && ! finite_loop_p (e->dest->loop_father))
kono
parents: 67
diff changeset
2501 break;
kono
parents: 67
diff changeset
2502 }
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2503 if (e)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2504 break;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2505
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2506 /* A loop might be infinite (TODO use simple loop analysis
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2507 to disprove this if possible). */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2508 if (bb->flags & BB_IRREDUCIBLE_LOOP)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2509 break;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2510
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2511 if (!flow_bb_inside_loop_p (inn_loop, bb))
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2512 break;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2513
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2514 if (bb->loop_father->header == bb)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2515 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2516 if (!dominated_by_p (CDI_DOMINATORS, loop->latch, bb))
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2517 break;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2518
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2519 /* In a loop that is always entered we may proceed anyway.
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2520 But record that we entered it and stop once we leave it. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2521 inn_loop = bb->loop_father;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2522 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2523 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2524
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2525 while (1)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2526 {
111
kono
parents: 67
diff changeset
2527 SET_ALWAYS_EXECUTED_IN (last, loop);
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2528 if (last == loop->header)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2529 break;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2530 last = get_immediate_dominator (CDI_DOMINATORS, last);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2531 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2532
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2533 free (bbs);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2534 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2535
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2536 for (loop = loop->inner; loop; loop = loop->next)
111
kono
parents: 67
diff changeset
2537 fill_always_executed_in_1 (loop, contains_call);
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2538 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2539
111
kono
parents: 67
diff changeset
2540 /* Fills ALWAYS_EXECUTED_IN information for basic blocks, i.e.
kono
parents: 67
diff changeset
2541 for each such basic block bb records the outermost loop for that execution
kono
parents: 67
diff changeset
2542 of its header implies execution of bb. */
kono
parents: 67
diff changeset
2543
kono
parents: 67
diff changeset
2544 static void
kono
parents: 67
diff changeset
2545 fill_always_executed_in (void)
kono
parents: 67
diff changeset
2546 {
kono
parents: 67
diff changeset
2547 basic_block bb;
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2548 class loop *loop;
111
kono
parents: 67
diff changeset
2549
kono
parents: 67
diff changeset
2550 auto_sbitmap contains_call (last_basic_block_for_fn (cfun));
kono
parents: 67
diff changeset
2551 bitmap_clear (contains_call);
kono
parents: 67
diff changeset
2552 FOR_EACH_BB_FN (bb, cfun)
kono
parents: 67
diff changeset
2553 {
kono
parents: 67
diff changeset
2554 gimple_stmt_iterator gsi;
kono
parents: 67
diff changeset
2555 for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
kono
parents: 67
diff changeset
2556 {
kono
parents: 67
diff changeset
2557 if (nonpure_call_p (gsi_stmt (gsi)))
kono
parents: 67
diff changeset
2558 break;
kono
parents: 67
diff changeset
2559 }
kono
parents: 67
diff changeset
2560
kono
parents: 67
diff changeset
2561 if (!gsi_end_p (gsi))
kono
parents: 67
diff changeset
2562 bitmap_set_bit (contains_call, bb->index);
kono
parents: 67
diff changeset
2563 }
kono
parents: 67
diff changeset
2564
kono
parents: 67
diff changeset
2565 for (loop = current_loops->tree_root->inner; loop; loop = loop->next)
kono
parents: 67
diff changeset
2566 fill_always_executed_in_1 (loop, contains_call);
kono
parents: 67
diff changeset
2567 }
kono
parents: 67
diff changeset
2568
kono
parents: 67
diff changeset
2569
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2570 /* Compute the global information needed by the loop invariant motion pass. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2571
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2572 static void
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2573 tree_ssa_lim_initialize (void)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2574 {
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2575 class loop *loop;
111
kono
parents: 67
diff changeset
2576 unsigned i;
kono
parents: 67
diff changeset
2577
kono
parents: 67
diff changeset
2578 bitmap_obstack_initialize (&lim_bitmap_obstack);
kono
parents: 67
diff changeset
2579 gcc_obstack_init (&mem_ref_obstack);
kono
parents: 67
diff changeset
2580 lim_aux_data_map = new hash_map<gimple *, lim_aux_data *>;
kono
parents: 67
diff changeset
2581
kono
parents: 67
diff changeset
2582 if (flag_tm)
kono
parents: 67
diff changeset
2583 compute_transaction_bits ();
kono
parents: 67
diff changeset
2584
kono
parents: 67
diff changeset
2585 alloc_aux_for_edges (0);
kono
parents: 67
diff changeset
2586
kono
parents: 67
diff changeset
2587 memory_accesses.refs = new hash_table<mem_ref_hasher> (100);
kono
parents: 67
diff changeset
2588 memory_accesses.refs_list.create (100);
kono
parents: 67
diff changeset
2589 /* Allocate a special, unanalyzable mem-ref with ID zero. */
kono
parents: 67
diff changeset
2590 memory_accesses.refs_list.quick_push
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2591 (mem_ref_alloc (NULL, 0, UNANALYZABLE_MEM_ID));
111
kono
parents: 67
diff changeset
2592
kono
parents: 67
diff changeset
2593 memory_accesses.refs_in_loop.create (number_of_loops (cfun));
kono
parents: 67
diff changeset
2594 memory_accesses.refs_in_loop.quick_grow (number_of_loops (cfun));
kono
parents: 67
diff changeset
2595 memory_accesses.refs_stored_in_loop.create (number_of_loops (cfun));
kono
parents: 67
diff changeset
2596 memory_accesses.refs_stored_in_loop.quick_grow (number_of_loops (cfun));
kono
parents: 67
diff changeset
2597 memory_accesses.all_refs_stored_in_loop.create (number_of_loops (cfun));
kono
parents: 67
diff changeset
2598 memory_accesses.all_refs_stored_in_loop.quick_grow (number_of_loops (cfun));
kono
parents: 67
diff changeset
2599
kono
parents: 67
diff changeset
2600 for (i = 0; i < number_of_loops (cfun); i++)
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2601 {
111
kono
parents: 67
diff changeset
2602 bitmap_initialize (&memory_accesses.refs_in_loop[i],
kono
parents: 67
diff changeset
2603 &lim_bitmap_obstack);
kono
parents: 67
diff changeset
2604 bitmap_initialize (&memory_accesses.refs_stored_in_loop[i],
kono
parents: 67
diff changeset
2605 &lim_bitmap_obstack);
kono
parents: 67
diff changeset
2606 bitmap_initialize (&memory_accesses.all_refs_stored_in_loop[i],
kono
parents: 67
diff changeset
2607 &lim_bitmap_obstack);
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2608 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2609
111
kono
parents: 67
diff changeset
2610 memory_accesses.ttae_cache = NULL;
kono
parents: 67
diff changeset
2611
kono
parents: 67
diff changeset
2612 /* Initialize bb_loop_postorder with a mapping from loop->num to
kono
parents: 67
diff changeset
2613 its postorder index. */
kono
parents: 67
diff changeset
2614 i = 0;
kono
parents: 67
diff changeset
2615 bb_loop_postorder = XNEWVEC (unsigned, number_of_loops (cfun));
kono
parents: 67
diff changeset
2616 FOR_EACH_LOOP (loop, LI_FROM_INNERMOST)
kono
parents: 67
diff changeset
2617 bb_loop_postorder[loop->num] = i++;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2618 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2619
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2620 /* Cleans up after the invariant motion pass. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2621
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2622 static void
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2623 tree_ssa_lim_finalize (void)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2624 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2625 basic_block bb;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2626 unsigned i;
111
kono
parents: 67
diff changeset
2627 im_mem_ref *ref;
kono
parents: 67
diff changeset
2628
kono
parents: 67
diff changeset
2629 free_aux_for_edges ();
kono
parents: 67
diff changeset
2630
kono
parents: 67
diff changeset
2631 FOR_EACH_BB_FN (bb, cfun)
kono
parents: 67
diff changeset
2632 SET_ALWAYS_EXECUTED_IN (bb, NULL);
kono
parents: 67
diff changeset
2633
kono
parents: 67
diff changeset
2634 bitmap_obstack_release (&lim_bitmap_obstack);
kono
parents: 67
diff changeset
2635 delete lim_aux_data_map;
kono
parents: 67
diff changeset
2636
kono
parents: 67
diff changeset
2637 delete memory_accesses.refs;
kono
parents: 67
diff changeset
2638 memory_accesses.refs = NULL;
kono
parents: 67
diff changeset
2639
kono
parents: 67
diff changeset
2640 FOR_EACH_VEC_ELT (memory_accesses.refs_list, i, ref)
kono
parents: 67
diff changeset
2641 memref_free (ref);
kono
parents: 67
diff changeset
2642 memory_accesses.refs_list.release ();
kono
parents: 67
diff changeset
2643 obstack_free (&mem_ref_obstack, NULL);
kono
parents: 67
diff changeset
2644
kono
parents: 67
diff changeset
2645 memory_accesses.refs_in_loop.release ();
kono
parents: 67
diff changeset
2646 memory_accesses.refs_stored_in_loop.release ();
kono
parents: 67
diff changeset
2647 memory_accesses.all_refs_stored_in_loop.release ();
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2648
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2649 if (memory_accesses.ttae_cache)
111
kono
parents: 67
diff changeset
2650 free_affine_expand_cache (&memory_accesses.ttae_cache);
kono
parents: 67
diff changeset
2651
kono
parents: 67
diff changeset
2652 free (bb_loop_postorder);
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2653 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2654
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2655 /* Moves invariants from loops. Only "expensive" invariants are moved out --
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2656 i.e. those that are likely to be win regardless of the register pressure. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2657
111
kono
parents: 67
diff changeset
2658 static unsigned int
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2659 tree_ssa_lim (void)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2660 {
63
b7f97abdc517 update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
2661 unsigned int todo;
b7f97abdc517 update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
2662
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2663 tree_ssa_lim_initialize ();
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2664
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2665 /* Gathers information about memory accesses in the loops. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2666 analyze_memory_references ();
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2667
111
kono
parents: 67
diff changeset
2668 /* Fills ALWAYS_EXECUTED_IN information for basic blocks. */
kono
parents: 67
diff changeset
2669 fill_always_executed_in ();
kono
parents: 67
diff changeset
2670
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2671 /* For each statement determine the outermost loop in that it is
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2672 invariant and cost for computing the invariant. */
111
kono
parents: 67
diff changeset
2673 invariantness_dom_walker (CDI_DOMINATORS)
kono
parents: 67
diff changeset
2674 .walk (cfun->cfg->x_entry_block_ptr);
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2675
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2676 /* Execute store motion. Force the necessary invariants to be moved
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2677 out of the loops as well. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2678 store_motion ();
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2679
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2680 /* Move the expressions that are expensive enough. */
63
b7f97abdc517 update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
2681 todo = move_computations ();
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2682
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2683 tree_ssa_lim_finalize ();
63
b7f97abdc517 update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
2684
b7f97abdc517 update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
2685 return todo;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2686 }
111
kono
parents: 67
diff changeset
2687
kono
parents: 67
diff changeset
2688 /* Loop invariant motion pass. */
kono
parents: 67
diff changeset
2689
kono
parents: 67
diff changeset
2690 namespace {
kono
parents: 67
diff changeset
2691
kono
parents: 67
diff changeset
2692 const pass_data pass_data_lim =
kono
parents: 67
diff changeset
2693 {
kono
parents: 67
diff changeset
2694 GIMPLE_PASS, /* type */
kono
parents: 67
diff changeset
2695 "lim", /* name */
kono
parents: 67
diff changeset
2696 OPTGROUP_LOOP, /* optinfo_flags */
kono
parents: 67
diff changeset
2697 TV_LIM, /* tv_id */
kono
parents: 67
diff changeset
2698 PROP_cfg, /* properties_required */
kono
parents: 67
diff changeset
2699 0, /* properties_provided */
kono
parents: 67
diff changeset
2700 0, /* properties_destroyed */
kono
parents: 67
diff changeset
2701 0, /* todo_flags_start */
kono
parents: 67
diff changeset
2702 0, /* todo_flags_finish */
kono
parents: 67
diff changeset
2703 };
kono
parents: 67
diff changeset
2704
kono
parents: 67
diff changeset
2705 class pass_lim : public gimple_opt_pass
kono
parents: 67
diff changeset
2706 {
kono
parents: 67
diff changeset
2707 public:
kono
parents: 67
diff changeset
2708 pass_lim (gcc::context *ctxt)
kono
parents: 67
diff changeset
2709 : gimple_opt_pass (pass_data_lim, ctxt)
kono
parents: 67
diff changeset
2710 {}
kono
parents: 67
diff changeset
2711
kono
parents: 67
diff changeset
2712 /* opt_pass methods: */
kono
parents: 67
diff changeset
2713 opt_pass * clone () { return new pass_lim (m_ctxt); }
kono
parents: 67
diff changeset
2714 virtual bool gate (function *) { return flag_tree_loop_im != 0; }
kono
parents: 67
diff changeset
2715 virtual unsigned int execute (function *);
kono
parents: 67
diff changeset
2716
kono
parents: 67
diff changeset
2717 }; // class pass_lim
kono
parents: 67
diff changeset
2718
kono
parents: 67
diff changeset
2719 unsigned int
kono
parents: 67
diff changeset
2720 pass_lim::execute (function *fun)
kono
parents: 67
diff changeset
2721 {
kono
parents: 67
diff changeset
2722 bool in_loop_pipeline = scev_initialized_p ();
kono
parents: 67
diff changeset
2723 if (!in_loop_pipeline)
kono
parents: 67
diff changeset
2724 loop_optimizer_init (LOOPS_NORMAL | LOOPS_HAVE_RECORDED_EXITS);
kono
parents: 67
diff changeset
2725
kono
parents: 67
diff changeset
2726 if (number_of_loops (fun) <= 1)
kono
parents: 67
diff changeset
2727 return 0;
kono
parents: 67
diff changeset
2728 unsigned int todo = tree_ssa_lim ();
kono
parents: 67
diff changeset
2729
kono
parents: 67
diff changeset
2730 if (!in_loop_pipeline)
kono
parents: 67
diff changeset
2731 loop_optimizer_finalize ();
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2732 else
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2733 scev_reset ();
111
kono
parents: 67
diff changeset
2734 return todo;
kono
parents: 67
diff changeset
2735 }
kono
parents: 67
diff changeset
2736
kono
parents: 67
diff changeset
2737 } // anon namespace
kono
parents: 67
diff changeset
2738
kono
parents: 67
diff changeset
2739 gimple_opt_pass *
kono
parents: 67
diff changeset
2740 make_pass_lim (gcc::context *ctxt)
kono
parents: 67
diff changeset
2741 {
kono
parents: 67
diff changeset
2742 return new pass_lim (ctxt);
kono
parents: 67
diff changeset
2743 }
kono
parents: 67
diff changeset
2744
kono
parents: 67
diff changeset
2745