Mercurial > hg > CbC > CbC_gcc
annotate gcc/tree-vect-generic.c @ 67:f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
author | nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp> |
---|---|
date | Tue, 22 Mar 2011 17:18:12 +0900 |
parents | b7f97abdc517 |
children | 04ced10e8804 |
rev | line source |
---|---|
0 | 1 /* Lower vector operations to scalar operations. |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2 Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010 |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
19
diff
changeset
|
3 Free Software Foundation, Inc. |
0 | 4 |
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:
19
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:
19
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:
19
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 #include "config.h" | |
22 #include "system.h" | |
23 #include "coretypes.h" | |
24 #include "tree.h" | |
25 #include "tm.h" | |
26 #include "langhooks.h" | |
27 #include "tree-flow.h" | |
28 #include "gimple.h" | |
29 #include "tree-iterator.h" | |
30 #include "tree-pass.h" | |
31 #include "flags.h" | |
32 #include "ggc.h" | |
33 | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
34 /* Need to include rtl.h, expr.h, etc. for optabs. */ |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
35 #include "expr.h" |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
36 #include "optabs.h" |
0 | 37 |
38 /* Build a constant of type TYPE, made of VALUE's bits replicated | |
39 every TYPE_SIZE (INNER_TYPE) bits to fit TYPE's precision. */ | |
40 static tree | |
41 build_replicated_const (tree type, tree inner_type, HOST_WIDE_INT value) | |
42 { | |
43 int width = tree_low_cst (TYPE_SIZE (inner_type), 1); | |
44 int n = HOST_BITS_PER_WIDE_INT / width; | |
45 unsigned HOST_WIDE_INT low, high, mask; | |
46 tree ret; | |
47 | |
48 gcc_assert (n); | |
49 | |
50 if (width == HOST_BITS_PER_WIDE_INT) | |
51 low = value; | |
52 else | |
53 { | |
54 mask = ((HOST_WIDE_INT)1 << width) - 1; | |
55 low = (unsigned HOST_WIDE_INT) ~0 / mask * (value & mask); | |
56 } | |
57 | |
58 if (TYPE_PRECISION (type) < HOST_BITS_PER_WIDE_INT) | |
59 low &= ((HOST_WIDE_INT)1 << TYPE_PRECISION (type)) - 1, high = 0; | |
60 else if (TYPE_PRECISION (type) == HOST_BITS_PER_WIDE_INT) | |
61 high = 0; | |
62 else if (TYPE_PRECISION (type) == 2 * HOST_BITS_PER_WIDE_INT) | |
63 high = low; | |
64 else | |
65 gcc_unreachable (); | |
66 | |
67 ret = build_int_cst_wide (type, low, high); | |
68 return ret; | |
69 } | |
70 | |
71 static GTY(()) tree vector_inner_type; | |
72 static GTY(()) tree vector_last_type; | |
73 static GTY(()) int vector_last_nunits; | |
74 | |
75 /* Return a suitable vector types made of SUBPARTS units each of mode | |
76 "word_mode" (the global variable). */ | |
77 static tree | |
78 build_word_mode_vector_type (int nunits) | |
79 { | |
80 if (!vector_inner_type) | |
81 vector_inner_type = lang_hooks.types.type_for_mode (word_mode, 1); | |
82 else if (vector_last_nunits == nunits) | |
83 { | |
84 gcc_assert (TREE_CODE (vector_last_type) == VECTOR_TYPE); | |
85 return vector_last_type; | |
86 } | |
87 | |
88 /* We build a new type, but we canonicalize it nevertheless, | |
89 because it still saves some memory. */ | |
90 vector_last_nunits = nunits; | |
91 vector_last_type = type_hash_canon (nunits, | |
92 build_vector_type (vector_inner_type, | |
93 nunits)); | |
94 return vector_last_type; | |
95 } | |
96 | |
97 typedef tree (*elem_op_func) (gimple_stmt_iterator *, | |
98 tree, tree, tree, tree, tree, enum tree_code); | |
99 | |
100 static inline tree | |
101 tree_vec_extract (gimple_stmt_iterator *gsi, tree type, | |
102 tree t, tree bitsize, tree bitpos) | |
103 { | |
104 if (bitpos) | |
105 return gimplify_build3 (gsi, BIT_FIELD_REF, type, t, bitsize, bitpos); | |
106 else | |
107 return gimplify_build1 (gsi, VIEW_CONVERT_EXPR, type, t); | |
108 } | |
109 | |
110 static tree | |
111 do_unop (gimple_stmt_iterator *gsi, tree inner_type, tree a, | |
112 tree b ATTRIBUTE_UNUSED, tree bitpos, tree bitsize, | |
113 enum tree_code code) | |
114 { | |
115 a = tree_vec_extract (gsi, inner_type, a, bitsize, bitpos); | |
116 return gimplify_build1 (gsi, code, inner_type, a); | |
117 } | |
118 | |
119 static tree | |
120 do_binop (gimple_stmt_iterator *gsi, tree inner_type, tree a, tree b, | |
121 tree bitpos, tree bitsize, enum tree_code code) | |
122 { | |
123 a = tree_vec_extract (gsi, inner_type, a, bitsize, bitpos); | |
124 b = tree_vec_extract (gsi, inner_type, b, bitsize, bitpos); | |
125 return gimplify_build2 (gsi, code, inner_type, a, b); | |
126 } | |
127 | |
128 /* Expand vector addition to scalars. This does bit twiddling | |
129 in order to increase parallelism: | |
130 | |
131 a + b = (((int) a & 0x7f7f7f7f) + ((int) b & 0x7f7f7f7f)) ^ | |
132 (a ^ b) & 0x80808080 | |
133 | |
134 a - b = (((int) a | 0x80808080) - ((int) b & 0x7f7f7f7f)) ^ | |
135 (a ^ ~b) & 0x80808080 | |
136 | |
137 -b = (0x80808080 - ((int) b & 0x7f7f7f7f)) ^ (~b & 0x80808080) | |
138 | |
139 This optimization should be done only if 4 vector items or more | |
140 fit into a word. */ | |
141 static tree | |
142 do_plus_minus (gimple_stmt_iterator *gsi, tree word_type, tree a, tree b, | |
143 tree bitpos ATTRIBUTE_UNUSED, tree bitsize ATTRIBUTE_UNUSED, | |
144 enum tree_code code) | |
145 { | |
146 tree inner_type = TREE_TYPE (TREE_TYPE (a)); | |
147 unsigned HOST_WIDE_INT max; | |
148 tree low_bits, high_bits, a_low, b_low, result_low, signs; | |
149 | |
150 max = GET_MODE_MASK (TYPE_MODE (inner_type)); | |
151 low_bits = build_replicated_const (word_type, inner_type, max >> 1); | |
152 high_bits = build_replicated_const (word_type, inner_type, max & ~(max >> 1)); | |
153 | |
154 a = tree_vec_extract (gsi, word_type, a, bitsize, bitpos); | |
155 b = tree_vec_extract (gsi, word_type, b, bitsize, bitpos); | |
156 | |
157 signs = gimplify_build2 (gsi, BIT_XOR_EXPR, word_type, a, b); | |
158 b_low = gimplify_build2 (gsi, BIT_AND_EXPR, word_type, b, low_bits); | |
159 if (code == PLUS_EXPR) | |
160 a_low = gimplify_build2 (gsi, BIT_AND_EXPR, word_type, a, low_bits); | |
161 else | |
162 { | |
163 a_low = gimplify_build2 (gsi, BIT_IOR_EXPR, word_type, a, high_bits); | |
164 signs = gimplify_build1 (gsi, BIT_NOT_EXPR, word_type, signs); | |
165 } | |
166 | |
167 signs = gimplify_build2 (gsi, BIT_AND_EXPR, word_type, signs, high_bits); | |
168 result_low = gimplify_build2 (gsi, code, word_type, a_low, b_low); | |
169 return gimplify_build2 (gsi, BIT_XOR_EXPR, word_type, result_low, signs); | |
170 } | |
171 | |
172 static tree | |
173 do_negate (gimple_stmt_iterator *gsi, tree word_type, tree b, | |
174 tree unused ATTRIBUTE_UNUSED, tree bitpos ATTRIBUTE_UNUSED, | |
175 tree bitsize ATTRIBUTE_UNUSED, | |
176 enum tree_code code ATTRIBUTE_UNUSED) | |
177 { | |
178 tree inner_type = TREE_TYPE (TREE_TYPE (b)); | |
179 HOST_WIDE_INT max; | |
180 tree low_bits, high_bits, b_low, result_low, signs; | |
181 | |
182 max = GET_MODE_MASK (TYPE_MODE (inner_type)); | |
183 low_bits = build_replicated_const (word_type, inner_type, max >> 1); | |
184 high_bits = build_replicated_const (word_type, inner_type, max & ~(max >> 1)); | |
185 | |
186 b = tree_vec_extract (gsi, word_type, b, bitsize, bitpos); | |
187 | |
188 b_low = gimplify_build2 (gsi, BIT_AND_EXPR, word_type, b, low_bits); | |
189 signs = gimplify_build1 (gsi, BIT_NOT_EXPR, word_type, b); | |
190 signs = gimplify_build2 (gsi, BIT_AND_EXPR, word_type, signs, high_bits); | |
191 result_low = gimplify_build2 (gsi, MINUS_EXPR, word_type, high_bits, b_low); | |
192 return gimplify_build2 (gsi, BIT_XOR_EXPR, word_type, result_low, signs); | |
193 } | |
194 | |
195 /* Expand a vector operation to scalars, by using many operations | |
196 whose type is the vector type's inner type. */ | |
197 static tree | |
198 expand_vector_piecewise (gimple_stmt_iterator *gsi, elem_op_func f, | |
199 tree type, tree inner_type, | |
200 tree a, tree b, enum tree_code code) | |
201 { | |
202 VEC(constructor_elt,gc) *v; | |
203 tree part_width = TYPE_SIZE (inner_type); | |
204 tree index = bitsize_int (0); | |
205 int nunits = TYPE_VECTOR_SUBPARTS (type); | |
206 int delta = tree_low_cst (part_width, 1) | |
207 / tree_low_cst (TYPE_SIZE (TREE_TYPE (type)), 1); | |
208 int i; | |
209 | |
210 v = VEC_alloc(constructor_elt, gc, (nunits + delta - 1) / delta); | |
211 for (i = 0; i < nunits; | |
212 i += delta, index = int_const_binop (PLUS_EXPR, index, part_width, 0)) | |
213 { | |
214 tree result = f (gsi, inner_type, a, b, index, part_width, code); | |
215 constructor_elt *ce = VEC_quick_push (constructor_elt, v, NULL); | |
216 ce->index = NULL_TREE; | |
217 ce->value = result; | |
218 } | |
219 | |
220 return build_constructor (type, v); | |
221 } | |
222 | |
223 /* Expand a vector operation to scalars with the freedom to use | |
224 a scalar integer type, or to use a different size for the items | |
225 in the vector type. */ | |
226 static tree | |
227 expand_vector_parallel (gimple_stmt_iterator *gsi, elem_op_func f, tree type, | |
228 tree a, tree b, | |
229 enum tree_code code) | |
230 { | |
231 tree result, compute_type; | |
232 enum machine_mode mode; | |
233 int n_words = tree_low_cst (TYPE_SIZE_UNIT (type), 1) / UNITS_PER_WORD; | |
234 | |
235 /* We have three strategies. If the type is already correct, just do | |
236 the operation an element at a time. Else, if the vector is wider than | |
237 one word, do it a word at a time; finally, if the vector is smaller | |
238 than one word, do it as a scalar. */ | |
239 if (TYPE_MODE (TREE_TYPE (type)) == word_mode) | |
240 return expand_vector_piecewise (gsi, f, | |
241 type, TREE_TYPE (type), | |
242 a, b, code); | |
243 else if (n_words > 1) | |
244 { | |
245 tree word_type = build_word_mode_vector_type (n_words); | |
246 result = expand_vector_piecewise (gsi, f, | |
247 word_type, TREE_TYPE (word_type), | |
248 a, b, code); | |
249 result = force_gimple_operand_gsi (gsi, result, true, NULL, true, | |
250 GSI_SAME_STMT); | |
251 } | |
252 else | |
253 { | |
254 /* Use a single scalar operation with a mode no wider than word_mode. */ | |
255 mode = mode_for_size (tree_low_cst (TYPE_SIZE (type), 1), MODE_INT, 0); | |
256 compute_type = lang_hooks.types.type_for_mode (mode, 1); | |
257 result = f (gsi, compute_type, a, b, NULL_TREE, NULL_TREE, code); | |
258 } | |
259 | |
260 return result; | |
261 } | |
262 | |
263 /* Expand a vector operation to scalars; for integer types we can use | |
264 special bit twiddling tricks to do the sums a word at a time, using | |
265 function F_PARALLEL instead of F. These tricks are done only if | |
266 they can process at least four items, that is, only if the vector | |
267 holds at least four items and if a word can hold four items. */ | |
268 static tree | |
269 expand_vector_addition (gimple_stmt_iterator *gsi, | |
270 elem_op_func f, elem_op_func f_parallel, | |
271 tree type, tree a, tree b, enum tree_code code) | |
272 { | |
273 int parts_per_word = UNITS_PER_WORD | |
274 / tree_low_cst (TYPE_SIZE_UNIT (TREE_TYPE (type)), 1); | |
275 | |
276 if (INTEGRAL_TYPE_P (TREE_TYPE (type)) | |
277 && parts_per_word >= 4 | |
278 && TYPE_VECTOR_SUBPARTS (type) >= 4) | |
279 return expand_vector_parallel (gsi, f_parallel, | |
280 type, a, b, code); | |
281 else | |
282 return expand_vector_piecewise (gsi, f, | |
283 type, TREE_TYPE (type), | |
284 a, b, code); | |
285 } | |
286 | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
287 /* Check if vector VEC consists of all the equal elements and |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
288 that the number of elements corresponds to the type of VEC. |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
289 The function returns first element of the vector |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
290 or NULL_TREE if the vector is not uniform. */ |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
291 static tree |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
292 uniform_vector_p (tree vec) |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
293 { |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
294 tree first, t, els; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
295 unsigned i; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
296 |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
297 if (vec == NULL_TREE) |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
298 return NULL_TREE; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
299 |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
300 if (TREE_CODE (vec) == VECTOR_CST) |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
301 { |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
302 els = TREE_VECTOR_CST_ELTS (vec); |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
303 first = TREE_VALUE (els); |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
304 els = TREE_CHAIN (els); |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
305 |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
306 for (t = els; t; t = TREE_CHAIN (t)) |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
307 if (!operand_equal_p (first, TREE_VALUE (t), 0)) |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
308 return NULL_TREE; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
309 |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
310 return first; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
311 } |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
312 |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
313 else if (TREE_CODE (vec) == CONSTRUCTOR) |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
314 { |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
315 first = error_mark_node; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
316 |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
317 FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (vec), i, t) |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
318 { |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
319 if (i == 0) |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
320 { |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
321 first = t; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
322 continue; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
323 } |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
324 if (!operand_equal_p (first, t, 0)) |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
325 return NULL_TREE; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
326 } |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
327 if (i != TYPE_VECTOR_SUBPARTS (TREE_TYPE (vec))) |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
328 return NULL_TREE; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
329 |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
330 return first; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
331 } |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
332 |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
333 return NULL_TREE; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
334 } |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
335 |
0 | 336 static tree |
337 expand_vector_operation (gimple_stmt_iterator *gsi, tree type, tree compute_type, | |
338 gimple assign, enum tree_code code) | |
339 { | |
340 enum machine_mode compute_mode = TYPE_MODE (compute_type); | |
341 | |
342 /* If the compute mode is not a vector mode (hence we are not decomposing | |
343 a BLKmode vector to smaller, hardware-supported vectors), we may want | |
344 to expand the operations in parallel. */ | |
345 if (GET_MODE_CLASS (compute_mode) != MODE_VECTOR_INT | |
346 && GET_MODE_CLASS (compute_mode) != MODE_VECTOR_FLOAT | |
347 && GET_MODE_CLASS (compute_mode) != MODE_VECTOR_FRACT | |
348 && GET_MODE_CLASS (compute_mode) != MODE_VECTOR_UFRACT | |
349 && GET_MODE_CLASS (compute_mode) != MODE_VECTOR_ACCUM | |
350 && GET_MODE_CLASS (compute_mode) != MODE_VECTOR_UACCUM) | |
351 switch (code) | |
352 { | |
353 case PLUS_EXPR: | |
354 case MINUS_EXPR: | |
355 if (!TYPE_OVERFLOW_TRAPS (type)) | |
356 return expand_vector_addition (gsi, do_binop, do_plus_minus, type, | |
357 gimple_assign_rhs1 (assign), | |
358 gimple_assign_rhs2 (assign), code); | |
359 break; | |
360 | |
361 case NEGATE_EXPR: | |
362 if (!TYPE_OVERFLOW_TRAPS (type)) | |
363 return expand_vector_addition (gsi, do_unop, do_negate, type, | |
364 gimple_assign_rhs1 (assign), | |
365 NULL_TREE, code); | |
366 break; | |
367 | |
368 case BIT_AND_EXPR: | |
369 case BIT_IOR_EXPR: | |
370 case BIT_XOR_EXPR: | |
371 return expand_vector_parallel (gsi, do_binop, type, | |
372 gimple_assign_rhs1 (assign), | |
373 gimple_assign_rhs2 (assign), code); | |
374 | |
375 case BIT_NOT_EXPR: | |
376 return expand_vector_parallel (gsi, do_unop, type, | |
377 gimple_assign_rhs1 (assign), | |
378 NULL_TREE, code); | |
379 | |
380 default: | |
381 break; | |
382 } | |
383 | |
384 if (TREE_CODE_CLASS (code) == tcc_unary) | |
385 return expand_vector_piecewise (gsi, do_unop, type, compute_type, | |
386 gimple_assign_rhs1 (assign), | |
387 NULL_TREE, code); | |
388 else | |
389 return expand_vector_piecewise (gsi, do_binop, type, compute_type, | |
390 gimple_assign_rhs1 (assign), | |
391 gimple_assign_rhs2 (assign), code); | |
392 } | |
393 | |
394 /* Return a type for the widest vector mode whose components are of mode | |
395 INNER_MODE, or NULL_TREE if none is found. | |
396 SATP is true for saturating fixed-point types. */ | |
397 | |
398 static tree | |
399 type_for_widest_vector_mode (enum machine_mode inner_mode, optab op, int satp) | |
400 { | |
401 enum machine_mode best_mode = VOIDmode, mode; | |
402 int best_nunits = 0; | |
403 | |
404 if (SCALAR_FLOAT_MODE_P (inner_mode)) | |
405 mode = MIN_MODE_VECTOR_FLOAT; | |
406 else if (SCALAR_FRACT_MODE_P (inner_mode)) | |
407 mode = MIN_MODE_VECTOR_FRACT; | |
408 else if (SCALAR_UFRACT_MODE_P (inner_mode)) | |
409 mode = MIN_MODE_VECTOR_UFRACT; | |
410 else if (SCALAR_ACCUM_MODE_P (inner_mode)) | |
411 mode = MIN_MODE_VECTOR_ACCUM; | |
412 else if (SCALAR_UACCUM_MODE_P (inner_mode)) | |
413 mode = MIN_MODE_VECTOR_UACCUM; | |
414 else | |
415 mode = MIN_MODE_VECTOR_INT; | |
416 | |
417 for (; mode != VOIDmode; mode = GET_MODE_WIDER_MODE (mode)) | |
418 if (GET_MODE_INNER (mode) == inner_mode | |
419 && GET_MODE_NUNITS (mode) > best_nunits | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
420 && optab_handler (op, mode) != CODE_FOR_nothing) |
0 | 421 best_mode = mode, best_nunits = GET_MODE_NUNITS (mode); |
422 | |
423 if (best_mode == VOIDmode) | |
424 return NULL_TREE; | |
425 else | |
426 { | |
427 /* For fixed-point modes, we need to pass satp as the 2nd parameter. */ | |
428 if (ALL_FIXED_POINT_MODE_P (best_mode)) | |
429 return lang_hooks.types.type_for_mode (best_mode, satp); | |
430 | |
431 return lang_hooks.types.type_for_mode (best_mode, 1); | |
432 } | |
433 } | |
434 | |
435 /* Process one statement. If we identify a vector operation, expand it. */ | |
436 | |
437 static void | |
438 expand_vector_operations_1 (gimple_stmt_iterator *gsi) | |
439 { | |
440 gimple stmt = gsi_stmt (*gsi); | |
441 tree lhs, rhs1, rhs2 = NULL, type, compute_type; | |
442 enum tree_code code; | |
443 enum machine_mode compute_mode; | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
444 optab op = NULL; |
0 | 445 enum gimple_rhs_class rhs_class; |
446 tree new_rhs; | |
447 | |
448 if (gimple_code (stmt) != GIMPLE_ASSIGN) | |
449 return; | |
450 | |
451 code = gimple_assign_rhs_code (stmt); | |
452 rhs_class = get_gimple_rhs_class (code); | |
453 | |
454 if (rhs_class != GIMPLE_UNARY_RHS && rhs_class != GIMPLE_BINARY_RHS) | |
455 return; | |
456 | |
457 lhs = gimple_assign_lhs (stmt); | |
458 rhs1 = gimple_assign_rhs1 (stmt); | |
459 type = gimple_expr_type (stmt); | |
460 if (rhs_class == GIMPLE_BINARY_RHS) | |
461 rhs2 = gimple_assign_rhs2 (stmt); | |
462 | |
463 if (TREE_CODE (type) != VECTOR_TYPE) | |
464 return; | |
465 | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
19
diff
changeset
|
466 if (code == NOP_EXPR |
0 | 467 || code == FLOAT_EXPR |
468 || code == FIX_TRUNC_EXPR | |
469 || code == VIEW_CONVERT_EXPR) | |
470 return; | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
19
diff
changeset
|
471 |
0 | 472 gcc_assert (code != CONVERT_EXPR); |
473 | |
474 /* The signedness is determined from input argument. */ | |
475 if (code == VEC_UNPACK_FLOAT_HI_EXPR | |
476 || code == VEC_UNPACK_FLOAT_LO_EXPR) | |
477 type = TREE_TYPE (rhs1); | |
478 | |
479 /* Choose between vector shift/rotate by vector and vector shift/rotate by | |
480 scalar */ | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
19
diff
changeset
|
481 if (code == LSHIFT_EXPR |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
19
diff
changeset
|
482 || code == RSHIFT_EXPR |
0 | 483 || code == LROTATE_EXPR |
484 || code == RROTATE_EXPR) | |
485 { | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
486 bool vector_scalar_shift; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
487 op = optab_for_tree_code (code, type, optab_scalar); |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
488 |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
489 /* Vector/Scalar shift is supported. */ |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
490 vector_scalar_shift = (op && (optab_handler (op, TYPE_MODE (type)) |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
491 != CODE_FOR_nothing)); |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
492 |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
493 /* If the 2nd argument is vector, we need a vector/vector shift. |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
494 Except all the elements in the second vector are the same. */ |
0 | 495 if (VECTOR_MODE_P (TYPE_MODE (TREE_TYPE (rhs2)))) |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
496 { |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
497 tree first; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
498 gimple def_stmt; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
499 |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
500 /* Check whether we have vector <op> {x,x,x,x} where x |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
501 could be a scalar variable or a constant. Transform |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
502 vector <op> {x,x,x,x} ==> vector <op> scalar. */ |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
503 if (vector_scalar_shift |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
504 && ((TREE_CODE (rhs2) == VECTOR_CST |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
505 && (first = uniform_vector_p (rhs2)) != NULL_TREE) |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
506 || (TREE_CODE (rhs2) == SSA_NAME |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
507 && (def_stmt = SSA_NAME_DEF_STMT (rhs2)) |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
508 && gimple_assign_single_p (def_stmt) |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
509 && (first = uniform_vector_p |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
510 (gimple_assign_rhs1 (def_stmt))) != NULL_TREE))) |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
511 { |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
512 gimple_assign_set_rhs2 (stmt, first); |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
513 update_stmt (stmt); |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
514 rhs2 = first; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
515 } |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
516 else |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
517 op = optab_for_tree_code (code, type, optab_vector); |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
518 } |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
519 |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
520 /* Try for a vector/scalar shift, and if we don't have one, see if we |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
521 have a vector/vector shift */ |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
522 else if (!vector_scalar_shift) |
0 | 523 { |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
524 op = optab_for_tree_code (code, type, optab_vector); |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
525 |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
526 if (op && (optab_handler (op, TYPE_MODE (type)) |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
527 != CODE_FOR_nothing)) |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
528 { |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
529 /* Transform vector <op> scalar => vector <op> {x,x,x,x}. */ |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
530 int n_parts = TYPE_VECTOR_SUBPARTS (type); |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
531 int part_size = tree_low_cst (TYPE_SIZE (TREE_TYPE (type)), 1); |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
532 tree part_type = lang_hooks.types.type_for_size (part_size, 1); |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
533 tree vect_type = build_vector_type (part_type, n_parts); |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
534 |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
535 rhs2 = fold_convert (part_type, rhs2); |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
536 rhs2 = build_vector_from_val (vect_type, rhs2); |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
537 gimple_assign_set_rhs2 (stmt, rhs2); |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
538 update_stmt (stmt); |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
539 } |
0 | 540 } |
541 } | |
542 else | |
543 op = optab_for_tree_code (code, type, optab_default); | |
544 | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
19
diff
changeset
|
545 /* For widening/narrowing vector operations, the relevant type is of the |
0 | 546 arguments, not the widened result. VEC_UNPACK_FLOAT_*_EXPR is |
547 calculated in the same way above. */ | |
548 if (code == WIDEN_SUM_EXPR | |
549 || code == VEC_WIDEN_MULT_HI_EXPR | |
550 || code == VEC_WIDEN_MULT_LO_EXPR | |
551 || code == VEC_UNPACK_HI_EXPR | |
552 || code == VEC_UNPACK_LO_EXPR | |
553 || code == VEC_PACK_TRUNC_EXPR | |
554 || code == VEC_PACK_SAT_EXPR | |
555 || code == VEC_PACK_FIX_TRUNC_EXPR) | |
556 type = TREE_TYPE (rhs1); | |
557 | |
558 /* Optabs will try converting a negation into a subtraction, so | |
559 look for it as well. TODO: negation of floating-point vectors | |
560 might be turned into an exclusive OR toggling the sign bit. */ | |
561 if (op == NULL | |
562 && code == NEGATE_EXPR | |
563 && INTEGRAL_TYPE_P (TREE_TYPE (type))) | |
564 op = optab_for_tree_code (MINUS_EXPR, type, optab_default); | |
565 | |
566 /* For very wide vectors, try using a smaller vector mode. */ | |
567 compute_type = type; | |
568 if (TYPE_MODE (type) == BLKmode && op) | |
569 { | |
570 tree vector_compute_type | |
571 = type_for_widest_vector_mode (TYPE_MODE (TREE_TYPE (type)), op, | |
572 TYPE_SATURATING (TREE_TYPE (type))); | |
19
58ad6c70ea60
update gcc from 4.4.0 to 4.4.1.
kent@firefly.cr.ie.u-ryukyu.ac.jp
parents:
0
diff
changeset
|
573 if (vector_compute_type != NULL_TREE |
58ad6c70ea60
update gcc from 4.4.0 to 4.4.1.
kent@firefly.cr.ie.u-ryukyu.ac.jp
parents:
0
diff
changeset
|
574 && (TYPE_VECTOR_SUBPARTS (vector_compute_type) |
58ad6c70ea60
update gcc from 4.4.0 to 4.4.1.
kent@firefly.cr.ie.u-ryukyu.ac.jp
parents:
0
diff
changeset
|
575 < TYPE_VECTOR_SUBPARTS (compute_type))) |
58ad6c70ea60
update gcc from 4.4.0 to 4.4.1.
kent@firefly.cr.ie.u-ryukyu.ac.jp
parents:
0
diff
changeset
|
576 compute_type = vector_compute_type; |
0 | 577 } |
578 | |
579 /* If we are breaking a BLKmode vector into smaller pieces, | |
580 type_for_widest_vector_mode has already looked into the optab, | |
581 so skip these checks. */ | |
582 if (compute_type == type) | |
583 { | |
584 compute_mode = TYPE_MODE (compute_type); | |
585 if ((GET_MODE_CLASS (compute_mode) == MODE_VECTOR_INT | |
586 || GET_MODE_CLASS (compute_mode) == MODE_VECTOR_FLOAT | |
587 || GET_MODE_CLASS (compute_mode) == MODE_VECTOR_FRACT | |
588 || GET_MODE_CLASS (compute_mode) == MODE_VECTOR_UFRACT | |
589 || GET_MODE_CLASS (compute_mode) == MODE_VECTOR_ACCUM | |
590 || GET_MODE_CLASS (compute_mode) == MODE_VECTOR_UACCUM) | |
591 && op != NULL | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
592 && optab_handler (op, compute_mode) != CODE_FOR_nothing) |
0 | 593 return; |
594 else | |
595 /* There is no operation in hardware, so fall back to scalars. */ | |
596 compute_type = TREE_TYPE (type); | |
597 } | |
598 | |
599 gcc_assert (code != VEC_LSHIFT_EXPR && code != VEC_RSHIFT_EXPR); | |
600 new_rhs = expand_vector_operation (gsi, type, compute_type, stmt, code); | |
601 if (!useless_type_conversion_p (TREE_TYPE (lhs), TREE_TYPE (new_rhs))) | |
602 new_rhs = gimplify_build1 (gsi, VIEW_CONVERT_EXPR, TREE_TYPE (lhs), | |
603 new_rhs); | |
604 | |
605 /* NOTE: We should avoid using gimple_assign_set_rhs_from_tree. One | |
606 way to do it is change expand_vector_operation and its callees to | |
607 return a tree_code, RHS1 and RHS2 instead of a tree. */ | |
608 gimple_assign_set_rhs_from_tree (gsi, new_rhs); | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
609 update_stmt (gsi_stmt (*gsi)); |
0 | 610 } |
611 | |
612 /* Use this to lower vector operations introduced by the vectorizer, | |
613 if it may need the bit-twiddling tricks implemented in this file. */ | |
614 | |
615 static bool | |
616 gate_expand_vector_operations (void) | |
617 { | |
618 return flag_tree_vectorize != 0; | |
619 } | |
620 | |
621 static unsigned int | |
622 expand_vector_operations (void) | |
623 { | |
624 gimple_stmt_iterator gsi; | |
625 basic_block bb; | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
626 bool cfg_changed = false; |
0 | 627 |
628 FOR_EACH_BB (bb) | |
629 { | |
630 for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi)) | |
631 { | |
632 expand_vector_operations_1 (&gsi); | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
633 /* ??? If we do not cleanup EH then we will ICE in |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
634 verification. But in reality we have created wrong-code |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
635 as we did not properly transition EH info and edges to |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
636 the piecewise computations. */ |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
637 if (maybe_clean_eh_stmt (gsi_stmt (gsi)) |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
638 && gimple_purge_dead_eh_edges (bb)) |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
639 cfg_changed = true; |
0 | 640 } |
641 } | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
642 |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
643 return cfg_changed ? TODO_cleanup_cfg : 0; |
0 | 644 } |
645 | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
19
diff
changeset
|
646 struct gimple_opt_pass pass_lower_vector = |
0 | 647 { |
648 { | |
649 GIMPLE_PASS, | |
650 "veclower", /* name */ | |
651 0, /* gate */ | |
652 expand_vector_operations, /* execute */ | |
653 NULL, /* sub */ | |
654 NULL, /* next */ | |
655 0, /* static_pass_number */ | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
19
diff
changeset
|
656 TV_NONE, /* tv_id */ |
0 | 657 PROP_cfg, /* properties_required */ |
658 0, /* properties_provided */ | |
659 0, /* properties_destroyed */ | |
660 0, /* todo_flags_start */ | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
661 TODO_dump_func | TODO_update_ssa /* todo_flags_finish */ |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
662 | TODO_verify_ssa |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
663 | TODO_verify_stmts | TODO_verify_flow |
0 | 664 } |
665 }; | |
666 | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
19
diff
changeset
|
667 struct gimple_opt_pass pass_lower_vector_ssa = |
0 | 668 { |
669 { | |
670 GIMPLE_PASS, | |
671 "veclower2", /* name */ | |
672 gate_expand_vector_operations, /* gate */ | |
673 expand_vector_operations, /* execute */ | |
674 NULL, /* sub */ | |
675 NULL, /* next */ | |
676 0, /* static_pass_number */ | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
19
diff
changeset
|
677 TV_NONE, /* tv_id */ |
0 | 678 PROP_cfg, /* properties_required */ |
679 0, /* properties_provided */ | |
680 0, /* properties_destroyed */ | |
681 0, /* todo_flags_start */ | |
682 TODO_dump_func | TODO_update_ssa /* todo_flags_finish */ | |
683 | TODO_verify_ssa | |
684 | TODO_verify_stmts | TODO_verify_flow | |
685 } | |
686 }; | |
687 | |
688 #include "gt-tree-vect-generic.h" |