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 (EDGE_COUNT (header->succs) == 1)
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 && EDGE_COUNT (header->preds) >= 2)
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 void
00124 copy_loop_headers (void)
00125 {
00126 struct loops *loops;
00127 unsigned i;
00128 struct loop *loop;
00129 basic_block header;
00130 edge exit;
00131 basic_block *bbs;
00132 unsigned n_bbs;
00133
00134 loops = loop_optimizer_init (dump_file);
00135 if (!loops)
00136 return;
00137 rewrite_into_loop_closed_ssa ();
00138
00139
00140
00141 loops->state &= ~LOOPS_HAVE_MARKED_IRREDUCIBLE_REGIONS;
00142
00143 #ifdef ENABLE_CHECKING
00144 verify_loop_structure (loops);
00145 #endif
00146
00147 bbs = xmalloc (sizeof (basic_block) * n_basic_blocks);
00148
00149 for (i = 1; i < loops->num; i++)
00150 {
00151
00152 int limit = 20;
00153
00154 loop = loops->parray[i];
00155 if (!loop)
00156 continue;
00157 header = loop->header;
00158
00159
00160
00161
00162
00163 if (do_while_loop_p (loop))
00164 continue;
00165
00166
00167
00168
00169
00170
00171
00172 exit = NULL;
00173 n_bbs = 0;
00174 while (should_duplicate_loop_header_p (header, loop, &limit))
00175 {
00176
00177
00178 if (flow_bb_inside_loop_p (loop, EDGE_SUCC (header, 0)->dest))
00179 exit = EDGE_SUCC (header, 0);
00180 else
00181 exit = EDGE_SUCC (header, 1);
00182 bbs[n_bbs++] = header;
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 (EDGE_COUNT (exit->dest->preds) > 1)
00197 exit = EDGE_SUCC (loop_split_edge_with (exit, NULL), 0);
00198
00199 if (!tree_duplicate_sese_region (loop_preheader_edge (loop), exit,
00200 bbs, n_bbs, NULL))
00201 {
00202 fprintf (dump_file, "Duplication failed.\n");
00203 continue;
00204 }
00205
00206
00207
00208 loop_split_edge_with (loop_preheader_edge (loop), NULL);
00209 loop_split_edge_with (loop_latch_edge (loop), NULL);
00210 }
00211
00212 free (bbs);
00213
00214 #ifdef ENABLE_CHECKING
00215 verify_loop_closed_ssa ();
00216 #endif
00217
00218 loop_optimizer_finalize (loops, NULL);
00219 }
00220
00221 static bool
00222 gate_ch (void)
00223 {
00224 return flag_tree_ch != 0;
00225 }
00226
00227 struct tree_opt_pass pass_ch =
00228 {
00229 "ch",
00230 gate_ch,
00231 copy_loop_headers,
00232 NULL,
00233 NULL,
00234 0,
00235 TV_TREE_CH,
00236 PROP_cfg | PROP_ssa,
00237 0,
00238 0,
00239 0,
00240 TODO_cleanup_cfg | TODO_dump_func
00241 | TODO_verify_ssa,
00242 0
00243 };