Mercurial > hg > CbC > CbC_gcc
annotate gcc/tree-ssa-address.c @ 56:3c8a44c06a95
Added tag gcc-4.4.5 for changeset 77e2b8dfacca
author | ryoma <e075725@ie.u-ryukyu.ac.jp> |
---|---|
date | Fri, 12 Feb 2010 23:41:23 +0900 |
parents | 77e2b8dfacca |
children | b7f97abdc517 |
rev | line source |
---|---|
0 | 1 /* Memory address lowering and addressing mode selection. |
2 Copyright (C) 2004, 2006, 2007, 2008, 2009 Free Software Foundation, Inc. | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
3 |
0 | 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:
0
diff
changeset
|
5 |
0 | 6 GCC is free software; you can redistribute it and/or modify it |
7 under the terms of the GNU General Public License as published by the | |
8 Free Software Foundation; either version 3, or (at your option) any | |
9 later version. | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
10 |
0 | 11 GCC is distributed in the hope that it will be useful, but WITHOUT |
12 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
13 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
14 for more details. | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
15 |
0 | 16 You should have received a copy of the GNU General Public License |
17 along with GCC; see the file COPYING3. If not see | |
18 <http://www.gnu.org/licenses/>. */ | |
19 | |
20 /* Utility functions for manipulation with TARGET_MEM_REFs -- tree expressions | |
21 that directly map to addressing modes of the target. */ | |
22 | |
23 #include "config.h" | |
24 #include "system.h" | |
25 #include "coretypes.h" | |
26 #include "tm.h" | |
27 #include "tree.h" | |
28 #include "rtl.h" | |
29 #include "tm_p.h" | |
30 #include "hard-reg-set.h" | |
31 #include "basic-block.h" | |
32 #include "output.h" | |
33 #include "diagnostic.h" | |
34 #include "tree-flow.h" | |
35 #include "tree-dump.h" | |
36 #include "tree-pass.h" | |
37 #include "timevar.h" | |
38 #include "flags.h" | |
39 #include "tree-inline.h" | |
40 #include "insn-config.h" | |
41 #include "recog.h" | |
42 #include "expr.h" | |
43 #include "ggc.h" | |
44 #include "tree-affine.h" | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
45 #include "target.h" |
0 | 46 |
47 /* TODO -- handling of symbols (according to Richard Hendersons | |
48 comments, http://gcc.gnu.org/ml/gcc-patches/2005-04/msg00949.html): | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
49 |
0 | 50 There are at least 5 different kinds of symbols that we can run up against: |
51 | |
52 (1) binds_local_p, small data area. | |
53 (2) binds_local_p, eg local statics | |
54 (3) !binds_local_p, eg global variables | |
55 (4) thread local, local_exec | |
56 (5) thread local, !local_exec | |
57 | |
58 Now, (1) won't appear often in an array context, but it certainly can. | |
59 All you have to do is set -GN high enough, or explicitly mark any | |
60 random object __attribute__((section (".sdata"))). | |
61 | |
62 All of these affect whether or not a symbol is in fact a valid address. | |
63 The only one tested here is (3). And that result may very well | |
64 be incorrect for (4) or (5). | |
65 | |
66 An incorrect result here does not cause incorrect results out the | |
67 back end, because the expander in expr.c validizes the address. However | |
68 it would be nice to improve the handling here in order to produce more | |
69 precise results. */ | |
70 | |
71 /* A "template" for memory address, used to determine whether the address is | |
72 valid for mode. */ | |
73 | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
74 typedef struct GTY (()) mem_addr_template { |
0 | 75 rtx ref; /* The template. */ |
76 rtx * GTY ((skip)) step_p; /* The point in template where the step should be | |
77 filled in. */ | |
78 rtx * GTY ((skip)) off_p; /* The point in template where the offset should | |
79 be filled in. */ | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
80 } mem_addr_template; |
0 | 81 |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
82 DEF_VEC_O (mem_addr_template); |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
83 DEF_VEC_ALLOC_O (mem_addr_template, gc); |
0 | 84 |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
85 /* The templates. Each of the low five bits of the index corresponds to one |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
86 component of TARGET_MEM_REF being present, while the high bits identify |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
87 the address space. See TEMPL_IDX. */ |
0 | 88 |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
89 static GTY(()) VEC (mem_addr_template, gc) *mem_addr_template_list; |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
90 |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
91 #define TEMPL_IDX(AS, SYMBOL, BASE, INDEX, STEP, OFFSET) \ |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
92 (((int) (AS) << 5) \ |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
93 | ((SYMBOL != 0) << 4) \ |
0 | 94 | ((BASE != 0) << 3) \ |
95 | ((INDEX != 0) << 2) \ | |
96 | ((STEP != 0) << 1) \ | |
97 | (OFFSET != 0)) | |
98 | |
99 /* Stores address for memory reference with parameters SYMBOL, BASE, INDEX, | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
100 STEP and OFFSET to *ADDR using address mode ADDRESS_MODE. Stores pointers |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
101 to where step is placed to *STEP_P and offset to *OFFSET_P. */ |
0 | 102 |
103 static void | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
104 gen_addr_rtx (enum machine_mode address_mode, |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
105 rtx symbol, rtx base, rtx index, rtx step, rtx offset, |
0 | 106 rtx *addr, rtx **step_p, rtx **offset_p) |
107 { | |
108 rtx act_elem; | |
109 | |
110 *addr = NULL_RTX; | |
111 if (step_p) | |
112 *step_p = NULL; | |
113 if (offset_p) | |
114 *offset_p = NULL; | |
115 | |
116 if (index) | |
117 { | |
118 act_elem = index; | |
119 if (step) | |
120 { | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
121 act_elem = gen_rtx_MULT (address_mode, act_elem, step); |
0 | 122 |
123 if (step_p) | |
124 *step_p = &XEXP (act_elem, 1); | |
125 } | |
126 | |
127 *addr = act_elem; | |
128 } | |
129 | |
130 if (base) | |
131 { | |
132 if (*addr) | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
133 *addr = simplify_gen_binary (PLUS, address_mode, base, *addr); |
0 | 134 else |
135 *addr = base; | |
136 } | |
137 | |
138 if (symbol) | |
139 { | |
140 act_elem = symbol; | |
141 if (offset) | |
142 { | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
143 act_elem = gen_rtx_PLUS (address_mode, act_elem, offset); |
0 | 144 |
145 if (offset_p) | |
146 *offset_p = &XEXP (act_elem, 1); | |
147 | |
148 if (GET_CODE (symbol) == SYMBOL_REF | |
149 || GET_CODE (symbol) == LABEL_REF | |
150 || GET_CODE (symbol) == CONST) | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
151 act_elem = gen_rtx_CONST (address_mode, act_elem); |
0 | 152 } |
153 | |
154 if (*addr) | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
155 *addr = gen_rtx_PLUS (address_mode, *addr, act_elem); |
0 | 156 else |
157 *addr = act_elem; | |
158 } | |
159 else if (offset) | |
160 { | |
161 if (*addr) | |
162 { | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
163 *addr = gen_rtx_PLUS (address_mode, *addr, offset); |
0 | 164 if (offset_p) |
165 *offset_p = &XEXP (*addr, 1); | |
166 } | |
167 else | |
168 { | |
169 *addr = offset; | |
170 if (offset_p) | |
171 *offset_p = addr; | |
172 } | |
173 } | |
174 | |
175 if (!*addr) | |
176 *addr = const0_rtx; | |
177 } | |
178 | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
179 /* Returns address for TARGET_MEM_REF with parameters given by ADDR |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
180 in address space AS. |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
181 If REALLY_EXPAND is false, just make fake registers instead |
0 | 182 of really expanding the operands, and perform the expansion in-place |
183 by using one of the "templates". */ | |
184 | |
185 rtx | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
186 addr_for_mem_ref (struct mem_address *addr, addr_space_t as, |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
187 bool really_expand) |
0 | 188 { |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
189 enum machine_mode address_mode = targetm.addr_space.address_mode (as); |
0 | 190 rtx address, sym, bse, idx, st, off; |
191 struct mem_addr_template *templ; | |
192 | |
193 if (addr->step && !integer_onep (addr->step)) | |
194 st = immed_double_const (TREE_INT_CST_LOW (addr->step), | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
195 TREE_INT_CST_HIGH (addr->step), address_mode); |
0 | 196 else |
197 st = NULL_RTX; | |
198 | |
199 if (addr->offset && !integer_zerop (addr->offset)) | |
200 off = immed_double_const (TREE_INT_CST_LOW (addr->offset), | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
201 TREE_INT_CST_HIGH (addr->offset), address_mode); |
0 | 202 else |
203 off = NULL_RTX; | |
204 | |
205 if (!really_expand) | |
206 { | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
207 unsigned int templ_index |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
208 = TEMPL_IDX (as, addr->symbol, addr->base, addr->index, st, off); |
0 | 209 |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
210 if (templ_index |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
211 >= VEC_length (mem_addr_template, mem_addr_template_list)) |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
212 VEC_safe_grow_cleared (mem_addr_template, gc, mem_addr_template_list, |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
213 templ_index + 1); |
0 | 214 |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
215 /* Reuse the templates for addresses, so that we do not waste memory. */ |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
216 templ = VEC_index (mem_addr_template, mem_addr_template_list, templ_index); |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
217 if (!templ->ref) |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
218 { |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
219 sym = (addr->symbol ? |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
220 gen_rtx_SYMBOL_REF (address_mode, ggc_strdup ("test_symbol")) |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
221 : NULL_RTX); |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
222 bse = (addr->base ? |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
223 gen_raw_REG (address_mode, LAST_VIRTUAL_REGISTER + 1) |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
224 : NULL_RTX); |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
225 idx = (addr->index ? |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
226 gen_raw_REG (address_mode, LAST_VIRTUAL_REGISTER + 2) |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
227 : NULL_RTX); |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
228 |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
229 gen_addr_rtx (address_mode, sym, bse, idx, |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
230 st? const0_rtx : NULL_RTX, |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
231 off? const0_rtx : NULL_RTX, |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
232 &templ->ref, |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
233 &templ->step_p, |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
234 &templ->off_p); |
0 | 235 } |
236 | |
237 if (st) | |
238 *templ->step_p = st; | |
239 if (off) | |
240 *templ->off_p = off; | |
241 | |
242 return templ->ref; | |
243 } | |
244 | |
245 /* Otherwise really expand the expressions. */ | |
246 sym = (addr->symbol | |
247 ? expand_expr (build_addr (addr->symbol, current_function_decl), | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
248 NULL_RTX, address_mode, EXPAND_NORMAL) |
0 | 249 : NULL_RTX); |
250 bse = (addr->base | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
251 ? expand_expr (addr->base, NULL_RTX, address_mode, EXPAND_NORMAL) |
0 | 252 : NULL_RTX); |
253 idx = (addr->index | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
254 ? expand_expr (addr->index, NULL_RTX, address_mode, EXPAND_NORMAL) |
0 | 255 : NULL_RTX); |
256 | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
257 gen_addr_rtx (address_mode, sym, bse, idx, st, off, &address, NULL, NULL); |
0 | 258 return address; |
259 } | |
260 | |
261 /* Returns address of MEM_REF in TYPE. */ | |
262 | |
263 tree | |
264 tree_mem_ref_addr (tree type, tree mem_ref) | |
265 { | |
266 tree addr; | |
267 tree act_elem; | |
268 tree step = TMR_STEP (mem_ref), offset = TMR_OFFSET (mem_ref); | |
269 tree sym = TMR_SYMBOL (mem_ref), base = TMR_BASE (mem_ref); | |
270 tree addr_base = NULL_TREE, addr_off = NULL_TREE; | |
271 | |
272 if (sym) | |
273 addr_base = fold_convert (type, build_addr (sym, current_function_decl)); | |
274 else if (base && POINTER_TYPE_P (TREE_TYPE (base))) | |
275 { | |
276 addr_base = fold_convert (type, base); | |
277 base = NULL_TREE; | |
278 } | |
279 | |
280 act_elem = TMR_INDEX (mem_ref); | |
281 if (act_elem) | |
282 { | |
283 if (step) | |
284 act_elem = fold_build2 (MULT_EXPR, sizetype, act_elem, step); | |
285 addr_off = act_elem; | |
286 } | |
287 | |
288 act_elem = base; | |
289 if (act_elem) | |
290 { | |
291 if (addr_off) | |
292 addr_off = fold_build2 (PLUS_EXPR, sizetype, addr_off, act_elem); | |
293 else | |
294 addr_off = act_elem; | |
295 } | |
296 | |
297 if (offset && !integer_zerop (offset)) | |
298 { | |
299 if (addr_off) | |
300 addr_off = fold_build2 (PLUS_EXPR, sizetype, addr_off, offset); | |
301 else | |
302 addr_off = offset; | |
303 } | |
304 | |
305 if (addr_off) | |
306 { | |
307 if (addr_base) | |
308 addr = fold_build2 (POINTER_PLUS_EXPR, type, addr_base, addr_off); | |
309 else | |
310 addr = fold_convert (type, addr_off); | |
311 } | |
312 else if (addr_base) | |
313 addr = addr_base; | |
314 else | |
315 addr = build_int_cst (type, 0); | |
316 | |
317 return addr; | |
318 } | |
319 | |
320 /* Returns true if a memory reference in MODE and with parameters given by | |
321 ADDR is valid on the current target. */ | |
322 | |
323 static bool | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
324 valid_mem_ref_p (enum machine_mode mode, addr_space_t as, |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
325 struct mem_address *addr) |
0 | 326 { |
327 rtx address; | |
328 | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
329 address = addr_for_mem_ref (addr, as, false); |
0 | 330 if (!address) |
331 return false; | |
332 | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
333 return memory_address_addr_space_p (mode, address, as); |
0 | 334 } |
335 | |
336 /* Checks whether a TARGET_MEM_REF with type TYPE and parameters given by ADDR | |
337 is valid on the current target and if so, creates and returns the | |
338 TARGET_MEM_REF. */ | |
339 | |
340 static tree | |
341 create_mem_ref_raw (tree type, struct mem_address *addr) | |
342 { | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
343 if (!valid_mem_ref_p (TYPE_MODE (type), TYPE_ADDR_SPACE (type), addr)) |
0 | 344 return NULL_TREE; |
345 | |
346 if (addr->step && integer_onep (addr->step)) | |
347 addr->step = NULL_TREE; | |
348 | |
349 if (addr->offset && integer_zerop (addr->offset)) | |
350 addr->offset = NULL_TREE; | |
351 | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
352 return build6 (TARGET_MEM_REF, type, |
0 | 353 addr->symbol, addr->base, addr->index, |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
354 addr->step, addr->offset, NULL); |
0 | 355 } |
356 | |
357 /* Returns true if OBJ is an object whose address is a link time constant. */ | |
358 | |
359 static bool | |
360 fixed_address_object_p (tree obj) | |
361 { | |
362 return (TREE_CODE (obj) == VAR_DECL | |
363 && (TREE_STATIC (obj) | |
364 || DECL_EXTERNAL (obj)) | |
365 && ! DECL_DLLIMPORT_P (obj)); | |
366 } | |
367 | |
368 /* If ADDR contains an address of object that is a link time constant, | |
369 move it to PARTS->symbol. */ | |
370 | |
371 static void | |
372 move_fixed_address_to_symbol (struct mem_address *parts, aff_tree *addr) | |
373 { | |
374 unsigned i; | |
375 tree val = NULL_TREE; | |
376 | |
377 for (i = 0; i < addr->n; i++) | |
378 { | |
379 if (!double_int_one_p (addr->elts[i].coef)) | |
380 continue; | |
381 | |
382 val = addr->elts[i].val; | |
383 if (TREE_CODE (val) == ADDR_EXPR | |
384 && fixed_address_object_p (TREE_OPERAND (val, 0))) | |
385 break; | |
386 } | |
387 | |
388 if (i == addr->n) | |
389 return; | |
390 | |
391 parts->symbol = TREE_OPERAND (val, 0); | |
392 aff_combination_remove_elt (addr, i); | |
393 } | |
394 | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
395 /* If ADDR contains an instance of BASE_HINT, move it to PARTS->base. */ |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
396 |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
397 static void |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
398 move_hint_to_base (tree type, struct mem_address *parts, tree base_hint, |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
399 aff_tree *addr) |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
400 { |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
401 unsigned i; |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
402 tree val = NULL_TREE; |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
403 int qual; |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
404 |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
405 for (i = 0; i < addr->n; i++) |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
406 { |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
407 if (!double_int_one_p (addr->elts[i].coef)) |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
408 continue; |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
409 |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
410 val = addr->elts[i].val; |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
411 if (operand_equal_p (val, base_hint, 0)) |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
412 break; |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
413 } |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
414 |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
415 if (i == addr->n) |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
416 return; |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
417 |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
418 /* Cast value to appropriate pointer type. We cannot use a pointer |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
419 to TYPE directly, as the back-end will assume registers of pointer |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
420 type are aligned, and just the base itself may not actually be. |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
421 We use void pointer to the type's address space instead. */ |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
422 qual = ENCODE_QUAL_ADDR_SPACE (TYPE_ADDR_SPACE (type)); |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
423 type = build_qualified_type (void_type_node, qual); |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
424 parts->base = fold_convert (build_pointer_type (type), val); |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
425 aff_combination_remove_elt (addr, i); |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
426 } |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
427 |
0 | 428 /* If ADDR contains an address of a dereferenced pointer, move it to |
429 PARTS->base. */ | |
430 | |
431 static void | |
432 move_pointer_to_base (struct mem_address *parts, aff_tree *addr) | |
433 { | |
434 unsigned i; | |
435 tree val = NULL_TREE; | |
436 | |
437 for (i = 0; i < addr->n; i++) | |
438 { | |
439 if (!double_int_one_p (addr->elts[i].coef)) | |
440 continue; | |
441 | |
442 val = addr->elts[i].val; | |
443 if (POINTER_TYPE_P (TREE_TYPE (val))) | |
444 break; | |
445 } | |
446 | |
447 if (i == addr->n) | |
448 return; | |
449 | |
450 parts->base = val; | |
451 aff_combination_remove_elt (addr, i); | |
452 } | |
453 | |
454 /* Adds ELT to PARTS. */ | |
455 | |
456 static void | |
457 add_to_parts (struct mem_address *parts, tree elt) | |
458 { | |
459 tree type; | |
460 | |
461 if (!parts->index) | |
462 { | |
463 parts->index = fold_convert (sizetype, elt); | |
464 return; | |
465 } | |
466 | |
467 if (!parts->base) | |
468 { | |
469 parts->base = elt; | |
470 return; | |
471 } | |
472 | |
473 /* Add ELT to base. */ | |
474 type = TREE_TYPE (parts->base); | |
475 if (POINTER_TYPE_P (type)) | |
476 parts->base = fold_build2 (POINTER_PLUS_EXPR, type, | |
477 parts->base, | |
478 fold_convert (sizetype, elt)); | |
479 else | |
480 parts->base = fold_build2 (PLUS_EXPR, type, | |
481 parts->base, elt); | |
482 } | |
483 | |
484 /* Finds the most expensive multiplication in ADDR that can be | |
485 expressed in an addressing mode and move the corresponding | |
486 element(s) to PARTS. */ | |
487 | |
488 static void | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
489 most_expensive_mult_to_index (tree type, struct mem_address *parts, |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
490 aff_tree *addr, bool speed) |
0 | 491 { |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
492 addr_space_t as = TYPE_ADDR_SPACE (type); |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
493 enum machine_mode address_mode = targetm.addr_space.address_mode (as); |
0 | 494 HOST_WIDE_INT coef; |
495 double_int best_mult, amult, amult_neg; | |
496 unsigned best_mult_cost = 0, acost; | |
497 tree mult_elt = NULL_TREE, elt; | |
498 unsigned i, j; | |
499 enum tree_code op_code; | |
500 | |
501 best_mult = double_int_zero; | |
502 for (i = 0; i < addr->n; i++) | |
503 { | |
504 if (!double_int_fits_in_shwi_p (addr->elts[i].coef)) | |
505 continue; | |
506 | |
507 coef = double_int_to_shwi (addr->elts[i].coef); | |
508 if (coef == 1 | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
509 || !multiplier_allowed_in_address_p (coef, TYPE_MODE (type), as)) |
0 | 510 continue; |
511 | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
512 acost = multiply_by_cost (coef, address_mode, speed); |
0 | 513 |
514 if (acost > best_mult_cost) | |
515 { | |
516 best_mult_cost = acost; | |
517 best_mult = addr->elts[i].coef; | |
518 } | |
519 } | |
520 | |
521 if (!best_mult_cost) | |
522 return; | |
523 | |
524 /* Collect elements multiplied by best_mult. */ | |
525 for (i = j = 0; i < addr->n; i++) | |
526 { | |
527 amult = addr->elts[i].coef; | |
528 amult_neg = double_int_ext_for_comb (double_int_neg (amult), addr); | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
529 |
0 | 530 if (double_int_equal_p (amult, best_mult)) |
531 op_code = PLUS_EXPR; | |
532 else if (double_int_equal_p (amult_neg, best_mult)) | |
533 op_code = MINUS_EXPR; | |
534 else | |
535 { | |
536 addr->elts[j] = addr->elts[i]; | |
537 j++; | |
538 continue; | |
539 } | |
540 | |
541 elt = fold_convert (sizetype, addr->elts[i].val); | |
542 if (mult_elt) | |
543 mult_elt = fold_build2 (op_code, sizetype, mult_elt, elt); | |
544 else if (op_code == PLUS_EXPR) | |
545 mult_elt = elt; | |
546 else | |
547 mult_elt = fold_build1 (NEGATE_EXPR, sizetype, elt); | |
548 } | |
549 addr->n = j; | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
550 |
0 | 551 parts->index = mult_elt; |
552 parts->step = double_int_to_tree (sizetype, best_mult); | |
553 } | |
554 | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
555 /* Splits address ADDR for a memory access of type TYPE into PARTS. |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
556 If BASE_HINT is non-NULL, it specifies an SSA name to be used |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
557 preferentially as base of the reference. |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
558 |
0 | 559 TODO -- be more clever about the distribution of the elements of ADDR |
560 to PARTS. Some architectures do not support anything but single | |
561 register in address, possibly with a small integer offset; while | |
562 create_mem_ref will simplify the address to an acceptable shape | |
563 later, it would be more efficient to know that asking for complicated | |
564 addressing modes is useless. */ | |
565 | |
566 static void | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
567 addr_to_parts (tree type, aff_tree *addr, tree base_hint, |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
568 struct mem_address *parts, bool speed) |
0 | 569 { |
570 tree part; | |
571 unsigned i; | |
572 | |
573 parts->symbol = NULL_TREE; | |
574 parts->base = NULL_TREE; | |
575 parts->index = NULL_TREE; | |
576 parts->step = NULL_TREE; | |
577 | |
578 if (!double_int_zero_p (addr->offset)) | |
579 parts->offset = double_int_to_tree (sizetype, addr->offset); | |
580 else | |
581 parts->offset = NULL_TREE; | |
582 | |
583 /* Try to find a symbol. */ | |
584 move_fixed_address_to_symbol (parts, addr); | |
585 | |
586 /* First move the most expensive feasible multiplication | |
587 to index. */ | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
588 most_expensive_mult_to_index (type, parts, addr, speed); |
0 | 589 |
590 /* Try to find a base of the reference. Since at the moment | |
591 there is no reliable way how to distinguish between pointer and its | |
592 offset, this is just a guess. */ | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
593 if (!parts->symbol && base_hint) |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
594 move_hint_to_base (type, parts, base_hint, addr); |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
595 if (!parts->symbol && !parts->base) |
0 | 596 move_pointer_to_base (parts, addr); |
597 | |
598 /* Then try to process the remaining elements. */ | |
599 for (i = 0; i < addr->n; i++) | |
600 { | |
601 part = fold_convert (sizetype, addr->elts[i].val); | |
602 if (!double_int_one_p (addr->elts[i].coef)) | |
603 part = fold_build2 (MULT_EXPR, sizetype, part, | |
604 double_int_to_tree (sizetype, addr->elts[i].coef)); | |
605 add_to_parts (parts, part); | |
606 } | |
607 if (addr->rest) | |
608 add_to_parts (parts, fold_convert (sizetype, addr->rest)); | |
609 } | |
610 | |
611 /* Force the PARTS to register. */ | |
612 | |
613 static void | |
614 gimplify_mem_ref_parts (gimple_stmt_iterator *gsi, struct mem_address *parts) | |
615 { | |
616 if (parts->base) | |
617 parts->base = force_gimple_operand_gsi (gsi, parts->base, | |
618 true, NULL_TREE, | |
619 true, GSI_SAME_STMT); | |
620 if (parts->index) | |
621 parts->index = force_gimple_operand_gsi (gsi, parts->index, | |
622 true, NULL_TREE, | |
623 true, GSI_SAME_STMT); | |
624 } | |
625 | |
626 /* Creates and returns a TARGET_MEM_REF for address ADDR. If necessary | |
627 computations are emitted in front of GSI. TYPE is the mode | |
628 of created memory reference. */ | |
629 | |
630 tree | |
631 create_mem_ref (gimple_stmt_iterator *gsi, tree type, aff_tree *addr, | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
632 tree base_hint, bool speed) |
0 | 633 { |
634 tree mem_ref, tmp; | |
635 tree atype; | |
636 struct mem_address parts; | |
637 | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
638 addr_to_parts (type, addr, base_hint, &parts, speed); |
0 | 639 gimplify_mem_ref_parts (gsi, &parts); |
640 mem_ref = create_mem_ref_raw (type, &parts); | |
641 if (mem_ref) | |
642 return mem_ref; | |
643 | |
644 /* The expression is too complicated. Try making it simpler. */ | |
645 | |
646 if (parts.step && !integer_onep (parts.step)) | |
647 { | |
648 /* Move the multiplication to index. */ | |
649 gcc_assert (parts.index); | |
650 parts.index = force_gimple_operand_gsi (gsi, | |
651 fold_build2 (MULT_EXPR, sizetype, | |
652 parts.index, parts.step), | |
653 true, NULL_TREE, true, GSI_SAME_STMT); | |
654 parts.step = NULL_TREE; | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
655 |
0 | 656 mem_ref = create_mem_ref_raw (type, &parts); |
657 if (mem_ref) | |
658 return mem_ref; | |
659 } | |
660 | |
661 if (parts.symbol) | |
662 { | |
663 tmp = build_addr (parts.symbol, current_function_decl); | |
664 gcc_assert (is_gimple_val (tmp)); | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
665 |
0 | 666 /* Add the symbol to base, eventually forcing it to register. */ |
667 if (parts.base) | |
668 { | |
669 gcc_assert (useless_type_conversion_p | |
670 (sizetype, TREE_TYPE (parts.base))); | |
671 | |
672 if (parts.index) | |
673 { | |
674 atype = TREE_TYPE (tmp); | |
675 parts.base = force_gimple_operand_gsi (gsi, | |
676 fold_build2 (POINTER_PLUS_EXPR, atype, | |
677 tmp, | |
678 fold_convert (sizetype, parts.base)), | |
679 true, NULL_TREE, true, GSI_SAME_STMT); | |
680 } | |
681 else | |
682 { | |
683 parts.index = parts.base; | |
684 parts.base = tmp; | |
685 } | |
686 } | |
687 else | |
688 parts.base = tmp; | |
689 parts.symbol = NULL_TREE; | |
690 | |
691 mem_ref = create_mem_ref_raw (type, &parts); | |
692 if (mem_ref) | |
693 return mem_ref; | |
694 } | |
695 | |
696 if (parts.index) | |
697 { | |
698 /* Add index to base. */ | |
699 if (parts.base) | |
700 { | |
701 atype = TREE_TYPE (parts.base); | |
702 parts.base = force_gimple_operand_gsi (gsi, | |
703 fold_build2 (POINTER_PLUS_EXPR, atype, | |
704 parts.base, | |
705 parts.index), | |
706 true, NULL_TREE, true, GSI_SAME_STMT); | |
707 } | |
708 else | |
709 parts.base = parts.index; | |
710 parts.index = NULL_TREE; | |
711 | |
712 mem_ref = create_mem_ref_raw (type, &parts); | |
713 if (mem_ref) | |
714 return mem_ref; | |
715 } | |
716 | |
717 if (parts.offset && !integer_zerop (parts.offset)) | |
718 { | |
719 /* Try adding offset to base. */ | |
720 if (parts.base) | |
721 { | |
722 atype = TREE_TYPE (parts.base); | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
723 parts.base = force_gimple_operand_gsi (gsi, |
0 | 724 fold_build2 (POINTER_PLUS_EXPR, atype, |
725 parts.base, | |
726 fold_convert (sizetype, parts.offset)), | |
727 true, NULL_TREE, true, GSI_SAME_STMT); | |
728 } | |
729 else | |
730 parts.base = parts.offset; | |
731 | |
732 parts.offset = NULL_TREE; | |
733 | |
734 mem_ref = create_mem_ref_raw (type, &parts); | |
735 if (mem_ref) | |
736 return mem_ref; | |
737 } | |
738 | |
739 /* Verify that the address is in the simplest possible shape | |
740 (only a register). If we cannot create such a memory reference, | |
741 something is really wrong. */ | |
742 gcc_assert (parts.symbol == NULL_TREE); | |
743 gcc_assert (parts.index == NULL_TREE); | |
744 gcc_assert (!parts.step || integer_onep (parts.step)); | |
745 gcc_assert (!parts.offset || integer_zerop (parts.offset)); | |
746 gcc_unreachable (); | |
747 } | |
748 | |
749 /* Copies components of the address from OP to ADDR. */ | |
750 | |
751 void | |
752 get_address_description (tree op, struct mem_address *addr) | |
753 { | |
754 addr->symbol = TMR_SYMBOL (op); | |
755 addr->base = TMR_BASE (op); | |
756 addr->index = TMR_INDEX (op); | |
757 addr->step = TMR_STEP (op); | |
758 addr->offset = TMR_OFFSET (op); | |
759 } | |
760 | |
761 /* Copies the additional information attached to target_mem_ref FROM to TO. */ | |
762 | |
763 void | |
764 copy_mem_ref_info (tree to, tree from) | |
765 { | |
766 /* And the info about the original reference. */ | |
767 TMR_ORIGINAL (to) = TMR_ORIGINAL (from); | |
768 } | |
769 | |
770 /* Move constants in target_mem_ref REF to offset. Returns the new target | |
771 mem ref if anything changes, NULL_TREE otherwise. */ | |
772 | |
773 tree | |
774 maybe_fold_tmr (tree ref) | |
775 { | |
776 struct mem_address addr; | |
777 bool changed = false; | |
778 tree ret, off; | |
779 | |
780 get_address_description (ref, &addr); | |
781 | |
782 if (addr.base && TREE_CODE (addr.base) == INTEGER_CST) | |
783 { | |
784 if (addr.offset) | |
785 addr.offset = fold_binary_to_constant (PLUS_EXPR, sizetype, | |
786 addr.offset, | |
787 fold_convert (sizetype, addr.base)); | |
788 else | |
789 addr.offset = addr.base; | |
790 | |
791 addr.base = NULL_TREE; | |
792 changed = true; | |
793 } | |
794 | |
795 if (addr.index && TREE_CODE (addr.index) == INTEGER_CST) | |
796 { | |
797 off = addr.index; | |
798 if (addr.step) | |
799 { | |
800 off = fold_binary_to_constant (MULT_EXPR, sizetype, | |
801 off, addr.step); | |
802 addr.step = NULL_TREE; | |
803 } | |
804 | |
805 if (addr.offset) | |
806 { | |
807 addr.offset = fold_binary_to_constant (PLUS_EXPR, sizetype, | |
808 addr.offset, off); | |
809 } | |
810 else | |
811 addr.offset = off; | |
812 | |
813 addr.index = NULL_TREE; | |
814 changed = true; | |
815 } | |
816 | |
817 if (!changed) | |
818 return NULL_TREE; | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
819 |
0 | 820 ret = create_mem_ref_raw (TREE_TYPE (ref), &addr); |
821 if (!ret) | |
822 return NULL_TREE; | |
823 | |
824 copy_mem_ref_info (ret, ref); | |
825 return ret; | |
826 } | |
827 | |
828 /* Dump PARTS to FILE. */ | |
829 | |
830 extern void dump_mem_address (FILE *, struct mem_address *); | |
831 void | |
832 dump_mem_address (FILE *file, struct mem_address *parts) | |
833 { | |
834 if (parts->symbol) | |
835 { | |
836 fprintf (file, "symbol: "); | |
837 print_generic_expr (file, parts->symbol, TDF_SLIM); | |
838 fprintf (file, "\n"); | |
839 } | |
840 if (parts->base) | |
841 { | |
842 fprintf (file, "base: "); | |
843 print_generic_expr (file, parts->base, TDF_SLIM); | |
844 fprintf (file, "\n"); | |
845 } | |
846 if (parts->index) | |
847 { | |
848 fprintf (file, "index: "); | |
849 print_generic_expr (file, parts->index, TDF_SLIM); | |
850 fprintf (file, "\n"); | |
851 } | |
852 if (parts->step) | |
853 { | |
854 fprintf (file, "step: "); | |
855 print_generic_expr (file, parts->step, TDF_SLIM); | |
856 fprintf (file, "\n"); | |
857 } | |
858 if (parts->offset) | |
859 { | |
860 fprintf (file, "offset: "); | |
861 print_generic_expr (file, parts->offset, TDF_SLIM); | |
862 fprintf (file, "\n"); | |
863 } | |
864 } | |
865 | |
866 #include "gt-tree-ssa-address.h" |