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 void
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 #ifdef ENABLE_CHECKING
00105 verify_dominators (CDI_DOMINATORS);
00106 verify_loop_structure (loops);
00107 #endif
00108 }
00109
00110 #if 0
00111
00112 if (changed)
00113 cleanup_tree_cfg_loop ();
00114 #endif
00115 }
00116
00117
00118
00119
00120 static tree
00121 tree_may_unswitch_on (basic_block bb, struct loop *loop)
00122 {
00123 tree stmt, def, cond;
00124 basic_block def_bb;
00125 use_optype uses;
00126 unsigned i;
00127
00128
00129 stmt = last_stmt (bb);
00130 if (!stmt || TREE_CODE (stmt) != COND_EXPR)
00131 return NULL_TREE;
00132
00133
00134 get_stmt_operands (stmt);
00135 uses = STMT_USE_OPS (stmt);
00136 for (i = 0; i < NUM_USES (uses); i++)
00137 {
00138 def = SSA_NAME_DEF_STMT (USE_OP (uses, i));
00139 def_bb = bb_for_stmt (def);
00140 if (def_bb
00141 && flow_bb_inside_loop_p (loop, def_bb))
00142 return NULL_TREE;
00143 }
00144
00145 cond = COND_EXPR_COND (stmt);
00146
00147
00148
00149 if (integer_zerop (cond) || integer_nonzerop (cond))
00150 return NULL_TREE;
00151
00152 return cond;
00153 }
00154
00155
00156
00157
00158
00159 static tree
00160 simplify_using_entry_checks (struct loop *loop, tree cond)
00161 {
00162 edge e = loop_preheader_edge (loop);
00163 tree stmt;
00164
00165 while (1)
00166 {
00167 stmt = last_stmt (e->src);
00168 if (stmt
00169 && TREE_CODE (stmt) == COND_EXPR
00170 && operand_equal_p (COND_EXPR_COND (stmt), cond, 0))
00171 return (e->flags & EDGE_TRUE_VALUE
00172 ? boolean_true_node
00173 : boolean_false_node);
00174
00175 if (EDGE_COUNT (e->src->preds) > 1)
00176 return cond;
00177
00178 e = EDGE_PRED (e->src, 0);
00179 if (e->src == ENTRY_BLOCK_PTR)
00180 return cond;
00181 }
00182 }
00183
00184
00185
00186
00187
00188 static bool
00189 tree_unswitch_single_loop (struct loops *loops, struct loop *loop, int num)
00190 {
00191 basic_block *bbs;
00192 struct loop *nloop;
00193 unsigned i;
00194 tree cond = NULL_TREE, stmt;
00195 bool changed = false;
00196
00197
00198 if (num > PARAM_VALUE (PARAM_MAX_UNSWITCH_LEVEL))
00199 {
00200 if (dump_file && (dump_flags & TDF_DETAILS))
00201 fprintf (dump_file, ";; Not unswitching anymore, hit max level\n");
00202 return false;
00203 }
00204
00205
00206 if (loop->inner)
00207 {
00208 if (dump_file && (dump_flags & TDF_DETAILS))
00209 fprintf (dump_file, ";; Not unswitching, not innermost loop\n");
00210 return false;
00211 }
00212
00213
00214 if (tree_num_loop_insns (loop)
00215 > (unsigned) PARAM_VALUE (PARAM_MAX_UNSWITCH_INSNS))
00216 {
00217 if (dump_file && (dump_flags & TDF_DETAILS))
00218 fprintf (dump_file, ";; Not unswitching, loop too big\n");
00219 return false;
00220 }
00221
00222 i = 0;
00223 bbs = get_loop_body (loop);
00224
00225 while (1)
00226 {
00227
00228 for (; i < loop->num_nodes; i++)
00229 if ((cond = tree_may_unswitch_on (bbs[i], loop)))
00230 break;
00231
00232 if (i == loop->num_nodes)
00233 {
00234 free (bbs);
00235 return changed;
00236 }
00237
00238 cond = simplify_using_entry_checks (loop, cond);
00239 stmt = last_stmt (bbs[i]);
00240 if (integer_nonzerop (cond))
00241 {
00242
00243 COND_EXPR_COND (stmt) = boolean_true_node;
00244 changed = true;
00245 }
00246 else if (integer_zerop (cond))
00247 {
00248
00249 COND_EXPR_COND (stmt) = boolean_false_node;
00250 changed = true;
00251 }
00252 else
00253 break;
00254
00255 modify_stmt (stmt);
00256 i++;
00257 }
00258
00259 if (dump_file && (dump_flags & TDF_DETAILS))
00260 fprintf (dump_file, ";; Unswitching loop\n");
00261
00262
00263 nloop = tree_unswitch_loop (loops, loop, bbs[i], cond);
00264 if (!nloop)
00265 return changed;
00266
00267
00268 tree_unswitch_single_loop (loops, nloop, num + 1);
00269 tree_unswitch_single_loop (loops, loop, num + 1);
00270 return true;
00271 }
00272
00273
00274
00275
00276
00277
00278 static struct loop *
00279 tree_unswitch_loop (struct loops *loops, struct loop *loop,
00280 basic_block unswitch_on, tree cond)
00281 {
00282 basic_block condition_bb;
00283
00284
00285 gcc_assert (flow_bb_inside_loop_p (loop, unswitch_on));
00286 gcc_assert (EDGE_COUNT (unswitch_on->succs) == 2);
00287 gcc_assert (loop->inner == NULL);
00288
00289 return tree_ssa_loop_version (loops, loop, unshare_expr (cond),
00290 &condition_bb);
00291 }