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 "timevar.h"
00035 #include "cfgloop.h"
00036 #include "domwalk.h"
00037 #include "params.h"
00038 #include "tree-pass.h"
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076 static struct loop *tree_unswitch_loop (struct loops *, struct loop *, basic_block,
00077 tree);
00078 static bool tree_unswitch_single_loop (struct loops *, struct loop *, int);
00079 static tree tree_may_unswitch_on (basic_block, struct loop *);
00080
00081
00082
00083 unsigned int
00084 tree_ssa_unswitch_loops (struct loops *loops)
00085 {
00086 int i, num;
00087 struct loop *loop;
00088 bool changed = false;
00089
00090
00091 num = loops->num;
00092
00093 for (i = 1; i < num; i++)
00094 {
00095
00096 loop = loops->parray[i];
00097 if (!loop)
00098 continue;
00099
00100 if (loop->inner)
00101 continue;
00102
00103 changed |= tree_unswitch_single_loop (loops, loop, 0);
00104 }
00105
00106 if (changed)
00107 return TODO_cleanup_cfg;
00108 return 0;
00109 }
00110
00111
00112
00113
00114 static tree
00115 tree_may_unswitch_on (basic_block bb, struct loop *loop)
00116 {
00117 tree stmt, def, cond, use;
00118 basic_block def_bb;
00119 ssa_op_iter iter;
00120
00121
00122 stmt = last_stmt (bb);
00123 if (!stmt || TREE_CODE (stmt) != COND_EXPR)
00124 return NULL_TREE;
00125
00126
00127 FOR_EACH_SSA_TREE_OPERAND (use, stmt, iter, SSA_OP_USE)
00128 {
00129 def = SSA_NAME_DEF_STMT (use);
00130 def_bb = bb_for_stmt (def);
00131 if (def_bb
00132 && flow_bb_inside_loop_p (loop, def_bb))
00133 return NULL_TREE;
00134 }
00135
00136 cond = COND_EXPR_COND (stmt);
00137
00138
00139
00140 if (integer_zerop (cond) || integer_nonzerop (cond))
00141 return NULL_TREE;
00142
00143 return cond;
00144 }
00145
00146
00147
00148
00149
00150 static tree
00151 simplify_using_entry_checks (struct loop *loop, tree cond)
00152 {
00153 edge e = loop_preheader_edge (loop);
00154 tree stmt;
00155
00156 while (1)
00157 {
00158 stmt = last_stmt (e->src);
00159 if (stmt
00160 && TREE_CODE (stmt) == COND_EXPR
00161 && operand_equal_p (COND_EXPR_COND (stmt), cond, 0))
00162 return (e->flags & EDGE_TRUE_VALUE
00163 ? boolean_true_node
00164 : boolean_false_node);
00165
00166 if (!single_pred_p (e->src))
00167 return cond;
00168
00169 e = single_pred_edge (e->src);
00170 if (e->src == ENTRY_BLOCK_PTR)
00171 return cond;
00172 }
00173 }
00174
00175
00176
00177
00178
00179 static bool
00180 tree_unswitch_single_loop (struct loops *loops, struct loop *loop, int num)
00181 {
00182 basic_block *bbs;
00183 struct loop *nloop;
00184 unsigned i;
00185 tree cond = NULL_TREE, stmt;
00186 bool changed = false;
00187
00188
00189 if (num > PARAM_VALUE (PARAM_MAX_UNSWITCH_LEVEL))
00190 {
00191 if (dump_file && (dump_flags & TDF_DETAILS))
00192 fprintf (dump_file, ";; Not unswitching anymore, hit max level\n");
00193 return false;
00194 }
00195
00196
00197 if (loop->inner)
00198 {
00199 if (dump_file && (dump_flags & TDF_DETAILS))
00200 fprintf (dump_file, ";; Not unswitching, not innermost loop\n");
00201 return false;
00202 }
00203
00204
00205 if (tree_num_loop_insns (loop)
00206 > (unsigned) PARAM_VALUE (PARAM_MAX_UNSWITCH_INSNS))
00207 {
00208 if (dump_file && (dump_flags & TDF_DETAILS))
00209 fprintf (dump_file, ";; Not unswitching, loop too big\n");
00210 return false;
00211 }
00212
00213 i = 0;
00214 bbs = get_loop_body (loop);
00215
00216 while (1)
00217 {
00218
00219 for (; i < loop->num_nodes; i++)
00220 if ((cond = tree_may_unswitch_on (bbs[i], loop)))
00221 break;
00222
00223 if (i == loop->num_nodes)
00224 {
00225 free (bbs);
00226 return changed;
00227 }
00228
00229 cond = simplify_using_entry_checks (loop, cond);
00230 stmt = last_stmt (bbs[i]);
00231 if (integer_nonzerop (cond))
00232 {
00233
00234 COND_EXPR_COND (stmt) = boolean_true_node;
00235 changed = true;
00236 }
00237 else if (integer_zerop (cond))
00238 {
00239
00240 COND_EXPR_COND (stmt) = boolean_false_node;
00241 changed = true;
00242 }
00243 else
00244 break;
00245
00246 update_stmt (stmt);
00247 i++;
00248 }
00249
00250 if (dump_file && (dump_flags & TDF_DETAILS))
00251 fprintf (dump_file, ";; Unswitching loop\n");
00252
00253 initialize_original_copy_tables ();
00254
00255 nloop = tree_unswitch_loop (loops, loop, bbs[i], cond);
00256 if (!nloop)
00257 {
00258 free_original_copy_tables ();
00259 free (bbs);
00260 return changed;
00261 }
00262
00263
00264 update_ssa (TODO_update_ssa);
00265 free_original_copy_tables ();
00266
00267
00268 tree_unswitch_single_loop (loops, nloop, num + 1);
00269 tree_unswitch_single_loop (loops, loop, num + 1);
00270 free (bbs);
00271 return true;
00272 }
00273
00274
00275
00276
00277
00278
00279 static struct loop *
00280 tree_unswitch_loop (struct loops *loops, struct loop *loop,
00281 basic_block unswitch_on, tree cond)
00282 {
00283 basic_block condition_bb;
00284
00285
00286 gcc_assert (flow_bb_inside_loop_p (loop, unswitch_on));
00287 gcc_assert (EDGE_COUNT (unswitch_on->succs) == 2);
00288 gcc_assert (loop->inner == NULL);
00289
00290 return loop_version (loops, loop, unshare_expr (cond),
00291 &condition_bb, false);
00292 }