00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "config.h"
00023 #include "system.h"
00024 #include "coretypes.h"
00025 #include "tm.h"
00026 #include "tree.h"
00027 #include "flags.h"
00028 #include "rtl.h"
00029 #include "tm_p.h"
00030 #include "ggc.h"
00031 #include "basic-block.h"
00032 #include "cfgloop.h"
00033 #include "output.h"
00034 #include "expr.h"
00035 #include "function.h"
00036 #include "diagnostic.h"
00037 #include "timevar.h"
00038 #include "tree-dump.h"
00039 #include "tree-flow.h"
00040 #include "domwalk.h"
00041 #include "real.h"
00042 #include "tree-pass.h"
00043 #include "tree-ssa-propagate.h"
00044 #include "langhooks.h"
00045 #include "params.h"
00046
00047
00048
00049
00050
00051 static int stmt_count;
00052
00053
00054
00055
00056 bool
00057 potentially_threadable_block (basic_block bb)
00058 {
00059 block_stmt_iterator bsi;
00060
00061
00062
00063 if (single_succ_p (bb) || single_pred_p (bb))
00064 return false;
00065
00066
00067
00068 bsi = bsi_last (bb);
00069 if (bsi_end_p (bsi)
00070 || ! bsi_stmt (bsi)
00071 || (TREE_CODE (bsi_stmt (bsi)) != COND_EXPR
00072 && TREE_CODE (bsi_stmt (bsi)) != GOTO_EXPR
00073 && TREE_CODE (bsi_stmt (bsi)) != SWITCH_EXPR))
00074 return false;
00075
00076 return true;
00077 }
00078
00079
00080
00081
00082
00083 static tree
00084 lhs_of_dominating_assert (tree op, basic_block bb, tree stmt)
00085 {
00086 imm_use_iterator imm_iter;
00087 tree use_stmt;
00088 use_operand_p use_p;
00089
00090 FOR_EACH_IMM_USE_FAST (use_p, imm_iter, op)
00091 {
00092 use_stmt = USE_STMT (use_p);
00093 if (use_stmt != stmt
00094 && TREE_CODE (use_stmt) == MODIFY_EXPR
00095 && TREE_CODE (TREE_OPERAND (use_stmt, 1)) == ASSERT_EXPR
00096 && TREE_OPERAND (TREE_OPERAND (use_stmt, 1), 0) == op
00097 && dominated_by_p (CDI_DOMINATORS, bb, bb_for_stmt (use_stmt)))
00098 {
00099 return TREE_OPERAND (use_stmt, 0);
00100 }
00101 }
00102 return op;
00103 }
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116 static void
00117 remove_temporary_equivalences (VEC(tree, heap) **stack)
00118 {
00119 while (VEC_length (tree, *stack) > 0)
00120 {
00121 tree prev_value, dest;
00122
00123 dest = VEC_pop (tree, *stack);
00124
00125
00126
00127 if (dest == NULL)
00128 break;
00129
00130 prev_value = VEC_pop (tree, *stack);
00131 SSA_NAME_VALUE (dest) = prev_value;
00132 }
00133 }
00134
00135
00136
00137
00138
00139 static void
00140 record_temporary_equivalence (tree x, tree y, VEC(tree, heap) **stack)
00141 {
00142 tree prev_x = SSA_NAME_VALUE (x);
00143
00144 if (TREE_CODE (y) == SSA_NAME)
00145 {
00146 tree tmp = SSA_NAME_VALUE (y);
00147 y = tmp ? tmp : y;
00148 }
00149
00150 SSA_NAME_VALUE (x) = y;
00151 VEC_reserve (tree, heap, *stack, 2);
00152 VEC_quick_push (tree, *stack, prev_x);
00153 VEC_quick_push (tree, *stack, x);
00154 }
00155
00156
00157
00158
00159
00160
00161
00162 static bool
00163 record_temporary_equivalences_from_phis (edge e, VEC(tree, heap) **stack)
00164 {
00165 tree phi;
00166
00167
00168
00169
00170 for (phi = phi_nodes (e->dest); phi; phi = PHI_CHAIN (phi))
00171 {
00172 tree src = PHI_ARG_DEF_FROM_EDGE (phi, e);
00173 tree dst = PHI_RESULT (phi);
00174
00175
00176
00177
00178 if (src != dst
00179 && TREE_CODE (src) == SSA_NAME
00180 && TREE_CODE (SSA_NAME_DEF_STMT (src)) == PHI_NODE
00181 && bb_for_stmt (SSA_NAME_DEF_STMT (src)) == e->dest)
00182 return false;
00183
00184
00185
00186 if (is_gimple_reg (dst))
00187 stmt_count++;
00188
00189 record_temporary_equivalence (dst, src, stack);
00190 }
00191 return true;
00192 }
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211 static tree
00212 record_temporary_equivalences_from_stmts_at_dest (edge e,
00213 VEC(tree, heap) **stack,
00214 tree (*simplify) (tree,
00215 tree))
00216 {
00217 block_stmt_iterator bsi;
00218 tree stmt = NULL;
00219 int max_stmt_count;
00220
00221 max_stmt_count = PARAM_VALUE (PARAM_MAX_JUMP_THREAD_DUPLICATION_STMTS);
00222
00223
00224
00225
00226
00227 for (bsi = bsi_start (e->dest); ! bsi_end_p (bsi); bsi_next (&bsi))
00228 {
00229 tree cached_lhs = NULL;
00230
00231 stmt = bsi_stmt (bsi);
00232
00233
00234 if (IS_EMPTY_STMT (stmt) || TREE_CODE (stmt) == LABEL_EXPR)
00235 continue;
00236
00237
00238
00239
00240 if (TREE_CODE (stmt) == ASM_EXPR && ASM_VOLATILE_P (stmt))
00241 return NULL;
00242
00243
00244
00245 stmt_count++;
00246 if (stmt_count > max_stmt_count)
00247 return NULL;
00248
00249
00250
00251
00252 if (TREE_CODE (stmt) != MODIFY_EXPR
00253 || TREE_CODE (TREE_OPERAND (stmt, 0)) != SSA_NAME)
00254 continue;
00255
00256
00257
00258
00259
00260
00261
00262
00263 if (TREE_CODE (TREE_OPERAND (stmt, 1)) == SSA_NAME)
00264 cached_lhs = TREE_OPERAND (stmt, 1);
00265 else if (TREE_CODE (TREE_OPERAND (stmt, 1)) == ASSERT_EXPR)
00266 cached_lhs = TREE_OPERAND (TREE_OPERAND (stmt, 1), 0);
00267 else
00268 {
00269
00270
00271
00272 tree *copy, pre_fold_expr;
00273 ssa_op_iter iter;
00274 use_operand_p use_p;
00275 unsigned int num, i = 0;
00276
00277 num = NUM_SSA_OPERANDS (stmt, (SSA_OP_USE | SSA_OP_VUSE));
00278 copy = XCNEWVEC (tree, num);
00279
00280
00281
00282 FOR_EACH_SSA_USE_OPERAND (use_p, stmt, iter, SSA_OP_USE | SSA_OP_VUSE)
00283 {
00284 tree tmp = NULL;
00285 tree use = USE_FROM_PTR (use_p);
00286
00287 copy[i++] = use;
00288 if (TREE_CODE (use) == SSA_NAME)
00289 tmp = SSA_NAME_VALUE (use);
00290 if (tmp && TREE_CODE (tmp) != VALUE_HANDLE)
00291 SET_USE (use_p, tmp);
00292 }
00293
00294
00295
00296
00297
00298
00299
00300 if (TREE_CODE (TREE_OPERAND (stmt, 1)) == COND_EXPR)
00301 {
00302 tree cond = COND_EXPR_COND (TREE_OPERAND (stmt, 1));
00303 cond = fold (cond);
00304 if (cond == boolean_true_node)
00305 pre_fold_expr = COND_EXPR_THEN (TREE_OPERAND (stmt, 1));
00306 else if (cond == boolean_false_node)
00307 pre_fold_expr = COND_EXPR_ELSE (TREE_OPERAND (stmt, 1));
00308 else
00309 pre_fold_expr = TREE_OPERAND (stmt, 1);
00310 }
00311 else
00312 pre_fold_expr = TREE_OPERAND (stmt, 1);
00313
00314 if (pre_fold_expr)
00315 {
00316 cached_lhs = fold (pre_fold_expr);
00317 if (TREE_CODE (cached_lhs) != SSA_NAME
00318 && !is_gimple_min_invariant (cached_lhs))
00319 cached_lhs = (*simplify) (stmt, stmt);
00320 }
00321
00322
00323 i = 0;
00324 FOR_EACH_SSA_USE_OPERAND (use_p, stmt, iter, SSA_OP_USE | SSA_OP_VUSE)
00325 SET_USE (use_p, copy[i++]);
00326
00327 free (copy);
00328 }
00329
00330
00331
00332 if (cached_lhs
00333 && (TREE_CODE (cached_lhs) == SSA_NAME
00334 || is_gimple_min_invariant (cached_lhs)))
00335 record_temporary_equivalence (TREE_OPERAND (stmt, 0),
00336 cached_lhs,
00337 stack);
00338 }
00339 return stmt;
00340 }
00341
00342
00343
00344
00345
00346
00347
00348
00349
00350
00351
00352
00353 static tree
00354 simplify_control_stmt_condition (edge e,
00355 tree stmt,
00356 tree dummy_cond,
00357 tree (*simplify) (tree, tree),
00358 bool handle_dominating_asserts)
00359 {
00360 tree cond, cached_lhs;
00361
00362 if (TREE_CODE (stmt) == COND_EXPR)
00363 cond = COND_EXPR_COND (stmt);
00364 else if (TREE_CODE (stmt) == GOTO_EXPR)
00365 cond = GOTO_DESTINATION (stmt);
00366 else
00367 cond = SWITCH_COND (stmt);
00368
00369
00370
00371 if (COMPARISON_CLASS_P (cond))
00372 {
00373 tree op0, op1;
00374 enum tree_code cond_code;
00375
00376 op0 = TREE_OPERAND (cond, 0);
00377 op1 = TREE_OPERAND (cond, 1);
00378 cond_code = TREE_CODE (cond);
00379
00380
00381 if (TREE_CODE (op0) == SSA_NAME)
00382 {
00383 tree tmp = SSA_NAME_VALUE (op0);
00384 if (tmp && TREE_CODE (tmp) != VALUE_HANDLE)
00385 op0 = tmp;
00386 }
00387
00388 if (TREE_CODE (op1) == SSA_NAME)
00389 {
00390 tree tmp = SSA_NAME_VALUE (op1);
00391 if (tmp && TREE_CODE (tmp) != VALUE_HANDLE)
00392 op1 = tmp;
00393 }
00394
00395 if (handle_dominating_asserts)
00396 {
00397
00398
00399
00400 if (TREE_CODE (op0) == SSA_NAME)
00401 op0 = lhs_of_dominating_assert (op0, e->src, stmt);
00402
00403 if (TREE_CODE (op1) == SSA_NAME)
00404 op1 = lhs_of_dominating_assert (op1, e->src, stmt);
00405 }
00406
00407
00408
00409
00410
00411 if (cond_code != SSA_NAME
00412 && tree_swap_operands_p (op0, op1, false))
00413 {
00414 tree tmp;
00415 cond_code = swap_tree_comparison (TREE_CODE (cond));
00416 tmp = op0;
00417 op0 = op1;
00418 op1 = tmp;
00419 }
00420
00421
00422
00423 TREE_SET_CODE (COND_EXPR_COND (dummy_cond), cond_code);
00424 TREE_OPERAND (COND_EXPR_COND (dummy_cond), 0) = op0;
00425 TREE_OPERAND (COND_EXPR_COND (dummy_cond), 1) = op1;
00426
00427
00428
00429 fold_defer_overflow_warnings ();
00430
00431 cached_lhs = fold (COND_EXPR_COND (dummy_cond));
00432 while (TREE_CODE (cached_lhs) == NOP_EXPR
00433 || TREE_CODE (cached_lhs) == CONVERT_EXPR
00434 || TREE_CODE (cached_lhs) == NON_LVALUE_EXPR)
00435 cached_lhs = TREE_OPERAND (cached_lhs, 0);
00436
00437 fold_undefer_overflow_warnings (is_gimple_min_invariant (cached_lhs),
00438 stmt, WARN_STRICT_OVERFLOW_CONDITIONAL);
00439
00440
00441
00442 if (! is_gimple_min_invariant (cached_lhs))
00443 cached_lhs = (*simplify) (dummy_cond, stmt);
00444 }
00445
00446
00447
00448 else if (TREE_CODE (cond) == SSA_NAME)
00449 {
00450 cached_lhs = cond;
00451
00452
00453
00454
00455
00456
00457 if (cached_lhs
00458 && TREE_CODE (cached_lhs) == SSA_NAME
00459 && SSA_NAME_VALUE (cached_lhs))
00460 cached_lhs = SSA_NAME_VALUE (cached_lhs);
00461
00462
00463
00464 if (handle_dominating_asserts && TREE_CODE (cached_lhs) == SSA_NAME)
00465 cached_lhs = lhs_of_dominating_assert (cached_lhs, e->src, stmt);
00466
00467
00468
00469 if (cached_lhs && ! is_gimple_min_invariant (cached_lhs))
00470 cached_lhs = (*simplify) (stmt, stmt);
00471 }
00472 else
00473 cached_lhs = NULL;
00474
00475 return cached_lhs;
00476 }
00477
00478
00479
00480
00481
00482
00483
00484
00485
00486
00487
00488
00489
00490
00491
00492
00493 void
00494 thread_across_edge (tree dummy_cond,
00495 edge e,
00496 bool handle_dominating_asserts,
00497 VEC(tree, heap) **stack,
00498 tree (*simplify) (tree, tree))
00499 {
00500 tree stmt;
00501
00502
00503
00504
00505
00506 if (e->flags & EDGE_DFS_BACK)
00507 {
00508 ssa_op_iter iter;
00509 use_operand_p use_p;
00510 tree last = bsi_stmt (bsi_last (e->dest));
00511
00512 FOR_EACH_SSA_USE_OPERAND (use_p, last, iter, SSA_OP_USE | SSA_OP_VUSE)
00513 {
00514 tree use = USE_FROM_PTR (use_p);
00515
00516 if (TREE_CODE (use) == SSA_NAME
00517 && TREE_CODE (SSA_NAME_DEF_STMT (use)) != PHI_NODE
00518 && bb_for_stmt (SSA_NAME_DEF_STMT (use)) == e->dest)
00519 goto fail;
00520 }
00521 }
00522
00523 stmt_count = 0;
00524
00525
00526 if (!record_temporary_equivalences_from_phis (e, stack))
00527 goto fail;
00528
00529
00530
00531 stmt = record_temporary_equivalences_from_stmts_at_dest (e, stack, simplify);
00532 if (!stmt)
00533 goto fail;
00534
00535
00536
00537 if (TREE_CODE (stmt) == COND_EXPR
00538 || TREE_CODE (stmt) == GOTO_EXPR
00539 || TREE_CODE (stmt) == SWITCH_EXPR)
00540 {
00541 tree cond;
00542
00543
00544 cond = simplify_control_stmt_condition (e, stmt, dummy_cond, simplify, handle_dominating_asserts);
00545
00546 if (cond && is_gimple_min_invariant (cond))
00547 {
00548 edge taken_edge = find_taken_edge (e->dest, cond);
00549 basic_block dest = (taken_edge ? taken_edge->dest : NULL);
00550
00551 if (dest == e->dest)
00552 goto fail;
00553
00554 remove_temporary_equivalences (stack);
00555 register_jump_thread (e, taken_edge);
00556 }
00557 }
00558
00559 fail:
00560 remove_temporary_equivalences (stack);
00561 }