]>
Commit | Line | Data |
---|---|---|
6de9cd9a DN |
1 | /* Const/copy propagation and SSA_NAME replacement support routines. |
2 | Copyright (C) 2004 Free Software Foundation, Inc. | |
3 | ||
4 | This file is part of GCC. | |
5 | ||
6 | GCC is free software; you can redistribute it and/or modify | |
7 | it under the terms of the GNU General Public License as published by | |
8 | the Free Software Foundation; either version 2, or (at your option) | |
9 | any later version. | |
10 | ||
11 | GCC is distributed in the hope that it will be useful, | |
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
14 | GNU General Public License for more details. | |
15 | ||
16 | You should have received a copy of the GNU General Public License | |
17 | along with GCC; see the file COPYING. If not, write to | |
18 | the Free Software Foundation, 59 Temple Place - Suite 330, | |
19 | Boston, MA 02111-1307, USA. */ | |
20 | ||
21 | #include "config.h" | |
22 | #include "system.h" | |
23 | #include "coretypes.h" | |
24 | #include "tm.h" | |
25 | #include "tree.h" | |
26 | #include "flags.h" | |
27 | #include "rtl.h" | |
28 | #include "tm_p.h" | |
29 | #include "ggc.h" | |
30 | #include "basic-block.h" | |
31 | #include "output.h" | |
32 | #include "errors.h" | |
33 | #include "expr.h" | |
34 | #include "function.h" | |
35 | #include "diagnostic.h" | |
36 | #include "timevar.h" | |
37 | #include "tree-dump.h" | |
38 | #include "tree-flow.h" | |
39 | #include "tree-pass.h" | |
40 | #include "langhooks.h" | |
41 | ||
42 | /* This file provides a handful of interfaces for performing const/copy | |
43 | propagation and simple expression replacement which keep variable | |
44 | annotations up-to-date. | |
45 | ||
46 | We require that for any copy operation where the RHS and LHS have | |
47 | a non-null memory tag that the memory tag be the same. It is OK | |
48 | for one or both of the memory tags to be NULL. | |
49 | ||
50 | We also require tracking if a variable is dereferenced in a load or | |
51 | store operation. | |
52 | ||
53 | We enforce these requirements by having all copy propagation and | |
54 | replacements of one SSA_NAME with a different SSA_NAME to use the | |
55 | APIs defined in this file. */ | |
56 | ||
6de9cd9a | 57 | |
63b88252 RH |
58 | /* Return true if we may propagate ORIG into DEST, false otherwise. */ |
59 | ||
60 | bool | |
61 | may_propagate_copy (tree dest, tree orig) | |
62 | { | |
63 | tree type_d = TREE_TYPE (dest); | |
64 | tree type_o = TREE_TYPE (orig); | |
65 | ||
66 | /* Do not copy between types for which we *do* need a conversion. */ | |
67 | if (!tree_ssa_useless_type_conversion_1 (type_d, type_o)) | |
68 | return false; | |
69 | ||
70 | /* FIXME. GIMPLE is allowing pointer assignments and comparisons of | |
71 | pointers that have different alias sets. This means that these | |
72 | pointers will have different memory tags associated to them. | |
19114537 | 73 | |
63b88252 RH |
74 | If we allow copy propagation in these cases, statements de-referencing |
75 | the new pointer will now have a reference to a different memory tag | |
76 | with potentially incorrect SSA information. | |
77 | ||
78 | This was showing up in libjava/java/util/zip/ZipFile.java with code | |
79 | like: | |
80 | ||
81 | struct java.io.BufferedInputStream *T.660; | |
82 | struct java.io.BufferedInputStream *T.647; | |
83 | struct java.io.InputStream *is; | |
84 | struct java.io.InputStream *is.662; | |
85 | [ ... ] | |
86 | T.660 = T.647; | |
87 | is = T.660; <-- This ought to be type-casted | |
88 | is.662 = is; | |
89 | ||
90 | Also, f/name.c exposed a similar problem with a COND_EXPR predicate | |
91 | that was causing DOM to generate and equivalence with two pointers of | |
92 | alias-incompatible types: | |
93 | ||
94 | struct _ffename_space *n; | |
95 | struct _ffename *ns; | |
96 | [ ... ] | |
97 | if (n == ns) | |
98 | goto lab; | |
99 | ... | |
100 | lab: | |
101 | return n; | |
102 | ||
103 | I think that GIMPLE should emit the appropriate type-casts. For the | |
104 | time being, blocking copy-propagation in these cases is the safe thing | |
105 | to do. */ | |
106 | if (TREE_CODE (dest) == SSA_NAME && TREE_CODE (orig) == SSA_NAME | |
107 | && POINTER_TYPE_P (type_d) && POINTER_TYPE_P (type_o)) | |
108 | { | |
109 | tree mt_dest = var_ann (SSA_NAME_VAR (dest))->type_mem_tag; | |
110 | tree mt_orig = var_ann (SSA_NAME_VAR (orig))->type_mem_tag; | |
111 | if (mt_dest && mt_orig && mt_dest != mt_orig) | |
112 | return false; | |
bbc630f5 DN |
113 | else if (!lang_hooks.types_compatible_p (type_d, type_o)) |
114 | return false; | |
b1940f0c AP |
115 | else if (get_alias_set (TREE_TYPE (type_d)) != |
116 | get_alias_set (TREE_TYPE (type_o))) | |
9ae2a5d1 | 117 | return false; |
63b88252 RH |
118 | } |
119 | ||
120 | /* If the destination is a SSA_NAME for a virtual operand, then we have | |
121 | some special cases to handle. */ | |
122 | if (TREE_CODE (dest) == SSA_NAME && !is_gimple_reg (dest)) | |
123 | { | |
124 | /* If both operands are SSA_NAMEs referring to virtual operands, then | |
125 | we can always propagate. */ | |
126 | if (TREE_CODE (orig) == SSA_NAME) | |
127 | { | |
128 | if (!is_gimple_reg (orig)) | |
129 | return true; | |
130 | ||
131 | #ifdef ENABLE_CHECKING | |
132 | /* If we have one real and one virtual operand, then something has | |
133 | gone terribly wrong. */ | |
1e128c5f | 134 | gcc_assert (!is_gimple_reg (orig)); |
63b88252 RH |
135 | #endif |
136 | } | |
137 | ||
138 | /* We have a "copy" from something like a constant into a virtual | |
139 | operand. Reject these. */ | |
140 | return false; | |
141 | } | |
142 | ||
143 | /* If ORIG flows in from an abnormal edge, it cannot be propagated. */ | |
144 | if (TREE_CODE (orig) == SSA_NAME | |
145 | && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (orig)) | |
146 | return false; | |
147 | ||
e670d9e4 RH |
148 | /* If DEST is an SSA_NAME that flows from an abnormal edge, then it |
149 | cannot be replaced. */ | |
63b88252 | 150 | if (TREE_CODE (dest) == SSA_NAME |
e670d9e4 | 151 | && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (dest)) |
63b88252 RH |
152 | return false; |
153 | ||
154 | /* Anything else is OK. */ | |
155 | return true; | |
156 | } | |
157 | ||
aa24864c RH |
158 | /* Similarly, but we know that we're propagating into an ASM_EXPR. */ |
159 | ||
160 | bool | |
161 | may_propagate_copy_into_asm (tree dest) | |
162 | { | |
163 | /* Hard register operands of asms are special. Do not bypass. */ | |
164 | return !(TREE_CODE (dest) == SSA_NAME | |
e670d9e4 | 165 | && TREE_CODE (SSA_NAME_VAR (dest)) == VAR_DECL |
aa24864c RH |
166 | && DECL_HARD_REGISTER (SSA_NAME_VAR (dest))); |
167 | } | |
168 | ||
6de9cd9a | 169 | |
bbc630f5 DN |
170 | /* Given two SSA_NAMEs pointers ORIG and NEW such that we are copy |
171 | propagating NEW into ORIG, consolidate aliasing information so that | |
172 | they both share the same memory tags. */ | |
19114537 | 173 | |
6de9cd9a | 174 | static void |
bbc630f5 | 175 | merge_alias_info (tree orig, tree new) |
6de9cd9a | 176 | { |
bbc630f5 DN |
177 | tree new_sym = SSA_NAME_VAR (new); |
178 | tree orig_sym = SSA_NAME_VAR (orig); | |
179 | var_ann_t new_ann = var_ann (new_sym); | |
180 | var_ann_t orig_ann = var_ann (orig_sym); | |
181 | ||
1e128c5f GB |
182 | gcc_assert (POINTER_TYPE_P (TREE_TYPE (orig))); |
183 | gcc_assert (POINTER_TYPE_P (TREE_TYPE (new))); | |
6de9cd9a | 184 | #if defined ENABLE_CHECKING |
1e128c5f GB |
185 | gcc_assert (lang_hooks.types_compatible_p (TREE_TYPE (orig), |
186 | TREE_TYPE (new))); | |
6de9cd9a | 187 | |
bbc630f5 DN |
188 | /* If the pointed-to alias sets are different, these two pointers |
189 | would never have the same memory tag. In this case, NEW should | |
190 | not have been propagated into ORIG. */ | |
1e128c5f GB |
191 | gcc_assert (get_alias_set (TREE_TYPE (TREE_TYPE (new_sym))) |
192 | == get_alias_set (TREE_TYPE (TREE_TYPE (orig_sym)))); | |
bbc630f5 | 193 | #endif |
6de9cd9a | 194 | |
bbc630f5 DN |
195 | /* Merge type-based alias info. */ |
196 | if (new_ann->type_mem_tag == NULL_TREE) | |
197 | new_ann->type_mem_tag = orig_ann->type_mem_tag; | |
198 | else if (orig_ann->type_mem_tag == NULL_TREE) | |
199 | orig_ann->type_mem_tag = new_ann->type_mem_tag; | |
1e128c5f GB |
200 | else |
201 | gcc_assert (new_ann->type_mem_tag == orig_ann->type_mem_tag); | |
19114537 | 202 | } |
d00ad49b | 203 | |
6de9cd9a DN |
204 | |
205 | /* Common code for propagate_value and replace_exp. | |
206 | ||
19114537 | 207 | Replace use operand OP_P with VAL. FOR_PROPAGATION indicates if the |
d00ad49b | 208 | replacement is done to propagate a value or not. */ |
6de9cd9a DN |
209 | |
210 | static void | |
bbc630f5 DN |
211 | replace_exp_1 (use_operand_p op_p, tree val, |
212 | bool for_propagation ATTRIBUTE_UNUSED) | |
6de9cd9a | 213 | { |
bbc630f5 DN |
214 | tree op = USE_FROM_PTR (op_p); |
215 | ||
216 | #if defined ENABLE_CHECKING | |
1e128c5f GB |
217 | gcc_assert (!(for_propagation |
218 | && TREE_CODE (op) == SSA_NAME | |
219 | && TREE_CODE (val) == SSA_NAME | |
220 | && !may_propagate_copy (op, val))); | |
bbc630f5 DN |
221 | #endif |
222 | ||
6de9cd9a DN |
223 | if (TREE_CODE (val) == SSA_NAME) |
224 | { | |
bbc630f5 DN |
225 | if (TREE_CODE (op) == SSA_NAME && POINTER_TYPE_P (TREE_TYPE (op))) |
226 | merge_alias_info (op, val); | |
d00ad49b | 227 | SET_USE (op_p, val); |
6de9cd9a DN |
228 | } |
229 | else | |
19114537 | 230 | SET_USE (op_p, unsave_expr_now (val)); |
6de9cd9a DN |
231 | } |
232 | ||
ff2ad0f7 | 233 | |
6de9cd9a DN |
234 | /* Propagate the value VAL (assumed to be a constant or another SSA_NAME) |
235 | into the operand pointed by OP_P. | |
236 | ||
237 | Use this version for const/copy propagation as it will perform additional | |
238 | checks to ensure validity of the const/copy propagation. */ | |
239 | ||
240 | void | |
d00ad49b | 241 | propagate_value (use_operand_p op_p, tree val) |
6de9cd9a DN |
242 | { |
243 | replace_exp_1 (op_p, val, true); | |
244 | } | |
245 | ||
ff2ad0f7 | 246 | |
d00ad49b AM |
247 | /* Propagate the value VAL (assumed to be a constant or another SSA_NAME) |
248 | into the tree pointed by OP_P. | |
249 | ||
19114537 EC |
250 | Use this version for const/copy propagation when SSA operands are not |
251 | available. It will perform the additional checks to ensure validity of | |
d00ad49b AM |
252 | the const/copy propagation, but will not update any operand information. |
253 | Be sure to mark the stmt as modified. */ | |
254 | ||
255 | void | |
256 | propagate_tree_value (tree *op_p, tree val) | |
257 | { | |
bbc630f5 | 258 | #if defined ENABLE_CHECKING |
1e128c5f GB |
259 | gcc_assert (!(TREE_CODE (val) == SSA_NAME |
260 | && TREE_CODE (*op_p) == SSA_NAME | |
261 | && !may_propagate_copy (*op_p, val))); | |
bbc630f5 DN |
262 | #endif |
263 | ||
d00ad49b AM |
264 | if (TREE_CODE (val) == SSA_NAME) |
265 | { | |
bbc630f5 DN |
266 | if (TREE_CODE (*op_p) == SSA_NAME && POINTER_TYPE_P (TREE_TYPE (*op_p))) |
267 | merge_alias_info (*op_p, val); | |
d00ad49b AM |
268 | *op_p = val; |
269 | } | |
270 | else | |
19114537 | 271 | *op_p = unsave_expr_now (val); |
d00ad49b AM |
272 | } |
273 | ||
ff2ad0f7 | 274 | |
6de9cd9a DN |
275 | /* Replace *OP_P with value VAL (assumed to be a constant or another SSA_NAME). |
276 | ||
277 | Use this version when not const/copy propagating values. For example, | |
278 | PRE uses this version when building expressions as they would appear | |
279 | in specific blocks taking into account actions of PHI nodes. */ | |
280 | ||
281 | void | |
d00ad49b | 282 | replace_exp (use_operand_p op_p, tree val) |
6de9cd9a DN |
283 | { |
284 | replace_exp_1 (op_p, val, false); | |
285 | } |