]> git.ipfire.org Git - thirdparty/gcc.git/blob - gcc/tree-ssa-reassoc.c
backport: ChangeLog.tuples: ChangeLog from gimple-tuples-branch.
[thirdparty/gcc.git] / gcc / tree-ssa-reassoc.c
1 /* Reassociation for trees.
2 Copyright (C) 2005, 2007 Free Software Foundation, Inc.
3 Contributed by Daniel Berlin <dan@dberlin.org>
4
5 This file is part of GCC.
6
7 GCC is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3, or (at your option)
10 any later version.
11
12 GCC is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with GCC; see the file COPYING3. If not see
19 <http://www.gnu.org/licenses/>. */
20
21 #include "config.h"
22 #include "system.h"
23 #include "coretypes.h"
24 #include "tm.h"
25 #include "errors.h"
26 #include "ggc.h"
27 #include "tree.h"
28 #include "basic-block.h"
29 #include "diagnostic.h"
30 #include "tree-inline.h"
31 #include "tree-flow.h"
32 #include "gimple.h"
33 #include "tree-dump.h"
34 #include "timevar.h"
35 #include "tree-iterator.h"
36 #include "tree-pass.h"
37 #include "alloc-pool.h"
38 #include "vec.h"
39 #include "langhooks.h"
40 #include "pointer-set.h"
41 #include "cfgloop.h"
42 #include "flags.h"
43
44 /* This is a simple global reassociation pass. It is, in part, based
45 on the LLVM pass of the same name (They do some things more/less
46 than we do, in different orders, etc).
47
48 It consists of five steps:
49
50 1. Breaking up subtract operations into addition + negate, where
51 it would promote the reassociation of adds.
52
53 2. Left linearization of the expression trees, so that (A+B)+(C+D)
54 becomes (((A+B)+C)+D), which is easier for us to rewrite later.
55 During linearization, we place the operands of the binary
56 expressions into a vector of operand_entry_t
57
58 3. Optimization of the operand lists, eliminating things like a +
59 -a, a & a, etc.
60
61 4. Rewrite the expression trees we linearized and optimized so
62 they are in proper rank order.
63
64 5. Repropagate negates, as nothing else will clean it up ATM.
65
66 A bit of theory on #4, since nobody seems to write anything down
67 about why it makes sense to do it the way they do it:
68
69 We could do this much nicer theoretically, but don't (for reasons
70 explained after how to do it theoretically nice :P).
71
72 In order to promote the most redundancy elimination, you want
73 binary expressions whose operands are the same rank (or
74 preferably, the same value) exposed to the redundancy eliminator,
75 for possible elimination.
76
77 So the way to do this if we really cared, is to build the new op
78 tree from the leaves to the roots, merging as you go, and putting the
79 new op on the end of the worklist, until you are left with one
80 thing on the worklist.
81
82 IE if you have to rewrite the following set of operands (listed with
83 rank in parentheses), with opcode PLUS_EXPR:
84
85 a (1), b (1), c (1), d (2), e (2)
86
87
88 We start with our merge worklist empty, and the ops list with all of
89 those on it.
90
91 You want to first merge all leaves of the same rank, as much as
92 possible.
93
94 So first build a binary op of
95
96 mergetmp = a + b, and put "mergetmp" on the merge worklist.
97
98 Because there is no three operand form of PLUS_EXPR, c is not going to
99 be exposed to redundancy elimination as a rank 1 operand.
100
101 So you might as well throw it on the merge worklist (you could also
102 consider it to now be a rank two operand, and merge it with d and e,
103 but in this case, you then have evicted e from a binary op. So at
104 least in this situation, you can't win.)
105
106 Then build a binary op of d + e
107 mergetmp2 = d + e
108
109 and put mergetmp2 on the merge worklist.
110
111 so merge worklist = {mergetmp, c, mergetmp2}
112
113 Continue building binary ops of these operations until you have only
114 one operation left on the worklist.
115
116 So we have
117
118 build binary op
119 mergetmp3 = mergetmp + c
120
121 worklist = {mergetmp2, mergetmp3}
122
123 mergetmp4 = mergetmp2 + mergetmp3
124
125 worklist = {mergetmp4}
126
127 because we have one operation left, we can now just set the original
128 statement equal to the result of that operation.
129
130 This will at least expose a + b and d + e to redundancy elimination
131 as binary operations.
132
133 For extra points, you can reuse the old statements to build the
134 mergetmps, since you shouldn't run out.
135
136 So why don't we do this?
137
138 Because it's expensive, and rarely will help. Most trees we are
139 reassociating have 3 or less ops. If they have 2 ops, they already
140 will be written into a nice single binary op. If you have 3 ops, a
141 single simple check suffices to tell you whether the first two are of the
142 same rank. If so, you know to order it
143
144 mergetmp = op1 + op2
145 newstmt = mergetmp + op3
146
147 instead of
148 mergetmp = op2 + op3
149 newstmt = mergetmp + op1
150
151 If all three are of the same rank, you can't expose them all in a
152 single binary operator anyway, so the above is *still* the best you
153 can do.
154
155 Thus, this is what we do. When we have three ops left, we check to see
156 what order to put them in, and call it a day. As a nod to vector sum
157 reduction, we check if any of ops are a really a phi node that is a
158 destructive update for the associating op, and keep the destructive
159 update together for vector sum reduction recognition. */
160
161
162 /* Statistics */
163 static struct
164 {
165 int linearized;
166 int constants_eliminated;
167 int ops_eliminated;
168 int rewritten;
169 } reassociate_stats;
170
171 /* Operator, rank pair. */
172 typedef struct operand_entry
173 {
174 unsigned int rank;
175 tree op;
176 } *operand_entry_t;
177
178 static alloc_pool operand_entry_pool;
179
180
181 /* Starting rank number for a given basic block, so that we can rank
182 operations using unmovable instructions in that BB based on the bb
183 depth. */
184 static long *bb_rank;
185
186 /* Operand->rank hashtable. */
187 static struct pointer_map_t *operand_rank;
188
189
190 /* Look up the operand rank structure for expression E. */
191
192 static inline long
193 find_operand_rank (tree e)
194 {
195 void **slot = pointer_map_contains (operand_rank, e);
196 return slot ? (long) *slot : -1;
197 }
198
199 /* Insert {E,RANK} into the operand rank hashtable. */
200
201 static inline void
202 insert_operand_rank (tree e, long rank)
203 {
204 void **slot;
205 gcc_assert (rank > 0);
206 slot = pointer_map_insert (operand_rank, e);
207 gcc_assert (!*slot);
208 *slot = (void *) rank;
209 }
210
211 /* Given an expression E, return the rank of the expression. */
212
213 static long
214 get_rank (tree e)
215 {
216 /* Constants have rank 0. */
217 if (is_gimple_min_invariant (e))
218 return 0;
219
220 /* SSA_NAME's have the rank of the expression they are the result
221 of.
222 For globals and uninitialized values, the rank is 0.
223 For function arguments, use the pre-setup rank.
224 For PHI nodes, stores, asm statements, etc, we use the rank of
225 the BB.
226 For simple operations, the rank is the maximum rank of any of
227 its operands, or the bb_rank, whichever is less.
228 I make no claims that this is optimal, however, it gives good
229 results. */
230
231 if (TREE_CODE (e) == SSA_NAME)
232 {
233 gimple stmt;
234 long rank, maxrank;
235 int i, n;
236
237 if (TREE_CODE (SSA_NAME_VAR (e)) == PARM_DECL
238 && SSA_NAME_IS_DEFAULT_DEF (e))
239 return find_operand_rank (e);
240
241 stmt = SSA_NAME_DEF_STMT (e);
242 if (gimple_bb (stmt) == NULL)
243 return 0;
244
245 if (!is_gimple_assign (stmt)
246 || !ZERO_SSA_OPERANDS (stmt, SSA_OP_VIRTUAL_DEFS))
247 return bb_rank[gimple_bb (stmt)->index];
248
249 /* If we already have a rank for this expression, use that. */
250 rank = find_operand_rank (e);
251 if (rank != -1)
252 return rank;
253
254 /* Otherwise, find the maximum rank for the operands, or the bb
255 rank, whichever is less. */
256 rank = 0;
257 maxrank = bb_rank[gimple_bb(stmt)->index];
258 if (gimple_assign_single_p (stmt))
259 {
260 tree rhs = gimple_assign_rhs1 (stmt);
261 n = TREE_OPERAND_LENGTH (rhs);
262 if (n == 0)
263 rank = MAX (rank, get_rank (rhs));
264 else
265 {
266 for (i = 0;
267 i < n && TREE_OPERAND (rhs, i) && rank != maxrank; i++)
268 rank = MAX(rank, get_rank (TREE_OPERAND (rhs, i)));
269 }
270 }
271 else
272 {
273 n = gimple_num_ops (stmt);
274 for (i = 1; i < n && rank != maxrank; i++)
275 {
276 gcc_assert (gimple_op (stmt, i));
277 rank = MAX(rank, get_rank (gimple_op (stmt, i)));
278 }
279 }
280
281 if (dump_file && (dump_flags & TDF_DETAILS))
282 {
283 fprintf (dump_file, "Rank for ");
284 print_generic_expr (dump_file, e, 0);
285 fprintf (dump_file, " is %ld\n", (rank + 1));
286 }
287
288 /* Note the rank in the hashtable so we don't recompute it. */
289 insert_operand_rank (e, (rank + 1));
290 return (rank + 1);
291 }
292
293 /* Globals, etc, are rank 0 */
294 return 0;
295 }
296
297 DEF_VEC_P(operand_entry_t);
298 DEF_VEC_ALLOC_P(operand_entry_t, heap);
299
300 /* We want integer ones to end up last no matter what, since they are
301 the ones we can do the most with. */
302 #define INTEGER_CONST_TYPE 1 << 3
303 #define FLOAT_CONST_TYPE 1 << 2
304 #define OTHER_CONST_TYPE 1 << 1
305
306 /* Classify an invariant tree into integer, float, or other, so that
307 we can sort them to be near other constants of the same type. */
308 static inline int
309 constant_type (tree t)
310 {
311 if (INTEGRAL_TYPE_P (TREE_TYPE (t)))
312 return INTEGER_CONST_TYPE;
313 else if (SCALAR_FLOAT_TYPE_P (TREE_TYPE (t)))
314 return FLOAT_CONST_TYPE;
315 else
316 return OTHER_CONST_TYPE;
317 }
318
319 /* qsort comparison function to sort operand entries PA and PB by rank
320 so that the sorted array is ordered by rank in decreasing order. */
321 static int
322 sort_by_operand_rank (const void *pa, const void *pb)
323 {
324 const operand_entry_t oea = *(const operand_entry_t *)pa;
325 const operand_entry_t oeb = *(const operand_entry_t *)pb;
326
327 /* It's nicer for optimize_expression if constants that are likely
328 to fold when added/multiplied//whatever are put next to each
329 other. Since all constants have rank 0, order them by type. */
330 if (oeb->rank == 0 && oea->rank == 0)
331 return constant_type (oeb->op) - constant_type (oea->op);
332
333 /* Lastly, make sure the versions that are the same go next to each
334 other. We use SSA_NAME_VERSION because it's stable. */
335 if ((oeb->rank - oea->rank == 0)
336 && TREE_CODE (oea->op) == SSA_NAME
337 && TREE_CODE (oeb->op) == SSA_NAME)
338 return SSA_NAME_VERSION (oeb->op) - SSA_NAME_VERSION (oea->op);
339
340 return oeb->rank - oea->rank;
341 }
342
343 /* Add an operand entry to *OPS for the tree operand OP. */
344
345 static void
346 add_to_ops_vec (VEC(operand_entry_t, heap) **ops, tree op)
347 {
348 operand_entry_t oe = (operand_entry_t) pool_alloc (operand_entry_pool);
349
350 oe->op = op;
351 oe->rank = get_rank (op);
352 VEC_safe_push (operand_entry_t, heap, *ops, oe);
353 }
354
355 /* Return true if STMT is reassociable operation containing a binary
356 operation with tree code CODE, and is inside LOOP. */
357
358 static bool
359 is_reassociable_op (gimple stmt, enum tree_code code, struct loop *loop)
360 {
361 basic_block bb = gimple_bb (stmt);
362
363 if (gimple_bb (stmt) == NULL)
364 return false;
365
366 if (!flow_bb_inside_loop_p (loop, bb))
367 return false;
368
369 if (is_gimple_assign (stmt)
370 && gimple_assign_rhs_code (stmt) == code
371 && has_single_use (gimple_assign_lhs (stmt)))
372 return true;
373
374 return false;
375 }
376
377
378 /* Given NAME, if NAME is defined by a unary operation OPCODE, return the
379 operand of the negate operation. Otherwise, return NULL. */
380
381 static tree
382 get_unary_op (tree name, enum tree_code opcode)
383 {
384 gimple stmt = SSA_NAME_DEF_STMT (name);
385
386 if (!is_gimple_assign (stmt))
387 return NULL_TREE;
388
389 if (gimple_assign_rhs_code (stmt) == opcode)
390 return gimple_assign_rhs1 (stmt);
391 return NULL_TREE;
392 }
393
394 /* If CURR and LAST are a pair of ops that OPCODE allows us to
395 eliminate through equivalences, do so, remove them from OPS, and
396 return true. Otherwise, return false. */
397
398 static bool
399 eliminate_duplicate_pair (enum tree_code opcode,
400 VEC (operand_entry_t, heap) **ops,
401 bool *all_done,
402 unsigned int i,
403 operand_entry_t curr,
404 operand_entry_t last)
405 {
406
407 /* If we have two of the same op, and the opcode is & |, min, or max,
408 we can eliminate one of them.
409 If we have two of the same op, and the opcode is ^, we can
410 eliminate both of them. */
411
412 if (last && last->op == curr->op)
413 {
414 switch (opcode)
415 {
416 case MAX_EXPR:
417 case MIN_EXPR:
418 case BIT_IOR_EXPR:
419 case BIT_AND_EXPR:
420 if (dump_file && (dump_flags & TDF_DETAILS))
421 {
422 fprintf (dump_file, "Equivalence: ");
423 print_generic_expr (dump_file, curr->op, 0);
424 fprintf (dump_file, " [&|minmax] ");
425 print_generic_expr (dump_file, last->op, 0);
426 fprintf (dump_file, " -> ");
427 print_generic_stmt (dump_file, last->op, 0);
428 }
429
430 VEC_ordered_remove (operand_entry_t, *ops, i);
431 reassociate_stats.ops_eliminated ++;
432
433 return true;
434
435 case BIT_XOR_EXPR:
436 if (dump_file && (dump_flags & TDF_DETAILS))
437 {
438 fprintf (dump_file, "Equivalence: ");
439 print_generic_expr (dump_file, curr->op, 0);
440 fprintf (dump_file, " ^ ");
441 print_generic_expr (dump_file, last->op, 0);
442 fprintf (dump_file, " -> nothing\n");
443 }
444
445 reassociate_stats.ops_eliminated += 2;
446
447 if (VEC_length (operand_entry_t, *ops) == 2)
448 {
449 VEC_free (operand_entry_t, heap, *ops);
450 *ops = NULL;
451 add_to_ops_vec (ops, fold_convert (TREE_TYPE (last->op),
452 integer_zero_node));
453 *all_done = true;
454 }
455 else
456 {
457 VEC_ordered_remove (operand_entry_t, *ops, i-1);
458 VEC_ordered_remove (operand_entry_t, *ops, i-1);
459 }
460
461 return true;
462
463 default:
464 break;
465 }
466 }
467 return false;
468 }
469
470 /* If OPCODE is PLUS_EXPR, CURR->OP is really a negate expression,
471 look in OPS for a corresponding positive operation to cancel it
472 out. If we find one, remove the other from OPS, replace
473 OPS[CURRINDEX] with 0, and return true. Otherwise, return
474 false. */
475
476 static bool
477 eliminate_plus_minus_pair (enum tree_code opcode,
478 VEC (operand_entry_t, heap) **ops,
479 unsigned int currindex,
480 operand_entry_t curr)
481 {
482 tree negateop;
483 unsigned int i;
484 operand_entry_t oe;
485
486 if (opcode != PLUS_EXPR || TREE_CODE (curr->op) != SSA_NAME)
487 return false;
488
489 negateop = get_unary_op (curr->op, NEGATE_EXPR);
490 if (negateop == NULL_TREE)
491 return false;
492
493 /* Any non-negated version will have a rank that is one less than
494 the current rank. So once we hit those ranks, if we don't find
495 one, we can stop. */
496
497 for (i = currindex + 1;
498 VEC_iterate (operand_entry_t, *ops, i, oe)
499 && oe->rank >= curr->rank - 1 ;
500 i++)
501 {
502 if (oe->op == negateop)
503 {
504
505 if (dump_file && (dump_flags & TDF_DETAILS))
506 {
507 fprintf (dump_file, "Equivalence: ");
508 print_generic_expr (dump_file, negateop, 0);
509 fprintf (dump_file, " + -");
510 print_generic_expr (dump_file, oe->op, 0);
511 fprintf (dump_file, " -> 0\n");
512 }
513
514 VEC_ordered_remove (operand_entry_t, *ops, i);
515 add_to_ops_vec (ops, fold_convert(TREE_TYPE (oe->op),
516 integer_zero_node));
517 VEC_ordered_remove (operand_entry_t, *ops, currindex);
518 reassociate_stats.ops_eliminated ++;
519
520 return true;
521 }
522 }
523
524 return false;
525 }
526
527 /* If OPCODE is BIT_IOR_EXPR, BIT_AND_EXPR, and, CURR->OP is really a
528 bitwise not expression, look in OPS for a corresponding operand to
529 cancel it out. If we find one, remove the other from OPS, replace
530 OPS[CURRINDEX] with 0, and return true. Otherwise, return
531 false. */
532
533 static bool
534 eliminate_not_pairs (enum tree_code opcode,
535 VEC (operand_entry_t, heap) **ops,
536 unsigned int currindex,
537 operand_entry_t curr)
538 {
539 tree notop;
540 unsigned int i;
541 operand_entry_t oe;
542
543 if ((opcode != BIT_IOR_EXPR && opcode != BIT_AND_EXPR)
544 || TREE_CODE (curr->op) != SSA_NAME)
545 return false;
546
547 notop = get_unary_op (curr->op, BIT_NOT_EXPR);
548 if (notop == NULL_TREE)
549 return false;
550
551 /* Any non-not version will have a rank that is one less than
552 the current rank. So once we hit those ranks, if we don't find
553 one, we can stop. */
554
555 for (i = currindex + 1;
556 VEC_iterate (operand_entry_t, *ops, i, oe)
557 && oe->rank >= curr->rank - 1;
558 i++)
559 {
560 if (oe->op == notop)
561 {
562 if (dump_file && (dump_flags & TDF_DETAILS))
563 {
564 fprintf (dump_file, "Equivalence: ");
565 print_generic_expr (dump_file, notop, 0);
566 if (opcode == BIT_AND_EXPR)
567 fprintf (dump_file, " & ~");
568 else if (opcode == BIT_IOR_EXPR)
569 fprintf (dump_file, " | ~");
570 print_generic_expr (dump_file, oe->op, 0);
571 if (opcode == BIT_AND_EXPR)
572 fprintf (dump_file, " -> 0\n");
573 else if (opcode == BIT_IOR_EXPR)
574 fprintf (dump_file, " -> -1\n");
575 }
576
577 if (opcode == BIT_AND_EXPR)
578 oe->op = fold_convert (TREE_TYPE (oe->op), integer_zero_node);
579 else if (opcode == BIT_IOR_EXPR)
580 oe->op = build_low_bits_mask (TREE_TYPE (oe->op),
581 TYPE_PRECISION (TREE_TYPE (oe->op)));
582
583 reassociate_stats.ops_eliminated
584 += VEC_length (operand_entry_t, *ops) - 1;
585 VEC_free (operand_entry_t, heap, *ops);
586 *ops = NULL;
587 VEC_safe_push (operand_entry_t, heap, *ops, oe);
588 return true;
589 }
590 }
591
592 return false;
593 }
594
595 /* Use constant value that may be present in OPS to try to eliminate
596 operands. Note that this function is only really used when we've
597 eliminated ops for other reasons, or merged constants. Across
598 single statements, fold already does all of this, plus more. There
599 is little point in duplicating logic, so I've only included the
600 identities that I could ever construct testcases to trigger. */
601
602 static void
603 eliminate_using_constants (enum tree_code opcode,
604 VEC(operand_entry_t, heap) **ops)
605 {
606 operand_entry_t oelast = VEC_last (operand_entry_t, *ops);
607 tree type = TREE_TYPE (oelast->op);
608
609 if (oelast->rank == 0
610 && (INTEGRAL_TYPE_P (type) || FLOAT_TYPE_P (type)))
611 {
612 switch (opcode)
613 {
614 case BIT_AND_EXPR:
615 if (integer_zerop (oelast->op))
616 {
617 if (VEC_length (operand_entry_t, *ops) != 1)
618 {
619 if (dump_file && (dump_flags & TDF_DETAILS))
620 fprintf (dump_file, "Found & 0, removing all other ops\n");
621
622 reassociate_stats.ops_eliminated
623 += VEC_length (operand_entry_t, *ops) - 1;
624
625 VEC_free (operand_entry_t, heap, *ops);
626 *ops = NULL;
627 VEC_safe_push (operand_entry_t, heap, *ops, oelast);
628 return;
629 }
630 }
631 else if (integer_all_onesp (oelast->op))
632 {
633 if (VEC_length (operand_entry_t, *ops) != 1)
634 {
635 if (dump_file && (dump_flags & TDF_DETAILS))
636 fprintf (dump_file, "Found & -1, removing\n");
637 VEC_pop (operand_entry_t, *ops);
638 reassociate_stats.ops_eliminated++;
639 }
640 }
641 break;
642 case BIT_IOR_EXPR:
643 if (integer_all_onesp (oelast->op))
644 {
645 if (VEC_length (operand_entry_t, *ops) != 1)
646 {
647 if (dump_file && (dump_flags & TDF_DETAILS))
648 fprintf (dump_file, "Found | -1, removing all other ops\n");
649
650 reassociate_stats.ops_eliminated
651 += VEC_length (operand_entry_t, *ops) - 1;
652
653 VEC_free (operand_entry_t, heap, *ops);
654 *ops = NULL;
655 VEC_safe_push (operand_entry_t, heap, *ops, oelast);
656 return;
657 }
658 }
659 else if (integer_zerop (oelast->op))
660 {
661 if (VEC_length (operand_entry_t, *ops) != 1)
662 {
663 if (dump_file && (dump_flags & TDF_DETAILS))
664 fprintf (dump_file, "Found | 0, removing\n");
665 VEC_pop (operand_entry_t, *ops);
666 reassociate_stats.ops_eliminated++;
667 }
668 }
669 break;
670 case MULT_EXPR:
671 if (integer_zerop (oelast->op)
672 || (FLOAT_TYPE_P (type)
673 && !HONOR_NANS (TYPE_MODE (type))
674 && !HONOR_SIGNED_ZEROS (TYPE_MODE (type))
675 && real_zerop (oelast->op)))
676 {
677 if (VEC_length (operand_entry_t, *ops) != 1)
678 {
679 if (dump_file && (dump_flags & TDF_DETAILS))
680 fprintf (dump_file, "Found * 0, removing all other ops\n");
681
682 reassociate_stats.ops_eliminated
683 += VEC_length (operand_entry_t, *ops) - 1;
684 VEC_free (operand_entry_t, heap, *ops);
685 *ops = NULL;
686 VEC_safe_push (operand_entry_t, heap, *ops, oelast);
687 return;
688 }
689 }
690 else if (integer_onep (oelast->op)
691 || (FLOAT_TYPE_P (type)
692 && !HONOR_SNANS (TYPE_MODE (type))
693 && real_onep (oelast->op)))
694 {
695 if (VEC_length (operand_entry_t, *ops) != 1)
696 {
697 if (dump_file && (dump_flags & TDF_DETAILS))
698 fprintf (dump_file, "Found * 1, removing\n");
699 VEC_pop (operand_entry_t, *ops);
700 reassociate_stats.ops_eliminated++;
701 return;
702 }
703 }
704 break;
705 case BIT_XOR_EXPR:
706 case PLUS_EXPR:
707 case MINUS_EXPR:
708 if (integer_zerop (oelast->op)
709 || (FLOAT_TYPE_P (type)
710 && (opcode == PLUS_EXPR || opcode == MINUS_EXPR)
711 && fold_real_zero_addition_p (type, oelast->op,
712 opcode == MINUS_EXPR)))
713 {
714 if (VEC_length (operand_entry_t, *ops) != 1)
715 {
716 if (dump_file && (dump_flags & TDF_DETAILS))
717 fprintf (dump_file, "Found [|^+] 0, removing\n");
718 VEC_pop (operand_entry_t, *ops);
719 reassociate_stats.ops_eliminated++;
720 return;
721 }
722 }
723 break;
724 default:
725 break;
726 }
727 }
728 }
729
730 /* Perform various identities and other optimizations on the list of
731 operand entries, stored in OPS. The tree code for the binary
732 operation between all the operands is OPCODE. */
733
734 static void
735 optimize_ops_list (enum tree_code opcode,
736 VEC (operand_entry_t, heap) **ops)
737 {
738 unsigned int length = VEC_length (operand_entry_t, *ops);
739 unsigned int i;
740 operand_entry_t oe;
741 operand_entry_t oelast = NULL;
742 bool iterate = false;
743
744 if (length == 1)
745 return;
746
747 oelast = VEC_last (operand_entry_t, *ops);
748
749 /* If the last two are constants, pop the constants off, merge them
750 and try the next two. */
751 if (oelast->rank == 0 && is_gimple_min_invariant (oelast->op))
752 {
753 operand_entry_t oelm1 = VEC_index (operand_entry_t, *ops, length - 2);
754
755 if (oelm1->rank == 0
756 && is_gimple_min_invariant (oelm1->op)
757 && useless_type_conversion_p (TREE_TYPE (oelm1->op),
758 TREE_TYPE (oelast->op)))
759 {
760 tree folded = fold_binary (opcode, TREE_TYPE (oelm1->op),
761 oelm1->op, oelast->op);
762
763 if (folded && is_gimple_min_invariant (folded))
764 {
765 if (dump_file && (dump_flags & TDF_DETAILS))
766 fprintf (dump_file, "Merging constants\n");
767
768 VEC_pop (operand_entry_t, *ops);
769 VEC_pop (operand_entry_t, *ops);
770
771 add_to_ops_vec (ops, folded);
772 reassociate_stats.constants_eliminated++;
773
774 optimize_ops_list (opcode, ops);
775 return;
776 }
777 }
778 }
779
780 eliminate_using_constants (opcode, ops);
781 oelast = NULL;
782
783 for (i = 0; VEC_iterate (operand_entry_t, *ops, i, oe);)
784 {
785 bool done = false;
786
787 if (eliminate_not_pairs (opcode, ops, i, oe))
788 return;
789 if (eliminate_duplicate_pair (opcode, ops, &done, i, oe, oelast)
790 || (!done && eliminate_plus_minus_pair (opcode, ops, i, oe)))
791 {
792 if (done)
793 return;
794 iterate = true;
795 oelast = NULL;
796 continue;
797 }
798 oelast = oe;
799 i++;
800 }
801
802 length = VEC_length (operand_entry_t, *ops);
803 oelast = VEC_last (operand_entry_t, *ops);
804
805 if (iterate)
806 optimize_ops_list (opcode, ops);
807 }
808
809 /* Return true if OPERAND is defined by a PHI node which uses the LHS
810 of STMT in it's operands. This is also known as a "destructive
811 update" operation. */
812
813 static bool
814 is_phi_for_stmt (gimple stmt, tree operand)
815 {
816 gimple def_stmt;
817 tree lhs;
818 use_operand_p arg_p;
819 ssa_op_iter i;
820
821 if (TREE_CODE (operand) != SSA_NAME)
822 return false;
823
824 lhs = gimple_assign_lhs (stmt);
825
826 def_stmt = SSA_NAME_DEF_STMT (operand);
827 if (gimple_code (def_stmt) != GIMPLE_PHI)
828 return false;
829
830 FOR_EACH_PHI_ARG (arg_p, def_stmt, i, SSA_OP_USE)
831 if (lhs == USE_FROM_PTR (arg_p))
832 return true;
833 return false;
834 }
835
836 /* Recursively rewrite our linearized statements so that the operators
837 match those in OPS[OPINDEX], putting the computation in rank
838 order. */
839
840 static void
841 rewrite_expr_tree (gimple stmt, unsigned int opindex,
842 VEC(operand_entry_t, heap) * ops)
843 {
844 tree rhs1 = gimple_assign_rhs1 (stmt);
845 tree rhs2 = gimple_assign_rhs2 (stmt);
846 operand_entry_t oe;
847
848 /* If we have three operands left, then we want to make sure the one
849 that gets the double binary op are the ones with the same rank.
850
851 The alternative we try is to see if this is a destructive
852 update style statement, which is like:
853 b = phi (a, ...)
854 a = c + b;
855 In that case, we want to use the destructive update form to
856 expose the possible vectorizer sum reduction opportunity.
857 In that case, the third operand will be the phi node.
858
859 We could, of course, try to be better as noted above, and do a
860 lot of work to try to find these opportunities in >3 operand
861 cases, but it is unlikely to be worth it. */
862 if (opindex + 3 == VEC_length (operand_entry_t, ops))
863 {
864 operand_entry_t oe1, oe2, oe3;
865
866 oe1 = VEC_index (operand_entry_t, ops, opindex);
867 oe2 = VEC_index (operand_entry_t, ops, opindex + 1);
868 oe3 = VEC_index (operand_entry_t, ops, opindex + 2);
869
870 if ((oe1->rank == oe2->rank
871 && oe2->rank != oe3->rank)
872 || (is_phi_for_stmt (stmt, oe3->op)
873 && !is_phi_for_stmt (stmt, oe1->op)
874 && !is_phi_for_stmt (stmt, oe2->op)))
875 {
876 struct operand_entry temp = *oe3;
877 oe3->op = oe1->op;
878 oe3->rank = oe1->rank;
879 oe1->op = temp.op;
880 oe1->rank= temp.rank;
881 }
882 else if ((oe1->rank == oe3->rank
883 && oe2->rank != oe3->rank)
884 || (is_phi_for_stmt (stmt, oe2->op)
885 && !is_phi_for_stmt (stmt, oe1->op)
886 && !is_phi_for_stmt (stmt, oe3->op)))
887 {
888 struct operand_entry temp = *oe2;
889 oe2->op = oe1->op;
890 oe2->rank = oe1->rank;
891 oe1->op = temp.op;
892 oe1->rank= temp.rank;
893 }
894 }
895
896 /* The final recursion case for this function is that you have
897 exactly two operations left.
898 If we had one exactly one op in the entire list to start with, we
899 would have never called this function, and the tail recursion
900 rewrites them one at a time. */
901 if (opindex + 2 == VEC_length (operand_entry_t, ops))
902 {
903 operand_entry_t oe1, oe2;
904
905 oe1 = VEC_index (operand_entry_t, ops, opindex);
906 oe2 = VEC_index (operand_entry_t, ops, opindex + 1);
907
908 if (rhs1 != oe1->op || rhs2 != oe2->op)
909 {
910 if (dump_file && (dump_flags & TDF_DETAILS))
911 {
912 fprintf (dump_file, "Transforming ");
913 print_gimple_stmt (dump_file, stmt, 0, 0);
914 }
915
916 gimple_assign_set_rhs1 (stmt, oe1->op);
917 gimple_assign_set_rhs2 (stmt, oe2->op);
918 update_stmt (stmt);
919
920 if (dump_file && (dump_flags & TDF_DETAILS))
921 {
922 fprintf (dump_file, " into ");
923 print_gimple_stmt (dump_file, stmt, 0, 0);
924 }
925
926 }
927 return;
928 }
929
930 /* If we hit here, we should have 3 or more ops left. */
931 gcc_assert (opindex + 2 < VEC_length (operand_entry_t, ops));
932
933 /* Rewrite the next operator. */
934 oe = VEC_index (operand_entry_t, ops, opindex);
935
936 if (oe->op != rhs2)
937 {
938
939 if (dump_file && (dump_flags & TDF_DETAILS))
940 {
941 fprintf (dump_file, "Transforming ");
942 print_gimple_stmt (dump_file, stmt, 0, 0);
943 }
944
945 gimple_assign_set_rhs2 (stmt, oe->op);
946 update_stmt (stmt);
947
948 if (dump_file && (dump_flags & TDF_DETAILS))
949 {
950 fprintf (dump_file, " into ");
951 print_gimple_stmt (dump_file, stmt, 0, 0);
952 }
953 }
954 /* Recurse on the LHS of the binary operator, which is guaranteed to
955 be the non-leaf side. */
956 rewrite_expr_tree (SSA_NAME_DEF_STMT (rhs1), opindex + 1, ops);
957 }
958
959 /* Transform STMT, which is really (A +B) + (C + D) into the left
960 linear form, ((A+B)+C)+D.
961 Recurse on D if necessary. */
962
963 static void
964 linearize_expr (gimple stmt)
965 {
966 gimple_stmt_iterator gsinow, gsirhs;
967 gimple binlhs = SSA_NAME_DEF_STMT (gimple_assign_rhs1 (stmt));
968 gimple binrhs = SSA_NAME_DEF_STMT (gimple_assign_rhs2 (stmt));
969 enum tree_code rhscode = gimple_assign_rhs_code (stmt);
970 gimple newbinrhs = NULL;
971 struct loop *loop = loop_containing_stmt (stmt);
972
973 gcc_assert (is_reassociable_op (binlhs, rhscode, loop)
974 && is_reassociable_op (binrhs, rhscode, loop));
975
976 gsinow = gsi_for_stmt (stmt);
977 gsirhs = gsi_for_stmt (binrhs);
978 gsi_move_before (&gsirhs, &gsinow);
979
980 gimple_assign_set_rhs2 (stmt, gimple_assign_rhs1 (binrhs));
981 gimple_assign_set_rhs1 (binrhs, gimple_assign_lhs (binlhs));
982 gimple_assign_set_rhs1 (stmt, gimple_assign_lhs (binrhs));
983
984 if (TREE_CODE (gimple_assign_rhs2 (stmt)) == SSA_NAME)
985 newbinrhs = SSA_NAME_DEF_STMT (gimple_assign_rhs2 (stmt));
986
987 if (dump_file && (dump_flags & TDF_DETAILS))
988 {
989 fprintf (dump_file, "Linearized: ");
990 print_gimple_stmt (dump_file, stmt, 0, 0);
991 }
992
993 reassociate_stats.linearized++;
994 update_stmt (binrhs);
995 update_stmt (binlhs);
996 update_stmt (stmt);
997
998 gimple_set_visited (stmt, true);
999 gimple_set_visited (binlhs, true);
1000 gimple_set_visited (binrhs, true);
1001
1002 /* Tail recurse on the new rhs if it still needs reassociation. */
1003 if (newbinrhs && is_reassociable_op (newbinrhs, rhscode, loop))
1004 /* ??? This should probably be linearize_expr (newbinrhs) but I don't
1005 want to change the algorithm while converting to tuples. */
1006 linearize_expr (stmt);
1007 }
1008
1009 /* If LHS has a single immediate use that is a GIMPLE_ASSIGN statement, return
1010 it. Otherwise, return NULL. */
1011
1012 static gimple
1013 get_single_immediate_use (tree lhs)
1014 {
1015 use_operand_p immuse;
1016 gimple immusestmt;
1017
1018 if (TREE_CODE (lhs) == SSA_NAME
1019 && single_imm_use (lhs, &immuse, &immusestmt)
1020 && is_gimple_assign (immusestmt))
1021 return immusestmt;
1022
1023 return NULL;
1024 }
1025
1026 static VEC(tree, heap) *broken_up_subtracts;
1027
1028 /* Recursively negate the value of TONEGATE, and return the SSA_NAME
1029 representing the negated value. Insertions of any necessary
1030 instructions go before GSI.
1031 This function is recursive in that, if you hand it "a_5" as the
1032 value to negate, and a_5 is defined by "a_5 = b_3 + b_4", it will
1033 transform b_3 + b_4 into a_5 = -b_3 + -b_4. */
1034
1035 static tree
1036 negate_value (tree tonegate, gimple_stmt_iterator *gsi)
1037 {
1038 gimple negatedefstmt= NULL;
1039 tree resultofnegate;
1040
1041 /* If we are trying to negate a name, defined by an add, negate the
1042 add operands instead. */
1043 if (TREE_CODE (tonegate) == SSA_NAME)
1044 negatedefstmt = SSA_NAME_DEF_STMT (tonegate);
1045 if (TREE_CODE (tonegate) == SSA_NAME
1046 && is_gimple_assign (negatedefstmt)
1047 && TREE_CODE (gimple_assign_lhs (negatedefstmt)) == SSA_NAME
1048 && has_single_use (gimple_assign_lhs (negatedefstmt))
1049 && gimple_assign_rhs_code (negatedefstmt) == PLUS_EXPR)
1050 {
1051 gimple_stmt_iterator gsi;
1052 tree rhs1 = gimple_assign_rhs1 (negatedefstmt);
1053 tree rhs2 = gimple_assign_rhs2 (negatedefstmt);
1054
1055 gsi = gsi_for_stmt (negatedefstmt);
1056 rhs1 = negate_value (rhs1, &gsi);
1057 gimple_assign_set_rhs1 (negatedefstmt, rhs1);
1058
1059 gsi = gsi_for_stmt (negatedefstmt);
1060 rhs2 = negate_value (rhs2, &gsi);
1061 gimple_assign_set_rhs2 (negatedefstmt, rhs2);
1062
1063 update_stmt (negatedefstmt);
1064 return gimple_assign_lhs (negatedefstmt);
1065 }
1066
1067 tonegate = fold_build1 (NEGATE_EXPR, TREE_TYPE (tonegate), tonegate);
1068 resultofnegate = force_gimple_operand_gsi (gsi, tonegate, true,
1069 NULL_TREE, true, GSI_SAME_STMT);
1070 VEC_safe_push (tree, heap, broken_up_subtracts, resultofnegate);
1071 return resultofnegate;
1072 }
1073
1074 /* Return true if we should break up the subtract in STMT into an add
1075 with negate. This is true when we the subtract operands are really
1076 adds, or the subtract itself is used in an add expression. In
1077 either case, breaking up the subtract into an add with negate
1078 exposes the adds to reassociation. */
1079
1080 static bool
1081 should_break_up_subtract (gimple stmt)
1082 {
1083 tree lhs = gimple_assign_lhs (stmt);
1084 tree binlhs = gimple_assign_rhs1 (stmt);
1085 tree binrhs = gimple_assign_rhs2 (stmt);
1086 gimple immusestmt;
1087 struct loop *loop = loop_containing_stmt (stmt);
1088
1089 if (TREE_CODE (binlhs) == SSA_NAME
1090 && is_reassociable_op (SSA_NAME_DEF_STMT (binlhs), PLUS_EXPR, loop))
1091 return true;
1092
1093 if (TREE_CODE (binrhs) == SSA_NAME
1094 && is_reassociable_op (SSA_NAME_DEF_STMT (binrhs), PLUS_EXPR, loop))
1095 return true;
1096
1097 if (TREE_CODE (lhs) == SSA_NAME
1098 && (immusestmt = get_single_immediate_use (lhs))
1099 && is_gimple_assign (immusestmt)
1100 && gimple_assign_rhs_code (immusestmt) == PLUS_EXPR)
1101 return true;
1102 return false;
1103 }
1104
1105 /* Transform STMT from A - B into A + -B. */
1106
1107 static void
1108 break_up_subtract (gimple stmt, gimple_stmt_iterator *gsip)
1109 {
1110 tree rhs1 = gimple_assign_rhs1 (stmt);
1111 tree rhs2 = gimple_assign_rhs2 (stmt);
1112
1113 if (dump_file && (dump_flags & TDF_DETAILS))
1114 {
1115 fprintf (dump_file, "Breaking up subtract ");
1116 print_gimple_stmt (dump_file, stmt, 0, 0);
1117 }
1118
1119 rhs2 = negate_value (rhs2, gsip);
1120 gimple_assign_set_rhs_with_ops (gsip, PLUS_EXPR, rhs1, rhs2);
1121 update_stmt (stmt);
1122 }
1123
1124 /* Recursively linearize a binary expression that is the RHS of STMT.
1125 Place the operands of the expression tree in the vector named OPS. */
1126
1127 static void
1128 linearize_expr_tree (VEC(operand_entry_t, heap) **ops, gimple stmt)
1129 {
1130 gimple_stmt_iterator gsinow, gsilhs;
1131 tree binlhs = gimple_assign_rhs1 (stmt);
1132 tree binrhs = gimple_assign_rhs2 (stmt);
1133 gimple binlhsdef, binrhsdef;
1134 bool binlhsisreassoc = false;
1135 bool binrhsisreassoc = false;
1136 enum tree_code rhscode = gimple_assign_rhs_code (stmt);
1137 struct loop *loop = loop_containing_stmt (stmt);
1138
1139 gimple_set_visited (stmt, true);
1140
1141 if (TREE_CODE (binlhs) == SSA_NAME)
1142 {
1143 binlhsdef = SSA_NAME_DEF_STMT (binlhs);
1144 binlhsisreassoc = is_reassociable_op (binlhsdef, rhscode, loop);
1145 }
1146
1147 if (TREE_CODE (binrhs) == SSA_NAME)
1148 {
1149 binrhsdef = SSA_NAME_DEF_STMT (binrhs);
1150 binrhsisreassoc = is_reassociable_op (binrhsdef, rhscode, loop);
1151 }
1152
1153 /* If the LHS is not reassociable, but the RHS is, we need to swap
1154 them. If neither is reassociable, there is nothing we can do, so
1155 just put them in the ops vector. If the LHS is reassociable,
1156 linearize it. If both are reassociable, then linearize the RHS
1157 and the LHS. */
1158
1159 if (!binlhsisreassoc)
1160 {
1161 tree temp;
1162
1163 if (!binrhsisreassoc)
1164 {
1165 add_to_ops_vec (ops, binrhs);
1166 add_to_ops_vec (ops, binlhs);
1167 return;
1168 }
1169
1170 if (dump_file && (dump_flags & TDF_DETAILS))
1171 {
1172 fprintf (dump_file, "swapping operands of ");
1173 print_gimple_stmt (dump_file, stmt, 0, 0);
1174 }
1175
1176 swap_tree_operands (stmt,
1177 gimple_assign_rhs1_ptr (stmt),
1178 gimple_assign_rhs2_ptr (stmt));
1179 update_stmt (stmt);
1180
1181 if (dump_file && (dump_flags & TDF_DETAILS))
1182 {
1183 fprintf (dump_file, " is now ");
1184 print_gimple_stmt (dump_file, stmt, 0, 0);
1185 }
1186
1187 /* We want to make it so the lhs is always the reassociative op,
1188 so swap. */
1189 temp = binlhs;
1190 binlhs = binrhs;
1191 binrhs = temp;
1192 }
1193 else if (binrhsisreassoc)
1194 {
1195 linearize_expr (stmt);
1196 binlhs = gimple_assign_rhs1 (stmt);
1197 binrhs = gimple_assign_rhs2 (stmt);
1198 }
1199
1200 gcc_assert (TREE_CODE (binrhs) != SSA_NAME
1201 || !is_reassociable_op (SSA_NAME_DEF_STMT (binrhs),
1202 rhscode, loop));
1203 gsinow = gsi_for_stmt (stmt);
1204 gsilhs = gsi_for_stmt (SSA_NAME_DEF_STMT (binlhs));
1205 gsi_move_before (&gsilhs, &gsinow);
1206 linearize_expr_tree (ops, SSA_NAME_DEF_STMT (binlhs));
1207 add_to_ops_vec (ops, binrhs);
1208 }
1209
1210 /* Repropagate the negates back into subtracts, since no other pass
1211 currently does it. */
1212
1213 static void
1214 repropagate_negates (void)
1215 {
1216 unsigned int i = 0;
1217 tree negate;
1218
1219 for (i = 0; VEC_iterate (tree, broken_up_subtracts, i, negate); i++)
1220 {
1221 gimple user = get_single_immediate_use (negate);
1222
1223 /* The negate operand can be either operand of a PLUS_EXPR
1224 (it can be the LHS if the RHS is a constant for example).
1225
1226 Force the negate operand to the RHS of the PLUS_EXPR, then
1227 transform the PLUS_EXPR into a MINUS_EXPR. */
1228 if (user
1229 && is_gimple_assign (user)
1230 && gimple_assign_rhs_code (user) == PLUS_EXPR)
1231 {
1232 /* If the negated operand appears on the LHS of the
1233 PLUS_EXPR, exchange the operands of the PLUS_EXPR
1234 to force the negated operand to the RHS of the PLUS_EXPR. */
1235 if (gimple_assign_rhs1 (user) == negate)
1236 {
1237 swap_tree_operands (user,
1238 gimple_assign_rhs1_ptr (user),
1239 gimple_assign_rhs2_ptr (user));
1240 }
1241
1242 /* Now transform the PLUS_EXPR into a MINUS_EXPR and replace
1243 the RHS of the PLUS_EXPR with the operand of the NEGATE_EXPR. */
1244 if (gimple_assign_rhs2 (user) == negate)
1245 {
1246 tree rhs1 = gimple_assign_rhs1 (user);
1247 tree rhs2 = get_unary_op (negate, NEGATE_EXPR);
1248 gimple_stmt_iterator gsi = gsi_for_stmt (user);
1249 gimple_assign_set_rhs_with_ops (&gsi, MINUS_EXPR, rhs1, rhs2);
1250 update_stmt (user);
1251 }
1252 }
1253 }
1254 }
1255
1256 /* Break up subtract operations in block BB.
1257
1258 We do this top down because we don't know whether the subtract is
1259 part of a possible chain of reassociation except at the top.
1260
1261 IE given
1262 d = f + g
1263 c = a + e
1264 b = c - d
1265 q = b - r
1266 k = t - q
1267
1268 we want to break up k = t - q, but we won't until we've transformed q
1269 = b - r, which won't be broken up until we transform b = c - d.
1270
1271 En passant, clear the GIMPLE visited flag on every statement. */
1272
1273 static void
1274 break_up_subtract_bb (basic_block bb)
1275 {
1276 gimple_stmt_iterator gsi;
1277 basic_block son;
1278
1279 for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
1280 {
1281 gimple stmt = gsi_stmt (gsi);
1282 gimple_set_visited (stmt, false);
1283
1284 /* Look for simple gimple subtract operations. */
1285 if (is_gimple_assign (stmt)
1286 && gimple_assign_rhs_code (stmt) == MINUS_EXPR)
1287 {
1288 tree lhs = gimple_assign_lhs (stmt);
1289 tree rhs1 = gimple_assign_rhs1 (stmt);
1290 tree rhs2 = gimple_assign_rhs2 (stmt);
1291
1292 /* If associative-math we can do reassociation for
1293 non-integral types. Or, we can do reassociation for
1294 non-saturating fixed-point types. */
1295 if ((!INTEGRAL_TYPE_P (TREE_TYPE (lhs))
1296 || !INTEGRAL_TYPE_P (TREE_TYPE (rhs1))
1297 || !INTEGRAL_TYPE_P (TREE_TYPE (rhs2)))
1298 && (!SCALAR_FLOAT_TYPE_P (TREE_TYPE (lhs))
1299 || !SCALAR_FLOAT_TYPE_P (TREE_TYPE(rhs1))
1300 || !SCALAR_FLOAT_TYPE_P (TREE_TYPE(rhs2))
1301 || !flag_associative_math)
1302 && (!NON_SAT_FIXED_POINT_TYPE_P (TREE_TYPE (lhs))
1303 || !NON_SAT_FIXED_POINT_TYPE_P (TREE_TYPE(rhs1))
1304 || !NON_SAT_FIXED_POINT_TYPE_P (TREE_TYPE(rhs2))))
1305 continue;
1306
1307 /* Check for a subtract used only in an addition. If this
1308 is the case, transform it into add of a negate for better
1309 reassociation. IE transform C = A-B into C = A + -B if C
1310 is only used in an addition. */
1311 if (should_break_up_subtract (stmt))
1312 break_up_subtract (stmt, &gsi);
1313 }
1314 }
1315 for (son = first_dom_son (CDI_DOMINATORS, bb);
1316 son;
1317 son = next_dom_son (CDI_DOMINATORS, son))
1318 break_up_subtract_bb (son);
1319 }
1320
1321 /* Reassociate expressions in basic block BB and its post-dominator as
1322 children. */
1323
1324 static void
1325 reassociate_bb (basic_block bb)
1326 {
1327 gimple_stmt_iterator gsi;
1328 basic_block son;
1329
1330 for (gsi = gsi_last_bb (bb); !gsi_end_p (gsi); gsi_prev (&gsi))
1331 {
1332 gimple stmt = gsi_stmt (gsi);
1333
1334 if (is_gimple_assign (stmt))
1335 {
1336 tree lhs, rhs1, rhs2;
1337 enum tree_code rhs_code = gimple_assign_rhs_code (stmt);
1338
1339 /* If this is not a gimple binary expression, there is
1340 nothing for us to do with it. */
1341 if (get_gimple_rhs_class (rhs_code) != GIMPLE_BINARY_RHS)
1342 continue;
1343
1344 /* If this was part of an already processed statement,
1345 we don't need to touch it again. */
1346 if (gimple_visited_p (stmt))
1347 continue;
1348
1349 lhs = gimple_assign_lhs (stmt);
1350 rhs1 = gimple_assign_rhs1 (stmt);
1351 rhs2 = gimple_assign_rhs2 (stmt);
1352
1353 /* If associative-math we can do reassociation for
1354 non-integral types. Or, we can do reassociation for
1355 non-saturating fixed-point types. */
1356 if ((!INTEGRAL_TYPE_P (TREE_TYPE (lhs))
1357 || !INTEGRAL_TYPE_P (TREE_TYPE (rhs1))
1358 || !INTEGRAL_TYPE_P (TREE_TYPE (rhs2)))
1359 && (!SCALAR_FLOAT_TYPE_P (TREE_TYPE (lhs))
1360 || !SCALAR_FLOAT_TYPE_P (TREE_TYPE(rhs1))
1361 || !SCALAR_FLOAT_TYPE_P (TREE_TYPE(rhs2))
1362 || !flag_associative_math)
1363 && (!NON_SAT_FIXED_POINT_TYPE_P (TREE_TYPE (lhs))
1364 || !NON_SAT_FIXED_POINT_TYPE_P (TREE_TYPE(rhs1))
1365 || !NON_SAT_FIXED_POINT_TYPE_P (TREE_TYPE(rhs2))))
1366 continue;
1367
1368 if (associative_tree_code (rhs_code))
1369 {
1370 VEC(operand_entry_t, heap) *ops = NULL;
1371
1372 /* There may be no immediate uses left by the time we
1373 get here because we may have eliminated them all. */
1374 if (TREE_CODE (lhs) == SSA_NAME && has_zero_uses (lhs))
1375 continue;
1376
1377 gimple_set_visited (stmt, true);
1378 linearize_expr_tree (&ops, stmt);
1379 qsort (VEC_address (operand_entry_t, ops),
1380 VEC_length (operand_entry_t, ops),
1381 sizeof (operand_entry_t),
1382 sort_by_operand_rank);
1383 optimize_ops_list (rhs_code, &ops);
1384
1385 if (VEC_length (operand_entry_t, ops) == 1)
1386 {
1387 if (dump_file && (dump_flags & TDF_DETAILS))
1388 {
1389 fprintf (dump_file, "Transforming ");
1390 print_gimple_stmt (dump_file, stmt, 0, 0);
1391 }
1392
1393 gimple_assign_set_rhs_from_tree (&gsi,
1394 VEC_last (operand_entry_t,
1395 ops)->op);
1396 update_stmt (stmt);
1397
1398 if (dump_file && (dump_flags & TDF_DETAILS))
1399 {
1400 fprintf (dump_file, " into ");
1401 print_gimple_stmt (dump_file, stmt, 0, 0);
1402 }
1403 }
1404 else
1405 {
1406 rewrite_expr_tree (stmt, 0, ops);
1407 }
1408
1409 VEC_free (operand_entry_t, heap, ops);
1410 }
1411 }
1412 }
1413 for (son = first_dom_son (CDI_POST_DOMINATORS, bb);
1414 son;
1415 son = next_dom_son (CDI_POST_DOMINATORS, son))
1416 reassociate_bb (son);
1417 }
1418
1419 void dump_ops_vector (FILE *file, VEC (operand_entry_t, heap) *ops);
1420 void debug_ops_vector (VEC (operand_entry_t, heap) *ops);
1421
1422 /* Dump the operand entry vector OPS to FILE. */
1423
1424 void
1425 dump_ops_vector (FILE *file, VEC (operand_entry_t, heap) *ops)
1426 {
1427 operand_entry_t oe;
1428 unsigned int i;
1429
1430 for (i = 0; VEC_iterate (operand_entry_t, ops, i, oe); i++)
1431 {
1432 fprintf (file, "Op %d -> rank: %d, tree: ", i, oe->rank);
1433 print_generic_expr (file, oe->op, 0);
1434 }
1435 }
1436
1437 /* Dump the operand entry vector OPS to STDERR. */
1438
1439 void
1440 debug_ops_vector (VEC (operand_entry_t, heap) *ops)
1441 {
1442 dump_ops_vector (stderr, ops);
1443 }
1444
1445 static void
1446 do_reassoc (void)
1447 {
1448 break_up_subtract_bb (ENTRY_BLOCK_PTR);
1449 reassociate_bb (EXIT_BLOCK_PTR);
1450 }
1451
1452 /* Initialize the reassociation pass. */
1453
1454 static void
1455 init_reassoc (void)
1456 {
1457 int i;
1458 long rank = 2;
1459 tree param;
1460 int *bbs = XNEWVEC (int, last_basic_block + 1);
1461
1462 /* Find the loops, so that we can prevent moving calculations in
1463 them. */
1464 loop_optimizer_init (AVOID_CFG_MODIFICATIONS);
1465
1466 memset (&reassociate_stats, 0, sizeof (reassociate_stats));
1467
1468 operand_entry_pool = create_alloc_pool ("operand entry pool",
1469 sizeof (struct operand_entry), 30);
1470
1471 /* Reverse RPO (Reverse Post Order) will give us something where
1472 deeper loops come later. */
1473 pre_and_rev_post_order_compute (NULL, bbs, false);
1474 bb_rank = XCNEWVEC (long, last_basic_block + 1);
1475 operand_rank = pointer_map_create ();
1476
1477 /* Give each argument a distinct rank. */
1478 for (param = DECL_ARGUMENTS (current_function_decl);
1479 param;
1480 param = TREE_CHAIN (param))
1481 {
1482 if (gimple_default_def (cfun, param) != NULL)
1483 {
1484 tree def = gimple_default_def (cfun, param);
1485 insert_operand_rank (def, ++rank);
1486 }
1487 }
1488
1489 /* Give the chain decl a distinct rank. */
1490 if (cfun->static_chain_decl != NULL)
1491 {
1492 tree def = gimple_default_def (cfun, cfun->static_chain_decl);
1493 if (def != NULL)
1494 insert_operand_rank (def, ++rank);
1495 }
1496
1497 /* Set up rank for each BB */
1498 for (i = 0; i < n_basic_blocks - NUM_FIXED_BLOCKS; i++)
1499 bb_rank[bbs[i]] = ++rank << 16;
1500
1501 free (bbs);
1502 calculate_dominance_info (CDI_POST_DOMINATORS);
1503 broken_up_subtracts = NULL;
1504 }
1505
1506 /* Cleanup after the reassociation pass, and print stats if
1507 requested. */
1508
1509 static void
1510 fini_reassoc (void)
1511 {
1512 statistics_counter_event (cfun, "Linearized",
1513 reassociate_stats.linearized);
1514 statistics_counter_event (cfun, "Constants eliminated",
1515 reassociate_stats.constants_eliminated);
1516 statistics_counter_event (cfun, "Ops eliminated",
1517 reassociate_stats.ops_eliminated);
1518 statistics_counter_event (cfun, "Statements rewritten",
1519 reassociate_stats.rewritten);
1520
1521 pointer_map_destroy (operand_rank);
1522 free_alloc_pool (operand_entry_pool);
1523 free (bb_rank);
1524 VEC_free (tree, heap, broken_up_subtracts);
1525 free_dominance_info (CDI_POST_DOMINATORS);
1526 loop_optimizer_finalize ();
1527 }
1528
1529 /* Gate and execute functions for Reassociation. */
1530
1531 static unsigned int
1532 execute_reassoc (void)
1533 {
1534 init_reassoc ();
1535
1536 do_reassoc ();
1537 repropagate_negates ();
1538
1539 fini_reassoc ();
1540 return 0;
1541 }
1542
1543 static bool
1544 gate_tree_ssa_reassoc (void)
1545 {
1546 return flag_tree_reassoc != 0;
1547 }
1548
1549 struct gimple_opt_pass pass_reassoc =
1550 {
1551 {
1552 GIMPLE_PASS,
1553 "reassoc", /* name */
1554 gate_tree_ssa_reassoc, /* gate */
1555 execute_reassoc, /* execute */
1556 NULL, /* sub */
1557 NULL, /* next */
1558 0, /* static_pass_number */
1559 TV_TREE_REASSOC, /* tv_id */
1560 PROP_cfg | PROP_ssa | PROP_alias, /* properties_required */
1561 0, /* properties_provided */
1562 0, /* properties_destroyed */
1563 0, /* todo_flags_start */
1564 TODO_dump_func | TODO_ggc_collect | TODO_verify_ssa /* todo_flags_finish */
1565 }
1566 };
1567