comparison gcc/tree-ssa-reassoc.c @ 55:77e2b8dfacca gcc-4.4.5

update it from 4.4.3 to 4.5.0
author ryoma <e075725@ie.u-ryukyu.ac.jp>
date Fri, 12 Feb 2010 23:39:51 +0900
parents a06113de4d67
children b7f97abdc517
comparison
equal deleted inserted replaced
52:c156f1bd5cd9 55:77e2b8dfacca
104 104
105 Then build a binary op of d + e 105 Then build a binary op of d + e
106 mergetmp2 = d + e 106 mergetmp2 = d + e
107 107
108 and put mergetmp2 on the merge worklist. 108 and put mergetmp2 on the merge worklist.
109 109
110 so merge worklist = {mergetmp, c, mergetmp2} 110 so merge worklist = {mergetmp, c, mergetmp2}
111 111
112 Continue building binary ops of these operations until you have only 112 Continue building binary ops of these operations until you have only
113 one operation left on the worklist. 113 one operation left on the worklist.
114 114
115 So we have 115 So we have
116 116
117 build binary op 117 build binary op
118 mergetmp3 = mergetmp + c 118 mergetmp3 = mergetmp + c
119 119
120 worklist = {mergetmp2, mergetmp3} 120 worklist = {mergetmp2, mergetmp3}
121 121
122 mergetmp4 = mergetmp2 + mergetmp3 122 mergetmp4 = mergetmp2 + mergetmp3
123 123
124 worklist = {mergetmp4} 124 worklist = {mergetmp4}
125 125
126 because we have one operation left, we can now just set the original 126 because we have one operation left, we can now just set the original
127 statement equal to the result of that operation. 127 statement equal to the result of that operation.
128 128
129 This will at least expose a + b and d + e to redundancy elimination 129 This will at least expose a + b and d + e to redundancy elimination
130 as binary operations. 130 as binary operations.
131 131
132 For extra points, you can reuse the old statements to build the 132 For extra points, you can reuse the old statements to build the
133 mergetmps, since you shouldn't run out. 133 mergetmps, since you shouldn't run out.
134 134
135 So why don't we do this? 135 So why don't we do this?
136 136
137 Because it's expensive, and rarely will help. Most trees we are 137 Because it's expensive, and rarely will help. Most trees we are
138 reassociating have 3 or less ops. If they have 2 ops, they already 138 reassociating have 3 or less ops. If they have 2 ops, they already
139 will be written into a nice single binary op. If you have 3 ops, a 139 will be written into a nice single binary op. If you have 3 ops, a
140 single simple check suffices to tell you whether the first two are of the 140 single simple check suffices to tell you whether the first two are of the
141 same rank. If so, you know to order it 141 same rank. If so, you know to order it
142 142
143 mergetmp = op1 + op2 143 mergetmp = op1 + op2
144 newstmt = mergetmp + op3 144 newstmt = mergetmp + op3
145 145
146 instead of 146 instead of
147 mergetmp = op2 + op3 147 mergetmp = op2 + op3
148 newstmt = mergetmp + op1 148 newstmt = mergetmp + op1
149 149
150 If all three are of the same rank, you can't expose them all in a 150 If all three are of the same rank, you can't expose them all in a
151 single binary operator anyway, so the above is *still* the best you 151 single binary operator anyway, so the above is *still* the best you
152 can do. 152 can do.
153 153
154 Thus, this is what we do. When we have three ops left, we check to see 154 Thus, this is what we do. When we have three ops left, we check to see
155 what order to put them in, and call it a day. As a nod to vector sum 155 what order to put them in, and call it a day. As a nod to vector sum
156 reduction, we check if any of the ops are really a phi node that is a 156 reduction, we check if any of the ops are really a phi node that is a
157 destructive update for the associating op, and keep the destructive 157 destructive update for the associating op, and keep the destructive
158 update together for vector sum reduction recognition. */ 158 update together for vector sum reduction recognition. */
190 190
191 static inline long 191 static inline long
192 find_operand_rank (tree e) 192 find_operand_rank (tree e)
193 { 193 {
194 void **slot = pointer_map_contains (operand_rank, e); 194 void **slot = pointer_map_contains (operand_rank, e);
195 return slot ? (long) *slot : -1; 195 return slot ? (long) (intptr_t) *slot : -1;
196 } 196 }
197 197
198 /* Insert {E,RANK} into the operand rank hashtable. */ 198 /* Insert {E,RANK} into the operand rank hashtable. */
199 199
200 static inline void 200 static inline void
202 { 202 {
203 void **slot; 203 void **slot;
204 gcc_assert (rank > 0); 204 gcc_assert (rank > 0);
205 slot = pointer_map_insert (operand_rank, e); 205 slot = pointer_map_insert (operand_rank, e);
206 gcc_assert (!*slot); 206 gcc_assert (!*slot);
207 *slot = (void *) rank; 207 *slot = (void *) (intptr_t) rank;
208 } 208 }
209 209
210 /* Given an expression E, return the rank of the expression. */ 210 /* Given an expression E, return the rank of the expression. */
211 211
212 static long 212 static long
240 stmt = SSA_NAME_DEF_STMT (e); 240 stmt = SSA_NAME_DEF_STMT (e);
241 if (gimple_bb (stmt) == NULL) 241 if (gimple_bb (stmt) == NULL)
242 return 0; 242 return 0;
243 243
244 if (!is_gimple_assign (stmt) 244 if (!is_gimple_assign (stmt)
245 || !ZERO_SSA_OPERANDS (stmt, SSA_OP_VIRTUAL_DEFS)) 245 || gimple_vdef (stmt))
246 return bb_rank[gimple_bb (stmt)->index]; 246 return bb_rank[gimple_bb (stmt)->index];
247 247
248 /* If we already have a rank for this expression, use that. */ 248 /* If we already have a rank for this expression, use that. */
249 rank = find_operand_rank (e); 249 rank = find_operand_rank (e);
250 if (rank != -1) 250 if (rank != -1)
445 445
446 if (VEC_length (operand_entry_t, *ops) == 2) 446 if (VEC_length (operand_entry_t, *ops) == 2)
447 { 447 {
448 VEC_free (operand_entry_t, heap, *ops); 448 VEC_free (operand_entry_t, heap, *ops);
449 *ops = NULL; 449 *ops = NULL;
450 add_to_ops_vec (ops, fold_convert (TREE_TYPE (last->op), 450 add_to_ops_vec (ops, fold_convert (TREE_TYPE (last->op),
451 integer_zero_node)); 451 integer_zero_node));
452 *all_done = true; 452 *all_done = true;
453 } 453 }
454 else 454 else
455 { 455 {
509 print_generic_expr (dump_file, oe->op, 0); 509 print_generic_expr (dump_file, oe->op, 0);
510 fprintf (dump_file, " -> 0\n"); 510 fprintf (dump_file, " -> 0\n");
511 } 511 }
512 512
513 VEC_ordered_remove (operand_entry_t, *ops, i); 513 VEC_ordered_remove (operand_entry_t, *ops, i);
514 add_to_ops_vec (ops, fold_convert(TREE_TYPE (oe->op), 514 add_to_ops_vec (ops, fold_convert(TREE_TYPE (oe->op),
515 integer_zero_node)); 515 integer_zero_node));
516 VEC_ordered_remove (operand_entry_t, *ops, currindex); 516 VEC_ordered_remove (operand_entry_t, *ops, currindex);
517 reassociate_stats.ops_eliminated ++; 517 reassociate_stats.ops_eliminated ++;
518 518
519 return true; 519 return true;
577 oe->op = fold_convert (TREE_TYPE (oe->op), integer_zero_node); 577 oe->op = fold_convert (TREE_TYPE (oe->op), integer_zero_node);
578 else if (opcode == BIT_IOR_EXPR) 578 else if (opcode == BIT_IOR_EXPR)
579 oe->op = build_low_bits_mask (TREE_TYPE (oe->op), 579 oe->op = build_low_bits_mask (TREE_TYPE (oe->op),
580 TYPE_PRECISION (TREE_TYPE (oe->op))); 580 TYPE_PRECISION (TREE_TYPE (oe->op)));
581 581
582 reassociate_stats.ops_eliminated 582 reassociate_stats.ops_eliminated
583 += VEC_length (operand_entry_t, *ops) - 1; 583 += VEC_length (operand_entry_t, *ops) - 1;
584 VEC_free (operand_entry_t, heap, *ops); 584 VEC_free (operand_entry_t, heap, *ops);
585 *ops = NULL; 585 *ops = NULL;
586 VEC_safe_push (operand_entry_t, heap, *ops, oe); 586 VEC_safe_push (operand_entry_t, heap, *ops, oe);
587 return true; 587 return true;
616 if (VEC_length (operand_entry_t, *ops) != 1) 616 if (VEC_length (operand_entry_t, *ops) != 1)
617 { 617 {
618 if (dump_file && (dump_flags & TDF_DETAILS)) 618 if (dump_file && (dump_flags & TDF_DETAILS))
619 fprintf (dump_file, "Found & 0, removing all other ops\n"); 619 fprintf (dump_file, "Found & 0, removing all other ops\n");
620 620
621 reassociate_stats.ops_eliminated 621 reassociate_stats.ops_eliminated
622 += VEC_length (operand_entry_t, *ops) - 1; 622 += VEC_length (operand_entry_t, *ops) - 1;
623 623
624 VEC_free (operand_entry_t, heap, *ops); 624 VEC_free (operand_entry_t, heap, *ops);
625 *ops = NULL; 625 *ops = NULL;
626 VEC_safe_push (operand_entry_t, heap, *ops, oelast); 626 VEC_safe_push (operand_entry_t, heap, *ops, oelast);
627 return; 627 return;
628 } 628 }
644 if (VEC_length (operand_entry_t, *ops) != 1) 644 if (VEC_length (operand_entry_t, *ops) != 1)
645 { 645 {
646 if (dump_file && (dump_flags & TDF_DETAILS)) 646 if (dump_file && (dump_flags & TDF_DETAILS))
647 fprintf (dump_file, "Found | -1, removing all other ops\n"); 647 fprintf (dump_file, "Found | -1, removing all other ops\n");
648 648
649 reassociate_stats.ops_eliminated 649 reassociate_stats.ops_eliminated
650 += VEC_length (operand_entry_t, *ops) - 1; 650 += VEC_length (operand_entry_t, *ops) - 1;
651 651
652 VEC_free (operand_entry_t, heap, *ops); 652 VEC_free (operand_entry_t, heap, *ops);
653 *ops = NULL; 653 *ops = NULL;
654 VEC_safe_push (operand_entry_t, heap, *ops, oelast); 654 VEC_safe_push (operand_entry_t, heap, *ops, oelast);
655 return; 655 return;
656 } 656 }
657 } 657 }
658 else if (integer_zerop (oelast->op)) 658 else if (integer_zerop (oelast->op))
659 { 659 {
660 if (VEC_length (operand_entry_t, *ops) != 1) 660 if (VEC_length (operand_entry_t, *ops) != 1)
661 { 661 {
662 if (dump_file && (dump_flags & TDF_DETAILS)) 662 if (dump_file && (dump_flags & TDF_DETAILS))
675 { 675 {
676 if (VEC_length (operand_entry_t, *ops) != 1) 676 if (VEC_length (operand_entry_t, *ops) != 1)
677 { 677 {
678 if (dump_file && (dump_flags & TDF_DETAILS)) 678 if (dump_file && (dump_flags & TDF_DETAILS))
679 fprintf (dump_file, "Found * 0, removing all other ops\n"); 679 fprintf (dump_file, "Found * 0, removing all other ops\n");
680 680
681 reassociate_stats.ops_eliminated 681 reassociate_stats.ops_eliminated
682 += VEC_length (operand_entry_t, *ops) - 1; 682 += VEC_length (operand_entry_t, *ops) - 1;
683 VEC_free (operand_entry_t, heap, *ops); 683 VEC_free (operand_entry_t, heap, *ops);
684 *ops = NULL; 684 *ops = NULL;
685 VEC_safe_push (operand_entry_t, heap, *ops, oelast); 685 VEC_safe_push (operand_entry_t, heap, *ops, oelast);
686 return; 686 return;
1738 1738
1739 /* Break up subtract operations in block BB. 1739 /* Break up subtract operations in block BB.
1740 1740
1741 We do this top down because we don't know whether the subtract is 1741 We do this top down because we don't know whether the subtract is
1742 part of a possible chain of reassociation except at the top. 1742 part of a possible chain of reassociation except at the top.
1743 1743
1744 IE given 1744 IE given
1745 d = f + g 1745 d = f + g
1746 c = a + e 1746 c = a + e
1747 b = c - d 1747 b = c - d
1748 q = b - r 1748 q = b - r
1749 k = t - q 1749 k = t - q
1750 1750
1751 we want to break up k = t - q, but we won't until we've transformed q 1751 we want to break up k = t - q, but we won't until we've transformed q
1752 = b - r, which won't be broken up until we transform b = c - d. 1752 = b - r, which won't be broken up until we transform b = c - d.
1753 1753
1754 En passant, clear the GIMPLE visited flag on every statement. */ 1754 En passant, clear the GIMPLE visited flag on every statement. */
1755 1755
2068 execute_reassoc, /* execute */ 2068 execute_reassoc, /* execute */
2069 NULL, /* sub */ 2069 NULL, /* sub */
2070 NULL, /* next */ 2070 NULL, /* next */
2071 0, /* static_pass_number */ 2071 0, /* static_pass_number */
2072 TV_TREE_REASSOC, /* tv_id */ 2072 TV_TREE_REASSOC, /* tv_id */
2073 PROP_cfg | PROP_ssa | PROP_alias, /* properties_required */ 2073 PROP_cfg | PROP_ssa, /* properties_required */
2074 0, /* properties_provided */ 2074 0, /* properties_provided */
2075 0, /* properties_destroyed */ 2075 0, /* properties_destroyed */
2076 0, /* todo_flags_start */ 2076 0, /* todo_flags_start */
2077 TODO_dump_func | TODO_ggc_collect | TODO_verify_ssa /* todo_flags_finish */ 2077 TODO_dump_func | TODO_ggc_collect | TODO_verify_ssa /* todo_flags_finish */
2078 } 2078 }