summaryrefslogtreecommitdiffstats
path: root/recipes-devtools/gcc/gcc-4.5/linaro/gcc-4.5-linaro-r99396.patch
diff options
context:
space:
mode:
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.patch1760
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 @@
12010-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