comparison gcc/fwprop.c @ 14:f6334be47118

update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
author nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
date Tue, 22 Mar 2011 17:18:12 +0900
parents b7f97abdc517
children 04ced10e8804
comparison
equal deleted inserted replaced
13:65488c3d617d 14:f6334be47118
1 /* RTL-based forward propagation pass for GNU compiler. 1 /* RTL-based forward propagation pass for GNU compiler.
2 Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010 2 Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011
3 Free Software Foundation, Inc. 3 Free Software Foundation, Inc.
4 Contributed by Paolo Bonzini and Steven Bosscher. 4 Contributed by Paolo Bonzini and Steven Bosscher.
5 5
6 This file is part of GCC. 6 This file is part of GCC.
7 7
21 21
22 #include "config.h" 22 #include "config.h"
23 #include "system.h" 23 #include "system.h"
24 #include "coretypes.h" 24 #include "coretypes.h"
25 #include "tm.h" 25 #include "tm.h"
26 #include "toplev.h" 26 #include "diagnostic-core.h"
27 27
28 #include "sparseset.h"
28 #include "timevar.h" 29 #include "timevar.h"
29 #include "rtl.h" 30 #include "rtl.h"
30 #include "tm_p.h" 31 #include "tm_p.h"
31 #include "emit-rtl.h"
32 #include "insn-config.h" 32 #include "insn-config.h"
33 #include "recog.h" 33 #include "recog.h"
34 #include "flags.h" 34 #include "flags.h"
35 #include "obstack.h" 35 #include "obstack.h"
36 #include "basic-block.h" 36 #include "basic-block.h"
38 #include "df.h" 38 #include "df.h"
39 #include "target.h" 39 #include "target.h"
40 #include "cfgloop.h" 40 #include "cfgloop.h"
41 #include "tree-pass.h" 41 #include "tree-pass.h"
42 #include "domwalk.h" 42 #include "domwalk.h"
43 #include "emit-rtl.h"
43 44
44 45
45 /* This pass does simple forward propagation and simplification when an 46 /* This pass does simple forward propagation and simplification when an
46 operand of an insn can only come from a single def. This pass uses 47 operand of an insn can only come from a single def. This pass uses
47 df.c, so it is global. However, we only do limited analysis of 48 df.c, so it is global. However, we only do limited analysis of
218 int bb_index = bb->index; 219 int bb_index = bb->index;
219 struct df_md_bb_info *md_bb_info = df_md_get_bb_info (bb_index); 220 struct df_md_bb_info *md_bb_info = df_md_get_bb_info (bb_index);
220 struct df_lr_bb_info *lr_bb_info = df_lr_get_bb_info (bb_index); 221 struct df_lr_bb_info *lr_bb_info = df_lr_get_bb_info (bb_index);
221 rtx insn; 222 rtx insn;
222 223
223 bitmap_copy (local_md, md_bb_info->in); 224 bitmap_copy (local_md, &md_bb_info->in);
224 bitmap_copy (local_lr, lr_bb_info->in); 225 bitmap_copy (local_lr, &lr_bb_info->in);
225 226
226 /* Push a marker for the leave_block callback. */ 227 /* Push a marker for the leave_block callback. */
227 VEC_safe_push (df_ref, heap, reg_defs_stack, NULL); 228 VEC_safe_push (df_ref, heap, reg_defs_stack, NULL);
228 229
229 process_uses (df_get_artificial_uses (bb_index), DF_REF_AT_TOP); 230 process_uses (df_get_artificial_uses (bb_index), DF_REF_AT_TOP);
846 847
847 return true; 848 return true;
848 } 849 }
849 850
850 851
851 struct find_occurrence_data 852 static df_ref *active_defs;
852 { 853 #ifdef ENABLE_CHECKING
853 rtx find; 854 static sparseset active_defs_check;
854 rtx *retval; 855 #endif
855 }; 856
856 857 /* Fill the ACTIVE_DEFS array with the use->def link for the registers
857 /* Callback for for_each_rtx, used in find_occurrence. 858 mentioned in USE_REC. Register the valid entries in ACTIVE_DEFS_CHECK
858 See if PX is the rtx we have to find. Return 1 to stop for_each_rtx 859 too, for checking purposes. */
859 if successful, or 0 to continue traversing otherwise. */ 860
860
861 static int
862 find_occurrence_callback (rtx *px, void *data)
863 {
864 struct find_occurrence_data *fod = (struct find_occurrence_data *) data;
865 rtx x = *px;
866 rtx find = fod->find;
867
868 if (x == find)
869 {
870 fod->retval = px;
871 return 1;
872 }
873
874 return 0;
875 }
876
877 /* Return a pointer to one of the occurrences of register FIND in *PX. */
878
879 static rtx *
880 find_occurrence (rtx *px, rtx find)
881 {
882 struct find_occurrence_data data;
883
884 gcc_assert (REG_P (find)
885 || (GET_CODE (find) == SUBREG
886 && REG_P (SUBREG_REG (find))));
887
888 data.find = find;
889 data.retval = NULL;
890 for_each_rtx (px, find_occurrence_callback, &data);
891 return data.retval;
892 }
893
894
895 /* Inside INSN, the expression rooted at *LOC has been changed, moving some
896 uses from USE_VEC. Find those that are present, and create new items
897 in the data flow object of the pass. Mark any new uses as having the
898 given TYPE. */
899 static void 861 static void
900 update_df (rtx insn, rtx *loc, df_ref *use_rec, enum df_ref_type type, 862 register_active_defs (df_ref *use_rec)
901 int new_flags) 863 {
902 {
903 bool changed = false;
904
905 /* Add a use for the registers that were propagated. */
906 while (*use_rec) 864 while (*use_rec)
907 { 865 {
908 df_ref use = *use_rec; 866 df_ref use = *use_rec++;
909 df_ref orig_use = use, new_use; 867 df_ref def = get_def_for_use (use);
910 int width = -1; 868 int regno = DF_REF_REGNO (use);
911 int offset = -1; 869
912 enum machine_mode mode = VOIDmode; 870 #ifdef ENABLE_CHECKING
913 rtx *new_loc = find_occurrence (loc, DF_REF_REG (orig_use)); 871 sparseset_set_bit (active_defs_check, regno);
914 use_rec++; 872 #endif
915 873 active_defs[regno] = def;
916 if (!new_loc) 874 }
917 continue; 875 }
918 876
919 if (DF_REF_FLAGS_IS_SET (orig_use, DF_REF_SIGN_EXTRACT | DF_REF_ZERO_EXTRACT)) 877
920 { 878 /* Build the use->def links that we use to update the dataflow info
921 width = DF_REF_EXTRACT_WIDTH (orig_use); 879 for new uses. Note that building the links is very cheap and if
922 offset = DF_REF_EXTRACT_OFFSET (orig_use); 880 it were done earlier, they could be used to rule out invalid
923 mode = DF_REF_EXTRACT_MODE (orig_use); 881 propagations (in addition to what is done in all_uses_available_at).
924 } 882 I'm not doing this yet, though. */
925 883
926 /* Add a new insn use. Use the original type, because it says if the 884 static void
927 use was within a MEM. */ 885 update_df_init (rtx def_insn, rtx insn)
928 new_use = df_ref_create (DF_REF_REG (orig_use), new_loc, 886 {
929 insn, BLOCK_FOR_INSN (insn), 887 #ifdef ENABLE_CHECKING
930 type, DF_REF_FLAGS (orig_use) | new_flags, 888 sparseset_clear (active_defs_check);
931 width, offset, mode); 889 #endif
890 register_active_defs (DF_INSN_USES (def_insn));
891 register_active_defs (DF_INSN_USES (insn));
892 register_active_defs (DF_INSN_EQ_USES (insn));
893 }
894
895
896 /* Update the USE_DEF_REF array for the given use, using the active definitions
897 in the ACTIVE_DEFS array to match pseudos to their def. */
898
899 static inline void
900 update_uses (df_ref *use_rec)
901 {
902 while (*use_rec)
903 {
904 df_ref use = *use_rec++;
905 int regno = DF_REF_REGNO (use);
932 906
933 /* Set up the use-def chain. */ 907 /* Set up the use-def chain. */
934 gcc_assert (DF_REF_ID (new_use) == (int) VEC_length (df_ref, use_def_ref)); 908 if (DF_REF_ID (use) >= (int) VEC_length (df_ref, use_def_ref))
935 VEC_safe_push (df_ref, heap, use_def_ref, get_def_for_use (orig_use)); 909 VEC_safe_grow_cleared (df_ref, heap, use_def_ref,
936 changed = true; 910 DF_REF_ID (use) + 1);
937 } 911
938 if (changed) 912 #ifdef ENABLE_CHECKING
939 df_insn_rescan (insn); 913 gcc_assert (sparseset_bit_p (active_defs_check, regno));
914 #endif
915 VEC_replace (df_ref, use_def_ref, DF_REF_ID (use), active_defs[regno]);
916 }
917 }
918
919
920 /* Update the USE_DEF_REF array for the uses in INSN. Only update note
921 uses if NOTES_ONLY is true. */
922
923 static void
924 update_df (rtx insn, rtx note)
925 {
926 struct df_insn_info *insn_info = DF_INSN_INFO_GET (insn);
927
928 if (note)
929 {
930 df_uses_create (&XEXP (note, 0), insn, DF_REF_IN_NOTE);
931 df_notes_rescan (insn);
932 }
933 else
934 {
935 df_uses_create (&PATTERN (insn), insn, 0);
936 df_insn_rescan (insn);
937 update_uses (DF_INSN_INFO_USES (insn_info));
938 }
939
940 update_uses (DF_INSN_INFO_EQ_USES (insn_info));
940 } 941 }
941 942
942 943
943 /* Try substituting NEW into LOC, which originated from forward propagation 944 /* Try substituting NEW into LOC, which originated from forward propagation
944 of USE's value from DEF_INSN. SET_REG_EQUAL says whether we are 945 of USE's value from DEF_INSN. SET_REG_EQUAL says whether we are
948 949
949 static bool 950 static bool
950 try_fwprop_subst (df_ref use, rtx *loc, rtx new_rtx, rtx def_insn, bool set_reg_equal) 951 try_fwprop_subst (df_ref use, rtx *loc, rtx new_rtx, rtx def_insn, bool set_reg_equal)
951 { 952 {
952 rtx insn = DF_REF_INSN (use); 953 rtx insn = DF_REF_INSN (use);
953 enum df_ref_type type = DF_REF_TYPE (use);
954 int flags = DF_REF_FLAGS (use);
955 rtx set = single_set (insn); 954 rtx set = single_set (insn);
955 rtx note = NULL_RTX;
956 bool speed = optimize_bb_for_speed_p (BLOCK_FOR_INSN (insn)); 956 bool speed = optimize_bb_for_speed_p (BLOCK_FOR_INSN (insn));
957 int old_cost = 0; 957 int old_cost = 0;
958 bool ok; 958 bool ok;
959
960 update_df_init (def_insn, insn);
959 961
960 /* forward_propagate_subreg may be operating on an instruction with 962 /* forward_propagate_subreg may be operating on an instruction with
961 multiple sets. If so, assume the cost of the new instruction is 963 multiple sets. If so, assume the cost of the new instruction is
962 not greater than the old one. */ 964 not greater than the old one. */
963 if (set) 965 if (set)
999 1001
1000 if (ok) 1002 if (ok)
1001 { 1003 {
1002 confirm_change_group (); 1004 confirm_change_group ();
1003 num_changes++; 1005 num_changes++;
1004
1005 df_ref_remove (use);
1006 if (!CONSTANT_P (new_rtx))
1007 {
1008 struct df_insn_info *insn_info = DF_INSN_INFO_GET (def_insn);
1009 update_df (insn, loc, DF_INSN_INFO_USES (insn_info), type, flags);
1010 update_df (insn, loc, DF_INSN_INFO_EQ_USES (insn_info), type, flags);
1011 }
1012 } 1006 }
1013 else 1007 else
1014 { 1008 {
1015 cancel_changes (0); 1009 cancel_changes (0);
1016 1010
1019 if (set_reg_equal) 1013 if (set_reg_equal)
1020 { 1014 {
1021 if (dump_file) 1015 if (dump_file)
1022 fprintf (dump_file, " Setting REG_EQUAL note\n"); 1016 fprintf (dump_file, " Setting REG_EQUAL note\n");
1023 1017
1024 set_unique_reg_note (insn, REG_EQUAL, copy_rtx (new_rtx)); 1018 note = set_unique_reg_note (insn, REG_EQUAL, copy_rtx (new_rtx));
1025
1026 /* ??? Is this still necessary if we add the note through
1027 set_unique_reg_note? */
1028 if (!CONSTANT_P (new_rtx))
1029 {
1030 struct df_insn_info *insn_info = DF_INSN_INFO_GET (def_insn);
1031 update_df (insn, loc, DF_INSN_INFO_USES (insn_info),
1032 type, DF_REF_IN_NOTE);
1033 update_df (insn, loc, DF_INSN_INFO_EQ_USES (insn_info),
1034 type, DF_REF_IN_NOTE);
1035 }
1036 } 1019 }
1037 } 1020 }
1021
1022 if ((ok || note) && !CONSTANT_P (new_rtx))
1023 update_df (insn, note);
1038 1024
1039 return ok; 1025 return ok;
1040 } 1026 }
1041 1027
1042 /* For the given single_set INSN, containing SRC known to be a 1028 /* For the given single_set INSN, containing SRC known to be a
1161 reg, as that could increase register pressure on the __asm. */ 1147 reg, as that could increase register pressure on the __asm. */
1162 use_vec = DF_INSN_USES (def_insn); 1148 use_vec = DF_INSN_USES (def_insn);
1163 if (use_vec[0] && use_vec[1]) 1149 if (use_vec[0] && use_vec[1])
1164 return false; 1150 return false;
1165 1151
1152 update_df_init (def_insn, use_insn);
1166 speed_p = optimize_bb_for_speed_p (BLOCK_FOR_INSN (use_insn)); 1153 speed_p = optimize_bb_for_speed_p (BLOCK_FOR_INSN (use_insn));
1167 asm_operands = NULL_RTX; 1154 asm_operands = NULL_RTX;
1168 switch (GET_CODE (use_pat)) 1155 switch (GET_CODE (use_pat))
1169 { 1156 {
1170 case ASM_OPERANDS: 1157 case ASM_OPERANDS:
1211 } 1198 }
1212 1199
1213 if (num_changes_pending () == 0 || !apply_change_group ()) 1200 if (num_changes_pending () == 0 || !apply_change_group ())
1214 return false; 1201 return false;
1215 1202
1203 update_df (use_insn, NULL);
1216 num_changes++; 1204 num_changes++;
1217 return true; 1205 return true;
1218 } 1206 }
1219 1207
1220 /* Try to replace USE with SRC (defined in DEF_INSN) and simplify the 1208 /* Try to replace USE with SRC (defined in DEF_INSN) and simplify the
1302 loc = &XEXP (note, 0); 1290 loc = &XEXP (note, 0);
1303 else 1291 else
1304 loc = &SET_SRC (use_set); 1292 loc = &SET_SRC (use_set);
1305 1293
1306 /* Do not replace an existing REG_EQUAL note if the insn is not 1294 /* Do not replace an existing REG_EQUAL note if the insn is not
1307 recognized. Either we're already replacing in the note, or 1295 recognized. Either we're already replacing in the note, or we'll
1308 we'll separately try plugging the definition in the note and 1296 separately try plugging the definition in the note and simplifying.
1309 simplifying. */ 1297 And only install a REQ_EQUAL note when the destination is a REG,
1310 set_reg_equal = (note == NULL_RTX); 1298 as the note would be invalid otherwise. */
1299 set_reg_equal = (note == NULL_RTX && REG_P (SET_DEST (use_set)));
1311 } 1300 }
1312 1301
1313 if (GET_MODE (*loc) == VOIDmode) 1302 if (GET_MODE (*loc) == VOIDmode)
1314 mode = GET_MODE (SET_DEST (use_set)); 1303 mode = GET_MODE (SET_DEST (use_set));
1315 else 1304 else
1324 return try_fwprop_subst (use, loc, new_rtx, def_insn, set_reg_equal); 1313 return try_fwprop_subst (use, loc, new_rtx, def_insn, set_reg_equal);
1325 } 1314 }
1326 1315
1327 1316
1328 /* Given a use USE of an insn, if it has a single reaching 1317 /* Given a use USE of an insn, if it has a single reaching
1329 definition, try to forward propagate it into that insn. */ 1318 definition, try to forward propagate it into that insn.
1330 1319 Return true if cfg cleanup will be needed. */
1331 static void 1320
1321 static bool
1332 forward_propagate_into (df_ref use) 1322 forward_propagate_into (df_ref use)
1333 { 1323 {
1334 df_ref def; 1324 df_ref def;
1335 rtx def_insn, def_set, use_insn; 1325 rtx def_insn, def_set, use_insn;
1336 rtx parent; 1326 rtx parent;
1337 1327
1338 if (DF_REF_FLAGS (use) & DF_REF_READ_WRITE) 1328 if (DF_REF_FLAGS (use) & DF_REF_READ_WRITE)
1339 return; 1329 return false;
1340 if (DF_REF_IS_ARTIFICIAL (use)) 1330 if (DF_REF_IS_ARTIFICIAL (use))
1341 return; 1331 return false;
1342 1332
1343 /* Only consider uses that have a single definition. */ 1333 /* Only consider uses that have a single definition. */
1344 def = get_def_for_use (use); 1334 def = get_def_for_use (use);
1345 if (!def) 1335 if (!def)
1346 return; 1336 return false;
1347 if (DF_REF_FLAGS (def) & DF_REF_READ_WRITE) 1337 if (DF_REF_FLAGS (def) & DF_REF_READ_WRITE)
1348 return; 1338 return false;
1349 if (DF_REF_IS_ARTIFICIAL (def)) 1339 if (DF_REF_IS_ARTIFICIAL (def))
1350 return; 1340 return false;
1351 1341
1352 /* Do not propagate loop invariant definitions inside the loop. */ 1342 /* Do not propagate loop invariant definitions inside the loop. */
1353 if (DF_REF_BB (def)->loop_father != DF_REF_BB (use)->loop_father) 1343 if (DF_REF_BB (def)->loop_father != DF_REF_BB (use)->loop_father)
1354 return; 1344 return false;
1355 1345
1356 /* Check if the use is still present in the insn! */ 1346 /* Check if the use is still present in the insn! */
1357 use_insn = DF_REF_INSN (use); 1347 use_insn = DF_REF_INSN (use);
1358 if (DF_REF_FLAGS (use) & DF_REF_IN_NOTE) 1348 if (DF_REF_FLAGS (use) & DF_REF_IN_NOTE)
1359 parent = find_reg_note (use_insn, REG_EQUAL, NULL_RTX); 1349 parent = find_reg_note (use_insn, REG_EQUAL, NULL_RTX);
1360 else 1350 else
1361 parent = PATTERN (use_insn); 1351 parent = PATTERN (use_insn);
1362 1352
1363 if (!reg_mentioned_p (DF_REF_REG (use), parent)) 1353 if (!reg_mentioned_p (DF_REF_REG (use), parent))
1364 return; 1354 return false;
1365 1355
1366 def_insn = DF_REF_INSN (def); 1356 def_insn = DF_REF_INSN (def);
1367 if (multiple_sets (def_insn)) 1357 if (multiple_sets (def_insn))
1368 return; 1358 return false;
1369 def_set = single_set (def_insn); 1359 def_set = single_set (def_insn);
1370 if (!def_set) 1360 if (!def_set)
1371 return; 1361 return false;
1372 1362
1373 /* Only try one kind of propagation. If two are possible, we'll 1363 /* Only try one kind of propagation. If two are possible, we'll
1374 do it on the following iterations. */ 1364 do it on the following iterations. */
1375 if (!forward_propagate_and_simplify (use, def_insn, def_set)) 1365 if (forward_propagate_and_simplify (use, def_insn, def_set)
1376 forward_propagate_subreg (use, def_insn, def_set); 1366 || forward_propagate_subreg (use, def_insn, def_set))
1367 {
1368 if (cfun->can_throw_non_call_exceptions
1369 && find_reg_note (use_insn, REG_EH_REGION, NULL_RTX)
1370 && purge_dead_edges (DF_REF_BB (use)))
1371 return true;
1372 }
1373 return false;
1377 } 1374 }
1378 1375
1379 1376
1380 static void 1377 static void
1381 fwprop_init (void) 1378 fwprop_init (void)
1389 insns (sadly) if we are not working in cfglayout mode. */ 1386 insns (sadly) if we are not working in cfglayout mode. */
1390 loop_optimizer_init (0); 1387 loop_optimizer_init (0);
1391 1388
1392 build_single_def_use_links (); 1389 build_single_def_use_links ();
1393 df_set_flags (DF_DEFER_INSN_RESCAN); 1390 df_set_flags (DF_DEFER_INSN_RESCAN);
1391
1392 active_defs = XNEWVEC (df_ref, max_reg_num ());
1393 #ifdef ENABLE_CHECKING
1394 active_defs_check = sparseset_alloc (max_reg_num ());
1395 #endif
1394 } 1396 }
1395 1397
1396 static void 1398 static void
1397 fwprop_done (void) 1399 fwprop_done (void)
1398 { 1400 {
1399 loop_optimizer_finalize (); 1401 loop_optimizer_finalize ();
1400 1402
1401 VEC_free (df_ref, heap, use_def_ref); 1403 VEC_free (df_ref, heap, use_def_ref);
1404 free (active_defs);
1405 #ifdef ENABLE_CHECKING
1406 sparseset_free (active_defs_check);
1407 #endif
1408
1402 free_dominance_info (CDI_DOMINATORS); 1409 free_dominance_info (CDI_DOMINATORS);
1403 cleanup_cfg (0); 1410 cleanup_cfg (0);
1404 delete_trivially_dead_insns (get_insns (), max_reg_num ()); 1411 delete_trivially_dead_insns (get_insns (), max_reg_num ());
1405 1412
1406 if (dump_file) 1413 if (dump_file)
1420 1427
1421 static unsigned int 1428 static unsigned int
1422 fwprop (void) 1429 fwprop (void)
1423 { 1430 {
1424 unsigned i; 1431 unsigned i;
1432 bool need_cleanup = false;
1425 1433
1426 fwprop_init (); 1434 fwprop_init ();
1427 1435
1428 /* Go through all the uses. update_df will create new ones at the 1436 /* Go through all the uses. df_uses_create will create new ones at the
1429 end, and we'll go through them as well. 1437 end, and we'll go through them as well.
1430 1438
1431 Do not forward propagate addresses into loops until after unrolling. 1439 Do not forward propagate addresses into loops until after unrolling.
1432 CSE did so because it was able to fix its own mess, but we are not. */ 1440 CSE did so because it was able to fix its own mess, but we are not. */
1433 1441
1437 if (use) 1445 if (use)
1438 if (DF_REF_TYPE (use) == DF_REF_REG_USE 1446 if (DF_REF_TYPE (use) == DF_REF_REG_USE
1439 || DF_REF_BB (use)->loop_father == NULL 1447 || DF_REF_BB (use)->loop_father == NULL
1440 /* The outer most loop is not really a loop. */ 1448 /* The outer most loop is not really a loop. */
1441 || loop_outer (DF_REF_BB (use)->loop_father) == NULL) 1449 || loop_outer (DF_REF_BB (use)->loop_father) == NULL)
1442 forward_propagate_into (use); 1450 need_cleanup |= forward_propagate_into (use);
1443 } 1451 }
1444 1452
1445 fwprop_done (); 1453 fwprop_done ();
1454 if (need_cleanup)
1455 cleanup_cfg (0);
1446 return 0; 1456 return 0;
1447 } 1457 }
1448 1458
1449 struct rtl_opt_pass pass_rtl_fwprop = 1459 struct rtl_opt_pass pass_rtl_fwprop =
1450 { 1460 {
1459 TV_FWPROP, /* tv_id */ 1469 TV_FWPROP, /* tv_id */
1460 0, /* properties_required */ 1470 0, /* properties_required */
1461 0, /* properties_provided */ 1471 0, /* properties_provided */
1462 0, /* properties_destroyed */ 1472 0, /* properties_destroyed */
1463 0, /* todo_flags_start */ 1473 0, /* todo_flags_start */
1464 TODO_df_finish | TODO_verify_rtl_sharing | 1474 TODO_df_finish
1465 TODO_dump_func /* todo_flags_finish */ 1475 | TODO_verify_flow
1476 | TODO_verify_rtl_sharing
1477 | TODO_dump_func /* todo_flags_finish */
1466 } 1478 }
1467 }; 1479 };
1468 1480
1469 static unsigned int 1481 static unsigned int
1470 fwprop_addr (void) 1482 fwprop_addr (void)
1471 { 1483 {
1472 unsigned i; 1484 unsigned i;
1485 bool need_cleanup = false;
1486
1473 fwprop_init (); 1487 fwprop_init ();
1474 1488
1475 /* Go through all the uses. update_df will create new ones at the 1489 /* Go through all the uses. df_uses_create will create new ones at the
1476 end, and we'll go through them as well. */ 1490 end, and we'll go through them as well. */
1477 for (i = 0; i < DF_USES_TABLE_SIZE (); i++) 1491 for (i = 0; i < DF_USES_TABLE_SIZE (); i++)
1478 { 1492 {
1479 df_ref use = DF_USES_GET (i); 1493 df_ref use = DF_USES_GET (i);
1480 if (use) 1494 if (use)
1481 if (DF_REF_TYPE (use) != DF_REF_REG_USE 1495 if (DF_REF_TYPE (use) != DF_REF_REG_USE
1482 && DF_REF_BB (use)->loop_father != NULL 1496 && DF_REF_BB (use)->loop_father != NULL
1483 /* The outer most loop is not really a loop. */ 1497 /* The outer most loop is not really a loop. */
1484 && loop_outer (DF_REF_BB (use)->loop_father) != NULL) 1498 && loop_outer (DF_REF_BB (use)->loop_father) != NULL)
1485 forward_propagate_into (use); 1499 need_cleanup |= forward_propagate_into (use);
1486 } 1500 }
1487 1501
1488 fwprop_done (); 1502 fwprop_done ();
1489 1503
1504 if (need_cleanup)
1505 cleanup_cfg (0);
1490 return 0; 1506 return 0;
1491 } 1507 }
1492 1508
1493 struct rtl_opt_pass pass_rtl_fwprop_addr = 1509 struct rtl_opt_pass pass_rtl_fwprop_addr =
1494 { 1510 {