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