00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070 #include "config.h"
00071 #include "system.h"
00072
00073 #include "rtl.h"
00074 #include "hard-reg-set.h"
00075 #include "basic-block.h"
00076 #include "ssa.h"
00077 #include "insn-config.h"
00078 #include "recog.h"
00079 #include "output.h"
00080
00081
00082
00083 typedef struct {
00084
00085
00086
00087 bitmap *data;
00088
00089 int length;
00090 } control_dependent_block_to_edge_map_s, *control_dependent_block_to_edge_map;
00091
00092
00093 static control_dependent_block_to_edge_map control_dependent_block_to_edge_map_create
00094 PARAMS((size_t num_basic_blocks));
00095 static void set_control_dependent_block_to_edge_map_bit
00096 PARAMS ((control_dependent_block_to_edge_map c, basic_block bb,
00097 int edge_index));
00098 static void control_dependent_block_to_edge_map_free
00099 PARAMS ((control_dependent_block_to_edge_map c));
00100 static void find_all_control_dependences
00101 PARAMS ((struct edge_list *el, dominance_info pdom,
00102 control_dependent_block_to_edge_map cdbte));
00103 static void find_control_dependence
00104 PARAMS ((struct edge_list *el, int edge_index, dominance_info pdom,
00105 control_dependent_block_to_edge_map cdbte));
00106 static basic_block find_pdom
00107 PARAMS ((dominance_info pdom, basic_block block));
00108 static int inherently_necessary_register_1
00109 PARAMS ((rtx *current_rtx, void *data));
00110 static int inherently_necessary_register
00111 PARAMS ((rtx current_rtx));
00112 static int find_inherently_necessary
00113 PARAMS ((rtx current_rtx));
00114 static int propagate_necessity_through_operand
00115 PARAMS ((rtx *current_rtx, void *data));
00116 static void note_inherently_necessary_set
00117 PARAMS ((rtx, rtx, void *));
00118
00119
00120
00121
00122 #define KILL_INSN(INSN) INSN_DEAD_CODE_P(INSN) = 1
00123
00124 #define RESURRECT_INSN(INSN) INSN_DEAD_CODE_P(INSN) = 0
00125
00126 #define UNNECESSARY_P(INSN) INSN_DEAD_CODE_P(INSN)
00127 static void mark_all_insn_unnecessary
00128 PARAMS ((void));
00129
00130
00131 #define EXECUTE_IF_UNNECESSARY(INSN, CODE) \
00132 { \
00133 rtx INSN; \
00134 \
00135 for (INSN = get_insns (); INSN != NULL_RTX; INSN = NEXT_INSN (INSN)) \
00136 if (INSN_DEAD_CODE_P (INSN)) { \
00137 CODE; \
00138 } \
00139 }
00140
00141 static rtx find_block_label
00142 PARAMS ((basic_block bb));
00143
00144 static void delete_insn_bb
00145 PARAMS ((rtx insn));
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159 static control_dependent_block_to_edge_map
00160 control_dependent_block_to_edge_map_create (num_basic_blocks)
00161 size_t num_basic_blocks;
00162 {
00163 int i;
00164 control_dependent_block_to_edge_map c
00165 = xmalloc (sizeof (control_dependent_block_to_edge_map_s));
00166 c->length = num_basic_blocks - (INVALID_BLOCK+1);
00167 c->data = xmalloc ((size_t) c->length*sizeof (bitmap));
00168 for (i = 0; i < c->length; ++i)
00169 c->data[i] = BITMAP_XMALLOC ();
00170
00171 return c;
00172 }
00173
00174
00175
00176
00177
00178 static void
00179 set_control_dependent_block_to_edge_map_bit (c, bb, edge_index)
00180 control_dependent_block_to_edge_map c;
00181 basic_block bb;
00182 int edge_index;
00183 {
00184 if (bb->index - (INVALID_BLOCK+1) >= c->length)
00185 abort ();
00186
00187 bitmap_set_bit (c->data[bb->index - (INVALID_BLOCK+1)],
00188 edge_index);
00189 }
00190
00191
00192
00193
00194
00195
00196 #define EXECUTE_IF_CONTROL_DEPENDENT(CDBTE, INSN, EDGE_NUMBER, CODE) \
00197 EXECUTE_IF_SET_IN_BITMAP \
00198 (CDBTE->data[BLOCK_NUM (INSN) - (INVALID_BLOCK+1)], 0, \
00199 EDGE_NUMBER, CODE)
00200
00201
00202
00203 static void
00204 control_dependent_block_to_edge_map_free (c)
00205 control_dependent_block_to_edge_map c;
00206 {
00207 int i;
00208 for (i = 0; i < c->length; ++i)
00209 BITMAP_XFREE (c->data[i]);
00210 free ((PTR) c);
00211 }
00212
00213
00214
00215
00216
00217
00218 static void
00219 find_all_control_dependences (el, pdom, cdbte)
00220 struct edge_list *el;
00221 dominance_info pdom;
00222 control_dependent_block_to_edge_map cdbte;
00223 {
00224 int i;
00225
00226 for (i = 0; i < NUM_EDGES (el); ++i)
00227 find_control_dependence (el, i, pdom, cdbte);
00228 }
00229
00230
00231
00232
00233
00234
00235
00236 static void
00237 find_control_dependence (el, edge_index, pdom, cdbte)
00238 struct edge_list *el;
00239 int edge_index;
00240 dominance_info pdom;
00241 control_dependent_block_to_edge_map cdbte;
00242 {
00243 basic_block current_block;
00244 basic_block ending_block;
00245
00246 if (INDEX_EDGE_PRED_BB (el, edge_index) == EXIT_BLOCK_PTR)
00247 abort ();
00248 ending_block =
00249 (INDEX_EDGE_PRED_BB (el, edge_index) == ENTRY_BLOCK_PTR)
00250 ? ENTRY_BLOCK_PTR->next_bb
00251 : find_pdom (pdom, INDEX_EDGE_PRED_BB (el, edge_index));
00252
00253 for (current_block = INDEX_EDGE_SUCC_BB (el, edge_index);
00254 current_block != ending_block && current_block != EXIT_BLOCK_PTR;
00255 current_block = find_pdom (pdom, current_block))
00256 {
00257 set_control_dependent_block_to_edge_map_bit (cdbte,
00258 current_block,
00259 edge_index);
00260 }
00261 }
00262
00263
00264
00265
00266
00267 static basic_block
00268 find_pdom (pdom, block)
00269 dominance_info pdom;
00270 basic_block block;
00271 {
00272 if (!block)
00273 abort ();
00274 if (block->index == INVALID_BLOCK)
00275 abort ();
00276
00277 if (block == ENTRY_BLOCK_PTR)
00278 return ENTRY_BLOCK_PTR->next_bb;
00279 else if (block == EXIT_BLOCK_PTR)
00280 return EXIT_BLOCK_PTR;
00281 else
00282 {
00283 basic_block bb = get_immediate_dominator (pdom, block);
00284 if (!bb)
00285 return EXIT_BLOCK_PTR;
00286 return bb;
00287 }
00288 }
00289
00290
00291
00292
00293
00294
00295
00296
00297
00298 static int
00299 inherently_necessary_register_1 (current_rtx, data)
00300 rtx *current_rtx;
00301 void *data ATTRIBUTE_UNUSED;
00302 {
00303 rtx x = *current_rtx;
00304
00305 if (x == NULL_RTX)
00306 return 0;
00307 switch (GET_CODE (x))
00308 {
00309 case CLOBBER:
00310
00311 return -1;
00312 break;
00313 case PC:
00314 return 0;
00315 break;
00316 case REG:
00317 if (CONVERT_REGISTER_TO_SSA_P (REGNO (x)) || x == pc_rtx)
00318 return 0;
00319 else
00320 return !0;
00321 break;
00322 default:
00323 return 0;
00324 break;
00325 }
00326 }
00327
00328
00329
00330 static int
00331 inherently_necessary_register (current_rtx)
00332 rtx current_rtx;
00333 {
00334 return for_each_rtx (¤t_rtx,
00335 &inherently_necessary_register_1, NULL);
00336 }
00337
00338
00339
00340
00341
00342
00343 static void
00344 note_inherently_necessary_set (dest, set, data)
00345 rtx set ATTRIBUTE_UNUSED;
00346 rtx dest;
00347 void *data;
00348 {
00349 int *inherently_necessary_set_p = (int *) data;
00350
00351 while (GET_CODE (dest) == SUBREG
00352 || GET_CODE (dest) == STRICT_LOW_PART
00353 || GET_CODE (dest) == ZERO_EXTRACT
00354 || GET_CODE (dest) == SIGN_EXTRACT)
00355 dest = XEXP (dest, 0);
00356
00357 if (GET_CODE (dest) == MEM
00358 || GET_CODE (dest) == UNSPEC
00359 || GET_CODE (dest) == UNSPEC_VOLATILE)
00360 *inherently_necessary_set_p = 1;
00361 }
00362
00363
00364
00365
00366
00367
00368 static int
00369 find_inherently_necessary (x)
00370 rtx x;
00371 {
00372 if (x == NULL_RTX)
00373 return 0;
00374 else if (inherently_necessary_register (x))
00375 return !0;
00376 else
00377 switch (GET_CODE (x))
00378 {
00379 case CALL_INSN:
00380 case BARRIER:
00381 case PREFETCH:
00382 return !0;
00383 case CODE_LABEL:
00384 case NOTE:
00385 return 0;
00386 case JUMP_INSN:
00387 return JUMP_TABLE_DATA_P (x) || computed_jump_p (x) != 0;
00388 case INSN:
00389 {
00390 int inherently_necessary_set = 0;
00391 note_stores (PATTERN (x),
00392 note_inherently_necessary_set,
00393 &inherently_necessary_set);
00394
00395
00396
00397
00398 return (inherently_necessary_set
00399 || GET_CODE (PATTERN (x)) == ASM_INPUT
00400 || asm_noperands (PATTERN (x)) >= 0);
00401 }
00402 default:
00403
00404 abort ();
00405 break;
00406 }
00407 }
00408
00409
00410
00411
00412
00413
00414 static int
00415 propagate_necessity_through_operand (current_rtx, data)
00416 rtx *current_rtx;
00417 void *data;
00418 {
00419 rtx x = *current_rtx;
00420 varray_type *unprocessed_instructions = (varray_type *) data;
00421
00422 if (x == NULL_RTX)
00423 return 0;
00424 switch ( GET_CODE (x))
00425 {
00426 case REG:
00427 if (CONVERT_REGISTER_TO_SSA_P (REGNO (x)))
00428 {
00429 rtx insn = VARRAY_RTX (ssa_definition, REGNO (x));
00430 if (insn != NULL_RTX && UNNECESSARY_P (insn))
00431 {
00432 RESURRECT_INSN (insn);
00433 VARRAY_PUSH_RTX (*unprocessed_instructions, insn);
00434 }
00435 }
00436 return 0;
00437
00438 default:
00439 return 0;
00440 }
00441 }
00442
00443
00444
00445 static void
00446 mark_all_insn_unnecessary ()
00447 {
00448 rtx insn;
00449 for (insn = get_insns (); insn != NULL_RTX; insn = NEXT_INSN (insn))
00450 KILL_INSN (insn);
00451 }
00452
00453
00454
00455 static rtx
00456 find_block_label (bb)
00457 basic_block bb;
00458 {
00459 rtx insn = bb->head;
00460 if (LABEL_P (insn))
00461 return insn;
00462 else
00463 {
00464 rtx new_label = emit_label_before (gen_label_rtx (), insn);
00465 if (insn == bb->head)
00466 bb->head = new_label;
00467 return new_label;
00468 }
00469 }
00470
00471
00472
00473 static void
00474 delete_insn_bb (insn)
00475 rtx insn;
00476 {
00477 if (!insn)
00478 abort ();
00479
00480
00481
00482
00483
00484
00485 if (! INSN_P (insn))
00486 return;
00487
00488 delete_insn (insn);
00489 }
00490
00491
00492
00493 void
00494 ssa_eliminate_dead_code ()
00495 {
00496 rtx insn;
00497 basic_block bb;
00498
00499 varray_type unprocessed_instructions;
00500
00501
00502 control_dependent_block_to_edge_map cdbte;
00503
00504 dominance_info pdom;
00505 struct edge_list *el;
00506
00507
00508 mark_all_insn_unnecessary ();
00509 VARRAY_RTX_INIT (unprocessed_instructions, 64,
00510 "unprocessed instructions");
00511 cdbte = control_dependent_block_to_edge_map_create (last_basic_block);
00512
00513
00514 connect_infinite_loops_to_exit ();
00515
00516
00517 pdom = calculate_dominance_info (CDI_POST_DOMINATORS);
00518 el = create_edge_list ();
00519 find_all_control_dependences (el, pdom, cdbte);
00520
00521
00522 for (insn = get_insns (); insn != NULL_RTX; insn = NEXT_INSN (insn))
00523 if (find_inherently_necessary (insn))
00524 {
00525 RESURRECT_INSN (insn);
00526 VARRAY_PUSH_RTX (unprocessed_instructions, insn);
00527 }
00528
00529
00530 while (VARRAY_ACTIVE_SIZE (unprocessed_instructions) > 0)
00531 {
00532 rtx current_instruction;
00533 int edge_number;
00534
00535 current_instruction = VARRAY_TOP_RTX (unprocessed_instructions);
00536 VARRAY_POP (unprocessed_instructions);
00537
00538
00539
00540
00541
00542
00543 if (INSN_P (current_instruction)
00544 && !JUMP_TABLE_DATA_P (current_instruction))
00545 {
00546
00547 EXECUTE_IF_CONTROL_DEPENDENT
00548 (cdbte, current_instruction, edge_number,
00549 {
00550 rtx jump_insn = (INDEX_EDGE_PRED_BB (el, edge_number))->end;
00551 if (GET_CODE (jump_insn) == JUMP_INSN
00552 && UNNECESSARY_P (jump_insn))
00553 {
00554 RESURRECT_INSN (jump_insn);
00555 VARRAY_PUSH_RTX (unprocessed_instructions, jump_insn);
00556 }
00557 });
00558
00559
00560 for_each_rtx (¤t_instruction,
00561 &propagate_necessity_through_operand,
00562 (PTR) &unprocessed_instructions);
00563
00564
00565
00566
00567
00568
00569
00570
00571
00572 if (PHI_NODE_P (current_instruction))
00573 {
00574 rtvec phi_vec = XVEC (SET_SRC (PATTERN (current_instruction)), 0);
00575 int num_elem = GET_NUM_ELEM (phi_vec);
00576 int v;
00577
00578 for (v = num_elem - 2; v >= 0; v -= 2)
00579 {
00580 basic_block bb;
00581
00582 bb = BASIC_BLOCK (INTVAL (RTVEC_ELT (phi_vec, v + 1)));
00583 EXECUTE_IF_CONTROL_DEPENDENT
00584 (cdbte, bb->end, edge_number,
00585 {
00586 rtx jump_insn;
00587
00588 jump_insn = (INDEX_EDGE_PRED_BB (el, edge_number))->end;
00589 if (((GET_CODE (jump_insn) == JUMP_INSN))
00590 && UNNECESSARY_P (jump_insn))
00591 {
00592 RESURRECT_INSN (jump_insn);
00593 VARRAY_PUSH_RTX (unprocessed_instructions, jump_insn);
00594 }
00595 });
00596
00597 }
00598 }
00599 }
00600 }
00601
00602
00603 EXECUTE_IF_UNNECESSARY (insn,
00604 {
00605 if (any_condjump_p (insn))
00606 {
00607 basic_block bb = BLOCK_FOR_INSN (insn);
00608 basic_block pdom_bb = find_pdom (pdom, bb);
00609 rtx lbl;
00610 edge e;
00611
00612
00613
00614
00615
00616
00617
00618
00619
00620
00621 if (pdom_bb == EXIT_BLOCK_PTR)
00622 {
00623
00624
00625
00626 e = bb->succ;
00627 while (e)
00628 {
00629 edge temp = e;
00630
00631 e = e->succ_next;
00632 if ((temp->flags & EDGE_FALLTHRU) == 0)
00633 {
00634
00635
00636 if (temp->dest != EXIT_BLOCK_PTR)
00637 {
00638 rtx insn
00639 = first_insn_after_basic_block_note (temp->dest);
00640
00641 while (PHI_NODE_P (insn))
00642 {
00643 remove_phi_alternative (PATTERN (insn), temp->src);
00644 insn = NEXT_INSN (insn);
00645 }
00646 }
00647
00648 remove_edge (temp);
00649 }
00650 }
00651
00652
00653 PUT_CODE (insn, NOTE);
00654 NOTE_LINE_NUMBER (insn) = NOTE_INSN_DELETED;
00655 continue;
00656 }
00657
00658
00659
00660
00661
00662 e = bb->succ;
00663 while (e)
00664 {
00665 edge temp = e;
00666
00667 e = e->succ_next;
00668
00669 if (temp->flags & EDGE_ABNORMAL)
00670 continue;
00671
00672
00673
00674 if (temp->dest != EXIT_BLOCK_PTR)
00675 {
00676 rtx insn = first_insn_after_basic_block_note (temp->dest);
00677
00678 while (PHI_NODE_P (insn))
00679 {
00680 remove_phi_alternative (PATTERN (insn), temp->src);
00681 insn = NEXT_INSN (insn);
00682 }
00683 }
00684
00685 remove_edge (temp);
00686 }
00687
00688
00689
00690 make_edge (bb, pdom_bb, 0);
00691
00692
00693
00694 lbl = find_block_label (pdom_bb);
00695 SET_SRC (PATTERN (insn)) = gen_rtx_LABEL_REF (VOIDmode, lbl);
00696 INSN_CODE (insn) = -1;
00697 JUMP_LABEL (insn) = lbl;
00698 LABEL_NUSES (lbl)++;
00699
00700
00701
00702
00703 emit_barrier_after (insn);
00704 }
00705 else if (!JUMP_P (insn))
00706 delete_insn_bb (insn);
00707 });
00708
00709
00710 remove_fake_edges ();
00711
00712
00713
00714
00715 FOR_EACH_BB (bb)
00716 {
00717 if (bb->succ == NULL)
00718 {
00719 rtx next = NEXT_INSN (bb->end);
00720
00721 if (!next || GET_CODE (next) != BARRIER)
00722 emit_barrier_after (bb->end);
00723 }
00724 }
00725
00726 for (insn = get_insns (); insn != NULL_RTX; insn = NEXT_INSN (insn))
00727 RESURRECT_INSN (insn);
00728 if (VARRAY_ACTIVE_SIZE (unprocessed_instructions) != 0)
00729 abort ();
00730 control_dependent_block_to_edge_map_free (cdbte);
00731 free ((PTR) pdom);
00732 free_edge_list (el);
00733 }