OSDN Git Service

2008-05-16 Kenneth Zadeck <zadeck@naturalbridge.com>
[pf3gnuchains/gcc-fork.git] / gcc / tree-ssa-dse.c
1 /* Dead store elimination
2    Copyright (C) 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
3
4 This file is part of GCC.
5
6 GCC is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3, or (at your option)
9 any later version.
10
11 GCC is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with GCC; see the file COPYING3.  If not see
18 <http://www.gnu.org/licenses/>.  */
19
20 #include "config.h"
21 #include "system.h"
22 #include "coretypes.h"
23 #include "tm.h"
24 #include "ggc.h"
25 #include "tree.h"
26 #include "rtl.h"
27 #include "tm_p.h"
28 #include "basic-block.h"
29 #include "timevar.h"
30 #include "diagnostic.h"
31 #include "tree-flow.h"
32 #include "tree-pass.h"
33 #include "tree-dump.h"
34 #include "domwalk.h"
35 #include "flags.h"
36
37 /* This file implements dead store elimination.
38
39    A dead store is a store into a memory location which will later be
40    overwritten by another store without any intervening loads.  In this
41    case the earlier store can be deleted.
42
43    In our SSA + virtual operand world we use immediate uses of virtual
44    operands to detect dead stores.  If a store's virtual definition
45    is used precisely once by a later store to the same location which
46    post dominates the first store, then the first store is dead. 
47
48    The single use of the store's virtual definition ensures that
49    there are no intervening aliased loads and the requirement that
50    the second load post dominate the first ensures that if the earlier
51    store executes, then the later stores will execute before the function
52    exits.
53
54    It may help to think of this as first moving the earlier store to
55    the point immediately before the later store.  Again, the single
56    use of the virtual definition and the post-dominance relationship
57    ensure that such movement would be safe.  Clearly if there are 
58    back to back stores, then the second is redundant.
59
60    Reviewing section 10.7.2 in Morgan's "Building an Optimizing Compiler"
61    may also help in understanding this code since it discusses the
62    relationship between dead store and redundant load elimination.  In
63    fact, they are the same transformation applied to different views of
64    the CFG.  */
65    
66
67 struct dse_global_data
68 {
69   /* This is the global bitmap for store statements.
70
71      Each statement has a unique ID.  When we encounter a store statement
72      that we want to record, set the bit corresponding to the statement's
73      unique ID in this bitmap.  */
74   bitmap stores;
75 };
76
77 /* We allocate a bitmap-per-block for stores which are encountered
78    during the scan of that block.  This allows us to restore the 
79    global bitmap of stores when we finish processing a block.  */
80 struct dse_block_local_data
81 {
82   bitmap stores;
83 };
84
85 /* Basic blocks of the potentially dead store and the following
86    store, for memory_address_same.  */
87 struct address_walk_data
88 {
89   basic_block store1_bb, store2_bb;
90 };
91
92 static bool gate_dse (void);
93 static unsigned int tree_ssa_dse (void);
94 static void dse_initialize_block_local_data (struct dom_walk_data *,
95                                              basic_block,
96                                              bool);
97 static void dse_optimize_stmt (struct dom_walk_data *,
98                                basic_block,
99                                block_stmt_iterator);
100 static void dse_record_phis (struct dom_walk_data *, basic_block);
101 static void dse_finalize_block (struct dom_walk_data *, basic_block);
102 static void record_voperand_set (bitmap, bitmap *, unsigned int);
103
104 /* Returns uid of statement STMT.  */
105
106 static unsigned
107 get_stmt_uid (tree stmt)
108 {
109   if (TREE_CODE (stmt) == PHI_NODE)
110     return SSA_NAME_VERSION (PHI_RESULT (stmt)) + gimple_stmt_max_uid (cfun);
111
112   return gimple_stmt_uid (stmt);
113 }
114
115 /* Set bit UID in bitmaps GLOBAL and *LOCAL, creating *LOCAL as needed.  */
116
117 static void
118 record_voperand_set (bitmap global, bitmap *local, unsigned int uid)
119 {
120   /* Lazily allocate the bitmap.  Note that we do not get a notification
121      when the block local data structures die, so we allocate the local
122      bitmap backed by the GC system.  */
123   if (*local == NULL)
124     *local = BITMAP_GGC_ALLOC ();
125
126   /* Set the bit in the local and global bitmaps.  */
127   bitmap_set_bit (*local, uid);
128   bitmap_set_bit (global, uid);
129 }
130
131 /* Initialize block local data structures.  */
132
133 static void
134 dse_initialize_block_local_data (struct dom_walk_data *walk_data,
135                                  basic_block bb ATTRIBUTE_UNUSED,
136                                  bool recycled)
137 {
138   struct dse_block_local_data *bd
139     = (struct dse_block_local_data *)
140         VEC_last (void_p, walk_data->block_data_stack);
141
142   /* If we are given a recycled block local data structure, ensure any
143      bitmap associated with the block is cleared.  */
144   if (recycled)
145     {
146       if (bd->stores)
147         bitmap_clear (bd->stores);
148     }
149 }
150
151 /* Helper function for memory_address_same via walk_tree.  Returns
152    non-NULL if it finds an SSA_NAME which is part of the address,
153    such that the definition of the SSA_NAME post-dominates the store
154    we want to delete but not the store that we believe makes it
155    redundant.  This indicates that the address may change between
156    the two stores.  */
157
158 static tree
159 memory_ssa_name_same (tree *expr_p, int *walk_subtrees ATTRIBUTE_UNUSED,
160                       void *data)
161 {
162   struct address_walk_data *walk_data = (struct address_walk_data *) data;
163   tree expr = *expr_p;
164   tree def_stmt;
165   basic_block def_bb;
166
167   if (TREE_CODE (expr) != SSA_NAME)
168     return NULL_TREE;
169
170   /* If we've found a default definition, then there's no problem.  Both
171      stores will post-dominate it.  And def_bb will be NULL.  */
172   if (SSA_NAME_IS_DEFAULT_DEF (expr))
173     return NULL_TREE;
174
175   def_stmt = SSA_NAME_DEF_STMT (expr);
176   def_bb = bb_for_stmt (def_stmt);
177
178   /* DEF_STMT must dominate both stores.  So if it is in the same
179      basic block as one, it does not post-dominate that store.  */
180   if (walk_data->store1_bb != def_bb
181       && dominated_by_p (CDI_POST_DOMINATORS, walk_data->store1_bb, def_bb))
182     {
183       if (walk_data->store2_bb == def_bb
184           || !dominated_by_p (CDI_POST_DOMINATORS, walk_data->store2_bb,
185                               def_bb))
186         /* Return non-NULL to stop the walk.  */
187         return def_stmt;
188     }
189
190   return NULL_TREE;
191 }
192
193 /* Return TRUE if the destination memory address in STORE1 and STORE2
194    might be modified after STORE1, before control reaches STORE2.  */
195
196 static bool
197 memory_address_same (tree store1, tree store2)
198 {
199   struct address_walk_data walk_data;
200
201   walk_data.store1_bb = bb_for_stmt (store1);
202   walk_data.store2_bb = bb_for_stmt (store2);
203
204   return (walk_tree (&GIMPLE_STMT_OPERAND (store1, 0), memory_ssa_name_same,
205                      &walk_data, NULL)
206           == NULL);
207 }
208
209 /* Return true if there is a stmt that kills the lhs of STMT and is in the
210    virtual def-use chain of STMT without a use inbetween the kill and STMT.
211    Returns false if no such stmt is found.
212    *FIRST_USE_P is set to the first use of the single virtual def of
213    STMT.  *USE_P is set to the vop killed by *USE_STMT.  */
214
215 static bool
216 get_kill_of_stmt_lhs (tree stmt,
217                       use_operand_p * first_use_p,
218                       use_operand_p * use_p, tree * use_stmt)
219 {
220   tree lhs;
221
222   gcc_assert (TREE_CODE (stmt) == GIMPLE_MODIFY_STMT);
223
224   lhs = GIMPLE_STMT_OPERAND (stmt, 0);
225
226   /* We now walk the chain of single uses of the single VDEFs.
227      We succeeded finding a kill if the lhs of the use stmt is
228      equal to the original lhs.  We can keep walking to the next
229      use if there are no possible uses of the original lhs in
230      the stmt.  */
231   do
232     {
233       tree use_lhs, use_rhs;
234       def_operand_p def_p;
235
236       /* The stmt must have a single VDEF.  */
237       def_p = SINGLE_SSA_DEF_OPERAND (stmt, SSA_OP_VDEF);
238       if (def_p == NULL_DEF_OPERAND_P)
239         return false;
240
241       /* Get the single immediate use of the def.  */
242       if (!single_imm_use (DEF_FROM_PTR (def_p), first_use_p, &stmt))
243         return false;
244       first_use_p = use_p;
245
246       /* If there are possible hidden uses, give up.  */
247       if (TREE_CODE (stmt) != GIMPLE_MODIFY_STMT)
248         return false;
249       use_rhs = GIMPLE_STMT_OPERAND (stmt, 1);
250       if (TREE_CODE (use_rhs) == CALL_EXPR
251           || (!is_gimple_min_invariant (use_rhs)
252               && TREE_CODE (use_rhs) != SSA_NAME))
253         return false;
254
255       /* If the use stmts lhs matches the original lhs we have
256          found the kill, otherwise continue walking.  */
257       use_lhs = GIMPLE_STMT_OPERAND (stmt, 0);
258       if (operand_equal_p (use_lhs, lhs, 0))
259         {
260           *use_stmt = stmt;
261           return true;
262         }
263     }
264   while (1);
265 }
266
267 /* A helper of dse_optimize_stmt.
268    Given a GIMPLE_MODIFY_STMT in STMT, check that each VDEF has one
269    use, and that one use is another VDEF clobbering the first one.
270
271    Return TRUE if the above conditions are met, otherwise FALSE.  */
272
273 static bool
274 dse_possible_dead_store_p (tree stmt,
275                            use_operand_p *first_use_p,
276                            use_operand_p *use_p,
277                            tree *use_stmt,
278                            struct dse_global_data *dse_gd,
279                            struct dse_block_local_data *bd)
280 {
281   ssa_op_iter op_iter;
282   bool fail = false;
283   def_operand_p var1;
284   vuse_vec_p vv;
285   tree defvar = NULL_TREE, temp;
286   tree prev_defvar = NULL_TREE;
287
288   /* We want to verify that each virtual definition in STMT has
289      precisely one use and that all the virtual definitions are
290      used by the same single statement.  When complete, we
291      want USE_STMT to refer to the one statement which uses
292      all of the virtual definitions from STMT.  */
293   *use_stmt = NULL;
294   FOR_EACH_SSA_VDEF_OPERAND (var1, vv, stmt, op_iter)
295     {
296       defvar = DEF_FROM_PTR (var1);
297
298       /* If this virtual def does not have precisely one use, then
299          we will not be able to eliminate STMT.  */
300       if (!has_single_use (defvar))
301         {
302           fail = true;
303           break;
304         }
305
306       /* Get the one and only immediate use of DEFVAR.  */
307       single_imm_use (defvar, use_p, &temp);
308       gcc_assert (*use_p != NULL_USE_OPERAND_P);
309       *first_use_p = *use_p;
310
311       /* ???  If we hit a PHI_NODE we could skip to the PHI_RESULT uses.
312          Don't bother to do that for now.  */
313       if (TREE_CODE (temp) == PHI_NODE)
314         {
315           fail = true;
316           break;
317         }
318
319       /* In the case of memory partitions, we may get:
320
321            # MPT.764_162 = VDEF <MPT.764_161(D)>
322            x = {};
323            # MPT.764_167 = VDEF <MPT.764_162>
324            y = {};
325
326            So we must make sure we're talking about the same LHS.
327       */
328       if (TREE_CODE (temp) == GIMPLE_MODIFY_STMT)
329         {
330           tree base1 = get_base_address (GIMPLE_STMT_OPERAND (stmt, 0));
331           tree base2 =  get_base_address (GIMPLE_STMT_OPERAND (temp, 0));
332
333           while (base1 && INDIRECT_REF_P (base1))
334             base1 = TREE_OPERAND (base1, 0);
335           while (base2 && INDIRECT_REF_P (base2))
336             base2 = TREE_OPERAND (base2, 0);
337
338           if (base1 != base2)
339             {
340               fail = true;
341               break;
342             }
343         }
344
345       /* If the immediate use of DEF_VAR is not the same as the
346          previously find immediate uses, then we will not be able
347          to eliminate STMT.  */
348       if (*use_stmt == NULL)
349         {
350           *use_stmt = temp;
351           prev_defvar = defvar;
352         }
353       else if (temp != *use_stmt)
354         {
355           fail = true;
356           break;
357         }
358     }
359
360   if (fail)
361     {
362       record_voperand_set (dse_gd->stores, &bd->stores, gimple_stmt_uid (stmt));
363       return false;
364     }
365
366   return true;
367 }
368
369
370 /* Attempt to eliminate dead stores in the statement referenced by BSI.
371
372    A dead store is a store into a memory location which will later be
373    overwritten by another store without any intervening loads.  In this
374    case the earlier store can be deleted.
375
376    In our SSA + virtual operand world we use immediate uses of virtual
377    operands to detect dead stores.  If a store's virtual definition
378    is used precisely once by a later store to the same location which
379    post dominates the first store, then the first store is dead.  */
380
381 static void
382 dse_optimize_stmt (struct dom_walk_data *walk_data,
383                    basic_block bb ATTRIBUTE_UNUSED,
384                    block_stmt_iterator bsi)
385 {
386   struct dse_block_local_data *bd
387     = (struct dse_block_local_data *)
388         VEC_last (void_p, walk_data->block_data_stack);
389   struct dse_global_data *dse_gd
390     = (struct dse_global_data *) walk_data->global_data;
391   tree stmt = bsi_stmt (bsi);
392   stmt_ann_t ann = stmt_ann (stmt);
393
394   /* If this statement has no virtual defs, then there is nothing
395      to do.  */
396   if (ZERO_SSA_OPERANDS (stmt, SSA_OP_VDEF))
397     return;
398
399   /* We know we have virtual definitions.  If this is a GIMPLE_MODIFY_STMT
400      that's not also a function call, then record it into our table.  */
401   if (get_call_expr_in (stmt))
402     return;
403
404   if (ann->has_volatile_ops)
405     return;
406
407   if (TREE_CODE (stmt) == GIMPLE_MODIFY_STMT)
408     {
409       use_operand_p first_use_p = NULL_USE_OPERAND_P;
410       use_operand_p use_p = NULL;
411       tree use_stmt;
412
413       if (!dse_possible_dead_store_p (stmt, &first_use_p, &use_p, &use_stmt,
414                                       dse_gd, bd))
415         return;
416
417       /* If we have precisely one immediate use at this point, then we may
418          have found redundant store.  Make sure that the stores are to
419          the same memory location.  This includes checking that any
420          SSA-form variables in the address will have the same values.  */
421       if (use_p != NULL_USE_OPERAND_P
422           && bitmap_bit_p (dse_gd->stores, get_stmt_uid (use_stmt))
423           && !operand_equal_p (GIMPLE_STMT_OPERAND (stmt, 0),
424                                GIMPLE_STMT_OPERAND (use_stmt, 0), 0)
425           && memory_address_same (stmt, use_stmt))
426         {
427           /* If we have precisely one immediate use at this point, but
428              the stores are not to the same memory location then walk the
429              virtual def-use chain to get the stmt which stores to that same
430              memory location.  */
431           if (!get_kill_of_stmt_lhs (stmt, &first_use_p, &use_p, &use_stmt))
432             {
433               record_voperand_set (dse_gd->stores, &bd->stores, gimple_stmt_uid (stmt));
434               return;
435             }
436         }
437
438       /* If we have precisely one immediate use at this point and the
439          stores are to the same memory location or there is a chain of
440          virtual uses from stmt and the stmt which stores to that same
441          memory location, then we may have found redundant store.  */
442       if (use_p != NULL_USE_OPERAND_P
443           && bitmap_bit_p (dse_gd->stores, get_stmt_uid (use_stmt))
444           && operand_equal_p (GIMPLE_STMT_OPERAND (stmt, 0),
445                               GIMPLE_STMT_OPERAND (use_stmt, 0), 0)
446           && memory_address_same (stmt, use_stmt))
447         {
448           ssa_op_iter op_iter;
449           def_operand_p var1;
450           vuse_vec_p vv;
451           tree stmt_lhs;
452
453           /* If use_stmt is or might be a nop assignment, e.g. for
454              struct { ... } S a, b, *p; ...
455              b = a; b = b;
456              or
457              b = a; b = *p; where p might be &b,
458              or
459              *p = a; *p = b; where p might be &b,
460              or
461              *p = *u; *p = *v; where p might be v, then USE_STMT
462              acts as a use as well as definition, so store in STMT
463              is not dead.  */
464           if (LOADED_SYMS (use_stmt)
465               && bitmap_intersect_p (LOADED_SYMS (use_stmt),
466                                      STORED_SYMS (use_stmt)))
467             {
468               record_voperand_set (dse_gd->stores, &bd->stores, ann->uid);
469               return;
470             }
471
472           if (dump_file && (dump_flags & TDF_DETAILS))
473             {
474               fprintf (dump_file, "  Deleted dead store '");
475               print_generic_expr (dump_file, bsi_stmt (bsi), dump_flags);
476               fprintf (dump_file, "'\n");
477             }
478
479           /* Then we need to fix the operand of the consuming stmt.  */
480           stmt_lhs = USE_FROM_PTR (first_use_p);
481           FOR_EACH_SSA_VDEF_OPERAND (var1, vv, stmt, op_iter)
482             {
483               tree usevar, temp;
484
485               single_imm_use (DEF_FROM_PTR (var1), &use_p, &temp);
486               gcc_assert (VUSE_VECT_NUM_ELEM (*vv) == 1);
487               usevar = VUSE_ELEMENT_VAR (*vv, 0);
488               SET_USE (use_p, usevar);
489
490               /* Make sure we propagate the ABNORMAL bit setting.  */
491               if (SSA_NAME_OCCURS_IN_ABNORMAL_PHI (stmt_lhs))
492                 SSA_NAME_OCCURS_IN_ABNORMAL_PHI (usevar) = 1;
493             }
494
495           /* Remove the dead store.  */
496           bsi_remove (&bsi, true);
497
498           /* And release any SSA_NAMEs set in this statement back to the
499              SSA_NAME manager.  */
500           release_defs (stmt);
501         }
502
503       record_voperand_set (dse_gd->stores, &bd->stores, gimple_stmt_uid (stmt));
504     }
505 }
506
507 /* Record that we have seen the PHIs at the start of BB which correspond
508    to virtual operands.  */
509 static void
510 dse_record_phis (struct dom_walk_data *walk_data, basic_block bb)
511 {
512   struct dse_block_local_data *bd
513     = (struct dse_block_local_data *)
514         VEC_last (void_p, walk_data->block_data_stack);
515   struct dse_global_data *dse_gd
516     = (struct dse_global_data *) walk_data->global_data;
517   tree phi;
518
519   for (phi = phi_nodes (bb); phi; phi = PHI_CHAIN (phi))
520     if (!is_gimple_reg (PHI_RESULT (phi)))
521       record_voperand_set (dse_gd->stores,
522                            &bd->stores,
523                            get_stmt_uid (phi));
524 }
525
526 static void
527 dse_finalize_block (struct dom_walk_data *walk_data,
528                     basic_block bb ATTRIBUTE_UNUSED)
529 {
530   struct dse_block_local_data *bd
531     = (struct dse_block_local_data *)
532         VEC_last (void_p, walk_data->block_data_stack);
533   struct dse_global_data *dse_gd
534     = (struct dse_global_data *) walk_data->global_data;
535   bitmap stores = dse_gd->stores;
536   unsigned int i;
537   bitmap_iterator bi;
538
539   /* Unwind the stores noted in this basic block.  */
540   if (bd->stores)
541     EXECUTE_IF_SET_IN_BITMAP (bd->stores, 0, i, bi)
542       {
543         bitmap_clear_bit (stores, i);
544       }
545 }
546
547 /* Main entry point.  */
548
549 static unsigned int
550 tree_ssa_dse (void)
551 {
552   struct dom_walk_data walk_data;
553   struct dse_global_data dse_gd;
554
555   renumber_gimple_stmt_uids ();
556
557   /* We might consider making this a property of each pass so that it
558      can be [re]computed on an as-needed basis.  Particularly since
559      this pass could be seen as an extension of DCE which needs post
560      dominators.  */
561   calculate_dominance_info (CDI_POST_DOMINATORS);
562
563   /* Dead store elimination is fundamentally a walk of the post-dominator
564      tree and a backwards walk of statements within each block.  */
565   walk_data.walk_stmts_backward = true;
566   walk_data.dom_direction = CDI_POST_DOMINATORS;
567   walk_data.initialize_block_local_data = dse_initialize_block_local_data;
568   walk_data.before_dom_children_before_stmts = NULL;
569   walk_data.before_dom_children_walk_stmts = dse_optimize_stmt;
570   walk_data.before_dom_children_after_stmts = dse_record_phis;
571   walk_data.after_dom_children_before_stmts = NULL;
572   walk_data.after_dom_children_walk_stmts = NULL;
573   walk_data.after_dom_children_after_stmts = dse_finalize_block;
574   walk_data.interesting_blocks = NULL;
575
576   walk_data.block_local_data_size = sizeof (struct dse_block_local_data);
577
578   /* This is the main hash table for the dead store elimination pass.  */
579   dse_gd.stores = BITMAP_ALLOC (NULL);
580   walk_data.global_data = &dse_gd;
581
582   /* Initialize the dominator walker.  */
583   init_walk_dominator_tree (&walk_data);
584
585   /* Recursively walk the dominator tree.  */
586   walk_dominator_tree (&walk_data, EXIT_BLOCK_PTR);
587
588   /* Finalize the dominator walker.  */
589   fini_walk_dominator_tree (&walk_data);
590
591   /* Release the main bitmap.  */
592   BITMAP_FREE (dse_gd.stores);
593
594   /* For now, just wipe the post-dominator information.  */
595   free_dominance_info (CDI_POST_DOMINATORS);
596   return 0;
597 }
598
599 static bool
600 gate_dse (void)
601 {
602   return flag_tree_dse != 0;
603 }
604
605 struct gimple_opt_pass pass_dse = 
606 {
607  {
608   GIMPLE_PASS,
609   "dse",                        /* name */
610   gate_dse,                     /* gate */
611   tree_ssa_dse,                 /* execute */
612   NULL,                         /* sub */
613   NULL,                         /* next */
614   0,                            /* static_pass_number */
615   TV_TREE_DSE,                  /* tv_id */
616   PROP_cfg
617     | PROP_ssa
618     | PROP_alias,               /* properties_required */
619   0,                            /* properties_provided */
620   0,                            /* properties_destroyed */
621   0,                            /* todo_flags_start */
622   TODO_dump_func
623     | TODO_ggc_collect
624     | TODO_verify_ssa           /* todo_flags_finish */
625  }
626 };
627
628 /* A very simple dead store pass eliminating write only local variables.
629    The pass does not require alias information and thus can be run before
630    inlining to quickly eliminate artifacts of some common C++ constructs.  */
631
632 static unsigned int
633 execute_simple_dse (void)
634 {
635   block_stmt_iterator bsi;
636   basic_block bb;
637   bitmap variables_loaded = BITMAP_ALLOC (NULL);
638   unsigned int todo = 0;
639
640   /* Collect into VARIABLES LOADED all variables that are read in function
641      body.  */
642   FOR_EACH_BB (bb)
643     for (bsi = bsi_start (bb); !bsi_end_p (bsi); bsi_next (&bsi))
644       if (LOADED_SYMS (bsi_stmt (bsi)))
645         bitmap_ior_into (variables_loaded,
646                          LOADED_SYMS (bsi_stmt (bsi)));
647
648   /* Look for statements writing into the write only variables.
649      And try to remove them.  */
650
651   FOR_EACH_BB (bb)
652     for (bsi = bsi_start (bb); !bsi_end_p (bsi);)
653       {
654         tree stmt = bsi_stmt (bsi), op;
655         bool removed = false;
656         ssa_op_iter iter;
657
658         if (STORED_SYMS (stmt) && TREE_CODE (stmt) == GIMPLE_MODIFY_STMT
659             && TREE_CODE (stmt) != RETURN_EXPR
660             && !bitmap_intersect_p (STORED_SYMS (stmt), variables_loaded))
661           {
662             unsigned int i;
663             bitmap_iterator bi;
664             bool dead = true;
665
666
667
668             /* See if STMT only stores to write-only variables and
669                verify that there are no volatile operands.  tree-ssa-operands
670                sets has_volatile_ops flag for all statements involving
671                reads and writes when aliases are not built to prevent passes
672                from removing them as dead.  The flag thus has no use for us
673                and we need to look into all operands.  */
674               
675             EXECUTE_IF_SET_IN_BITMAP (STORED_SYMS (stmt), 0, i, bi)
676               {
677                 tree var = referenced_var_lookup (i);
678                 if (TREE_ADDRESSABLE (var)
679                     || is_global_var (var)
680                     || TREE_THIS_VOLATILE (var))
681                   dead = false;
682               }
683
684             if (dead && LOADED_SYMS (stmt))
685               EXECUTE_IF_SET_IN_BITMAP (LOADED_SYMS (stmt), 0, i, bi)
686                 if (TREE_THIS_VOLATILE (referenced_var_lookup (i)))
687                   dead = false;
688
689             if (dead)
690               FOR_EACH_SSA_TREE_OPERAND (op, stmt, iter, SSA_OP_ALL_OPERANDS)
691                 if (TREE_THIS_VOLATILE (op))
692                   dead = false;
693
694             /* Look for possible occurence var = indirect_ref (...) where
695                indirect_ref itself is volatile.  */
696
697             if (dead && TREE_THIS_VOLATILE (GIMPLE_STMT_OPERAND (stmt, 1)))
698               dead = false;
699
700             if (dead)
701               {
702                 tree call = get_call_expr_in (stmt);
703
704                 /* When LHS of var = call (); is dead, simplify it into
705                    call (); saving one operand.  */
706                 if (TREE_CODE (stmt) == GIMPLE_MODIFY_STMT
707                     && call
708                     && TREE_SIDE_EFFECTS (call))
709                   {
710                     if (dump_file && (dump_flags & TDF_DETAILS))
711                       {
712                         fprintf (dump_file, "Deleted LHS of call: ");
713                         print_generic_stmt (dump_file, stmt, TDF_SLIM);
714                         fprintf (dump_file, "\n");
715                       }
716                     push_stmt_changes (bsi_stmt_ptr (bsi));
717                     TREE_BLOCK (call) = TREE_BLOCK (stmt);
718                     bsi_replace (&bsi, call, false);
719                     maybe_clean_or_replace_eh_stmt (stmt, call);
720                     mark_symbols_for_renaming (call);
721                     pop_stmt_changes (bsi_stmt_ptr (bsi));
722                   }
723                 else
724                   {
725                     if (dump_file && (dump_flags & TDF_DETAILS))
726                       {
727                         fprintf (dump_file, "  Deleted dead store '");
728                         print_generic_expr (dump_file, stmt, dump_flags);
729                         fprintf (dump_file, "'\n");
730                       }
731                     removed = true;
732                     bsi_remove (&bsi, true);
733                     todo |= TODO_cleanup_cfg;
734                   }
735                 todo |= TODO_remove_unused_locals | TODO_ggc_collect;
736               }
737           }
738         if (!removed)
739           bsi_next (&bsi);
740       }
741   BITMAP_FREE (variables_loaded);
742   return todo;
743 }
744
745 struct gimple_opt_pass pass_simple_dse =
746 {
747  {
748   GIMPLE_PASS,
749   "sdse",                               /* name */
750   NULL,                                 /* gate */
751   execute_simple_dse,                   /* execute */
752   NULL,                                 /* sub */
753   NULL,                                 /* next */
754   0,                                    /* static_pass_number */
755   0,                                    /* tv_id */
756   PROP_ssa,                             /* properties_required */
757   0,                                    /* properties_provided */
758   0,                                    /* properties_destroyed */
759   0,                                    /* todo_flags_start */
760   TODO_dump_func                        /* todo_flags_finish */
761  }
762 };