comparison gcc/tree-ssa-propagate.c @ 132:d34655255c78

update gcc-8.2
author mir3636
date Thu, 25 Oct 2018 10:21:07 +0900
parents 84e7813d76e9
children 1830386684a0
comparison
equal deleted inserted replaced
130:e108057fa461 132:d34655255c78
1 /* Generic SSA value propagation engine. 1 /* Generic SSA value propagation engine.
2 Copyright (C) 2004-2017 Free Software Foundation, Inc. 2 Copyright (C) 2004-2018 Free Software Foundation, Inc.
3 Contributed by Diego Novillo <dnovillo@redhat.com> 3 Contributed by Diego Novillo <dnovillo@redhat.com>
4 4
5 This file is part of GCC. 5 This file is part of GCC.
6 6
7 GCC is free software; you can redistribute it and/or modify it 7 GCC is free software; you can redistribute it and/or modify it
106 Robert Morgan, Butterworth-Heinemann, 1998, Section 8.9. 106 Robert Morgan, Butterworth-Heinemann, 1998, Section 8.9.
107 107
108 [3] Advanced Compiler Design and Implementation, 108 [3] Advanced Compiler Design and Implementation,
109 Steven Muchnick, Morgan Kaufmann, 1997, Section 12.6 */ 109 Steven Muchnick, Morgan Kaufmann, 1997, Section 12.6 */
110 110
111 /* Function pointers used to parameterize the propagation engine. */ 111 /* Worklists of control flow edge destinations. This contains
112 static ssa_prop_visit_stmt_fn ssa_prop_visit_stmt;
113 static ssa_prop_visit_phi_fn ssa_prop_visit_phi;
114
115 /* Worklist of control flow edge destinations. This contains
116 the CFG order number of the blocks so we can iterate in CFG 112 the CFG order number of the blocks so we can iterate in CFG
117 order by visiting in bit-order. */ 113 order by visiting in bit-order. We use two worklists to
114 first make forward progress before iterating. */
118 static bitmap cfg_blocks; 115 static bitmap cfg_blocks;
116 static bitmap cfg_blocks_back;
119 static int *bb_to_cfg_order; 117 static int *bb_to_cfg_order;
120 static int *cfg_order_to_bb; 118 static int *cfg_order_to_bb;
121 119
122 /* Worklist of SSA edges which will need reexamination as their 120 /* Worklists of SSA edges which will need reexamination as their
123 definition has changed. SSA edges are def-use edges in the SSA 121 definition has changed. SSA edges are def-use edges in the SSA
124 web. For each D-U edge, we store the target statement or PHI node 122 web. For each D-U edge, we store the target statement or PHI node
125 UID in a bitmap. UIDs order stmts in execution order. */ 123 UID in a bitmap. UIDs order stmts in execution order. We use
124 two worklists to first make forward progress before iterating. */
126 static bitmap ssa_edge_worklist; 125 static bitmap ssa_edge_worklist;
126 static bitmap ssa_edge_worklist_back;
127 static vec<gimple *> uid_to_stmt; 127 static vec<gimple *> uid_to_stmt;
128 128
129 /* Return true if the block worklist empty. */ 129 /* Current RPO index in the iteration. */
130 130 static int curr_order;
131 static inline bool
132 cfg_blocks_empty_p (void)
133 {
134 return bitmap_empty_p (cfg_blocks);
135 }
136
137
138 /* Add a basic block to the worklist. The block must not be the ENTRY
139 or EXIT block. */
140
141 static void
142 cfg_blocks_add (basic_block bb)
143 {
144 gcc_assert (bb != ENTRY_BLOCK_PTR_FOR_FN (cfun)
145 && bb != EXIT_BLOCK_PTR_FOR_FN (cfun));
146 bitmap_set_bit (cfg_blocks, bb_to_cfg_order[bb->index]);
147 }
148
149
150 /* Remove a block from the worklist. */
151
152 static basic_block
153 cfg_blocks_get (void)
154 {
155 gcc_assert (!cfg_blocks_empty_p ());
156 int order_index = bitmap_first_set_bit (cfg_blocks);
157 bitmap_clear_bit (cfg_blocks, order_index);
158 return BASIC_BLOCK_FOR_FN (cfun, cfg_order_to_bb [order_index]);
159 }
160 131
161 132
162 /* We have just defined a new value for VAR. If IS_VARYING is true, 133 /* We have just defined a new value for VAR. If IS_VARYING is true,
163 add all immediate uses of VAR to VARYING_SSA_EDGES, otherwise add 134 add all immediate uses of VAR to VARYING_SSA_EDGES, otherwise add
164 them to INTERESTING_SSA_EDGES. */ 135 them to INTERESTING_SSA_EDGES. */
170 use_operand_p use_p; 141 use_operand_p use_p;
171 142
172 FOR_EACH_IMM_USE_FAST (use_p, iter, var) 143 FOR_EACH_IMM_USE_FAST (use_p, iter, var)
173 { 144 {
174 gimple *use_stmt = USE_STMT (use_p); 145 gimple *use_stmt = USE_STMT (use_p);
146 if (!prop_simulate_again_p (use_stmt))
147 continue;
175 148
176 /* If we did not yet simulate the block wait for this to happen 149 /* If we did not yet simulate the block wait for this to happen
177 and do not add the stmt to the SSA edge worklist. */ 150 and do not add the stmt to the SSA edge worklist. */
178 if (! (gimple_bb (use_stmt)->flags & BB_VISITED)) 151 basic_block use_bb = gimple_bb (use_stmt);
152 if (! (use_bb->flags & BB_VISITED))
179 continue; 153 continue;
180 154
181 if (prop_simulate_again_p (use_stmt) 155 /* If this is a use on a not yet executable edge do not bother to
182 && bitmap_set_bit (ssa_edge_worklist, gimple_uid (use_stmt))) 156 queue it. */
157 if (gimple_code (use_stmt) == GIMPLE_PHI
158 && !(EDGE_PRED (use_bb, PHI_ARG_INDEX_FROM_USE (use_p))->flags
159 & EDGE_EXECUTABLE))
160 continue;
161
162 bitmap worklist;
163 if (bb_to_cfg_order[gimple_bb (use_stmt)->index] < curr_order)
164 worklist = ssa_edge_worklist_back;
165 else
166 worklist = ssa_edge_worklist;
167 if (bitmap_set_bit (worklist, gimple_uid (use_stmt)))
183 { 168 {
184 uid_to_stmt[gimple_uid (use_stmt)] = use_stmt; 169 uid_to_stmt[gimple_uid (use_stmt)] = use_stmt;
185 if (dump_file && (dump_flags & TDF_DETAILS)) 170 if (dump_file && (dump_flags & TDF_DETAILS))
186 { 171 {
187 fprintf (dump_file, "ssa_edge_worklist: adding SSA use in "); 172 fprintf (dump_file, "ssa_edge_worklist: adding SSA use in ");
205 if (e->flags & EDGE_EXECUTABLE) 190 if (e->flags & EDGE_EXECUTABLE)
206 return; 191 return;
207 192
208 e->flags |= EDGE_EXECUTABLE; 193 e->flags |= EDGE_EXECUTABLE;
209 194
210 cfg_blocks_add (bb); 195 int bb_order = bb_to_cfg_order[bb->index];
196 if (bb_order < curr_order)
197 bitmap_set_bit (cfg_blocks_back, bb_order);
198 else
199 bitmap_set_bit (cfg_blocks, bb_order);
211 200
212 if (dump_file && (dump_flags & TDF_DETAILS)) 201 if (dump_file && (dump_flags & TDF_DETAILS))
213 fprintf (dump_file, "Adding destination of edge (%d -> %d) to worklist\n", 202 fprintf (dump_file, "Adding destination of edge (%d -> %d) to worklist\n",
214 e->src->index, e->dest->index); 203 e->src->index, e->dest->index);
215 } 204 }
216 205
217 206
218 /* Simulate the execution of STMT and update the work lists accordingly. */ 207 /* Simulate the execution of STMT and update the work lists accordingly. */
219 208
220 static void 209 void
221 simulate_stmt (gimple *stmt) 210 ssa_propagation_engine::simulate_stmt (gimple *stmt)
222 { 211 {
223 enum ssa_prop_result val = SSA_PROP_NOT_INTERESTING; 212 enum ssa_prop_result val = SSA_PROP_NOT_INTERESTING;
224 edge taken_edge = NULL; 213 edge taken_edge = NULL;
225 tree output_name = NULL_TREE; 214 tree output_name = NULL_TREE;
226 215
232 if (!prop_simulate_again_p (stmt)) 221 if (!prop_simulate_again_p (stmt))
233 return; 222 return;
234 223
235 if (gimple_code (stmt) == GIMPLE_PHI) 224 if (gimple_code (stmt) == GIMPLE_PHI)
236 { 225 {
237 val = ssa_prop_visit_phi (as_a <gphi *> (stmt)); 226 val = visit_phi (as_a <gphi *> (stmt));
238 output_name = gimple_phi_result (stmt); 227 output_name = gimple_phi_result (stmt);
239 } 228 }
240 else 229 else
241 val = ssa_prop_visit_stmt (stmt, &taken_edge, &output_name); 230 val = visit_stmt (stmt, &taken_edge, &output_name);
242 231
243 if (val == SSA_PROP_VARYING) 232 if (val == SSA_PROP_VARYING)
244 { 233 {
245 prop_set_simulate_again (stmt, false); 234 prop_set_simulate_again (stmt, false);
246 235
312 fprintf (dump_file, "marking stmt to be not simulated again\n"); 301 fprintf (dump_file, "marking stmt to be not simulated again\n");
313 prop_set_simulate_again (stmt, false); 302 prop_set_simulate_again (stmt, false);
314 } 303 }
315 } 304 }
316 305
317 /* Process an SSA edge worklist. WORKLIST is the SSA edge worklist to
318 drain. This pops statements off the given WORKLIST and processes
319 them until one statement was simulated or there are no more statements
320 on WORKLIST. We take a pointer to WORKLIST because it may be reallocated
321 when an SSA edge is added to it in simulate_stmt. Return true if a stmt
322 was simulated. */
323
324 static void
325 process_ssa_edge_worklist ()
326 {
327 /* Process the next entry from the worklist. */
328 unsigned stmt_uid = bitmap_first_set_bit (ssa_edge_worklist);
329 bitmap_clear_bit (ssa_edge_worklist, stmt_uid);
330 gimple *stmt = uid_to_stmt[stmt_uid];
331
332 /* We should not have stmts in not yet simulated BBs on the worklist. */
333 gcc_assert (gimple_bb (stmt)->flags & BB_VISITED);
334
335 if (dump_file && (dump_flags & TDF_DETAILS))
336 {
337 fprintf (dump_file, "\nSimulating statement: ");
338 print_gimple_stmt (dump_file, stmt, 0, dump_flags);
339 }
340
341 simulate_stmt (stmt);
342 }
343
344 306
345 /* Simulate the execution of BLOCK. Evaluate the statement associated 307 /* Simulate the execution of BLOCK. Evaluate the statement associated
346 with each variable reference inside the block. */ 308 with each variable reference inside the block. */
347 309
348 static void 310 void
349 simulate_block (basic_block block) 311 ssa_propagation_engine::simulate_block (basic_block block)
350 { 312 {
351 gimple_stmt_iterator gsi; 313 gimple_stmt_iterator gsi;
352 314
353 /* There is nothing to do for the exit block. */ 315 /* There is nothing to do for the exit block. */
354 if (block == EXIT_BLOCK_PTR_FOR_FN (cfun)) 316 if (block == EXIT_BLOCK_PTR_FOR_FN (cfun))
416 edge_iterator ei; 378 edge_iterator ei;
417 basic_block bb; 379 basic_block bb;
418 380
419 /* Worklists of SSA edges. */ 381 /* Worklists of SSA edges. */
420 ssa_edge_worklist = BITMAP_ALLOC (NULL); 382 ssa_edge_worklist = BITMAP_ALLOC (NULL);
383 ssa_edge_worklist_back = BITMAP_ALLOC (NULL);
384 bitmap_tree_view (ssa_edge_worklist);
385 bitmap_tree_view (ssa_edge_worklist_back);
421 386
422 /* Worklist of basic-blocks. */ 387 /* Worklist of basic-blocks. */
423 bb_to_cfg_order = XNEWVEC (int, last_basic_block_for_fn (cfun) + 1); 388 bb_to_cfg_order = XNEWVEC (int, last_basic_block_for_fn (cfun) + 1);
424 cfg_order_to_bb = XNEWVEC (int, n_basic_blocks_for_fn (cfun)); 389 cfg_order_to_bb = XNEWVEC (int, n_basic_blocks_for_fn (cfun));
425 int n = pre_and_rev_post_order_compute_fn (cfun, NULL, 390 int n = pre_and_rev_post_order_compute_fn (cfun, NULL,
426 cfg_order_to_bb, false); 391 cfg_order_to_bb, false);
427 for (int i = 0; i < n; ++i) 392 for (int i = 0; i < n; ++i)
428 bb_to_cfg_order[cfg_order_to_bb[i]] = i; 393 bb_to_cfg_order[cfg_order_to_bb[i]] = i;
429 cfg_blocks = BITMAP_ALLOC (NULL); 394 cfg_blocks = BITMAP_ALLOC (NULL);
430 395 cfg_blocks_back = BITMAP_ALLOC (NULL);
431 if (dump_file && (dump_flags & TDF_DETAILS))
432 dump_immediate_uses (dump_file);
433 396
434 /* Initially assume that every edge in the CFG is not executable. 397 /* Initially assume that every edge in the CFG is not executable.
435 (including the edges coming out of the entry block). Mark blocks 398 (including the edges coming out of the entry block). Mark blocks
436 as not visited, blocks not yet visited will have all their statements 399 as not visited, blocks not yet visited will have all their statements
437 simulated once an incoming edge gets executable. */ 400 simulated once an incoming edge gets executable. */
473 436
474 static void 437 static void
475 ssa_prop_fini (void) 438 ssa_prop_fini (void)
476 { 439 {
477 BITMAP_FREE (cfg_blocks); 440 BITMAP_FREE (cfg_blocks);
441 BITMAP_FREE (cfg_blocks_back);
478 free (bb_to_cfg_order); 442 free (bb_to_cfg_order);
479 free (cfg_order_to_bb); 443 free (cfg_order_to_bb);
480 BITMAP_FREE (ssa_edge_worklist); 444 BITMAP_FREE (ssa_edge_worklist);
445 BITMAP_FREE (ssa_edge_worklist_back);
481 uid_to_stmt.release (); 446 uid_to_stmt.release ();
482 } 447 }
483 448
484 449
485 /* Return true if EXPR is an acceptable right-hand-side for a 450 /* Return true if EXPR is an acceptable right-hand-side for a
779 /* The call simplified to an expression that is 744 /* The call simplified to an expression that is
780 not a valid GIMPLE RHS. */ 745 not a valid GIMPLE RHS. */
781 return false; 746 return false;
782 } 747 }
783 748
784
785 /* Entry point to the propagation engine. 749 /* Entry point to the propagation engine.
786 750
787 VISIT_STMT is called for every statement visited. 751 The VISIT_STMT virtual function is called for every statement
788 VISIT_PHI is called for every PHI node visited. */ 752 visited and the VISIT_PHI virtual function is called for every PHI
753 node visited. */
789 754
790 void 755 void
791 ssa_propagate (ssa_prop_visit_stmt_fn visit_stmt, 756 ssa_propagation_engine::ssa_propagate (void)
792 ssa_prop_visit_phi_fn visit_phi) 757 {
793 {
794 ssa_prop_visit_stmt = visit_stmt;
795 ssa_prop_visit_phi = visit_phi;
796
797 ssa_prop_init (); 758 ssa_prop_init ();
798 759
799 /* Iterate until the worklists are empty. */ 760 curr_order = 0;
800 while (! cfg_blocks_empty_p () 761
801 || ! bitmap_empty_p (ssa_edge_worklist)) 762 /* Iterate until the worklists are empty. We iterate both blocks
802 { 763 and stmts in RPO order, using sets of two worklists to first
803 /* First simulate whole blocks. */ 764 complete the current iteration before iterating over backedges. */
804 if (! cfg_blocks_empty_p ()) 765 while (1)
805 { 766 {
806 /* Pull the next block to simulate off the worklist. */ 767 int next_block_order = (bitmap_empty_p (cfg_blocks)
807 basic_block dest_block = cfg_blocks_get (); 768 ? -1 : bitmap_first_set_bit (cfg_blocks));
808 simulate_block (dest_block); 769 int next_stmt_uid = (bitmap_empty_p (ssa_edge_worklist)
770 ? -1 : bitmap_first_set_bit (ssa_edge_worklist));
771 if (next_block_order == -1 && next_stmt_uid == -1)
772 {
773 if (bitmap_empty_p (cfg_blocks_back)
774 && bitmap_empty_p (ssa_edge_worklist_back))
775 break;
776
777 if (dump_file && (dump_flags & TDF_DETAILS))
778 fprintf (dump_file, "Regular worklists empty, now processing "
779 "backedge destinations\n");
780 std::swap (cfg_blocks, cfg_blocks_back);
781 std::swap (ssa_edge_worklist, ssa_edge_worklist_back);
809 continue; 782 continue;
810 } 783 }
811 784
812 /* Then simulate from the SSA edge worklist. */ 785 int next_stmt_bb_order = -1;
813 process_ssa_edge_worklist (); 786 gimple *next_stmt = NULL;
787 if (next_stmt_uid != -1)
788 {
789 next_stmt = uid_to_stmt[next_stmt_uid];
790 next_stmt_bb_order = bb_to_cfg_order[gimple_bb (next_stmt)->index];
791 }
792
793 /* Pull the next block to simulate off the worklist if it comes first. */
794 if (next_block_order != -1
795 && (next_stmt_bb_order == -1
796 || next_block_order <= next_stmt_bb_order))
797 {
798 curr_order = next_block_order;
799 bitmap_clear_bit (cfg_blocks, next_block_order);
800 basic_block bb
801 = BASIC_BLOCK_FOR_FN (cfun, cfg_order_to_bb [next_block_order]);
802 simulate_block (bb);
803 }
804 /* Else simulate from the SSA edge worklist. */
805 else
806 {
807 curr_order = next_stmt_bb_order;
808 if (dump_file && (dump_flags & TDF_DETAILS))
809 {
810 fprintf (dump_file, "\nSimulating statement: ");
811 print_gimple_stmt (dump_file, next_stmt, 0, dump_flags);
812 }
813 simulate_stmt (next_stmt);
814 }
814 } 815 }
815 816
816 ssa_prop_fini (); 817 ssa_prop_fini ();
817 } 818 }
818 819
859 860
860 /* Replace USE references in statement STMT with the values stored in 861 /* Replace USE references in statement STMT with the values stored in
861 PROP_VALUE. Return true if at least one reference was replaced. */ 862 PROP_VALUE. Return true if at least one reference was replaced. */
862 863
863 bool 864 bool
864 replace_uses_in (gimple *stmt, ssa_prop_get_value_fn get_value) 865 substitute_and_fold_engine::replace_uses_in (gimple *stmt)
865 { 866 {
866 bool replaced = false; 867 bool replaced = false;
867 use_operand_p use; 868 use_operand_p use;
868 ssa_op_iter iter; 869 ssa_op_iter iter;
869 870
870 FOR_EACH_SSA_USE_OPERAND (use, stmt, iter, SSA_OP_USE) 871 FOR_EACH_SSA_USE_OPERAND (use, stmt, iter, SSA_OP_USE)
871 { 872 {
872 tree tuse = USE_FROM_PTR (use); 873 tree tuse = USE_FROM_PTR (use);
873 tree val = (*get_value) (tuse); 874 tree val = get_value (tuse);
874 875
875 if (val == tuse || val == NULL_TREE) 876 if (val == tuse || val == NULL_TREE)
876 continue; 877 continue;
877 878
878 if (gimple_code (stmt) == GIMPLE_ASM 879 if (gimple_code (stmt) == GIMPLE_ASM
897 898
898 899
899 /* Replace propagated values into all the arguments for PHI using the 900 /* Replace propagated values into all the arguments for PHI using the
900 values from PROP_VALUE. */ 901 values from PROP_VALUE. */
901 902
902 static bool 903 bool
903 replace_phi_args_in (gphi *phi, ssa_prop_get_value_fn get_value) 904 substitute_and_fold_engine::replace_phi_args_in (gphi *phi)
904 { 905 {
905 size_t i; 906 size_t i;
906 bool replaced = false; 907 bool replaced = false;
907 908
908 if (dump_file && (dump_flags & TDF_DETAILS)) 909 if (dump_file && (dump_flags & TDF_DETAILS))
915 { 916 {
916 tree arg = gimple_phi_arg_def (phi, i); 917 tree arg = gimple_phi_arg_def (phi, i);
917 918
918 if (TREE_CODE (arg) == SSA_NAME) 919 if (TREE_CODE (arg) == SSA_NAME)
919 { 920 {
920 tree val = (*get_value) (arg); 921 tree val = get_value (arg);
921 922
922 if (val && val != arg && may_propagate_copy (arg, val)) 923 if (val && val != arg && may_propagate_copy (arg, val))
923 { 924 {
924 edge e = gimple_phi_arg_edge (phi, i); 925 edge e = gimple_phi_arg_edge (phi, i);
925 926
966 967
967 class substitute_and_fold_dom_walker : public dom_walker 968 class substitute_and_fold_dom_walker : public dom_walker
968 { 969 {
969 public: 970 public:
970 substitute_and_fold_dom_walker (cdi_direction direction, 971 substitute_and_fold_dom_walker (cdi_direction direction,
971 ssa_prop_get_value_fn get_value_fn_, 972 class substitute_and_fold_engine *engine)
972 ssa_prop_fold_stmt_fn fold_fn_) 973 : dom_walker (direction),
973 : dom_walker (direction), get_value_fn (get_value_fn_), 974 something_changed (false),
974 fold_fn (fold_fn_), something_changed (false) 975 substitute_and_fold_engine (engine)
975 { 976 {
976 stmts_to_remove.create (0); 977 stmts_to_remove.create (0);
977 stmts_to_fixup.create (0); 978 stmts_to_fixup.create (0);
978 need_eh_cleanup = BITMAP_ALLOC (NULL); 979 need_eh_cleanup = BITMAP_ALLOC (NULL);
979 } 980 }
985 } 986 }
986 987
987 virtual edge before_dom_children (basic_block); 988 virtual edge before_dom_children (basic_block);
988 virtual void after_dom_children (basic_block) {} 989 virtual void after_dom_children (basic_block) {}
989 990
990 ssa_prop_get_value_fn get_value_fn;
991 ssa_prop_fold_stmt_fn fold_fn;
992 bool something_changed; 991 bool something_changed;
993 vec<gimple *> stmts_to_remove; 992 vec<gimple *> stmts_to_remove;
994 vec<gimple *> stmts_to_fixup; 993 vec<gimple *> stmts_to_fixup;
995 bitmap need_eh_cleanup; 994 bitmap need_eh_cleanup;
995
996 class substitute_and_fold_engine *substitute_and_fold_engine;
996 }; 997 };
997 998
998 edge 999 edge
999 substitute_and_fold_dom_walker::before_dom_children (basic_block bb) 1000 substitute_and_fold_dom_walker::before_dom_children (basic_block bb)
1000 { 1001 {
1007 tree res = gimple_phi_result (phi); 1008 tree res = gimple_phi_result (phi);
1008 if (virtual_operand_p (res)) 1009 if (virtual_operand_p (res))
1009 continue; 1010 continue;
1010 if (res && TREE_CODE (res) == SSA_NAME) 1011 if (res && TREE_CODE (res) == SSA_NAME)
1011 { 1012 {
1012 tree sprime = get_value_fn (res); 1013 tree sprime = substitute_and_fold_engine->get_value (res);
1013 if (sprime 1014 if (sprime
1014 && sprime != res 1015 && sprime != res
1015 && may_propagate_copy (res, sprime)) 1016 && may_propagate_copy (res, sprime))
1016 { 1017 {
1017 stmts_to_remove.safe_push (phi); 1018 stmts_to_remove.safe_push (phi);
1018 continue; 1019 continue;
1019 } 1020 }
1020 } 1021 }
1021 something_changed |= replace_phi_args_in (phi, get_value_fn); 1022 something_changed |= substitute_and_fold_engine->replace_phi_args_in (phi);
1022 } 1023 }
1023 1024
1024 /* Propagate known values into stmts. In some case it exposes 1025 /* Propagate known values into stmts. In some case it exposes
1025 more trivially deletable stmts to walk backward. */ 1026 more trivially deletable stmts to walk backward. */
1026 for (gimple_stmt_iterator i = gsi_start_bb (bb); 1027 for (gimple_stmt_iterator i = gsi_start_bb (bb);
1033 /* No point propagating into a stmt we have a value for we 1034 /* No point propagating into a stmt we have a value for we
1034 can propagate into all uses. Mark it for removal instead. */ 1035 can propagate into all uses. Mark it for removal instead. */
1035 tree lhs = gimple_get_lhs (stmt); 1036 tree lhs = gimple_get_lhs (stmt);
1036 if (lhs && TREE_CODE (lhs) == SSA_NAME) 1037 if (lhs && TREE_CODE (lhs) == SSA_NAME)
1037 { 1038 {
1038 tree sprime = get_value_fn (lhs); 1039 tree sprime = substitute_and_fold_engine->get_value (lhs);
1039 if (sprime 1040 if (sprime
1040 && sprime != lhs 1041 && sprime != lhs
1041 && may_propagate_copy (lhs, sprime) 1042 && may_propagate_copy (lhs, sprime)
1042 && !stmt_could_throw_p (stmt) 1043 && !stmt_could_throw_p (cfun, stmt)
1043 && !gimple_has_side_effects (stmt) 1044 && !gimple_has_side_effects (stmt)
1044 /* We have to leave ASSERT_EXPRs around for jump-threading. */ 1045 /* We have to leave ASSERT_EXPRs around for jump-threading. */
1045 && (!is_gimple_assign (stmt) 1046 && (!is_gimple_assign (stmt)
1046 || gimple_assign_rhs_code (stmt) != ASSERT_EXPR)) 1047 || gimple_assign_rhs_code (stmt) != ASSERT_EXPR))
1047 { 1048 {
1062 gimple *old_stmt = stmt; 1063 gimple *old_stmt = stmt;
1063 bool was_noreturn = (is_gimple_call (stmt) 1064 bool was_noreturn = (is_gimple_call (stmt)
1064 && gimple_call_noreturn_p (stmt)); 1065 && gimple_call_noreturn_p (stmt));
1065 1066
1066 /* Replace real uses in the statement. */ 1067 /* Replace real uses in the statement. */
1067 did_replace |= replace_uses_in (stmt, get_value_fn); 1068 did_replace |= substitute_and_fold_engine->replace_uses_in (stmt);
1068 1069
1069 /* If we made a replacement, fold the statement. */ 1070 /* If we made a replacement, fold the statement. */
1070 if (did_replace) 1071 if (did_replace)
1071 { 1072 {
1072 fold_stmt (&i, follow_single_use_edges); 1073 fold_stmt (&i, follow_single_use_edges);
1075 } 1076 }
1076 1077
1077 /* Some statements may be simplified using propagator 1078 /* Some statements may be simplified using propagator
1078 specific information. Do this before propagating 1079 specific information. Do this before propagating
1079 into the stmt to not disturb pass specific information. */ 1080 into the stmt to not disturb pass specific information. */
1080 if (fold_fn) 1081 update_stmt_if_modified (stmt);
1081 { 1082 if (substitute_and_fold_engine->fold_stmt(&i))
1082 update_stmt_if_modified (stmt); 1083 {
1083 if ((*fold_fn)(&i)) 1084 did_replace = true;
1084 { 1085 prop_stats.num_stmts_folded++;
1085 did_replace = true; 1086 stmt = gsi_stmt (i);
1086 prop_stats.num_stmts_folded++; 1087 gimple_set_modified (stmt, true);
1087 stmt = gsi_stmt (i);
1088 gimple_set_modified (stmt, true);
1089 }
1090 } 1088 }
1091 1089
1092 /* If this is a control statement the propagator left edges 1090 /* If this is a control statement the propagator left edges
1093 unexecuted on force the condition in a way consistent with 1091 unexecuted on force the condition in a way consistent with
1094 that. See PR66945 for cases where the propagator can end 1092 that. See PR66945 for cases where the propagator can end
1170 last to first element. Otherwise we scan from first to last element. 1168 last to first element. Otherwise we scan from first to last element.
1171 1169
1172 Return TRUE when something changed. */ 1170 Return TRUE when something changed. */
1173 1171
1174 bool 1172 bool
1175 substitute_and_fold (ssa_prop_get_value_fn get_value_fn, 1173 substitute_and_fold_engine::substitute_and_fold (void)
1176 ssa_prop_fold_stmt_fn fold_fn) 1174 {
1177 {
1178 gcc_assert (get_value_fn);
1179
1180 if (dump_file && (dump_flags & TDF_DETAILS)) 1175 if (dump_file && (dump_flags & TDF_DETAILS))
1181 fprintf (dump_file, "\nSubstituting values and folding statements\n\n"); 1176 fprintf (dump_file, "\nSubstituting values and folding statements\n\n");
1182 1177
1183 memset (&prop_stats, 0, sizeof (prop_stats)); 1178 memset (&prop_stats, 0, sizeof (prop_stats));
1184 1179
1185 calculate_dominance_info (CDI_DOMINATORS); 1180 calculate_dominance_info (CDI_DOMINATORS);
1186 substitute_and_fold_dom_walker walker(CDI_DOMINATORS, 1181 substitute_and_fold_dom_walker walker (CDI_DOMINATORS, this);
1187 get_value_fn, fold_fn);
1188 walker.walk (ENTRY_BLOCK_PTR_FOR_FN (cfun)); 1182 walker.walk (ENTRY_BLOCK_PTR_FOR_FN (cfun));
1189 1183
1190 /* We cannot remove stmts during the BB walk, especially not release 1184 /* We cannot remove stmts during the BB walk, especially not release
1191 SSA names there as that destroys the lattice of our callers. 1185 SSA names there as that destroys the lattice of our callers.
1192 Remove stmts in reverse order to make debug stmt creation possible. */ 1186 Remove stmts in reverse order to make debug stmt creation possible. */