00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "config.h"
00022 #include "system.h"
00023 #include "coretypes.h"
00024 #include "tm.h"
00025 #include "tree.h"
00026 #include "rtl.h"
00027 #include "tm_p.h"
00028 #include "hard-reg-set.h"
00029 #include "basic-block.h"
00030 #include "output.h"
00031 #include "diagnostic.h"
00032 #include "tree-flow.h"
00033 #include "tree-dump.h"
00034 #include "tree-pass.h"
00035 #include "timevar.h"
00036 #include "cfgloop.h"
00037 #include "tree-inline.h"
00038 #include "flags.h"
00039 #include "tree-inline.h"
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050 static bool
00051 should_duplicate_loop_header_p (basic_block header, struct loop *loop,
00052 int *limit)
00053 {
00054 block_stmt_iterator bsi;
00055 tree last;
00056
00057
00058
00059 if (header->aux)
00060 return false;
00061
00062 gcc_assert (EDGE_COUNT (header->succs) > 0);
00063 if (single_succ_p (header))
00064 return false;
00065 if (flow_bb_inside_loop_p (loop, EDGE_SUCC (header, 0)->dest)
00066 && flow_bb_inside_loop_p (loop, EDGE_SUCC (header, 1)->dest))
00067 return false;
00068
00069
00070
00071 if (header != loop->header && !single_pred_p (header))
00072 return false;
00073
00074 last = last_stmt (header);
00075 if (TREE_CODE (last) != COND_EXPR)
00076 return false;
00077
00078
00079
00080 for (bsi = bsi_start (header); !bsi_end_p (bsi); bsi_next (&bsi))
00081 {
00082 last = bsi_stmt (bsi);
00083
00084 if (TREE_CODE (last) == LABEL_EXPR)
00085 continue;
00086
00087 if (get_call_expr_in (last))
00088 return false;
00089
00090 *limit -= estimate_num_insns (last);
00091 if (*limit < 0)
00092 return false;
00093 }
00094
00095 return true;
00096 }
00097
00098
00099
00100 static bool
00101 do_while_loop_p (struct loop *loop)
00102 {
00103 tree stmt = last_stmt (loop->latch);
00104
00105
00106 if (stmt
00107 && TREE_CODE (stmt) != LABEL_EXPR)
00108 return false;
00109
00110
00111 stmt = last_and_only_stmt (loop->header);
00112 if (stmt
00113 && TREE_CODE (stmt) == COND_EXPR)
00114 return false;
00115
00116 return true;
00117 }
00118
00119
00120
00121
00122
00123 static unsigned int
00124 copy_loop_headers (void)
00125 {
00126 struct loops *loops;
00127 unsigned i;
00128 struct loop *loop;
00129 basic_block header;
00130 edge exit, entry;
00131 basic_block *bbs, *copied_bbs;
00132 unsigned n_bbs;
00133 unsigned bbs_size;
00134
00135 loops = loop_optimizer_init (LOOPS_HAVE_PREHEADERS
00136 | LOOPS_HAVE_SIMPLE_LATCHES);
00137 if (!loops)
00138 return 0;
00139
00140 #ifdef ENABLE_CHECKING
00141 verify_loop_structure (loops);
00142 #endif
00143
00144 bbs = XNEWVEC (basic_block, n_basic_blocks);
00145 copied_bbs = XNEWVEC (basic_block, n_basic_blocks);
00146 bbs_size = n_basic_blocks;
00147
00148 for (i = 1; i < loops->num; i++)
00149 {
00150
00151 int limit = 20;
00152
00153 loop = loops->parray[i];
00154 if (!loop)
00155 continue;
00156 header = loop->header;
00157
00158
00159
00160
00161
00162 if (do_while_loop_p (loop))
00163 continue;
00164
00165
00166
00167
00168
00169
00170
00171 exit = NULL;
00172 n_bbs = 0;
00173 while (should_duplicate_loop_header_p (header, loop, &limit))
00174 {
00175
00176
00177 if (flow_bb_inside_loop_p (loop, EDGE_SUCC (header, 0)->dest))
00178 exit = EDGE_SUCC (header, 0);
00179 else
00180 exit = EDGE_SUCC (header, 1);
00181 bbs[n_bbs++] = header;
00182 gcc_assert (bbs_size > n_bbs);
00183 header = exit->dest;
00184 }
00185
00186 if (!exit)
00187 continue;
00188
00189 if (dump_file && (dump_flags & TDF_DETAILS))
00190 fprintf (dump_file,
00191 "Duplicating header of the loop %d up to edge %d->%d.\n",
00192 loop->num, exit->src->index, exit->dest->index);
00193
00194
00195
00196 if (!single_pred_p (exit->dest))
00197 exit = single_pred_edge (loop_split_edge_with (exit, NULL));
00198
00199 entry = loop_preheader_edge (loop);
00200
00201 if (!tree_duplicate_sese_region (entry, exit, bbs, n_bbs, copied_bbs))
00202 {
00203 fprintf (dump_file, "Duplication failed.\n");
00204 continue;
00205 }
00206
00207
00208
00209
00210
00211
00212
00213
00214 if (warn_strict_overflow > 0)
00215 {
00216 unsigned int i;
00217
00218 for (i = 0; i < n_bbs; ++i)
00219 {
00220 tree last;
00221
00222 last = last_stmt (copied_bbs[i]);
00223 if (TREE_CODE (last) == COND_EXPR)
00224 TREE_NO_WARNING (last) = 1;
00225 }
00226 }
00227
00228
00229
00230 loop_split_edge_with (loop_preheader_edge (loop), NULL);
00231 loop_split_edge_with (loop_latch_edge (loop), NULL);
00232 }
00233
00234 free (bbs);
00235 free (copied_bbs);
00236
00237 loop_optimizer_finalize (loops);
00238 return 0;
00239 }
00240
00241 static bool
00242 gate_ch (void)
00243 {
00244 return flag_tree_ch != 0;
00245 }
00246
00247 struct tree_opt_pass pass_ch =
00248 {
00249 "ch",
00250 gate_ch,
00251 copy_loop_headers,
00252 NULL,
00253 NULL,
00254 0,
00255 TV_TREE_CH,
00256 PROP_cfg | PROP_ssa,
00257 0,
00258 0,
00259 0,
00260 TODO_cleanup_cfg | TODO_dump_func
00261 | TODO_verify_ssa,
00262 0
00263 };