diff options
Diffstat (limited to 'recipes-devtools/gcc/gcc-4.5/linaro/gcc-4.5-linaro-r99396.patch')
-rw-r--r-- | recipes-devtools/gcc/gcc-4.5/linaro/gcc-4.5-linaro-r99396.patch | 1760 |
1 files changed, 1760 insertions, 0 deletions
diff --git a/recipes-devtools/gcc/gcc-4.5/linaro/gcc-4.5-linaro-r99396.patch b/recipes-devtools/gcc/gcc-4.5/linaro/gcc-4.5-linaro-r99396.patch new file mode 100644 index 0000000000..655399ab11 --- /dev/null +++ b/recipes-devtools/gcc/gcc-4.5/linaro/gcc-4.5-linaro-r99396.patch | |||
@@ -0,0 +1,1760 @@ | |||
1 | 2010-09-15 Chung-Lin Tang <cltang@codesourcery.com> | ||
2 | |||
3 | Issue #9441 | ||
4 | |||
5 | Backport from mainline: | ||
6 | |||
7 | 2010-06-25 Bernd Schmidt <bernds@codesourcery.com> | ||
8 | |||
9 | With large parts from Jim Wilson: | ||
10 | PR target/43902 | ||
11 | |||
12 | gcc/ | ||
13 | * tree-pretty-print.c (dump_generic_node, op_code_prio): Add | ||
14 | WIDEN_MULT_PLUS_EXPR and WIDEN_MULT_MINUS_EXPR. | ||
15 | * optabs.c (optab_for_tree_code): Likewise. | ||
16 | (expand_widen_pattern_expr): Likewise. | ||
17 | * tree-ssa-math-opts.c (convert_mult_to_widen): New function, broken | ||
18 | out of execute_optimize_widening_mul. | ||
19 | (convert_plusminus_to_widen): New function. | ||
20 | (execute_optimize_widening_mul): Use the two new functions. | ||
21 | * expr.c (expand_expr_real_2): Add support for GIMPLE_TERNARY_RHS. | ||
22 | Remove code to generate widening multiply-accumulate. Add support | ||
23 | for WIDEN_MULT_PLUS_EXPR and WIDEN_MULT_MINUS_EXPR. | ||
24 | * gimple-pretty-print.c (dump_ternary_rhs): New function. | ||
25 | (dump_gimple_assign): Call it when appropriate. | ||
26 | * tree.def (WIDEN_MULT_PLUS_EXPR, WIDEN_MULT_MINUS_EXPR): New codes. | ||
27 | * cfgexpand.c (gimple_assign_rhs_to_tree): Likewise. | ||
28 | (expand_gimple_stmt_1): Likewise. | ||
29 | (expand_debug_expr): Support WIDEN_MULT_PLUS_EXPR and | ||
30 | WIDEN_MULT_MINUS_EXPR. | ||
31 | * tree-ssa-operands.c (get_expr_operands): Likewise. | ||
32 | * tree-inline.c (estimate_operator_cost): Likewise. | ||
33 | * gimple.c (extract_ops_from_tree_1): Renamed from | ||
34 | extract_ops_from_tree. Add new arg for a third operand; fill it. | ||
35 | (gimple_build_assign_stat): Support operations with three operands. | ||
36 | (gimple_build_assign_with_ops_stat): Likewise. | ||
37 | (gimple_assign_set_rhs_from_tree): Likewise. | ||
38 | (gimple_assign_set_rhs_with_ops_1): Renamed from | ||
39 | gimple_assign_set_rhs_with_ops. Add new arg for a third operand. | ||
40 | (get_gimple_rhs_num_ops): Support GIMPLE_TERNARY_RHS. | ||
41 | (get_gimple_rhs_num_ops): Handle WIDEN_MULT_PLUS_EXPR and | ||
42 | WIDEN_MULT_MINUS_EXPR. | ||
43 | * gimple.h (enum gimple_rhs_class): Add GIMPLE_TERNARY_RHS. | ||
44 | (extract_ops_from_tree_1): Adjust declaration. | ||
45 | (gimple_assign_set_rhs_with_ops_1): Likewise. | ||
46 | (gimple_build_assign_with_ops): Pass NULL for last operand. | ||
47 | (gimple_build_assign_with_ops3): New macro. | ||
48 | (gimple_assign_rhs3, gimple_assign_rhs3_ptr, gimple_assign_set_rhs3, | ||
49 | gimple_assign_set_rhs_with_ops, extract_ops_from_tree): New inline | ||
50 | functions. | ||
51 | * tree-cfg.c (verify_gimple_assign_ternary): New static function. | ||
52 | (verify_gimple_assign): Call it. | ||
53 | * doc/gimple.texi (Manipulating operands): Document GIMPLE_TERNARY_RHS. | ||
54 | (Tuple specific accessors, subsection GIMPLE_ASSIGN): Document new | ||
55 | functions for dealing with three-operand statements. | ||
56 | * tree.c (commutative_ternary_tree_code): New function. | ||
57 | * tree.h (commutative_ternary_tree_code): Declare it. | ||
58 | * tree-vrp.c (gimple_assign_nonnegative_warnv_p): Return false for | ||
59 | ternary statements. | ||
60 | (gimple_assign_nonzero_warnv_p): Likewise. | ||
61 | * tree-ssa-sccvn.c (stmt_has_constants): Handle GIMPLE_TERNARY_RHS. | ||
62 | * tree-ssa-ccp.c (get_rhs_assign_op_for_ccp): New static function. | ||
63 | (ccp_fold): Use it. Handle GIMPLE_TERNARY_RHS. | ||
64 | * tree-ssa-dom.c (enum expr_kind): Add EXPR_TERNARY. | ||
65 | (struct hashtable_expr): New member ternary in the union. | ||
66 | (initialize_hash_element): Handle GIMPLE_TERNARY_RHS. | ||
67 | (hashable_expr_equal_p): Fix indentation. Handle EXPR_TERNARY. | ||
68 | (iterative_hash_hashable_expr): Likewise. | ||
69 | (print_expr_hash_elt): Handle EXPR_TERNARY. | ||
70 | * gimple-fold.c (fold_gimple_assign): Handle GIMPLE_TERNARY_RHS. | ||
71 | * tree-ssa-threadedge.c (fold_assignment_stmt): Remove useless break | ||
72 | statements. Handle GIMPLE_TERNARY_RHS. | ||
73 | |||
74 | From Jim Wilson: | ||
75 | gcc/testsuite/ | ||
76 | * gcc.target/mips/madd-9.c: New test. | ||
77 | |||
78 | 2010-06-29 Bernd Schmidt <bernds@codesourcery.com> | ||
79 | |||
80 | PR target/43902 | ||
81 | gcc/ | ||
82 | * config/arm/arm.md (maddsidi4, umaddsidi4): New expanders. | ||
83 | (maddhisi4): Renamed from mulhisi3addsi. Operands renumbered. | ||
84 | (maddhidi4): Likewise. | ||
85 | |||
86 | gcc/testsuite/ | ||
87 | * gcc.target/arm/wmul-1.c: Test for smlabb instead of smulbb. | ||
88 | * gcc.target/arm/wmul-3.c: New test. | ||
89 | * gcc.target/arm/wmul-4.c: New test. | ||
90 | |||
91 | 2010-07-22 Richard Sandiford <rdsandiford@googlemail.com> | ||
92 | |||
93 | gcc/ | ||
94 | * tree-ssa-math-opts.c (is_widening_mult_rhs_p): New function. | ||
95 | (is_widening_mult_p): Likewise. | ||
96 | (convert_to_widen): Use them. | ||
97 | (convert_plusminus_to_widen): Likewise. Handle fixed-point types as | ||
98 | well as integer ones. | ||
99 | |||
100 | 2010-07-31 Richard Sandiford <rdsandiford@googlemail.com> | ||
101 | |||
102 | gcc/ | ||
103 | * tree-ssa-math-opts.c (convert_plusminus_to_widen): Fix type | ||
104 | used in the call to optab_for_tree_code. Fix the second | ||
105 | is_widening_mult_p call. Check that both unwidened operands | ||
106 | have the same sign. | ||
107 | |||
108 | 2010-09-15 Jie Zhang <jie@codesourcery.com> | ||
109 | |||
110 | Backport from mainline: | ||
111 | |||
112 | === modified file 'gcc/cfgexpand.c' | ||
113 | --- old/gcc/cfgexpand.c 2010-09-01 13:29:58 +0000 | ||
114 | +++ new/gcc/cfgexpand.c 2010-09-16 09:15:46 +0000 | ||
115 | @@ -64,7 +64,13 @@ | ||
116 | |||
117 | grhs_class = get_gimple_rhs_class (gimple_expr_code (stmt)); | ||
118 | |||
119 | - if (grhs_class == GIMPLE_BINARY_RHS) | ||
120 | + if (grhs_class == GIMPLE_TERNARY_RHS) | ||
121 | + t = build3 (gimple_assign_rhs_code (stmt), | ||
122 | + TREE_TYPE (gimple_assign_lhs (stmt)), | ||
123 | + gimple_assign_rhs1 (stmt), | ||
124 | + gimple_assign_rhs2 (stmt), | ||
125 | + gimple_assign_rhs3 (stmt)); | ||
126 | + else if (grhs_class == GIMPLE_BINARY_RHS) | ||
127 | t = build2 (gimple_assign_rhs_code (stmt), | ||
128 | TREE_TYPE (gimple_assign_lhs (stmt)), | ||
129 | gimple_assign_rhs1 (stmt), | ||
130 | @@ -1887,6 +1893,9 @@ | ||
131 | ops.type = TREE_TYPE (lhs); | ||
132 | switch (get_gimple_rhs_class (gimple_expr_code (stmt))) | ||
133 | { | ||
134 | + case GIMPLE_TERNARY_RHS: | ||
135 | + ops.op2 = gimple_assign_rhs3 (stmt); | ||
136 | + /* Fallthru */ | ||
137 | case GIMPLE_BINARY_RHS: | ||
138 | ops.op1 = gimple_assign_rhs2 (stmt); | ||
139 | /* Fallthru */ | ||
140 | @@ -2237,6 +2246,8 @@ | ||
141 | { | ||
142 | case COND_EXPR: | ||
143 | case DOT_PROD_EXPR: | ||
144 | + case WIDEN_MULT_PLUS_EXPR: | ||
145 | + case WIDEN_MULT_MINUS_EXPR: | ||
146 | goto ternary; | ||
147 | |||
148 | case TRUTH_ANDIF_EXPR: | ||
149 | @@ -3023,6 +3034,8 @@ | ||
150 | return NULL; | ||
151 | |||
152 | case WIDEN_MULT_EXPR: | ||
153 | + case WIDEN_MULT_PLUS_EXPR: | ||
154 | + case WIDEN_MULT_MINUS_EXPR: | ||
155 | if (SCALAR_INT_MODE_P (GET_MODE (op0)) | ||
156 | && SCALAR_INT_MODE_P (mode)) | ||
157 | { | ||
158 | @@ -3035,7 +3048,13 @@ | ||
159 | op1 = simplify_gen_unary (ZERO_EXTEND, mode, op1, inner_mode); | ||
160 | else | ||
161 | op1 = simplify_gen_unary (SIGN_EXTEND, mode, op1, inner_mode); | ||
162 | - return gen_rtx_MULT (mode, op0, op1); | ||
163 | + op0 = gen_rtx_MULT (mode, op0, op1); | ||
164 | + if (TREE_CODE (exp) == WIDEN_MULT_EXPR) | ||
165 | + return op0; | ||
166 | + else if (TREE_CODE (exp) == WIDEN_MULT_PLUS_EXPR) | ||
167 | + return gen_rtx_PLUS (mode, op0, op2); | ||
168 | + else | ||
169 | + return gen_rtx_MINUS (mode, op2, op0); | ||
170 | } | ||
171 | return NULL; | ||
172 | |||
173 | |||
174 | === modified file 'gcc/config/arm/arm.md' | ||
175 | --- old/gcc/config/arm/arm.md 2010-09-15 16:55:55 +0000 | ||
176 | +++ new/gcc/config/arm/arm.md 2010-09-16 09:15:46 +0000 | ||
177 | @@ -1507,7 +1507,15 @@ | ||
178 | (set_attr "predicable" "yes")] | ||
179 | ) | ||
180 | |||
181 | -;; Unnamed template to match long long multiply-accumulate (smlal) | ||
182 | +(define_expand "maddsidi4" | ||
183 | + [(set (match_operand:DI 0 "s_register_operand" "") | ||
184 | + (plus:DI | ||
185 | + (mult:DI | ||
186 | + (sign_extend:DI (match_operand:SI 1 "s_register_operand" "")) | ||
187 | + (sign_extend:DI (match_operand:SI 2 "s_register_operand" ""))) | ||
188 | + (match_operand:DI 3 "s_register_operand" "")))] | ||
189 | + "TARGET_32BIT && arm_arch3m" | ||
190 | + "") | ||
191 | |||
192 | (define_insn "*mulsidi3adddi" | ||
193 | [(set (match_operand:DI 0 "s_register_operand" "=&r") | ||
194 | @@ -1603,7 +1611,15 @@ | ||
195 | (set_attr "predicable" "yes")] | ||
196 | ) | ||
197 | |||
198 | -;; Unnamed template to match long long unsigned multiply-accumulate (umlal) | ||
199 | +(define_expand "umaddsidi4" | ||
200 | + [(set (match_operand:DI 0 "s_register_operand" "") | ||
201 | + (plus:DI | ||
202 | + (mult:DI | ||
203 | + (zero_extend:DI (match_operand:SI 1 "s_register_operand" "")) | ||
204 | + (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))) | ||
205 | + (match_operand:DI 3 "s_register_operand" "")))] | ||
206 | + "TARGET_32BIT && arm_arch3m" | ||
207 | + "") | ||
208 | |||
209 | (define_insn "*umulsidi3adddi" | ||
210 | [(set (match_operand:DI 0 "s_register_operand" "=&r") | ||
211 | @@ -1771,29 +1787,29 @@ | ||
212 | (set_attr "predicable" "yes")] | ||
213 | ) | ||
214 | |||
215 | -(define_insn "*mulhisi3addsi" | ||
216 | +(define_insn "maddhisi4" | ||
217 | [(set (match_operand:SI 0 "s_register_operand" "=r") | ||
218 | - (plus:SI (match_operand:SI 1 "s_register_operand" "r") | ||
219 | + (plus:SI (match_operand:SI 3 "s_register_operand" "r") | ||
220 | (mult:SI (sign_extend:SI | ||
221 | - (match_operand:HI 2 "s_register_operand" "%r")) | ||
222 | + (match_operand:HI 1 "s_register_operand" "%r")) | ||
223 | (sign_extend:SI | ||
224 | - (match_operand:HI 3 "s_register_operand" "r")))))] | ||
225 | + (match_operand:HI 2 "s_register_operand" "r")))))] | ||
226 | "TARGET_DSP_MULTIPLY" | ||
227 | - "smlabb%?\\t%0, %2, %3, %1" | ||
228 | + "smlabb%?\\t%0, %1, %2, %3" | ||
229 | [(set_attr "insn" "smlaxy") | ||
230 | (set_attr "predicable" "yes")] | ||
231 | ) | ||
232 | |||
233 | -(define_insn "*mulhidi3adddi" | ||
234 | +(define_insn "*maddhidi4" | ||
235 | [(set (match_operand:DI 0 "s_register_operand" "=r") | ||
236 | (plus:DI | ||
237 | - (match_operand:DI 1 "s_register_operand" "0") | ||
238 | + (match_operand:DI 3 "s_register_operand" "0") | ||
239 | (mult:DI (sign_extend:DI | ||
240 | - (match_operand:HI 2 "s_register_operand" "%r")) | ||
241 | + (match_operand:HI 1 "s_register_operand" "%r")) | ||
242 | (sign_extend:DI | ||
243 | - (match_operand:HI 3 "s_register_operand" "r")))))] | ||
244 | + (match_operand:HI 2 "s_register_operand" "r")))))] | ||
245 | "TARGET_DSP_MULTIPLY" | ||
246 | - "smlalbb%?\\t%Q0, %R0, %2, %3" | ||
247 | + "smlalbb%?\\t%Q0, %R0, %1, %2" | ||
248 | [(set_attr "insn" "smlalxy") | ||
249 | (set_attr "predicable" "yes")]) | ||
250 | |||
251 | |||
252 | === modified file 'gcc/doc/gimple.texi' | ||
253 | --- old/gcc/doc/gimple.texi 2010-07-06 19:23:53 +0000 | ||
254 | +++ new/gcc/doc/gimple.texi 2010-09-16 09:15:46 +0000 | ||
255 | @@ -554,6 +554,9 @@ | ||
256 | @item @code{GIMPLE_INVALID_RHS} | ||
257 | The tree cannot be used as a GIMPLE operand. | ||
258 | |||
259 | +@item @code{GIMPLE_TERNARY_RHS} | ||
260 | +The tree is a valid GIMPLE ternary operation. | ||
261 | + | ||
262 | @item @code{GIMPLE_BINARY_RHS} | ||
263 | The tree is a valid GIMPLE binary operation. | ||
264 | |||
265 | @@ -575,10 +578,11 @@ | ||
266 | expressions should be flattened into the operand vector. | ||
267 | @end itemize | ||
268 | |||
269 | -For tree nodes in the categories @code{GIMPLE_BINARY_RHS} and | ||
270 | -@code{GIMPLE_UNARY_RHS}, they cannot be stored inside tuples directly. | ||
271 | -They first need to be flattened and separated into individual | ||
272 | -components. For instance, given the GENERIC expression | ||
273 | +For tree nodes in the categories @code{GIMPLE_TERNARY_RHS}, | ||
274 | +@code{GIMPLE_BINARY_RHS} and @code{GIMPLE_UNARY_RHS}, they cannot be | ||
275 | +stored inside tuples directly. They first need to be flattened and | ||
276 | +separated into individual components. For instance, given the GENERIC | ||
277 | +expression | ||
278 | |||
279 | @smallexample | ||
280 | a = b + c | ||
281 | @@ -1082,7 +1086,16 @@ | ||
282 | Return the address of the second operand on the @code{RHS} of assignment | ||
283 | statement @code{G}. | ||
284 | @end deftypefn | ||
285 | + | ||
286 | +@deftypefn {GIMPLE function} tree gimple_assign_rhs3 (gimple g) | ||
287 | +Return the third operand on the @code{RHS} of assignment statement @code{G}. | ||
288 | +@end deftypefn | ||
289 | |||
290 | +@deftypefn {GIMPLE function} tree *gimple_assign_rhs3_ptr (gimple g) | ||
291 | +Return the address of the third operand on the @code{RHS} of assignment | ||
292 | +statement @code{G}. | ||
293 | +@end deftypefn | ||
294 | + | ||
295 | @deftypefn {GIMPLE function} void gimple_assign_set_lhs (gimple g, tree lhs) | ||
296 | Set @code{LHS} to be the @code{LHS} operand of assignment statement @code{G}. | ||
297 | @end deftypefn | ||
298 | @@ -1092,20 +1105,16 @@ | ||
299 | statement @code{G}. | ||
300 | @end deftypefn | ||
301 | |||
302 | -@deftypefn {GIMPLE function} tree gimple_assign_rhs2 (gimple g) | ||
303 | -Return the second operand on the @code{RHS} of assignment statement @code{G}. | ||
304 | -@end deftypefn | ||
305 | - | ||
306 | -@deftypefn {GIMPLE function} tree *gimple_assign_rhs2_ptr (gimple g) | ||
307 | -Return a pointer to the second operand on the @code{RHS} of assignment | ||
308 | -statement @code{G}. | ||
309 | -@end deftypefn | ||
310 | - | ||
311 | @deftypefn {GIMPLE function} void gimple_assign_set_rhs2 (gimple g, tree rhs) | ||
312 | Set @code{RHS} to be the second operand on the @code{RHS} of assignment | ||
313 | statement @code{G}. | ||
314 | @end deftypefn | ||
315 | |||
316 | +@deftypefn {GIMPLE function} void gimple_assign_set_rhs3 (gimple g, tree rhs) | ||
317 | +Set @code{RHS} to be the third operand on the @code{RHS} of assignment | ||
318 | +statement @code{G}. | ||
319 | +@end deftypefn | ||
320 | + | ||
321 | @deftypefn {GIMPLE function} bool gimple_assign_cast_p (gimple s) | ||
322 | Return true if @code{S} is a type-cast assignment. | ||
323 | @end deftypefn | ||
324 | |||
325 | === modified file 'gcc/expr.c' | ||
326 | --- old/gcc/expr.c 2010-09-01 13:29:58 +0000 | ||
327 | +++ new/gcc/expr.c 2010-09-16 09:15:46 +0000 | ||
328 | @@ -7225,8 +7225,6 @@ | ||
329 | rtx subtarget, original_target; | ||
330 | int ignore; | ||
331 | bool reduce_bit_field; | ||
332 | - gimple subexp0_def, subexp1_def; | ||
333 | - tree top0, top1; | ||
334 | location_t loc = ops->location; | ||
335 | tree treeop0, treeop1; | ||
336 | #define REDUCE_BIT_FIELD(expr) (reduce_bit_field \ | ||
337 | @@ -7246,7 +7244,8 @@ | ||
338 | exactly those that are valid in gimple expressions that aren't | ||
339 | GIMPLE_SINGLE_RHS (or invalid). */ | ||
340 | gcc_assert (get_gimple_rhs_class (code) == GIMPLE_UNARY_RHS | ||
341 | - || get_gimple_rhs_class (code) == GIMPLE_BINARY_RHS); | ||
342 | + || get_gimple_rhs_class (code) == GIMPLE_BINARY_RHS | ||
343 | + || get_gimple_rhs_class (code) == GIMPLE_TERNARY_RHS); | ||
344 | |||
345 | ignore = (target == const0_rtx | ||
346 | || ((CONVERT_EXPR_CODE_P (code) | ||
347 | @@ -7421,58 +7420,6 @@ | ||
348 | fold_convert_loc (loc, ssizetype, | ||
349 | treeop1)); | ||
350 | case PLUS_EXPR: | ||
351 | - | ||
352 | - /* Check if this is a case for multiplication and addition. */ | ||
353 | - if ((TREE_CODE (type) == INTEGER_TYPE | ||
354 | - || TREE_CODE (type) == FIXED_POINT_TYPE) | ||
355 | - && (subexp0_def = get_def_for_expr (treeop0, | ||
356 | - MULT_EXPR))) | ||
357 | - { | ||
358 | - tree subsubexp0, subsubexp1; | ||
359 | - gimple subsubexp0_def, subsubexp1_def; | ||
360 | - enum tree_code this_code; | ||
361 | - | ||
362 | - this_code = TREE_CODE (type) == INTEGER_TYPE ? NOP_EXPR | ||
363 | - : FIXED_CONVERT_EXPR; | ||
364 | - subsubexp0 = gimple_assign_rhs1 (subexp0_def); | ||
365 | - subsubexp0_def = get_def_for_expr (subsubexp0, this_code); | ||
366 | - subsubexp1 = gimple_assign_rhs2 (subexp0_def); | ||
367 | - subsubexp1_def = get_def_for_expr (subsubexp1, this_code); | ||
368 | - if (subsubexp0_def && subsubexp1_def | ||
369 | - && (top0 = gimple_assign_rhs1 (subsubexp0_def)) | ||
370 | - && (top1 = gimple_assign_rhs1 (subsubexp1_def)) | ||
371 | - && (TYPE_PRECISION (TREE_TYPE (top0)) | ||
372 | - < TYPE_PRECISION (TREE_TYPE (subsubexp0))) | ||
373 | - && (TYPE_PRECISION (TREE_TYPE (top0)) | ||
374 | - == TYPE_PRECISION (TREE_TYPE (top1))) | ||
375 | - && (TYPE_UNSIGNED (TREE_TYPE (top0)) | ||
376 | - == TYPE_UNSIGNED (TREE_TYPE (top1)))) | ||
377 | - { | ||
378 | - tree op0type = TREE_TYPE (top0); | ||
379 | - enum machine_mode innermode = TYPE_MODE (op0type); | ||
380 | - bool zextend_p = TYPE_UNSIGNED (op0type); | ||
381 | - bool sat_p = TYPE_SATURATING (TREE_TYPE (subsubexp0)); | ||
382 | - if (sat_p == 0) | ||
383 | - this_optab = zextend_p ? umadd_widen_optab : smadd_widen_optab; | ||
384 | - else | ||
385 | - this_optab = zextend_p ? usmadd_widen_optab | ||
386 | - : ssmadd_widen_optab; | ||
387 | - if (mode == GET_MODE_2XWIDER_MODE (innermode) | ||
388 | - && (optab_handler (this_optab, mode)->insn_code | ||
389 | - != CODE_FOR_nothing)) | ||
390 | - { | ||
391 | - expand_operands (top0, top1, NULL_RTX, &op0, &op1, | ||
392 | - EXPAND_NORMAL); | ||
393 | - op2 = expand_expr (treeop1, subtarget, | ||
394 | - VOIDmode, EXPAND_NORMAL); | ||
395 | - temp = expand_ternary_op (mode, this_optab, op0, op1, op2, | ||
396 | - target, unsignedp); | ||
397 | - gcc_assert (temp); | ||
398 | - return REDUCE_BIT_FIELD (temp); | ||
399 | - } | ||
400 | - } | ||
401 | - } | ||
402 | - | ||
403 | /* If we are adding a constant, a VAR_DECL that is sp, fp, or ap, and | ||
404 | something else, make sure we add the register to the constant and | ||
405 | then to the other thing. This case can occur during strength | ||
406 | @@ -7587,57 +7534,6 @@ | ||
407 | return REDUCE_BIT_FIELD (simplify_gen_binary (PLUS, mode, op0, op1)); | ||
408 | |||
409 | case MINUS_EXPR: | ||
410 | - /* Check if this is a case for multiplication and subtraction. */ | ||
411 | - if ((TREE_CODE (type) == INTEGER_TYPE | ||
412 | - || TREE_CODE (type) == FIXED_POINT_TYPE) | ||
413 | - && (subexp1_def = get_def_for_expr (treeop1, | ||
414 | - MULT_EXPR))) | ||
415 | - { | ||
416 | - tree subsubexp0, subsubexp1; | ||
417 | - gimple subsubexp0_def, subsubexp1_def; | ||
418 | - enum tree_code this_code; | ||
419 | - | ||
420 | - this_code = TREE_CODE (type) == INTEGER_TYPE ? NOP_EXPR | ||
421 | - : FIXED_CONVERT_EXPR; | ||
422 | - subsubexp0 = gimple_assign_rhs1 (subexp1_def); | ||
423 | - subsubexp0_def = get_def_for_expr (subsubexp0, this_code); | ||
424 | - subsubexp1 = gimple_assign_rhs2 (subexp1_def); | ||
425 | - subsubexp1_def = get_def_for_expr (subsubexp1, this_code); | ||
426 | - if (subsubexp0_def && subsubexp1_def | ||
427 | - && (top0 = gimple_assign_rhs1 (subsubexp0_def)) | ||
428 | - && (top1 = gimple_assign_rhs1 (subsubexp1_def)) | ||
429 | - && (TYPE_PRECISION (TREE_TYPE (top0)) | ||
430 | - < TYPE_PRECISION (TREE_TYPE (subsubexp0))) | ||
431 | - && (TYPE_PRECISION (TREE_TYPE (top0)) | ||
432 | - == TYPE_PRECISION (TREE_TYPE (top1))) | ||
433 | - && (TYPE_UNSIGNED (TREE_TYPE (top0)) | ||
434 | - == TYPE_UNSIGNED (TREE_TYPE (top1)))) | ||
435 | - { | ||
436 | - tree op0type = TREE_TYPE (top0); | ||
437 | - enum machine_mode innermode = TYPE_MODE (op0type); | ||
438 | - bool zextend_p = TYPE_UNSIGNED (op0type); | ||
439 | - bool sat_p = TYPE_SATURATING (TREE_TYPE (subsubexp0)); | ||
440 | - if (sat_p == 0) | ||
441 | - this_optab = zextend_p ? umsub_widen_optab : smsub_widen_optab; | ||
442 | - else | ||
443 | - this_optab = zextend_p ? usmsub_widen_optab | ||
444 | - : ssmsub_widen_optab; | ||
445 | - if (mode == GET_MODE_2XWIDER_MODE (innermode) | ||
446 | - && (optab_handler (this_optab, mode)->insn_code | ||
447 | - != CODE_FOR_nothing)) | ||
448 | - { | ||
449 | - expand_operands (top0, top1, NULL_RTX, &op0, &op1, | ||
450 | - EXPAND_NORMAL); | ||
451 | - op2 = expand_expr (treeop0, subtarget, | ||
452 | - VOIDmode, EXPAND_NORMAL); | ||
453 | - temp = expand_ternary_op (mode, this_optab, op0, op1, op2, | ||
454 | - target, unsignedp); | ||
455 | - gcc_assert (temp); | ||
456 | - return REDUCE_BIT_FIELD (temp); | ||
457 | - } | ||
458 | - } | ||
459 | - } | ||
460 | - | ||
461 | /* For initializers, we are allowed to return a MINUS of two | ||
462 | symbolic constants. Here we handle all cases when both operands | ||
463 | are constant. */ | ||
464 | @@ -7678,6 +7574,14 @@ | ||
465 | |||
466 | goto binop2; | ||
467 | |||
468 | + case WIDEN_MULT_PLUS_EXPR: | ||
469 | + case WIDEN_MULT_MINUS_EXPR: | ||
470 | + expand_operands (treeop0, treeop1, NULL_RTX, &op0, &op1, EXPAND_NORMAL); | ||
471 | + op2 = expand_normal (ops->op2); | ||
472 | + target = expand_widen_pattern_expr (ops, op0, op1, op2, | ||
473 | + target, unsignedp); | ||
474 | + return target; | ||
475 | + | ||
476 | case WIDEN_MULT_EXPR: | ||
477 | /* If first operand is constant, swap them. | ||
478 | Thus the following special case checks need only | ||
479 | |||
480 | === modified file 'gcc/gimple-pretty-print.c' | ||
481 | --- old/gcc/gimple-pretty-print.c 2009-11-25 10:55:54 +0000 | ||
482 | +++ new/gcc/gimple-pretty-print.c 2010-09-16 09:15:46 +0000 | ||
483 | @@ -376,6 +376,34 @@ | ||
484 | } | ||
485 | } | ||
486 | |||
487 | +/* Helper for dump_gimple_assign. Print the ternary RHS of the | ||
488 | + assignment GS. BUFFER, SPC and FLAGS are as in dump_gimple_stmt. */ | ||
489 | + | ||
490 | +static void | ||
491 | +dump_ternary_rhs (pretty_printer *buffer, gimple gs, int spc, int flags) | ||
492 | +{ | ||
493 | + const char *p; | ||
494 | + enum tree_code code = gimple_assign_rhs_code (gs); | ||
495 | + switch (code) | ||
496 | + { | ||
497 | + case WIDEN_MULT_PLUS_EXPR: | ||
498 | + case WIDEN_MULT_MINUS_EXPR: | ||
499 | + for (p = tree_code_name [(int) code]; *p; p++) | ||
500 | + pp_character (buffer, TOUPPER (*p)); | ||
501 | + pp_string (buffer, " <"); | ||
502 | + dump_generic_node (buffer, gimple_assign_rhs1 (gs), spc, flags, false); | ||
503 | + pp_string (buffer, ", "); | ||
504 | + dump_generic_node (buffer, gimple_assign_rhs2 (gs), spc, flags, false); | ||
505 | + pp_string (buffer, ", "); | ||
506 | + dump_generic_node (buffer, gimple_assign_rhs3 (gs), spc, flags, false); | ||
507 | + pp_character (buffer, '>'); | ||
508 | + break; | ||
509 | + | ||
510 | + default: | ||
511 | + gcc_unreachable (); | ||
512 | + } | ||
513 | +} | ||
514 | + | ||
515 | |||
516 | /* Dump the gimple assignment GS. BUFFER, SPC and FLAGS are as in | ||
517 | dump_gimple_stmt. */ | ||
518 | @@ -418,6 +446,8 @@ | ||
519 | dump_unary_rhs (buffer, gs, spc, flags); | ||
520 | else if (gimple_num_ops (gs) == 3) | ||
521 | dump_binary_rhs (buffer, gs, spc, flags); | ||
522 | + else if (gimple_num_ops (gs) == 4) | ||
523 | + dump_ternary_rhs (buffer, gs, spc, flags); | ||
524 | else | ||
525 | gcc_unreachable (); | ||
526 | if (!(flags & TDF_RHS_ONLY)) | ||
527 | |||
528 | === modified file 'gcc/gimple.c' | ||
529 | --- old/gcc/gimple.c 2010-09-15 16:47:52 +0000 | ||
530 | +++ new/gcc/gimple.c 2010-09-16 09:15:46 +0000 | ||
531 | @@ -289,31 +289,40 @@ | ||
532 | |||
533 | |||
534 | /* Extract the operands and code for expression EXPR into *SUBCODE_P, | ||
535 | - *OP1_P and *OP2_P respectively. */ | ||
536 | + *OP1_P, *OP2_P and *OP3_P respectively. */ | ||
537 | |||
538 | void | ||
539 | -extract_ops_from_tree (tree expr, enum tree_code *subcode_p, tree *op1_p, | ||
540 | - tree *op2_p) | ||
541 | +extract_ops_from_tree_1 (tree expr, enum tree_code *subcode_p, tree *op1_p, | ||
542 | + tree *op2_p, tree *op3_p) | ||
543 | { | ||
544 | enum gimple_rhs_class grhs_class; | ||
545 | |||
546 | *subcode_p = TREE_CODE (expr); | ||
547 | grhs_class = get_gimple_rhs_class (*subcode_p); | ||
548 | |||
549 | - if (grhs_class == GIMPLE_BINARY_RHS) | ||
550 | - { | ||
551 | - *op1_p = TREE_OPERAND (expr, 0); | ||
552 | - *op2_p = TREE_OPERAND (expr, 1); | ||
553 | + if (grhs_class == GIMPLE_TERNARY_RHS) | ||
554 | + { | ||
555 | + *op1_p = TREE_OPERAND (expr, 0); | ||
556 | + *op2_p = TREE_OPERAND (expr, 1); | ||
557 | + *op3_p = TREE_OPERAND (expr, 2); | ||
558 | + } | ||
559 | + else if (grhs_class == GIMPLE_BINARY_RHS) | ||
560 | + { | ||
561 | + *op1_p = TREE_OPERAND (expr, 0); | ||
562 | + *op2_p = TREE_OPERAND (expr, 1); | ||
563 | + *op3_p = NULL_TREE; | ||
564 | } | ||
565 | else if (grhs_class == GIMPLE_UNARY_RHS) | ||
566 | { | ||
567 | *op1_p = TREE_OPERAND (expr, 0); | ||
568 | *op2_p = NULL_TREE; | ||
569 | + *op3_p = NULL_TREE; | ||
570 | } | ||
571 | else if (grhs_class == GIMPLE_SINGLE_RHS) | ||
572 | { | ||
573 | *op1_p = expr; | ||
574 | *op2_p = NULL_TREE; | ||
575 | + *op3_p = NULL_TREE; | ||
576 | } | ||
577 | else | ||
578 | gcc_unreachable (); | ||
579 | @@ -329,10 +338,10 @@ | ||
580 | gimple_build_assign_stat (tree lhs, tree rhs MEM_STAT_DECL) | ||
581 | { | ||
582 | enum tree_code subcode; | ||
583 | - tree op1, op2; | ||
584 | + tree op1, op2, op3; | ||
585 | |||
586 | - extract_ops_from_tree (rhs, &subcode, &op1, &op2); | ||
587 | - return gimple_build_assign_with_ops_stat (subcode, lhs, op1, op2 | ||
588 | + extract_ops_from_tree_1 (rhs, &subcode, &op1, &op2, &op3); | ||
589 | + return gimple_build_assign_with_ops_stat (subcode, lhs, op1, op2, op3 | ||
590 | PASS_MEM_STAT); | ||
591 | } | ||
592 | |||
593 | @@ -343,7 +352,7 @@ | ||
594 | |||
595 | gimple | ||
596 | gimple_build_assign_with_ops_stat (enum tree_code subcode, tree lhs, tree op1, | ||
597 | - tree op2 MEM_STAT_DECL) | ||
598 | + tree op2, tree op3 MEM_STAT_DECL) | ||
599 | { | ||
600 | unsigned num_ops; | ||
601 | gimple p; | ||
602 | @@ -362,6 +371,12 @@ | ||
603 | gimple_assign_set_rhs2 (p, op2); | ||
604 | } | ||
605 | |||
606 | + if (op3) | ||
607 | + { | ||
608 | + gcc_assert (num_ops > 3); | ||
609 | + gimple_assign_set_rhs3 (p, op3); | ||
610 | + } | ||
611 | + | ||
612 | return p; | ||
613 | } | ||
614 | |||
615 | @@ -1860,22 +1875,22 @@ | ||
616 | gimple_assign_set_rhs_from_tree (gimple_stmt_iterator *gsi, tree expr) | ||
617 | { | ||
618 | enum tree_code subcode; | ||
619 | - tree op1, op2; | ||
620 | + tree op1, op2, op3; | ||
621 | |||
622 | - extract_ops_from_tree (expr, &subcode, &op1, &op2); | ||
623 | - gimple_assign_set_rhs_with_ops (gsi, subcode, op1, op2); | ||
624 | + extract_ops_from_tree_1 (expr, &subcode, &op1, &op2, &op3); | ||
625 | + gimple_assign_set_rhs_with_ops_1 (gsi, subcode, op1, op2, op3); | ||
626 | } | ||
627 | |||
628 | |||
629 | /* Set the RHS of assignment statement pointed-to by GSI to CODE with | ||
630 | - operands OP1 and OP2. | ||
631 | + operands OP1, OP2 and OP3. | ||
632 | |||
633 | NOTE: The statement pointed-to by GSI may be reallocated if it | ||
634 | did not have enough operand slots. */ | ||
635 | |||
636 | void | ||
637 | -gimple_assign_set_rhs_with_ops (gimple_stmt_iterator *gsi, enum tree_code code, | ||
638 | - tree op1, tree op2) | ||
639 | +gimple_assign_set_rhs_with_ops_1 (gimple_stmt_iterator *gsi, enum tree_code code, | ||
640 | + tree op1, tree op2, tree op3) | ||
641 | { | ||
642 | unsigned new_rhs_ops = get_gimple_rhs_num_ops (code); | ||
643 | gimple stmt = gsi_stmt (*gsi); | ||
644 | @@ -1899,6 +1914,8 @@ | ||
645 | gimple_assign_set_rhs1 (stmt, op1); | ||
646 | if (new_rhs_ops > 1) | ||
647 | gimple_assign_set_rhs2 (stmt, op2); | ||
648 | + if (new_rhs_ops > 2) | ||
649 | + gimple_assign_set_rhs3 (stmt, op3); | ||
650 | } | ||
651 | |||
652 | |||
653 | @@ -2378,6 +2395,8 @@ | ||
654 | return 1; | ||
655 | else if (rhs_class == GIMPLE_BINARY_RHS) | ||
656 | return 2; | ||
657 | + else if (rhs_class == GIMPLE_TERNARY_RHS) | ||
658 | + return 3; | ||
659 | else | ||
660 | gcc_unreachable (); | ||
661 | } | ||
662 | @@ -2394,6 +2413,8 @@ | ||
663 | || (SYM) == TRUTH_OR_EXPR \ | ||
664 | || (SYM) == TRUTH_XOR_EXPR) ? GIMPLE_BINARY_RHS \ | ||
665 | : (SYM) == TRUTH_NOT_EXPR ? GIMPLE_UNARY_RHS \ | ||
666 | + : ((SYM) == WIDEN_MULT_PLUS_EXPR \ | ||
667 | + || (SYM) == WIDEN_MULT_MINUS_EXPR) ? GIMPLE_TERNARY_RHS \ | ||
668 | : ((SYM) == COND_EXPR \ | ||
669 | || (SYM) == CONSTRUCTOR \ | ||
670 | || (SYM) == OBJ_TYPE_REF \ | ||
671 | |||
672 | === modified file 'gcc/gimple.h' | ||
673 | --- old/gcc/gimple.h 2010-08-10 13:31:21 +0000 | ||
674 | +++ new/gcc/gimple.h 2010-09-16 09:15:46 +0000 | ||
675 | @@ -80,6 +80,7 @@ | ||
676 | enum gimple_rhs_class | ||
677 | { | ||
678 | GIMPLE_INVALID_RHS, /* The expression cannot be used on the RHS. */ | ||
679 | + GIMPLE_TERNARY_RHS, /* The expression is a ternary operation. */ | ||
680 | GIMPLE_BINARY_RHS, /* The expression is a binary operation. */ | ||
681 | GIMPLE_UNARY_RHS, /* The expression is a unary operation. */ | ||
682 | GIMPLE_SINGLE_RHS /* The expression is a single object (an SSA | ||
683 | @@ -786,12 +787,14 @@ | ||
684 | gimple gimple_build_assign_stat (tree, tree MEM_STAT_DECL); | ||
685 | #define gimple_build_assign(l,r) gimple_build_assign_stat (l, r MEM_STAT_INFO) | ||
686 | |||
687 | -void extract_ops_from_tree (tree, enum tree_code *, tree *, tree *); | ||
688 | +void extract_ops_from_tree_1 (tree, enum tree_code *, tree *, tree *, tree *); | ||
689 | |||
690 | gimple gimple_build_assign_with_ops_stat (enum tree_code, tree, tree, | ||
691 | - tree MEM_STAT_DECL); | ||
692 | -#define gimple_build_assign_with_ops(c,o1,o2,o3) \ | ||
693 | - gimple_build_assign_with_ops_stat (c, o1, o2, o3 MEM_STAT_INFO) | ||
694 | + tree, tree MEM_STAT_DECL); | ||
695 | +#define gimple_build_assign_with_ops(c,o1,o2,o3) \ | ||
696 | + gimple_build_assign_with_ops_stat (c, o1, o2, o3, NULL_TREE MEM_STAT_INFO) | ||
697 | +#define gimple_build_assign_with_ops3(c,o1,o2,o3,o4) \ | ||
698 | + gimple_build_assign_with_ops_stat (c, o1, o2, o3, o4 MEM_STAT_INFO) | ||
699 | |||
700 | gimple gimple_build_debug_bind_stat (tree, tree, gimple MEM_STAT_DECL); | ||
701 | #define gimple_build_debug_bind(var,val,stmt) \ | ||
702 | @@ -850,8 +853,8 @@ | ||
703 | bool gimple_assign_unary_nop_p (gimple); | ||
704 | void gimple_set_bb (gimple, struct basic_block_def *); | ||
705 | void gimple_assign_set_rhs_from_tree (gimple_stmt_iterator *, tree); | ||
706 | -void gimple_assign_set_rhs_with_ops (gimple_stmt_iterator *, enum tree_code, | ||
707 | - tree, tree); | ||
708 | +void gimple_assign_set_rhs_with_ops_1 (gimple_stmt_iterator *, enum tree_code, | ||
709 | + tree, tree, tree); | ||
710 | tree gimple_get_lhs (const_gimple); | ||
711 | void gimple_set_lhs (gimple, tree); | ||
712 | void gimple_replace_lhs (gimple, tree); | ||
713 | @@ -1793,6 +1796,63 @@ | ||
714 | gimple_set_op (gs, 2, rhs); | ||
715 | } | ||
716 | |||
717 | +/* Return the third operand on the RHS of assignment statement GS. | ||
718 | + If GS does not have two operands, NULL is returned instead. */ | ||
719 | + | ||
720 | +static inline tree | ||
721 | +gimple_assign_rhs3 (const_gimple gs) | ||
722 | +{ | ||
723 | + GIMPLE_CHECK (gs, GIMPLE_ASSIGN); | ||
724 | + | ||
725 | + if (gimple_num_ops (gs) >= 4) | ||
726 | + return gimple_op (gs, 3); | ||
727 | + else | ||
728 | + return NULL_TREE; | ||
729 | +} | ||
730 | + | ||
731 | +/* Return a pointer to the third operand on the RHS of assignment | ||
732 | + statement GS. */ | ||
733 | + | ||
734 | +static inline tree * | ||
735 | +gimple_assign_rhs3_ptr (const_gimple gs) | ||
736 | +{ | ||
737 | + GIMPLE_CHECK (gs, GIMPLE_ASSIGN); | ||
738 | + return gimple_op_ptr (gs, 3); | ||
739 | +} | ||
740 | + | ||
741 | + | ||
742 | +/* Set RHS to be the third operand on the RHS of assignment statement GS. */ | ||
743 | + | ||
744 | +static inline void | ||
745 | +gimple_assign_set_rhs3 (gimple gs, tree rhs) | ||
746 | +{ | ||
747 | + GIMPLE_CHECK (gs, GIMPLE_ASSIGN); | ||
748 | + | ||
749 | + gimple_set_op (gs, 3, rhs); | ||
750 | +} | ||
751 | + | ||
752 | +/* A wrapper around gimple_assign_set_rhs_with_ops_1, for callers which expect | ||
753 | + to see only a maximum of two operands. */ | ||
754 | + | ||
755 | +static inline void | ||
756 | +gimple_assign_set_rhs_with_ops (gimple_stmt_iterator *gsi, enum tree_code code, | ||
757 | + tree op1, tree op2) | ||
758 | +{ | ||
759 | + gimple_assign_set_rhs_with_ops_1 (gsi, code, op1, op2, NULL); | ||
760 | +} | ||
761 | + | ||
762 | +/* A wrapper around extract_ops_from_tree_1, for callers which expect | ||
763 | + to see only a maximum of two operands. */ | ||
764 | + | ||
765 | +static inline void | ||
766 | +extract_ops_from_tree (tree expr, enum tree_code *code, tree *op0, | ||
767 | + tree *op1) | ||
768 | +{ | ||
769 | + tree op2; | ||
770 | + extract_ops_from_tree_1 (expr, code, op0, op1, &op2); | ||
771 | + gcc_assert (op2 == NULL_TREE); | ||
772 | +} | ||
773 | + | ||
774 | /* Returns true if GS is a nontemporal move. */ | ||
775 | |||
776 | static inline bool | ||
777 | |||
778 | === modified file 'gcc/optabs.c' | ||
779 | --- old/gcc/optabs.c 2010-03-19 19:45:01 +0000 | ||
780 | +++ new/gcc/optabs.c 2010-09-16 09:15:46 +0000 | ||
781 | @@ -408,6 +408,20 @@ | ||
782 | case DOT_PROD_EXPR: | ||
783 | return TYPE_UNSIGNED (type) ? udot_prod_optab : sdot_prod_optab; | ||
784 | |||
785 | + case WIDEN_MULT_PLUS_EXPR: | ||
786 | + return (TYPE_UNSIGNED (type) | ||
787 | + ? (TYPE_SATURATING (type) | ||
788 | + ? usmadd_widen_optab : umadd_widen_optab) | ||
789 | + : (TYPE_SATURATING (type) | ||
790 | + ? ssmadd_widen_optab : smadd_widen_optab)); | ||
791 | + | ||
792 | + case WIDEN_MULT_MINUS_EXPR: | ||
793 | + return (TYPE_UNSIGNED (type) | ||
794 | + ? (TYPE_SATURATING (type) | ||
795 | + ? usmsub_widen_optab : umsub_widen_optab) | ||
796 | + : (TYPE_SATURATING (type) | ||
797 | + ? ssmsub_widen_optab : smsub_widen_optab)); | ||
798 | + | ||
799 | case REDUC_MAX_EXPR: | ||
800 | return TYPE_UNSIGNED (type) ? reduc_umax_optab : reduc_smax_optab; | ||
801 | |||
802 | @@ -547,7 +561,12 @@ | ||
803 | tmode0 = TYPE_MODE (TREE_TYPE (oprnd0)); | ||
804 | widen_pattern_optab = | ||
805 | optab_for_tree_code (ops->code, TREE_TYPE (oprnd0), optab_default); | ||
806 | - icode = (int) optab_handler (widen_pattern_optab, tmode0)->insn_code; | ||
807 | + if (ops->code == WIDEN_MULT_PLUS_EXPR | ||
808 | + || ops->code == WIDEN_MULT_MINUS_EXPR) | ||
809 | + icode = (int) optab_handler (widen_pattern_optab, | ||
810 | + TYPE_MODE (TREE_TYPE (ops->op2)))->insn_code; | ||
811 | + else | ||
812 | + icode = (int) optab_handler (widen_pattern_optab, tmode0)->insn_code; | ||
813 | gcc_assert (icode != CODE_FOR_nothing); | ||
814 | xmode0 = insn_data[icode].operand[1].mode; | ||
815 | |||
816 | |||
817 | === modified file 'gcc/testsuite/gcc.target/arm/wmul-1.c' | ||
818 | --- old/gcc/testsuite/gcc.target/arm/wmul-1.c 2010-09-01 13:29:58 +0000 | ||
819 | +++ new/gcc/testsuite/gcc.target/arm/wmul-1.c 2010-09-16 09:15:46 +0000 | ||
820 | @@ -15,4 +15,4 @@ | ||
821 | return sqr; | ||
822 | } | ||
823 | |||
824 | -/* { dg-final { scan-assembler-times "smulbb" 2 } } */ | ||
825 | +/* { dg-final { scan-assembler-times "smlabb" 2 } } */ | ||
826 | |||
827 | === modified file 'gcc/tree-cfg.c' | ||
828 | --- old/gcc/tree-cfg.c 2010-09-01 13:29:58 +0000 | ||
829 | +++ new/gcc/tree-cfg.c 2010-09-16 09:15:46 +0000 | ||
830 | @@ -3483,6 +3483,65 @@ | ||
831 | return false; | ||
832 | } | ||
833 | |||
834 | +/* Verify a gimple assignment statement STMT with a ternary rhs. | ||
835 | + Returns true if anything is wrong. */ | ||
836 | + | ||
837 | +static bool | ||
838 | +verify_gimple_assign_ternary (gimple stmt) | ||
839 | +{ | ||
840 | + enum tree_code rhs_code = gimple_assign_rhs_code (stmt); | ||
841 | + tree lhs = gimple_assign_lhs (stmt); | ||
842 | + tree lhs_type = TREE_TYPE (lhs); | ||
843 | + tree rhs1 = gimple_assign_rhs1 (stmt); | ||
844 | + tree rhs1_type = TREE_TYPE (rhs1); | ||
845 | + tree rhs2 = gimple_assign_rhs2 (stmt); | ||
846 | + tree rhs2_type = TREE_TYPE (rhs2); | ||
847 | + tree rhs3 = gimple_assign_rhs3 (stmt); | ||
848 | + tree rhs3_type = TREE_TYPE (rhs3); | ||
849 | + | ||
850 | + if (!is_gimple_reg (lhs) | ||
851 | + && !(optimize == 0 | ||
852 | + && TREE_CODE (lhs_type) == COMPLEX_TYPE)) | ||
853 | + { | ||
854 | + error ("non-register as LHS of ternary operation"); | ||
855 | + return true; | ||
856 | + } | ||
857 | + | ||
858 | + if (!is_gimple_val (rhs1) | ||
859 | + || !is_gimple_val (rhs2) | ||
860 | + || !is_gimple_val (rhs3)) | ||
861 | + { | ||
862 | + error ("invalid operands in ternary operation"); | ||
863 | + return true; | ||
864 | + } | ||
865 | + | ||
866 | + /* First handle operations that involve different types. */ | ||
867 | + switch (rhs_code) | ||
868 | + { | ||
869 | + case WIDEN_MULT_PLUS_EXPR: | ||
870 | + case WIDEN_MULT_MINUS_EXPR: | ||
871 | + if ((!INTEGRAL_TYPE_P (rhs1_type) | ||
872 | + && !FIXED_POINT_TYPE_P (rhs1_type)) | ||
873 | + || !useless_type_conversion_p (rhs1_type, rhs2_type) | ||
874 | + || !useless_type_conversion_p (lhs_type, rhs3_type) | ||
875 | + || 2 * TYPE_PRECISION (rhs1_type) != TYPE_PRECISION (lhs_type) | ||
876 | + || TYPE_PRECISION (rhs1_type) != TYPE_PRECISION (rhs2_type)) | ||
877 | + { | ||
878 | + error ("type mismatch in widening multiply-accumulate expression"); | ||
879 | + debug_generic_expr (lhs_type); | ||
880 | + debug_generic_expr (rhs1_type); | ||
881 | + debug_generic_expr (rhs2_type); | ||
882 | + debug_generic_expr (rhs3_type); | ||
883 | + return true; | ||
884 | + } | ||
885 | + break; | ||
886 | + | ||
887 | + default: | ||
888 | + gcc_unreachable (); | ||
889 | + } | ||
890 | + return false; | ||
891 | +} | ||
892 | + | ||
893 | /* Verify a gimple assignment statement STMT with a single rhs. | ||
894 | Returns true if anything is wrong. */ | ||
895 | |||
896 | @@ -3615,6 +3674,9 @@ | ||
897 | case GIMPLE_BINARY_RHS: | ||
898 | return verify_gimple_assign_binary (stmt); | ||
899 | |||
900 | + case GIMPLE_TERNARY_RHS: | ||
901 | + return verify_gimple_assign_ternary (stmt); | ||
902 | + | ||
903 | default: | ||
904 | gcc_unreachable (); | ||
905 | } | ||
906 | |||
907 | === modified file 'gcc/tree-inline.c' | ||
908 | --- old/gcc/tree-inline.c 2010-09-01 13:29:58 +0000 | ||
909 | +++ new/gcc/tree-inline.c 2010-09-16 09:15:46 +0000 | ||
910 | @@ -3199,6 +3199,8 @@ | ||
911 | case WIDEN_SUM_EXPR: | ||
912 | case WIDEN_MULT_EXPR: | ||
913 | case DOT_PROD_EXPR: | ||
914 | + case WIDEN_MULT_PLUS_EXPR: | ||
915 | + case WIDEN_MULT_MINUS_EXPR: | ||
916 | |||
917 | case VEC_WIDEN_MULT_HI_EXPR: | ||
918 | case VEC_WIDEN_MULT_LO_EXPR: | ||
919 | |||
920 | === modified file 'gcc/tree-pretty-print.c' | ||
921 | --- old/gcc/tree-pretty-print.c 2009-11-30 10:36:54 +0000 | ||
922 | +++ new/gcc/tree-pretty-print.c 2010-09-16 09:15:46 +0000 | ||
923 | @@ -1939,6 +1939,26 @@ | ||
924 | pp_string (buffer, " > "); | ||
925 | break; | ||
926 | |||
927 | + case WIDEN_MULT_PLUS_EXPR: | ||
928 | + pp_string (buffer, " WIDEN_MULT_PLUS_EXPR < "); | ||
929 | + dump_generic_node (buffer, TREE_OPERAND (node, 0), spc, flags, false); | ||
930 | + pp_string (buffer, ", "); | ||
931 | + dump_generic_node (buffer, TREE_OPERAND (node, 1), spc, flags, false); | ||
932 | + pp_string (buffer, ", "); | ||
933 | + dump_generic_node (buffer, TREE_OPERAND (node, 2), spc, flags, false); | ||
934 | + pp_string (buffer, " > "); | ||
935 | + break; | ||
936 | + | ||
937 | + case WIDEN_MULT_MINUS_EXPR: | ||
938 | + pp_string (buffer, " WIDEN_MULT_MINUS_EXPR < "); | ||
939 | + dump_generic_node (buffer, TREE_OPERAND (node, 0), spc, flags, false); | ||
940 | + pp_string (buffer, ", "); | ||
941 | + dump_generic_node (buffer, TREE_OPERAND (node, 1), spc, flags, false); | ||
942 | + pp_string (buffer, ", "); | ||
943 | + dump_generic_node (buffer, TREE_OPERAND (node, 2), spc, flags, false); | ||
944 | + pp_string (buffer, " > "); | ||
945 | + break; | ||
946 | + | ||
947 | case OMP_PARALLEL: | ||
948 | pp_string (buffer, "#pragma omp parallel"); | ||
949 | dump_omp_clauses (buffer, OMP_PARALLEL_CLAUSES (node), spc, flags); | ||
950 | @@ -2432,6 +2452,8 @@ | ||
951 | case VEC_WIDEN_MULT_LO_EXPR: | ||
952 | case WIDEN_MULT_EXPR: | ||
953 | case DOT_PROD_EXPR: | ||
954 | + case WIDEN_MULT_PLUS_EXPR: | ||
955 | + case WIDEN_MULT_MINUS_EXPR: | ||
956 | case MULT_EXPR: | ||
957 | case TRUNC_DIV_EXPR: | ||
958 | case CEIL_DIV_EXPR: | ||
959 | |||
960 | === modified file 'gcc/tree-ssa-ccp.c' | ||
961 | --- old/gcc/tree-ssa-ccp.c 2010-08-10 13:31:21 +0000 | ||
962 | +++ new/gcc/tree-ssa-ccp.c 2010-09-16 09:15:46 +0000 | ||
963 | @@ -915,6 +915,23 @@ | ||
964 | TREE_TYPE (TREE_OPERAND (addr, 0)))); | ||
965 | } | ||
966 | |||
967 | +/* Get operand number OPNR from the rhs of STMT. Before returning it, | ||
968 | + simplify it to a constant if possible. */ | ||
969 | + | ||
970 | +static tree | ||
971 | +get_rhs_assign_op_for_ccp (gimple stmt, int opnr) | ||
972 | +{ | ||
973 | + tree op = gimple_op (stmt, opnr); | ||
974 | + | ||
975 | + if (TREE_CODE (op) == SSA_NAME) | ||
976 | + { | ||
977 | + prop_value_t *val = get_value (op); | ||
978 | + if (val->lattice_val == CONSTANT) | ||
979 | + op = get_value (op)->value; | ||
980 | + } | ||
981 | + return op; | ||
982 | +} | ||
983 | + | ||
984 | /* CCP specific front-end to the non-destructive constant folding | ||
985 | routines. | ||
986 | |||
987 | @@ -1037,15 +1054,7 @@ | ||
988 | Note that we know the single operand must be a constant, | ||
989 | so this should almost always return a simplified RHS. */ | ||
990 | tree lhs = gimple_assign_lhs (stmt); | ||
991 | - tree op0 = gimple_assign_rhs1 (stmt); | ||
992 | - | ||
993 | - /* Simplify the operand down to a constant. */ | ||
994 | - if (TREE_CODE (op0) == SSA_NAME) | ||
995 | - { | ||
996 | - prop_value_t *val = get_value (op0); | ||
997 | - if (val->lattice_val == CONSTANT) | ||
998 | - op0 = get_value (op0)->value; | ||
999 | - } | ||
1000 | + tree op0 = get_rhs_assign_op_for_ccp (stmt, 1); | ||
1001 | |||
1002 | /* Conversions are useless for CCP purposes if they are | ||
1003 | value-preserving. Thus the restrictions that | ||
1004 | @@ -1082,23 +1091,8 @@ | ||
1005 | case GIMPLE_BINARY_RHS: | ||
1006 | { | ||
1007 | /* Handle binary operators that can appear in GIMPLE form. */ | ||
1008 | - tree op0 = gimple_assign_rhs1 (stmt); | ||
1009 | - tree op1 = gimple_assign_rhs2 (stmt); | ||
1010 | - | ||
1011 | - /* Simplify the operands down to constants when appropriate. */ | ||
1012 | - if (TREE_CODE (op0) == SSA_NAME) | ||
1013 | - { | ||
1014 | - prop_value_t *val = get_value (op0); | ||
1015 | - if (val->lattice_val == CONSTANT) | ||
1016 | - op0 = val->value; | ||
1017 | - } | ||
1018 | - | ||
1019 | - if (TREE_CODE (op1) == SSA_NAME) | ||
1020 | - { | ||
1021 | - prop_value_t *val = get_value (op1); | ||
1022 | - if (val->lattice_val == CONSTANT) | ||
1023 | - op1 = val->value; | ||
1024 | - } | ||
1025 | + tree op0 = get_rhs_assign_op_for_ccp (stmt, 1); | ||
1026 | + tree op1 = get_rhs_assign_op_for_ccp (stmt, 2); | ||
1027 | |||
1028 | /* Fold &foo + CST into an invariant reference if possible. */ | ||
1029 | if (gimple_assign_rhs_code (stmt) == POINTER_PLUS_EXPR | ||
1030 | @@ -1115,6 +1109,17 @@ | ||
1031 | gimple_expr_type (stmt), op0, op1); | ||
1032 | } | ||
1033 | |||
1034 | + case GIMPLE_TERNARY_RHS: | ||
1035 | + { | ||
1036 | + /* Handle binary operators that can appear in GIMPLE form. */ | ||
1037 | + tree op0 = get_rhs_assign_op_for_ccp (stmt, 1); | ||
1038 | + tree op1 = get_rhs_assign_op_for_ccp (stmt, 2); | ||
1039 | + tree op2 = get_rhs_assign_op_for_ccp (stmt, 3); | ||
1040 | + | ||
1041 | + return fold_ternary_loc (loc, subcode, | ||
1042 | + gimple_expr_type (stmt), op0, op1, op2); | ||
1043 | + } | ||
1044 | + | ||
1045 | default: | ||
1046 | gcc_unreachable (); | ||
1047 | } | ||
1048 | @@ -2959,6 +2964,33 @@ | ||
1049 | } | ||
1050 | break; | ||
1051 | |||
1052 | + case GIMPLE_TERNARY_RHS: | ||
1053 | + result = fold_ternary_loc (loc, subcode, | ||
1054 | + TREE_TYPE (gimple_assign_lhs (stmt)), | ||
1055 | + gimple_assign_rhs1 (stmt), | ||
1056 | + gimple_assign_rhs2 (stmt), | ||
1057 | + gimple_assign_rhs3 (stmt)); | ||
1058 | + | ||
1059 | + if (result) | ||
1060 | + { | ||
1061 | + STRIP_USELESS_TYPE_CONVERSION (result); | ||
1062 | + if (valid_gimple_rhs_p (result)) | ||
1063 | + return result; | ||
1064 | + | ||
1065 | + /* Fold might have produced non-GIMPLE, so if we trust it blindly | ||
1066 | + we lose canonicalization opportunities. Do not go again | ||
1067 | + through fold here though, or the same non-GIMPLE will be | ||
1068 | + produced. */ | ||
1069 | + if (commutative_ternary_tree_code (subcode) | ||
1070 | + && tree_swap_operands_p (gimple_assign_rhs1 (stmt), | ||
1071 | + gimple_assign_rhs2 (stmt), false)) | ||
1072 | + return build3 (subcode, TREE_TYPE (gimple_assign_lhs (stmt)), | ||
1073 | + gimple_assign_rhs2 (stmt), | ||
1074 | + gimple_assign_rhs1 (stmt), | ||
1075 | + gimple_assign_rhs3 (stmt)); | ||
1076 | + } | ||
1077 | + break; | ||
1078 | + | ||
1079 | case GIMPLE_INVALID_RHS: | ||
1080 | gcc_unreachable (); | ||
1081 | } | ||
1082 | |||
1083 | === modified file 'gcc/tree-ssa-dom.c' | ||
1084 | --- old/gcc/tree-ssa-dom.c 2010-07-20 11:44:16 +0000 | ||
1085 | +++ new/gcc/tree-ssa-dom.c 2010-09-16 09:15:46 +0000 | ||
1086 | @@ -54,6 +54,7 @@ | ||
1087 | EXPR_SINGLE, | ||
1088 | EXPR_UNARY, | ||
1089 | EXPR_BINARY, | ||
1090 | + EXPR_TERNARY, | ||
1091 | EXPR_CALL | ||
1092 | }; | ||
1093 | |||
1094 | @@ -64,7 +65,8 @@ | ||
1095 | union { | ||
1096 | struct { tree rhs; } single; | ||
1097 | struct { enum tree_code op; tree opnd; } unary; | ||
1098 | - struct { enum tree_code op; tree opnd0; tree opnd1; } binary; | ||
1099 | + struct { enum tree_code op; tree opnd0, opnd1; } binary; | ||
1100 | + struct { enum tree_code op; tree opnd0, opnd1, opnd2; } ternary; | ||
1101 | struct { tree fn; bool pure; size_t nargs; tree *args; } call; | ||
1102 | } ops; | ||
1103 | }; | ||
1104 | @@ -214,22 +216,30 @@ | ||
1105 | switch (get_gimple_rhs_class (subcode)) | ||
1106 | { | ||
1107 | case GIMPLE_SINGLE_RHS: | ||
1108 | - expr->kind = EXPR_SINGLE; | ||
1109 | - expr->ops.single.rhs = gimple_assign_rhs1 (stmt); | ||
1110 | - break; | ||
1111 | + expr->kind = EXPR_SINGLE; | ||
1112 | + expr->ops.single.rhs = gimple_assign_rhs1 (stmt); | ||
1113 | + break; | ||
1114 | case GIMPLE_UNARY_RHS: | ||
1115 | - expr->kind = EXPR_UNARY; | ||
1116 | + expr->kind = EXPR_UNARY; | ||
1117 | expr->type = TREE_TYPE (gimple_assign_lhs (stmt)); | ||
1118 | - expr->ops.unary.op = subcode; | ||
1119 | - expr->ops.unary.opnd = gimple_assign_rhs1 (stmt); | ||
1120 | - break; | ||
1121 | + expr->ops.unary.op = subcode; | ||
1122 | + expr->ops.unary.opnd = gimple_assign_rhs1 (stmt); | ||
1123 | + break; | ||
1124 | case GIMPLE_BINARY_RHS: | ||
1125 | - expr->kind = EXPR_BINARY; | ||
1126 | - expr->type = TREE_TYPE (gimple_assign_lhs (stmt)); | ||
1127 | - expr->ops.binary.op = subcode; | ||
1128 | - expr->ops.binary.opnd0 = gimple_assign_rhs1 (stmt); | ||
1129 | - expr->ops.binary.opnd1 = gimple_assign_rhs2 (stmt); | ||
1130 | - break; | ||
1131 | + expr->kind = EXPR_BINARY; | ||
1132 | + expr->type = TREE_TYPE (gimple_assign_lhs (stmt)); | ||
1133 | + expr->ops.binary.op = subcode; | ||
1134 | + expr->ops.binary.opnd0 = gimple_assign_rhs1 (stmt); | ||
1135 | + expr->ops.binary.opnd1 = gimple_assign_rhs2 (stmt); | ||
1136 | + break; | ||
1137 | + case GIMPLE_TERNARY_RHS: | ||
1138 | + expr->kind = EXPR_TERNARY; | ||
1139 | + expr->type = TREE_TYPE (gimple_assign_lhs (stmt)); | ||
1140 | + expr->ops.ternary.op = subcode; | ||
1141 | + expr->ops.ternary.opnd0 = gimple_assign_rhs1 (stmt); | ||
1142 | + expr->ops.ternary.opnd1 = gimple_assign_rhs2 (stmt); | ||
1143 | + expr->ops.ternary.opnd2 = gimple_assign_rhs3 (stmt); | ||
1144 | + break; | ||
1145 | default: | ||
1146 | gcc_unreachable (); | ||
1147 | } | ||
1148 | @@ -374,23 +384,40 @@ | ||
1149 | expr1->ops.unary.opnd, 0); | ||
1150 | |||
1151 | case EXPR_BINARY: | ||
1152 | - { | ||
1153 | - if (expr0->ops.binary.op != expr1->ops.binary.op) | ||
1154 | - return false; | ||
1155 | - | ||
1156 | - if (operand_equal_p (expr0->ops.binary.opnd0, | ||
1157 | - expr1->ops.binary.opnd0, 0) | ||
1158 | - && operand_equal_p (expr0->ops.binary.opnd1, | ||
1159 | - expr1->ops.binary.opnd1, 0)) | ||
1160 | - return true; | ||
1161 | - | ||
1162 | - /* For commutative ops, allow the other order. */ | ||
1163 | - return (commutative_tree_code (expr0->ops.binary.op) | ||
1164 | - && operand_equal_p (expr0->ops.binary.opnd0, | ||
1165 | - expr1->ops.binary.opnd1, 0) | ||
1166 | - && operand_equal_p (expr0->ops.binary.opnd1, | ||
1167 | - expr1->ops.binary.opnd0, 0)); | ||
1168 | - } | ||
1169 | + if (expr0->ops.binary.op != expr1->ops.binary.op) | ||
1170 | + return false; | ||
1171 | + | ||
1172 | + if (operand_equal_p (expr0->ops.binary.opnd0, | ||
1173 | + expr1->ops.binary.opnd0, 0) | ||
1174 | + && operand_equal_p (expr0->ops.binary.opnd1, | ||
1175 | + expr1->ops.binary.opnd1, 0)) | ||
1176 | + return true; | ||
1177 | + | ||
1178 | + /* For commutative ops, allow the other order. */ | ||
1179 | + return (commutative_tree_code (expr0->ops.binary.op) | ||
1180 | + && operand_equal_p (expr0->ops.binary.opnd0, | ||
1181 | + expr1->ops.binary.opnd1, 0) | ||
1182 | + && operand_equal_p (expr0->ops.binary.opnd1, | ||
1183 | + expr1->ops.binary.opnd0, 0)); | ||
1184 | + | ||
1185 | + case EXPR_TERNARY: | ||
1186 | + if (expr0->ops.ternary.op != expr1->ops.ternary.op | ||
1187 | + || !operand_equal_p (expr0->ops.ternary.opnd2, | ||
1188 | + expr1->ops.ternary.opnd2, 0)) | ||
1189 | + return false; | ||
1190 | + | ||
1191 | + if (operand_equal_p (expr0->ops.ternary.opnd0, | ||
1192 | + expr1->ops.ternary.opnd0, 0) | ||
1193 | + && operand_equal_p (expr0->ops.ternary.opnd1, | ||
1194 | + expr1->ops.ternary.opnd1, 0)) | ||
1195 | + return true; | ||
1196 | + | ||
1197 | + /* For commutative ops, allow the other order. */ | ||
1198 | + return (commutative_ternary_tree_code (expr0->ops.ternary.op) | ||
1199 | + && operand_equal_p (expr0->ops.ternary.opnd0, | ||
1200 | + expr1->ops.ternary.opnd1, 0) | ||
1201 | + && operand_equal_p (expr0->ops.ternary.opnd1, | ||
1202 | + expr1->ops.ternary.opnd0, 0)); | ||
1203 | |||
1204 | case EXPR_CALL: | ||
1205 | { | ||
1206 | @@ -453,8 +480,8 @@ | ||
1207 | case EXPR_BINARY: | ||
1208 | val = iterative_hash_object (expr->ops.binary.op, val); | ||
1209 | if (commutative_tree_code (expr->ops.binary.op)) | ||
1210 | - val = iterative_hash_exprs_commutative (expr->ops.binary.opnd0, | ||
1211 | - expr->ops.binary.opnd1, val); | ||
1212 | + val = iterative_hash_exprs_commutative (expr->ops.binary.opnd0, | ||
1213 | + expr->ops.binary.opnd1, val); | ||
1214 | else | ||
1215 | { | ||
1216 | val = iterative_hash_expr (expr->ops.binary.opnd0, val); | ||
1217 | @@ -462,6 +489,19 @@ | ||
1218 | } | ||
1219 | break; | ||
1220 | |||
1221 | + case EXPR_TERNARY: | ||
1222 | + val = iterative_hash_object (expr->ops.ternary.op, val); | ||
1223 | + if (commutative_ternary_tree_code (expr->ops.ternary.op)) | ||
1224 | + val = iterative_hash_exprs_commutative (expr->ops.ternary.opnd0, | ||
1225 | + expr->ops.ternary.opnd1, val); | ||
1226 | + else | ||
1227 | + { | ||
1228 | + val = iterative_hash_expr (expr->ops.ternary.opnd0, val); | ||
1229 | + val = iterative_hash_expr (expr->ops.ternary.opnd1, val); | ||
1230 | + } | ||
1231 | + val = iterative_hash_expr (expr->ops.ternary.opnd2, val); | ||
1232 | + break; | ||
1233 | + | ||
1234 | case EXPR_CALL: | ||
1235 | { | ||
1236 | size_t i; | ||
1237 | @@ -514,6 +554,16 @@ | ||
1238 | print_generic_expr (stream, element->expr.ops.binary.opnd1, 0); | ||
1239 | break; | ||
1240 | |||
1241 | + case EXPR_TERNARY: | ||
1242 | + fprintf (stream, " %s <", tree_code_name[element->expr.ops.ternary.op]); | ||
1243 | + print_generic_expr (stream, element->expr.ops.ternary.opnd0, 0); | ||
1244 | + fputs (", ", stream); | ||
1245 | + print_generic_expr (stream, element->expr.ops.ternary.opnd1, 0); | ||
1246 | + fputs (", ", stream); | ||
1247 | + print_generic_expr (stream, element->expr.ops.ternary.opnd2, 0); | ||
1248 | + fputs (">", stream); | ||
1249 | + break; | ||
1250 | + | ||
1251 | case EXPR_CALL: | ||
1252 | { | ||
1253 | size_t i; | ||
1254 | |||
1255 | === modified file 'gcc/tree-ssa-math-opts.c' | ||
1256 | --- old/gcc/tree-ssa-math-opts.c 2010-09-01 13:29:58 +0000 | ||
1257 | +++ new/gcc/tree-ssa-math-opts.c 2010-09-16 09:15:46 +0000 | ||
1258 | @@ -1261,6 +1261,235 @@ | ||
1259 | } | ||
1260 | }; | ||
1261 | |||
1262 | +/* Return true if RHS is a suitable operand for a widening multiplication. | ||
1263 | + There are two cases: | ||
1264 | + | ||
1265 | + - RHS makes some value twice as wide. Store that value in *NEW_RHS_OUT | ||
1266 | + if so, and store its type in *TYPE_OUT. | ||
1267 | + | ||
1268 | + - RHS is an integer constant. Store that value in *NEW_RHS_OUT if so, | ||
1269 | + but leave *TYPE_OUT untouched. */ | ||
1270 | + | ||
1271 | +static bool | ||
1272 | +is_widening_mult_rhs_p (tree rhs, tree *type_out, tree *new_rhs_out) | ||
1273 | +{ | ||
1274 | + gimple stmt; | ||
1275 | + tree type, type1, rhs1; | ||
1276 | + enum tree_code rhs_code; | ||
1277 | + | ||
1278 | + if (TREE_CODE (rhs) == SSA_NAME) | ||
1279 | + { | ||
1280 | + type = TREE_TYPE (rhs); | ||
1281 | + stmt = SSA_NAME_DEF_STMT (rhs); | ||
1282 | + if (!is_gimple_assign (stmt)) | ||
1283 | + return false; | ||
1284 | + | ||
1285 | + rhs_code = gimple_assign_rhs_code (stmt); | ||
1286 | + if (TREE_CODE (type) == INTEGER_TYPE | ||
1287 | + ? !CONVERT_EXPR_CODE_P (rhs_code) | ||
1288 | + : rhs_code != FIXED_CONVERT_EXPR) | ||
1289 | + return false; | ||
1290 | + | ||
1291 | + rhs1 = gimple_assign_rhs1 (stmt); | ||
1292 | + type1 = TREE_TYPE (rhs1); | ||
1293 | + if (TREE_CODE (type1) != TREE_CODE (type) | ||
1294 | + || TYPE_PRECISION (type1) * 2 != TYPE_PRECISION (type)) | ||
1295 | + return false; | ||
1296 | + | ||
1297 | + *new_rhs_out = rhs1; | ||
1298 | + *type_out = type1; | ||
1299 | + return true; | ||
1300 | + } | ||
1301 | + | ||
1302 | + if (TREE_CODE (rhs) == INTEGER_CST) | ||
1303 | + { | ||
1304 | + *new_rhs_out = rhs; | ||
1305 | + *type_out = NULL; | ||
1306 | + return true; | ||
1307 | + } | ||
1308 | + | ||
1309 | + return false; | ||
1310 | +} | ||
1311 | + | ||
1312 | +/* Return true if STMT performs a widening multiplication. If so, | ||
1313 | + store the unwidened types of the operands in *TYPE1_OUT and *TYPE2_OUT | ||
1314 | + respectively. Also fill *RHS1_OUT and *RHS2_OUT such that converting | ||
1315 | + those operands to types *TYPE1_OUT and *TYPE2_OUT would give the | ||
1316 | + operands of the multiplication. */ | ||
1317 | + | ||
1318 | +static bool | ||
1319 | +is_widening_mult_p (gimple stmt, | ||
1320 | + tree *type1_out, tree *rhs1_out, | ||
1321 | + tree *type2_out, tree *rhs2_out) | ||
1322 | +{ | ||
1323 | + tree type; | ||
1324 | + | ||
1325 | + type = TREE_TYPE (gimple_assign_lhs (stmt)); | ||
1326 | + if (TREE_CODE (type) != INTEGER_TYPE | ||
1327 | + && TREE_CODE (type) != FIXED_POINT_TYPE) | ||
1328 | + return false; | ||
1329 | + | ||
1330 | + if (!is_widening_mult_rhs_p (gimple_assign_rhs1 (stmt), type1_out, rhs1_out)) | ||
1331 | + return false; | ||
1332 | + | ||
1333 | + if (!is_widening_mult_rhs_p (gimple_assign_rhs2 (stmt), type2_out, rhs2_out)) | ||
1334 | + return false; | ||
1335 | + | ||
1336 | + if (*type1_out == NULL) | ||
1337 | + { | ||
1338 | + if (*type2_out == NULL || !int_fits_type_p (*rhs1_out, *type2_out)) | ||
1339 | + return false; | ||
1340 | + *type1_out = *type2_out; | ||
1341 | + } | ||
1342 | + | ||
1343 | + if (*type2_out == NULL) | ||
1344 | + { | ||
1345 | + if (!int_fits_type_p (*rhs2_out, *type1_out)) | ||
1346 | + return false; | ||
1347 | + *type2_out = *type1_out; | ||
1348 | + } | ||
1349 | + | ||
1350 | + return true; | ||
1351 | +} | ||
1352 | + | ||
1353 | +/* Process a single gimple statement STMT, which has a MULT_EXPR as | ||
1354 | + its rhs, and try to convert it into a WIDEN_MULT_EXPR. The return | ||
1355 | + value is true iff we converted the statement. */ | ||
1356 | + | ||
1357 | +static bool | ||
1358 | +convert_mult_to_widen (gimple stmt) | ||
1359 | +{ | ||
1360 | + tree lhs, rhs1, rhs2, type, type1, type2; | ||
1361 | + enum insn_code handler; | ||
1362 | + | ||
1363 | + lhs = gimple_assign_lhs (stmt); | ||
1364 | + type = TREE_TYPE (lhs); | ||
1365 | + if (TREE_CODE (type) != INTEGER_TYPE) | ||
1366 | + return false; | ||
1367 | + | ||
1368 | + if (!is_widening_mult_p (stmt, &type1, &rhs1, &type2, &rhs2)) | ||
1369 | + return false; | ||
1370 | + | ||
1371 | + if (TYPE_UNSIGNED (type1) && TYPE_UNSIGNED (type2)) | ||
1372 | + handler = optab_handler (umul_widen_optab, TYPE_MODE (type))->insn_code; | ||
1373 | + else if (!TYPE_UNSIGNED (type1) && !TYPE_UNSIGNED (type2)) | ||
1374 | + handler = optab_handler (smul_widen_optab, TYPE_MODE (type))->insn_code; | ||
1375 | + else | ||
1376 | + handler = optab_handler (usmul_widen_optab, TYPE_MODE (type))->insn_code; | ||
1377 | + | ||
1378 | + if (handler == CODE_FOR_nothing) | ||
1379 | + return false; | ||
1380 | + | ||
1381 | + gimple_assign_set_rhs1 (stmt, fold_convert (type1, rhs1)); | ||
1382 | + gimple_assign_set_rhs2 (stmt, fold_convert (type2, rhs2)); | ||
1383 | + gimple_assign_set_rhs_code (stmt, WIDEN_MULT_EXPR); | ||
1384 | + update_stmt (stmt); | ||
1385 | + return true; | ||
1386 | +} | ||
1387 | + | ||
1388 | +/* Process a single gimple statement STMT, which is found at the | ||
1389 | + iterator GSI and has a either a PLUS_EXPR or a MINUS_EXPR as its | ||
1390 | + rhs (given by CODE), and try to convert it into a | ||
1391 | + WIDEN_MULT_PLUS_EXPR or a WIDEN_MULT_MINUS_EXPR. The return value | ||
1392 | + is true iff we converted the statement. */ | ||
1393 | + | ||
1394 | +static bool | ||
1395 | +convert_plusminus_to_widen (gimple_stmt_iterator *gsi, gimple stmt, | ||
1396 | + enum tree_code code) | ||
1397 | +{ | ||
1398 | + gimple rhs1_stmt = NULL, rhs2_stmt = NULL; | ||
1399 | + tree type, type1, type2; | ||
1400 | + tree lhs, rhs1, rhs2, mult_rhs1, mult_rhs2, add_rhs; | ||
1401 | + enum tree_code rhs1_code = ERROR_MARK, rhs2_code = ERROR_MARK; | ||
1402 | + optab this_optab; | ||
1403 | + enum tree_code wmult_code; | ||
1404 | + | ||
1405 | + lhs = gimple_assign_lhs (stmt); | ||
1406 | + type = TREE_TYPE (lhs); | ||
1407 | + if (TREE_CODE (type) != INTEGER_TYPE | ||
1408 | + && TREE_CODE (type) != FIXED_POINT_TYPE) | ||
1409 | + return false; | ||
1410 | + | ||
1411 | + if (code == MINUS_EXPR) | ||
1412 | + wmult_code = WIDEN_MULT_MINUS_EXPR; | ||
1413 | + else | ||
1414 | + wmult_code = WIDEN_MULT_PLUS_EXPR; | ||
1415 | + | ||
1416 | + rhs1 = gimple_assign_rhs1 (stmt); | ||
1417 | + rhs2 = gimple_assign_rhs2 (stmt); | ||
1418 | + | ||
1419 | + if (TREE_CODE (rhs1) == SSA_NAME) | ||
1420 | + { | ||
1421 | + rhs1_stmt = SSA_NAME_DEF_STMT (rhs1); | ||
1422 | + if (is_gimple_assign (rhs1_stmt)) | ||
1423 | + rhs1_code = gimple_assign_rhs_code (rhs1_stmt); | ||
1424 | + } | ||
1425 | + else | ||
1426 | + return false; | ||
1427 | + | ||
1428 | + if (TREE_CODE (rhs2) == SSA_NAME) | ||
1429 | + { | ||
1430 | + rhs2_stmt = SSA_NAME_DEF_STMT (rhs2); | ||
1431 | + if (is_gimple_assign (rhs2_stmt)) | ||
1432 | + rhs2_code = gimple_assign_rhs_code (rhs2_stmt); | ||
1433 | + } | ||
1434 | + else | ||
1435 | + return false; | ||
1436 | + | ||
1437 | + if (code == PLUS_EXPR && rhs1_code == MULT_EXPR) | ||
1438 | + { | ||
1439 | + if (!is_widening_mult_p (rhs1_stmt, &type1, &mult_rhs1, | ||
1440 | + &type2, &mult_rhs2)) | ||
1441 | + return false; | ||
1442 | + add_rhs = rhs2; | ||
1443 | + } | ||
1444 | + else if (rhs2_code == MULT_EXPR) | ||
1445 | + { | ||
1446 | + if (!is_widening_mult_p (rhs2_stmt, &type1, &mult_rhs1, | ||
1447 | + &type2, &mult_rhs2)) | ||
1448 | + return false; | ||
1449 | + add_rhs = rhs1; | ||
1450 | + } | ||
1451 | + else if (code == PLUS_EXPR && rhs1_code == WIDEN_MULT_EXPR) | ||
1452 | + { | ||
1453 | + mult_rhs1 = gimple_assign_rhs1 (rhs1_stmt); | ||
1454 | + mult_rhs2 = gimple_assign_rhs2 (rhs1_stmt); | ||
1455 | + type1 = TREE_TYPE (mult_rhs1); | ||
1456 | + type2 = TREE_TYPE (mult_rhs2); | ||
1457 | + add_rhs = rhs2; | ||
1458 | + } | ||
1459 | + else if (rhs2_code == WIDEN_MULT_EXPR) | ||
1460 | + { | ||
1461 | + mult_rhs1 = gimple_assign_rhs1 (rhs2_stmt); | ||
1462 | + mult_rhs2 = gimple_assign_rhs2 (rhs2_stmt); | ||
1463 | + type1 = TREE_TYPE (mult_rhs1); | ||
1464 | + type2 = TREE_TYPE (mult_rhs2); | ||
1465 | + add_rhs = rhs1; | ||
1466 | + } | ||
1467 | + else | ||
1468 | + return false; | ||
1469 | + | ||
1470 | + if (TYPE_UNSIGNED (type1) != TYPE_UNSIGNED (type2)) | ||
1471 | + return false; | ||
1472 | + | ||
1473 | + /* Verify that the machine can perform a widening multiply | ||
1474 | + accumulate in this mode/signedness combination, otherwise | ||
1475 | + this transformation is likely to pessimize code. */ | ||
1476 | + this_optab = optab_for_tree_code (wmult_code, type1, optab_default); | ||
1477 | + if (optab_handler (this_optab, TYPE_MODE (type))->insn_code | ||
1478 | + == CODE_FOR_nothing) | ||
1479 | + return false; | ||
1480 | + | ||
1481 | + /* ??? May need some type verification here? */ | ||
1482 | + | ||
1483 | + gimple_assign_set_rhs_with_ops_1 (gsi, wmult_code, | ||
1484 | + fold_convert (type1, mult_rhs1), | ||
1485 | + fold_convert (type2, mult_rhs2), | ||
1486 | + add_rhs); | ||
1487 | + update_stmt (gsi_stmt (*gsi)); | ||
1488 | + return true; | ||
1489 | +} | ||
1490 | + | ||
1491 | /* Find integer multiplications where the operands are extended from | ||
1492 | smaller types, and replace the MULT_EXPR with a WIDEN_MULT_EXPR | ||
1493 | where appropriate. */ | ||
1494 | @@ -1278,94 +1507,19 @@ | ||
1495 | for (gsi = gsi_after_labels (bb); !gsi_end_p (gsi); gsi_next (&gsi)) | ||
1496 | { | ||
1497 | gimple stmt = gsi_stmt (gsi); | ||
1498 | - gimple rhs1_stmt = NULL, rhs2_stmt = NULL; | ||
1499 | - tree type, type1 = NULL, type2 = NULL; | ||
1500 | - tree rhs1, rhs2, rhs1_convop = NULL, rhs2_convop = NULL; | ||
1501 | - enum tree_code rhs1_code, rhs2_code; | ||
1502 | - | ||
1503 | - if (!is_gimple_assign (stmt) | ||
1504 | - || gimple_assign_rhs_code (stmt) != MULT_EXPR) | ||
1505 | - continue; | ||
1506 | - | ||
1507 | - type = TREE_TYPE (gimple_assign_lhs (stmt)); | ||
1508 | - | ||
1509 | - if (TREE_CODE (type) != INTEGER_TYPE) | ||
1510 | - continue; | ||
1511 | - | ||
1512 | - rhs1 = gimple_assign_rhs1 (stmt); | ||
1513 | - rhs2 = gimple_assign_rhs2 (stmt); | ||
1514 | - | ||
1515 | - if (TREE_CODE (rhs1) == SSA_NAME) | ||
1516 | - { | ||
1517 | - rhs1_stmt = SSA_NAME_DEF_STMT (rhs1); | ||
1518 | - if (!is_gimple_assign (rhs1_stmt)) | ||
1519 | - continue; | ||
1520 | - rhs1_code = gimple_assign_rhs_code (rhs1_stmt); | ||
1521 | - if (!CONVERT_EXPR_CODE_P (rhs1_code)) | ||
1522 | - continue; | ||
1523 | - rhs1_convop = gimple_assign_rhs1 (rhs1_stmt); | ||
1524 | - type1 = TREE_TYPE (rhs1_convop); | ||
1525 | - if (TYPE_PRECISION (type1) * 2 != TYPE_PRECISION (type)) | ||
1526 | - continue; | ||
1527 | - } | ||
1528 | - else if (TREE_CODE (rhs1) != INTEGER_CST) | ||
1529 | - continue; | ||
1530 | - | ||
1531 | - if (TREE_CODE (rhs2) == SSA_NAME) | ||
1532 | - { | ||
1533 | - rhs2_stmt = SSA_NAME_DEF_STMT (rhs2); | ||
1534 | - if (!is_gimple_assign (rhs2_stmt)) | ||
1535 | - continue; | ||
1536 | - rhs2_code = gimple_assign_rhs_code (rhs2_stmt); | ||
1537 | - if (!CONVERT_EXPR_CODE_P (rhs2_code)) | ||
1538 | - continue; | ||
1539 | - rhs2_convop = gimple_assign_rhs1 (rhs2_stmt); | ||
1540 | - type2 = TREE_TYPE (rhs2_convop); | ||
1541 | - if (TYPE_PRECISION (type2) * 2 != TYPE_PRECISION (type)) | ||
1542 | - continue; | ||
1543 | - } | ||
1544 | - else if (TREE_CODE (rhs2) != INTEGER_CST) | ||
1545 | - continue; | ||
1546 | - | ||
1547 | - if (rhs1_stmt == NULL && rhs2_stmt == NULL) | ||
1548 | - continue; | ||
1549 | - | ||
1550 | - /* Verify that the machine can perform a widening multiply in this | ||
1551 | - mode/signedness combination, otherwise this transformation is | ||
1552 | - likely to pessimize code. */ | ||
1553 | - if ((rhs1_stmt == NULL || TYPE_UNSIGNED (type1)) | ||
1554 | - && (rhs2_stmt == NULL || TYPE_UNSIGNED (type2)) | ||
1555 | - && (optab_handler (umul_widen_optab, TYPE_MODE (type)) | ||
1556 | - ->insn_code == CODE_FOR_nothing)) | ||
1557 | - continue; | ||
1558 | - else if ((rhs1_stmt == NULL || !TYPE_UNSIGNED (type1)) | ||
1559 | - && (rhs2_stmt == NULL || !TYPE_UNSIGNED (type2)) | ||
1560 | - && (optab_handler (smul_widen_optab, TYPE_MODE (type)) | ||
1561 | - ->insn_code == CODE_FOR_nothing)) | ||
1562 | - continue; | ||
1563 | - else if (rhs1_stmt != NULL && rhs2_stmt != 0 | ||
1564 | - && (TYPE_UNSIGNED (type1) != TYPE_UNSIGNED (type2)) | ||
1565 | - && (optab_handler (usmul_widen_optab, TYPE_MODE (type)) | ||
1566 | - ->insn_code == CODE_FOR_nothing)) | ||
1567 | - continue; | ||
1568 | - | ||
1569 | - if ((rhs1_stmt == NULL && !int_fits_type_p (rhs1, type2)) | ||
1570 | - || (rhs2_stmt == NULL && !int_fits_type_p (rhs2, type1))) | ||
1571 | - continue; | ||
1572 | - | ||
1573 | - if (rhs1_stmt == NULL) | ||
1574 | - gimple_assign_set_rhs1 (stmt, fold_convert (type2, rhs1)); | ||
1575 | - else | ||
1576 | - gimple_assign_set_rhs1 (stmt, rhs1_convop); | ||
1577 | - if (rhs2_stmt == NULL) | ||
1578 | - gimple_assign_set_rhs2 (stmt, fold_convert (type1, rhs2)); | ||
1579 | - else | ||
1580 | - gimple_assign_set_rhs2 (stmt, rhs2_convop); | ||
1581 | - gimple_assign_set_rhs_code (stmt, WIDEN_MULT_EXPR); | ||
1582 | - update_stmt (stmt); | ||
1583 | - changed = true; | ||
1584 | + enum tree_code code; | ||
1585 | + | ||
1586 | + if (!is_gimple_assign (stmt)) | ||
1587 | + continue; | ||
1588 | + | ||
1589 | + code = gimple_assign_rhs_code (stmt); | ||
1590 | + if (code == MULT_EXPR) | ||
1591 | + changed |= convert_mult_to_widen (stmt); | ||
1592 | + else if (code == PLUS_EXPR || code == MINUS_EXPR) | ||
1593 | + changed |= convert_plusminus_to_widen (&gsi, stmt, code); | ||
1594 | } | ||
1595 | } | ||
1596 | + | ||
1597 | return (changed ? TODO_dump_func | TODO_update_ssa | TODO_verify_ssa | ||
1598 | | TODO_verify_stmts : 0); | ||
1599 | } | ||
1600 | |||
1601 | === modified file 'gcc/tree-ssa-operands.c' | ||
1602 | --- old/gcc/tree-ssa-operands.c 2010-04-02 18:54:46 +0000 | ||
1603 | +++ new/gcc/tree-ssa-operands.c 2010-09-16 09:15:46 +0000 | ||
1604 | @@ -994,11 +994,13 @@ | ||
1605 | |||
1606 | case DOT_PROD_EXPR: | ||
1607 | case REALIGN_LOAD_EXPR: | ||
1608 | + case WIDEN_MULT_PLUS_EXPR: | ||
1609 | + case WIDEN_MULT_MINUS_EXPR: | ||
1610 | { | ||
1611 | get_expr_operands (stmt, &TREE_OPERAND (expr, 0), flags); | ||
1612 | - get_expr_operands (stmt, &TREE_OPERAND (expr, 1), flags); | ||
1613 | - get_expr_operands (stmt, &TREE_OPERAND (expr, 2), flags); | ||
1614 | - return; | ||
1615 | + get_expr_operands (stmt, &TREE_OPERAND (expr, 1), flags); | ||
1616 | + get_expr_operands (stmt, &TREE_OPERAND (expr, 2), flags); | ||
1617 | + return; | ||
1618 | } | ||
1619 | |||
1620 | case FUNCTION_DECL: | ||
1621 | |||
1622 | === modified file 'gcc/tree-ssa-sccvn.c' | ||
1623 | --- old/gcc/tree-ssa-sccvn.c 2010-05-14 11:40:18 +0000 | ||
1624 | +++ new/gcc/tree-ssa-sccvn.c 2010-09-16 09:15:46 +0000 | ||
1625 | @@ -2277,6 +2277,10 @@ | ||
1626 | case GIMPLE_BINARY_RHS: | ||
1627 | return (is_gimple_min_invariant (gimple_assign_rhs1 (stmt)) | ||
1628 | || is_gimple_min_invariant (gimple_assign_rhs2 (stmt))); | ||
1629 | + case GIMPLE_TERNARY_RHS: | ||
1630 | + return (is_gimple_min_invariant (gimple_assign_rhs1 (stmt)) | ||
1631 | + || is_gimple_min_invariant (gimple_assign_rhs2 (stmt)) | ||
1632 | + || is_gimple_min_invariant (gimple_assign_rhs3 (stmt))); | ||
1633 | case GIMPLE_SINGLE_RHS: | ||
1634 | /* Constants inside reference ops are rarely interesting, but | ||
1635 | it can take a lot of looking to find them. */ | ||
1636 | |||
1637 | === modified file 'gcc/tree-ssa-threadedge.c' | ||
1638 | --- old/gcc/tree-ssa-threadedge.c 2009-11-25 10:55:54 +0000 | ||
1639 | +++ new/gcc/tree-ssa-threadedge.c 2010-09-16 09:15:46 +0000 | ||
1640 | @@ -247,14 +247,14 @@ | ||
1641 | |||
1642 | return fold (rhs); | ||
1643 | } | ||
1644 | - break; | ||
1645 | + | ||
1646 | case GIMPLE_UNARY_RHS: | ||
1647 | { | ||
1648 | tree lhs = gimple_assign_lhs (stmt); | ||
1649 | tree op0 = gimple_assign_rhs1 (stmt); | ||
1650 | return fold_unary (subcode, TREE_TYPE (lhs), op0); | ||
1651 | } | ||
1652 | - break; | ||
1653 | + | ||
1654 | case GIMPLE_BINARY_RHS: | ||
1655 | { | ||
1656 | tree lhs = gimple_assign_lhs (stmt); | ||
1657 | @@ -262,7 +262,16 @@ | ||
1658 | tree op1 = gimple_assign_rhs2 (stmt); | ||
1659 | return fold_binary (subcode, TREE_TYPE (lhs), op0, op1); | ||
1660 | } | ||
1661 | - break; | ||
1662 | + | ||
1663 | + case GIMPLE_TERNARY_RHS: | ||
1664 | + { | ||
1665 | + tree lhs = gimple_assign_lhs (stmt); | ||
1666 | + tree op0 = gimple_assign_rhs1 (stmt); | ||
1667 | + tree op1 = gimple_assign_rhs2 (stmt); | ||
1668 | + tree op2 = gimple_assign_rhs3 (stmt); | ||
1669 | + return fold_ternary (subcode, TREE_TYPE (lhs), op0, op1, op2); | ||
1670 | + } | ||
1671 | + | ||
1672 | default: | ||
1673 | gcc_unreachable (); | ||
1674 | } | ||
1675 | |||
1676 | === modified file 'gcc/tree-vrp.c' | ||
1677 | --- old/gcc/tree-vrp.c 2010-06-14 14:23:31 +0000 | ||
1678 | +++ new/gcc/tree-vrp.c 2010-09-16 09:15:46 +0000 | ||
1679 | @@ -864,6 +864,8 @@ | ||
1680 | gimple_assign_rhs1 (stmt), | ||
1681 | gimple_assign_rhs2 (stmt), | ||
1682 | strict_overflow_p); | ||
1683 | + case GIMPLE_TERNARY_RHS: | ||
1684 | + return false; | ||
1685 | case GIMPLE_SINGLE_RHS: | ||
1686 | return tree_single_nonnegative_warnv_p (gimple_assign_rhs1 (stmt), | ||
1687 | strict_overflow_p); | ||
1688 | @@ -935,6 +937,8 @@ | ||
1689 | gimple_assign_rhs1 (stmt), | ||
1690 | gimple_assign_rhs2 (stmt), | ||
1691 | strict_overflow_p); | ||
1692 | + case GIMPLE_TERNARY_RHS: | ||
1693 | + return false; | ||
1694 | case GIMPLE_SINGLE_RHS: | ||
1695 | return tree_single_nonzero_warnv_p (gimple_assign_rhs1 (stmt), | ||
1696 | strict_overflow_p); | ||
1697 | |||
1698 | === modified file 'gcc/tree.c' | ||
1699 | --- old/gcc/tree.c 2010-08-10 13:31:21 +0000 | ||
1700 | +++ new/gcc/tree.c 2010-09-16 09:15:46 +0000 | ||
1701 | @@ -6538,6 +6538,23 @@ | ||
1702 | return false; | ||
1703 | } | ||
1704 | |||
1705 | +/* Return true if CODE represents a ternary tree code for which the | ||
1706 | + first two operands are commutative. Otherwise return false. */ | ||
1707 | +bool | ||
1708 | +commutative_ternary_tree_code (enum tree_code code) | ||
1709 | +{ | ||
1710 | + switch (code) | ||
1711 | + { | ||
1712 | + case WIDEN_MULT_PLUS_EXPR: | ||
1713 | + case WIDEN_MULT_MINUS_EXPR: | ||
1714 | + return true; | ||
1715 | + | ||
1716 | + default: | ||
1717 | + break; | ||
1718 | + } | ||
1719 | + return false; | ||
1720 | +} | ||
1721 | + | ||
1722 | /* Generate a hash value for an expression. This can be used iteratively | ||
1723 | by passing a previous result as the VAL argument. | ||
1724 | |||
1725 | |||
1726 | === modified file 'gcc/tree.def' | ||
1727 | --- old/gcc/tree.def 2010-04-02 18:54:46 +0000 | ||
1728 | +++ new/gcc/tree.def 2010-09-16 09:15:46 +0000 | ||
1729 | @@ -1083,6 +1083,18 @@ | ||
1730 | the arguments from type t1 to type t2, and then multiplying them. */ | ||
1731 | DEFTREECODE (WIDEN_MULT_EXPR, "widen_mult_expr", tcc_binary, 2) | ||
1732 | |||
1733 | +/* Widening multiply-accumulate. | ||
1734 | + The first two arguments are of type t1. | ||
1735 | + The third argument and the result are of type t2, such as t2 is at least | ||
1736 | + twice the size of t1. t1 and t2 must be integral or fixed-point types. | ||
1737 | + The expression is equivalent to a WIDEN_MULT_EXPR operation | ||
1738 | + of the first two operands followed by an add or subtract of the third | ||
1739 | + operand. */ | ||
1740 | +DEFTREECODE (WIDEN_MULT_PLUS_EXPR, "widen_mult_plus_expr", tcc_expression, 3) | ||
1741 | +/* This is like the above, except in the final expression the multiply result | ||
1742 | + is subtracted from t3. */ | ||
1743 | +DEFTREECODE (WIDEN_MULT_MINUS_EXPR, "widen_mult_plus_expr", tcc_expression, 3) | ||
1744 | + | ||
1745 | /* Whole vector left/right shift in bits. | ||
1746 | Operand 0 is a vector to be shifted. | ||
1747 | Operand 1 is an integer shift amount in bits. */ | ||
1748 | |||
1749 | === modified file 'gcc/tree.h' | ||
1750 | --- old/gcc/tree.h 2010-08-10 13:31:21 +0000 | ||
1751 | +++ new/gcc/tree.h 2010-09-16 09:15:46 +0000 | ||
1752 | @@ -4705,6 +4705,7 @@ | ||
1753 | extern int type_num_arguments (const_tree); | ||
1754 | extern bool associative_tree_code (enum tree_code); | ||
1755 | extern bool commutative_tree_code (enum tree_code); | ||
1756 | +extern bool commutative_ternary_tree_code (enum tree_code); | ||
1757 | extern tree upper_bound_in_type (tree, tree); | ||
1758 | extern tree lower_bound_in_type (tree, tree); | ||
1759 | extern int operand_equal_for_phi_arg_p (const_tree, const_tree); | ||
1760 | |||