00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037 #include "config.h"
00038 #include "system.h"
00039 #include "coretypes.h"
00040 #include "tm.h"
00041 #include "tree.h"
00042 #include "flags.h"
00043 #include "rtl.h"
00044 #include "tm_p.h"
00045 #include "ggc.h"
00046 #include "basic-block.h"
00047 #include "output.h"
00048 #include "errors.h"
00049 #include "expr.h"
00050 #include "function.h"
00051 #include "diagnostic.h"
00052 #include "timevar.h"
00053 #include "tree-dump.h"
00054 #include "tree-flow.h"
00055 #include "tree-pass.h"
00056 #include "tree-ssa-propagate.h"
00057 #include "langhooks.h"
00058
00059
00060
00061 typedef enum
00062 {
00063 UNINITIALIZED = 0,
00064 UNDEFINED,
00065 UNKNOWN_VAL,
00066 CONSTANT,
00067 VARYING
00068 } latticevalue;
00069
00070
00071
00072 typedef struct
00073 {
00074 latticevalue lattice_val;
00075 tree const_val;
00076 } value;
00077
00078
00079 static value *value_vector;
00080
00081
00082
00083
00084 static void
00085 dump_lattice_value (FILE *outf, const char *prefix, value val)
00086 {
00087 switch (val.lattice_val)
00088 {
00089 case UNDEFINED:
00090 fprintf (outf, "%sUNDEFINED", prefix);
00091 break;
00092 case VARYING:
00093 fprintf (outf, "%sVARYING", prefix);
00094 break;
00095 case UNKNOWN_VAL:
00096 fprintf (outf, "%sUNKNOWN_VAL", prefix);
00097 break;
00098 case CONSTANT:
00099 fprintf (outf, "%sCONSTANT ", prefix);
00100 print_generic_expr (outf, val.const_val, dump_flags);
00101 break;
00102 default:
00103 gcc_unreachable ();
00104 }
00105 }
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122 static value
00123 get_default_value (tree var)
00124 {
00125 value val;
00126 tree sym;
00127
00128 if (TREE_CODE (var) == SSA_NAME)
00129 sym = SSA_NAME_VAR (var);
00130 else
00131 {
00132 gcc_assert (DECL_P (var));
00133 sym = var;
00134 }
00135
00136 val.lattice_val = UNDEFINED;
00137 val.const_val = NULL_TREE;
00138
00139 if (TREE_CODE (var) == SSA_NAME
00140 && SSA_NAME_VALUE (var)
00141 && is_gimple_min_invariant (SSA_NAME_VALUE (var)))
00142 {
00143 val.lattice_val = CONSTANT;
00144 val.const_val = SSA_NAME_VALUE (var);
00145 }
00146 else if (TREE_CODE (sym) == PARM_DECL || TREE_THIS_VOLATILE (sym))
00147 {
00148
00149 val.lattice_val = VARYING;
00150 }
00151 else if (TREE_STATIC (sym))
00152 {
00153
00154
00155 if (TREE_READONLY (sym)
00156 && DECL_INITIAL (sym)
00157 && is_gimple_min_invariant (DECL_INITIAL (sym)))
00158 {
00159 val.lattice_val = CONSTANT;
00160 val.const_val = DECL_INITIAL (sym);
00161 }
00162 else
00163 {
00164 val.const_val = NULL_TREE;
00165 val.lattice_val = UNKNOWN_VAL;
00166 }
00167 }
00168 else if (!is_gimple_reg (sym))
00169 {
00170 val.const_val = NULL_TREE;
00171 val.lattice_val = UNKNOWN_VAL;
00172 }
00173 else
00174 {
00175 enum tree_code code;
00176 tree stmt = SSA_NAME_DEF_STMT (var);
00177
00178 if (!IS_EMPTY_STMT (stmt))
00179 {
00180 code = TREE_CODE (stmt);
00181 if (code != MODIFY_EXPR && code != PHI_NODE)
00182 val.lattice_val = VARYING;
00183 }
00184 }
00185
00186 return val;
00187 }
00188
00189
00190
00191 static value *
00192 get_value (tree var)
00193 {
00194 value *val;
00195
00196 gcc_assert (TREE_CODE (var) == SSA_NAME);
00197
00198 val = &value_vector[SSA_NAME_VERSION (var)];
00199 if (val->lattice_val == UNINITIALIZED)
00200 *val = get_default_value (var);
00201
00202 return val;
00203 }
00204
00205
00206
00207
00208
00209 static bool
00210 set_lattice_value (tree var, value val)
00211 {
00212 value *old = get_value (var);
00213
00214 if (val.lattice_val == UNDEFINED)
00215 {
00216
00217 gcc_assert (old->lattice_val != CONSTANT);
00218
00219
00220 gcc_assert (old->lattice_val != UNKNOWN_VAL);
00221
00222
00223
00224 gcc_assert (old->lattice_val != VARYING
00225 || get_default_value (var).lattice_val == VARYING);
00226 }
00227 else if (val.lattice_val == CONSTANT)
00228
00229
00230 gcc_assert (old->lattice_val != VARYING
00231 || get_default_value (var).lattice_val == VARYING);
00232
00233
00234 if (old->lattice_val == CONSTANT
00235 && val.lattice_val == CONSTANT
00236 && !simple_cst_equal (old->const_val, val.const_val))
00237 {
00238 val.lattice_val = VARYING;
00239 val.const_val = NULL_TREE;
00240 }
00241
00242 if (old->lattice_val != val.lattice_val)
00243 {
00244 if (dump_file && (dump_flags & TDF_DETAILS))
00245 {
00246 dump_lattice_value (dump_file, "Lattice value changed to ", val);
00247 fprintf (dump_file, ". Adding definition to SSA edges.\n");
00248 }
00249
00250 *old = val;
00251 return true;
00252 }
00253
00254 return false;
00255 }
00256
00257
00258
00259
00260 static void
00261 def_to_varying (tree var)
00262 {
00263 value val;
00264 val.lattice_val = VARYING;
00265 val.const_val = NULL_TREE;
00266 set_lattice_value (var, val);
00267 }
00268
00269
00270
00271
00272
00273
00274
00275
00276
00277
00278
00279
00280 static latticevalue
00281 likely_value (tree stmt)
00282 {
00283 vuse_optype vuses;
00284 int found_constant = 0;
00285 stmt_ann_t ann;
00286 tree use;
00287 ssa_op_iter iter;
00288
00289
00290
00291 ann = stmt_ann (stmt);
00292 if (ann->makes_aliased_loads || ann->has_volatile_ops)
00293 return VARYING;
00294
00295
00296
00297 if (get_call_expr_in (stmt) != NULL_TREE)
00298 return VARYING;
00299
00300 get_stmt_operands (stmt);
00301
00302 FOR_EACH_SSA_TREE_OPERAND (use, stmt, iter, SSA_OP_USE)
00303 {
00304 value *val = get_value (use);
00305
00306 if (val->lattice_val == UNDEFINED)
00307 return UNDEFINED;
00308
00309 if (val->lattice_val == CONSTANT)
00310 found_constant = 1;
00311 }
00312
00313 vuses = VUSE_OPS (ann);
00314
00315 if (NUM_VUSES (vuses))
00316 {
00317 tree vuse = VUSE_OP (vuses, 0);
00318 value *val = get_value (vuse);
00319
00320 if (val->lattice_val == UNKNOWN_VAL)
00321 return UNKNOWN_VAL;
00322
00323
00324 gcc_assert (val->lattice_val != UNDEFINED);
00325
00326 if (val->lattice_val == CONSTANT)
00327 found_constant = 1;
00328 }
00329
00330 return ((found_constant || (!USE_OPS (ann) && !vuses)) ? CONSTANT : VARYING);
00331 }
00332
00333
00334
00335
00336
00337 static bool
00338 need_imm_uses_for (tree var)
00339 {
00340 return get_value (var)->lattice_val != VARYING;
00341 }
00342
00343
00344
00345
00346 static void
00347 ccp_initialize (void)
00348 {
00349 basic_block bb;
00350 sbitmap is_may_def;
00351
00352 value_vector = (value *) xmalloc (num_ssa_names * sizeof (value));
00353 memset (value_vector, 0, num_ssa_names * sizeof (value));
00354
00355
00356 is_may_def = sbitmap_alloc (num_ssa_names);
00357 sbitmap_zero (is_may_def);
00358
00359
00360 FOR_EACH_BB (bb)
00361 {
00362 block_stmt_iterator i;
00363
00364
00365 for (i = bsi_start (bb); !bsi_end_p (i); bsi_next (&i))
00366 {
00367 bool is_varying = false;
00368 tree stmt = bsi_stmt (i);
00369 ssa_op_iter iter;
00370 tree def;
00371
00372 get_stmt_operands (stmt);
00373
00374
00375 FOR_EACH_SSA_TREE_OPERAND (def, stmt, iter,
00376 (SSA_OP_DEF | SSA_OP_VMUSTDEF))
00377 {
00378 if (get_value (def)->lattice_val == VARYING)
00379 is_varying = true;
00380 }
00381
00382
00383 FOR_EACH_SSA_TREE_OPERAND (def, stmt, iter, SSA_OP_VMAYDEF)
00384 {
00385 get_value (def)->lattice_val = VARYING;
00386 SET_BIT (is_may_def, SSA_NAME_VERSION (def));
00387 }
00388
00389
00390
00391
00392 if (TREE_CODE (stmt) != MODIFY_EXPR
00393 && TREE_CODE (stmt) != COND_EXPR
00394 && TREE_CODE (stmt) != SWITCH_EXPR)
00395 is_varying = true;
00396
00397 DONT_SIMULATE_AGAIN (stmt) = is_varying;
00398 }
00399 }
00400
00401
00402 FOR_EACH_BB (bb)
00403 {
00404 tree phi, var;
00405 int x;
00406
00407 for (phi = phi_nodes (bb); phi; phi = PHI_CHAIN (phi))
00408 {
00409 value *val = get_value (PHI_RESULT (phi));
00410
00411 for (x = 0; x < PHI_NUM_ARGS (phi); x++)
00412 {
00413 var = PHI_ARG_DEF (phi, x);
00414
00415
00416
00417 if (TREE_CODE (var) == SSA_NAME)
00418 {
00419 if (TEST_BIT (is_may_def, SSA_NAME_VERSION (var)))
00420 {
00421 val->lattice_val = VARYING;
00422 SET_BIT (is_may_def, SSA_NAME_VERSION (PHI_RESULT (phi)));
00423 break;
00424 }
00425 }
00426 }
00427
00428 DONT_SIMULATE_AGAIN (phi) = (val->lattice_val == VARYING);
00429 }
00430 }
00431
00432 sbitmap_free (is_may_def);
00433
00434
00435 compute_immediate_uses (TDFA_USE_OPS | TDFA_USE_VOPS, need_imm_uses_for);
00436 }
00437
00438
00439
00440
00441
00442
00443
00444 static bool
00445 replace_uses_in (tree stmt, bool *replaced_addresses_p)
00446 {
00447 bool replaced = false;
00448 use_operand_p use;
00449 ssa_op_iter iter;
00450
00451 if (replaced_addresses_p)
00452 *replaced_addresses_p = false;
00453
00454 get_stmt_operands (stmt);
00455
00456 FOR_EACH_SSA_USE_OPERAND (use, stmt, iter, SSA_OP_USE)
00457 {
00458 tree tuse = USE_FROM_PTR (use);
00459 value *val = get_value (tuse);
00460
00461 if (val->lattice_val != CONSTANT)
00462 continue;
00463
00464 if (TREE_CODE (stmt) == ASM_EXPR
00465 && !may_propagate_copy_into_asm (tuse))
00466 continue;
00467
00468 SET_USE (use, val->const_val);
00469
00470 replaced = true;
00471 if (POINTER_TYPE_P (TREE_TYPE (tuse)) && replaced_addresses_p)
00472 *replaced_addresses_p = true;
00473 }
00474
00475 return replaced;
00476 }
00477
00478
00479
00480
00481
00482
00483
00484 static bool
00485 replace_vuse_in (tree stmt, bool *replaced_addresses_p)
00486 {
00487 bool replaced = false;
00488 vuse_optype vuses;
00489 use_operand_p vuse;
00490 value *val;
00491
00492 if (replaced_addresses_p)
00493 *replaced_addresses_p = false;
00494
00495 get_stmt_operands (stmt);
00496
00497 vuses = STMT_VUSE_OPS (stmt);
00498
00499 if (NUM_VUSES (vuses) != 1)
00500 return false;
00501
00502 vuse = VUSE_OP_PTR (vuses, 0);
00503 val = get_value (USE_FROM_PTR (vuse));
00504
00505 if (val->lattice_val == CONSTANT
00506 && TREE_CODE (stmt) == MODIFY_EXPR
00507 && DECL_P (TREE_OPERAND (stmt, 1))
00508 && TREE_OPERAND (stmt, 1) == SSA_NAME_VAR (USE_FROM_PTR (vuse)))
00509 {
00510 TREE_OPERAND (stmt, 1) = val->const_val;
00511 replaced = true;
00512 if (POINTER_TYPE_P (TREE_TYPE (USE_FROM_PTR (vuse)))
00513 && replaced_addresses_p)
00514 *replaced_addresses_p = true;
00515 }
00516
00517 return replaced;
00518 }
00519
00520
00521
00522
00523
00524 static void
00525 substitute_and_fold (void)
00526 {
00527 basic_block bb;
00528 unsigned int i;
00529
00530 if (dump_file && (dump_flags & TDF_DETAILS))
00531 fprintf (dump_file,
00532 "\nSubstituing constants and folding statements\n\n");
00533
00534
00535 FOR_EACH_BB (bb)
00536 {
00537 block_stmt_iterator i;
00538 tree phi;
00539
00540
00541 for (phi = phi_nodes (bb); phi; phi = PHI_CHAIN (phi))
00542 {
00543 int i;
00544
00545 for (i = 0; i < PHI_NUM_ARGS (phi); i++)
00546 {
00547 value *new_val;
00548 use_operand_p orig_p = PHI_ARG_DEF_PTR (phi, i);
00549 tree orig = USE_FROM_PTR (orig_p);
00550
00551 if (! SSA_VAR_P (orig))
00552 break;
00553
00554 new_val = get_value (orig);
00555 if (new_val->lattice_val == CONSTANT
00556 && may_propagate_copy (orig, new_val->const_val))
00557 SET_USE (orig_p, new_val->const_val);
00558 }
00559 }
00560
00561 for (i = bsi_start (bb); !bsi_end_p (i); bsi_next (&i))
00562 {
00563 bool replaced_address;
00564 tree stmt = bsi_stmt (i);
00565
00566
00567 if (stmt_modified_p (stmt) || !is_exec_stmt (stmt))
00568 continue;
00569
00570
00571
00572 if (dump_file && (dump_flags & TDF_DETAILS))
00573 {
00574 fprintf (dump_file, "Line %d: replaced ", get_lineno (stmt));
00575 print_generic_stmt (dump_file, stmt, TDF_SLIM);
00576 }
00577
00578 if (replace_uses_in (stmt, &replaced_address)
00579 || replace_vuse_in (stmt, &replaced_address))
00580 {
00581 bool changed = fold_stmt (bsi_stmt_ptr (i));
00582 stmt = bsi_stmt(i);
00583
00584
00585
00586 if (replaced_address || changed)
00587 mark_new_vars_to_rename (stmt, vars_to_rename);
00588
00589
00590
00591 if (maybe_clean_eh_stmt (stmt))
00592 tree_purge_dead_eh_edges (bb);
00593
00594 modify_stmt (stmt);
00595 }
00596
00597 if (dump_file && (dump_flags & TDF_DETAILS))
00598 {
00599 fprintf (dump_file, " with ");
00600 print_generic_stmt (dump_file, stmt, TDF_SLIM);
00601 fprintf (dump_file, "\n");
00602 }
00603 }
00604 }
00605
00606
00607
00608
00609
00610 for (i = 0; i < num_ssa_names; i++)
00611 {
00612 tree name = ssa_name (i);
00613 value *value;
00614
00615 if (!name)
00616 continue;
00617
00618 value = get_value (name);
00619 if (value->lattice_val == CONSTANT
00620 && is_gimple_reg (name)
00621 && is_gimple_min_invariant (value->const_val))
00622 SSA_NAME_VALUE (name) = value->const_val;
00623 }
00624 }
00625
00626
00627
00628
00629 static void
00630 ccp_finalize (void)
00631 {
00632
00633 substitute_and_fold ();
00634
00635 free (value_vector);
00636 }
00637
00638
00639
00640
00641
00642
00643
00644
00645
00646
00647 static value
00648 ccp_lattice_meet (value val1, value val2)
00649 {
00650 value result;
00651
00652
00653 if (val1.lattice_val == UNDEFINED)
00654 return val2;
00655 else if (val2.lattice_val == UNDEFINED)
00656 return val1;
00657
00658
00659 if (val1.lattice_val == VARYING || val2.lattice_val == VARYING)
00660 {
00661 result.lattice_val = VARYING;
00662 result.const_val = NULL_TREE;
00663 return result;
00664 }
00665
00666
00667 if (val1.lattice_val == UNKNOWN_VAL
00668 || val2.lattice_val == UNKNOWN_VAL)
00669 {
00670 result.lattice_val = UNKNOWN_VAL;
00671 result.const_val = NULL_TREE;
00672 return result;
00673 }
00674
00675
00676
00677 if (simple_cst_equal (val1.const_val, val2.const_val) == 1)
00678 {
00679 result.lattice_val = CONSTANT;
00680 result.const_val = val1.const_val;
00681 }
00682 else
00683 {
00684 result.lattice_val = VARYING;
00685 result.const_val = NULL_TREE;
00686 }
00687
00688 return result;
00689 }
00690
00691
00692
00693
00694
00695
00696
00697 static enum ssa_prop_result
00698 ccp_visit_phi_node (tree phi)
00699 {
00700 value new_val, *old_val;
00701 int i;
00702
00703 if (dump_file && (dump_flags & TDF_DETAILS))
00704 {
00705 fprintf (dump_file, "\nVisiting PHI node: ");
00706 print_generic_expr (dump_file, phi, dump_flags);
00707 }
00708
00709 old_val = get_value (PHI_RESULT (phi));
00710 switch (old_val->lattice_val)
00711 {
00712 case VARYING:
00713 return SSA_PROP_NOT_INTERESTING;
00714
00715 case CONSTANT:
00716 new_val = *old_val;
00717 break;
00718
00719 case UNKNOWN_VAL:
00720
00721
00722
00723
00724
00725
00726 new_val.lattice_val = UNDEFINED;
00727 new_val.const_val = NULL_TREE;
00728 break;
00729
00730 case UNDEFINED:
00731 case UNINITIALIZED:
00732 new_val.lattice_val = UNDEFINED;
00733 new_val.const_val = NULL_TREE;
00734 break;
00735
00736 default:
00737 gcc_unreachable ();
00738 }
00739
00740 for (i = 0; i < PHI_NUM_ARGS (phi); i++)
00741 {
00742
00743 edge e = PHI_ARG_EDGE (phi, i);
00744
00745 if (dump_file && (dump_flags & TDF_DETAILS))
00746 {
00747 fprintf (dump_file,
00748 "\n Argument #%d (%d -> %d %sexecutable)\n",
00749 i, e->src->index, e->dest->index,
00750 (e->flags & EDGE_EXECUTABLE) ? "" : "not ");
00751 }
00752
00753
00754
00755 if (e->flags & EDGE_EXECUTABLE)
00756 {
00757 tree rdef = PHI_ARG_DEF (phi, i);
00758 value *rdef_val, val;
00759
00760 if (is_gimple_min_invariant (rdef))
00761 {
00762 val.lattice_val = CONSTANT;
00763 val.const_val = rdef;
00764 rdef_val = &val;
00765 }
00766 else
00767 rdef_val = get_value (rdef);
00768
00769 new_val = ccp_lattice_meet (new_val, *rdef_val);
00770
00771 if (dump_file && (dump_flags & TDF_DETAILS))
00772 {
00773 fprintf (dump_file, "\t");
00774 print_generic_expr (dump_file, rdef, dump_flags);
00775 dump_lattice_value (dump_file, "\tValue: ", *rdef_val);
00776 fprintf (dump_file, "\n");
00777 }
00778
00779 if (new_val.lattice_val == VARYING)
00780 break;
00781 }
00782 }
00783
00784 if (dump_file && (dump_flags & TDF_DETAILS))
00785 {
00786 dump_lattice_value (dump_file, "\n PHI node value: ", new_val);
00787 fprintf (dump_file, "\n\n");
00788 }
00789
00790
00791 if (old_val->lattice_val == UNKNOWN_VAL
00792 && new_val.lattice_val == UNDEFINED)
00793 return SSA_PROP_NOT_INTERESTING;
00794
00795
00796 if (set_lattice_value (PHI_RESULT (phi), new_val))
00797 {
00798 if (new_val.lattice_val == VARYING)
00799 return SSA_PROP_VARYING;
00800 else
00801 return SSA_PROP_INTERESTING;
00802 }
00803 else
00804 return SSA_PROP_NOT_INTERESTING;
00805 }
00806
00807
00808
00809
00810
00811
00812
00813
00814
00815
00816
00817 static tree
00818 ccp_fold (tree stmt)
00819 {
00820 tree rhs = get_rhs (stmt);
00821 enum tree_code code = TREE_CODE (rhs);
00822 enum tree_code_class kind = TREE_CODE_CLASS (code);
00823 tree retval = NULL_TREE;
00824 vuse_optype vuses;
00825
00826 vuses = STMT_VUSE_OPS (stmt);
00827
00828
00829
00830 if (TREE_CODE (rhs) == SSA_NAME)
00831 return get_value (rhs)->const_val;
00832 else if (DECL_P (rhs)
00833 && NUM_VUSES (vuses) == 1
00834 && rhs == SSA_NAME_VAR (VUSE_OP (vuses, 0)))
00835 return get_value (VUSE_OP (vuses, 0))->const_val;
00836
00837
00838
00839
00840 if (kind == tcc_unary)
00841 {
00842
00843 tree op0 = TREE_OPERAND (rhs, 0);
00844
00845
00846 if (TREE_CODE (op0) == SSA_NAME)
00847 {
00848 value *val = get_value (op0);
00849 if (val->lattice_val == CONSTANT)
00850 op0 = get_value (op0)->const_val;
00851 }
00852
00853 retval = fold_unary_to_constant (code, TREE_TYPE (rhs), op0);
00854
00855
00856
00857 if (retval && ! is_gimple_min_invariant (retval))
00858 return NULL;
00859
00860
00861
00862
00863
00864
00865
00866
00867
00868
00869
00870
00871
00872 if (! retval && is_gimple_min_invariant (op0))
00873 return build1 (code, TREE_TYPE (rhs), op0);
00874 }
00875
00876
00877
00878 else if (kind == tcc_binary
00879 || kind == tcc_comparison
00880 || code == TRUTH_AND_EXPR
00881 || code == TRUTH_OR_EXPR
00882 || code == TRUTH_XOR_EXPR)
00883 {
00884
00885
00886 tree op0 = TREE_OPERAND (rhs, 0);
00887 tree op1 = TREE_OPERAND (rhs, 1);
00888
00889
00890 if (TREE_CODE (op0) == SSA_NAME)
00891 {
00892 value *val = get_value (op0);
00893 if (val->lattice_val == CONSTANT)
00894 op0 = val->const_val;
00895 }
00896
00897 if (TREE_CODE (op1) == SSA_NAME)
00898 {
00899 value *val = get_value (op1);
00900 if (val->lattice_val == CONSTANT)
00901 op1 = val->const_val;
00902 }
00903
00904 retval = fold_binary_to_constant (code, TREE_TYPE (rhs), op0, op1);
00905
00906
00907
00908 if (retval && ! is_gimple_min_invariant (retval))
00909 return NULL;
00910
00911
00912
00913
00914
00915
00916
00917
00918
00919
00920
00921
00922
00923 if (! retval
00924 && is_gimple_min_invariant (op0)
00925 && is_gimple_min_invariant (op1))
00926 return build (code, TREE_TYPE (rhs), op0, op1);
00927 }
00928
00929
00930
00931 else if (code == CALL_EXPR
00932 && TREE_CODE (TREE_OPERAND (rhs, 0)) == ADDR_EXPR
00933 && (TREE_CODE (TREE_OPERAND (TREE_OPERAND (rhs, 0), 0))
00934 == FUNCTION_DECL)
00935 && DECL_BUILT_IN (TREE_OPERAND (TREE_OPERAND (rhs, 0), 0)))
00936 {
00937 use_optype uses = STMT_USE_OPS (stmt);
00938 if (NUM_USES (uses) != 0)
00939 {
00940 tree *orig;
00941 size_t i;
00942
00943
00944 orig = xmalloc (sizeof (tree) * NUM_USES (uses));
00945 for (i = 0; i < NUM_USES (uses); i++)
00946 orig[i] = USE_OP (uses, i);
00947
00948
00949 replace_uses_in (stmt, NULL);
00950 retval = fold_builtin (rhs, false);
00951
00952
00953 for (i = 0; i < NUM_USES (uses); i++)
00954 SET_USE_OP (uses, i, orig[i]);
00955 free (orig);
00956 }
00957 }
00958 else
00959 return rhs;
00960
00961
00962 if (retval)
00963 return fold_convert (TREE_TYPE (rhs), retval);
00964
00965
00966 return rhs;
00967 }
00968
00969
00970
00971
00972 static value
00973 evaluate_stmt (tree stmt)
00974 {
00975 value val;
00976 tree simplified;
00977 latticevalue likelyvalue = likely_value (stmt);
00978
00979
00980
00981 if (likelyvalue == CONSTANT)
00982 simplified = ccp_fold (stmt);
00983
00984
00985 else if (likelyvalue == VARYING)
00986 simplified = get_rhs (stmt);
00987
00988
00989 else
00990 simplified = NULL_TREE;
00991
00992 if (simplified && is_gimple_min_invariant (simplified))
00993 {
00994
00995 val.lattice_val = CONSTANT;
00996 val.const_val = simplified;
00997 }
00998 else
00999 {
01000
01001
01002
01003
01004 val.lattice_val = (likelyvalue == UNDEFINED ? UNDEFINED : VARYING);
01005 val.lattice_val = (likelyvalue == UNKNOWN_VAL
01006 ? UNKNOWN_VAL : val.lattice_val);
01007 val.const_val = NULL_TREE;
01008 }
01009
01010 return val;
01011 }
01012
01013
01014
01015
01016
01017 static enum ssa_prop_result
01018 visit_assignment (tree stmt, tree *output_p)
01019 {
01020 value val;
01021 tree lhs, rhs;
01022 vuse_optype vuses;
01023 v_must_def_optype v_must_defs;
01024
01025 lhs = TREE_OPERAND (stmt, 0);
01026 rhs = TREE_OPERAND (stmt, 1);
01027 vuses = STMT_VUSE_OPS (stmt);
01028 v_must_defs = STMT_V_MUST_DEF_OPS (stmt);
01029
01030 gcc_assert (NUM_V_MAY_DEFS (STMT_V_MAY_DEF_OPS (stmt)) == 0);
01031 gcc_assert (NUM_V_MUST_DEFS (v_must_defs) == 1
01032 || TREE_CODE (lhs) == SSA_NAME);
01033
01034
01035
01036 if (TREE_CODE (lhs) != SSA_NAME)
01037 {
01038
01039
01040 lhs = V_MUST_DEF_RESULT (v_must_defs, 0);
01041 }
01042
01043 if (TREE_CODE (rhs) == SSA_NAME)
01044 {
01045
01046 value *nval = get_value (rhs);
01047 val = *nval;
01048 }
01049 else if (DECL_P (rhs)
01050 && NUM_VUSES (vuses) == 1
01051 && rhs == SSA_NAME_VAR (VUSE_OP (vuses, 0)))
01052 {
01053
01054
01055 value *nval = get_value (VUSE_OP (vuses, 0));
01056 val = *nval;
01057 }
01058 else
01059
01060 val = evaluate_stmt (stmt);
01061
01062
01063
01064
01065
01066
01067
01068 {
01069 tree orig_lhs = TREE_OPERAND (stmt, 0);
01070
01071 if (TREE_CODE (orig_lhs) == VIEW_CONVERT_EXPR
01072 && val.lattice_val == CONSTANT)
01073 {
01074 tree w = fold (build1 (VIEW_CONVERT_EXPR,
01075 TREE_TYPE (TREE_OPERAND (orig_lhs, 0)),
01076 val.const_val));
01077
01078 orig_lhs = TREE_OPERAND (orig_lhs, 1);
01079 if (w && is_gimple_min_invariant (w))
01080 val.const_val = w;
01081 else
01082 {
01083 val.lattice_val = VARYING;
01084 val.const_val = NULL;
01085 }
01086 }
01087
01088 if (val.lattice_val == CONSTANT
01089 && TREE_CODE (orig_lhs) == COMPONENT_REF
01090 && DECL_BIT_FIELD (TREE_OPERAND (orig_lhs, 1)))
01091 {
01092 tree w = widen_bitfield (val.const_val, TREE_OPERAND (orig_lhs, 1),
01093 orig_lhs);
01094
01095 if (w && is_gimple_min_invariant (w))
01096 val.const_val = w;
01097 else
01098 {
01099 val.lattice_val = VARYING;
01100 val.const_val = NULL;
01101 }
01102 }
01103 }
01104
01105
01106
01107 if (!is_gimple_reg (SSA_NAME_VAR (lhs))
01108 && val.lattice_val == UNDEFINED)
01109 val.lattice_val = UNKNOWN_VAL;
01110
01111
01112 if (set_lattice_value (lhs, val))
01113 {
01114 *output_p = lhs;
01115 if (val.lattice_val == VARYING)
01116 return SSA_PROP_VARYING;
01117 else
01118 return SSA_PROP_INTERESTING;
01119 }
01120 else
01121 return SSA_PROP_NOT_INTERESTING;
01122 }
01123
01124
01125
01126
01127
01128
01129 static enum ssa_prop_result
01130 visit_cond_stmt (tree stmt, edge *taken_edge_p)
01131 {
01132 value val;
01133 basic_block block;
01134
01135 block = bb_for_stmt (stmt);
01136 val = evaluate_stmt (stmt);
01137
01138
01139
01140
01141
01142 *taken_edge_p = val.const_val ? find_taken_edge (block, val.const_val) : 0;
01143 if (*taken_edge_p)
01144 return SSA_PROP_INTERESTING;
01145 else
01146 return SSA_PROP_VARYING;
01147 }
01148
01149
01150
01151
01152
01153
01154
01155
01156
01157
01158
01159 static enum ssa_prop_result
01160 ccp_visit_stmt (tree stmt, edge *taken_edge_p, tree *output_p)
01161 {
01162 stmt_ann_t ann;
01163 v_may_def_optype v_may_defs;
01164 v_must_def_optype v_must_defs;
01165 tree def;
01166 ssa_op_iter iter;
01167
01168 if (dump_file && (dump_flags & TDF_DETAILS))
01169 {
01170 fprintf (dump_file, "\nVisiting statement: ");
01171 print_generic_stmt (dump_file, stmt, TDF_SLIM);
01172 fprintf (dump_file, "\n");
01173 }
01174
01175 ann = stmt_ann (stmt);
01176
01177 v_must_defs = V_MUST_DEF_OPS (ann);
01178 v_may_defs = V_MAY_DEF_OPS (ann);
01179 if (TREE_CODE (stmt) == MODIFY_EXPR
01180 && NUM_V_MAY_DEFS (v_may_defs) == 0
01181 && (NUM_V_MUST_DEFS (v_must_defs) == 1
01182 || TREE_CODE (TREE_OPERAND (stmt, 0)) == SSA_NAME))
01183 {
01184
01185
01186
01187 return visit_assignment (stmt, output_p);
01188 }
01189 else if (TREE_CODE (stmt) == COND_EXPR || TREE_CODE (stmt) == SWITCH_EXPR)
01190 {
01191
01192
01193 return visit_cond_stmt (stmt, taken_edge_p);
01194 }
01195
01196
01197
01198 if (dump_file && (dump_flags & TDF_DETAILS))
01199 fprintf (dump_file, "No interesting values produced. Marked VARYING.\n");
01200
01201
01202
01203
01204 FOR_EACH_SSA_TREE_OPERAND (def, stmt, iter, SSA_OP_DEF)
01205 def_to_varying (def);
01206
01207
01208 FOR_EACH_SSA_TREE_OPERAND (def, stmt, iter, SSA_OP_VMAYDEF)
01209 def_to_varying (def);
01210
01211 return SSA_PROP_VARYING;
01212 }
01213
01214
01215
01216
01217
01218
01219 static void
01220 execute_ssa_ccp (void)
01221 {
01222 ccp_initialize ();
01223 ssa_propagate (ccp_visit_stmt, ccp_visit_phi_node);
01224 ccp_finalize ();
01225 }
01226
01227
01228 static bool
01229 gate_ccp (void)
01230 {
01231 return flag_tree_ccp != 0;
01232 }
01233
01234
01235 struct tree_opt_pass pass_ccp =
01236 {
01237 "ccp",
01238 gate_ccp,
01239 execute_ssa_ccp,
01240 NULL,
01241 NULL,
01242 0,
01243 TV_TREE_CCP,
01244 PROP_cfg | PROP_ssa | PROP_alias,
01245 0,
01246 0,
01247 0,
01248 TODO_cleanup_cfg | TODO_dump_func | TODO_rename_vars
01249 | TODO_ggc_collect | TODO_verify_ssa
01250 | TODO_verify_stmts,
01251 0
01252 };
01253
01254
01255
01256
01257
01258
01259 tree
01260 widen_bitfield (tree val, tree field, tree var)
01261 {
01262 unsigned HOST_WIDE_INT var_size, field_size;
01263 tree wide_val;
01264 unsigned HOST_WIDE_INT mask;
01265 unsigned int i;
01266
01267
01268
01269 if (!host_integerp (TYPE_SIZE (TREE_TYPE (var)), 1)
01270 || !host_integerp (DECL_SIZE (field), 1)
01271 || !host_integerp (val, 0))
01272 return NULL_TREE;
01273
01274 var_size = tree_low_cst (TYPE_SIZE (TREE_TYPE (var)), 1);
01275 field_size = tree_low_cst (DECL_SIZE (field), 1);
01276
01277
01278 if (field_size > HOST_BITS_PER_WIDE_INT || var_size > HOST_BITS_PER_WIDE_INT)
01279 return NULL_TREE;
01280
01281 gcc_assert (var_size >= field_size);
01282
01283
01284
01285 if (DECL_UNSIGNED (field)
01286 || !(tree_low_cst (val, 0) & (((HOST_WIDE_INT)1) << (field_size - 1))))
01287 {
01288
01289
01290
01291 for (i = 0, mask = 0; i < field_size; i++)
01292 mask |= ((HOST_WIDE_INT) 1) << i;
01293
01294 wide_val = build2 (BIT_AND_EXPR, TREE_TYPE (var), val,
01295 build_int_cst (TREE_TYPE (var), mask));
01296 }
01297 else
01298 {
01299
01300
01301
01302 for (i = 0, mask = 0; i < (var_size - field_size); i++)
01303 mask |= ((HOST_WIDE_INT) 1) << (var_size - i - 1);
01304
01305 wide_val = build2 (BIT_IOR_EXPR, TREE_TYPE (var), val,
01306 build_int_cst (TREE_TYPE (var), mask));
01307 }
01308
01309 return fold (wide_val);
01310 }
01311
01312
01313
01314
01315
01316
01317 static tree
01318 maybe_fold_offset_to_array_ref (tree base, tree offset, tree orig_type)
01319 {
01320 tree min_idx, idx, elt_offset = integer_zero_node;
01321 tree array_type, elt_type, elt_size;
01322
01323
01324
01325
01326
01327
01328 if (TREE_CODE (base) == ARRAY_REF)
01329 {
01330 tree low_bound = array_ref_low_bound (base);
01331
01332 elt_offset = TREE_OPERAND (base, 1);
01333 if (TREE_CODE (low_bound) != INTEGER_CST
01334 || TREE_CODE (elt_offset) != INTEGER_CST)
01335 return NULL_TREE;
01336
01337 elt_offset = int_const_binop (MINUS_EXPR, elt_offset, low_bound, 0);
01338 base = TREE_OPERAND (base, 0);
01339 }
01340
01341
01342 array_type = TREE_TYPE (base);
01343 if (TREE_CODE (array_type) != ARRAY_TYPE)
01344 return NULL_TREE;
01345 elt_type = TREE_TYPE (array_type);
01346 if (!lang_hooks.types_compatible_p (orig_type, elt_type))
01347 return NULL_TREE;
01348
01349
01350
01351
01352
01353 elt_size = TYPE_SIZE_UNIT (elt_type);
01354 if (integer_zerop (offset))
01355 {
01356 if (TREE_CODE (elt_size) != INTEGER_CST)
01357 elt_size = size_int (TYPE_ALIGN (elt_type));
01358
01359 idx = integer_zero_node;
01360 }
01361 else
01362 {
01363 unsigned HOST_WIDE_INT lquo, lrem;
01364 HOST_WIDE_INT hquo, hrem;
01365
01366 if (TREE_CODE (elt_size) != INTEGER_CST
01367 || div_and_round_double (TRUNC_DIV_EXPR, 1,
01368 TREE_INT_CST_LOW (offset),
01369 TREE_INT_CST_HIGH (offset),
01370 TREE_INT_CST_LOW (elt_size),
01371 TREE_INT_CST_HIGH (elt_size),
01372 &lquo, &hquo, &lrem, &hrem)
01373 || lrem || hrem)
01374 return NULL_TREE;
01375
01376 idx = build_int_cst_wide (NULL_TREE, lquo, hquo);
01377 }
01378
01379
01380
01381
01382 min_idx = integer_zero_node;
01383 if (TYPE_DOMAIN (array_type))
01384 {
01385 if (TYPE_MIN_VALUE (TYPE_DOMAIN (array_type)))
01386 min_idx = TYPE_MIN_VALUE (TYPE_DOMAIN (array_type));
01387 else
01388 min_idx = fold_convert (TYPE_DOMAIN (array_type), min_idx);
01389
01390 if (TREE_CODE (min_idx) != INTEGER_CST)
01391 return NULL_TREE;
01392
01393 idx = fold_convert (TYPE_DOMAIN (array_type), idx);
01394 elt_offset = fold_convert (TYPE_DOMAIN (array_type), elt_offset);
01395 }
01396
01397 if (!integer_zerop (min_idx))
01398 idx = int_const_binop (PLUS_EXPR, idx, min_idx, 0);
01399 if (!integer_zerop (elt_offset))
01400 idx = int_const_binop (PLUS_EXPR, idx, elt_offset, 0);
01401
01402 return build (ARRAY_REF, orig_type, base, idx, min_idx,
01403 size_int (tree_low_cst (elt_size, 1)
01404 / (TYPE_ALIGN_UNIT (elt_type))));
01405 }
01406
01407
01408
01409
01410
01411
01412
01413 static tree
01414 maybe_fold_offset_to_component_ref (tree record_type, tree base, tree offset,
01415 tree orig_type, bool base_is_ptr)
01416 {
01417 tree f, t, field_type, tail_array_field, field_offset;
01418
01419 if (TREE_CODE (record_type) != RECORD_TYPE
01420 && TREE_CODE (record_type) != UNION_TYPE
01421 && TREE_CODE (record_type) != QUAL_UNION_TYPE)
01422 return NULL_TREE;
01423
01424
01425 if (lang_hooks.types_compatible_p (record_type, orig_type))
01426 return NULL_TREE;
01427
01428 tail_array_field = NULL_TREE;
01429 for (f = TYPE_FIELDS (record_type); f ; f = TREE_CHAIN (f))
01430 {
01431 int cmp;
01432
01433 if (TREE_CODE (f) != FIELD_DECL)
01434 continue;
01435 if (DECL_BIT_FIELD (f))
01436 continue;
01437
01438 field_offset = byte_position (f);
01439 if (TREE_CODE (field_offset) != INTEGER_CST)
01440 continue;
01441
01442
01443
01444
01445 if (!DECL_FIELD_CONTEXT (f))
01446 continue;
01447
01448
01449 tail_array_field = NULL_TREE;
01450
01451
01452 cmp = tree_int_cst_compare (field_offset, offset);
01453 if (cmp > 0)
01454 continue;
01455
01456 field_type = TREE_TYPE (f);
01457
01458
01459
01460 if (cmp == 0
01461 && lang_hooks.types_compatible_p (orig_type, field_type))
01462 {
01463 if (base_is_ptr)
01464 base = build1 (INDIRECT_REF, record_type, base);
01465 t = build (COMPONENT_REF, field_type, base, f, NULL_TREE);
01466 return t;
01467 }
01468
01469
01470 if (!AGGREGATE_TYPE_P (field_type))
01471 continue;
01472
01473
01474
01475
01476 if (TREE_CODE (field_type) == ARRAY_TYPE)
01477 tail_array_field = f;
01478
01479
01480 if (!DECL_SIZE_UNIT (f)
01481 || TREE_CODE (DECL_SIZE_UNIT (f)) != INTEGER_CST)
01482 continue;
01483 t = int_const_binop (MINUS_EXPR, offset, field_offset, 1);
01484 if (!tree_int_cst_lt (t, DECL_SIZE_UNIT (f)))
01485 continue;
01486
01487
01488
01489 offset = t;
01490 goto found;
01491 }
01492
01493 if (!tail_array_field)
01494 return NULL_TREE;
01495
01496 f = tail_array_field;
01497 field_type = TREE_TYPE (f);
01498 offset = int_const_binop (MINUS_EXPR, offset, byte_position (f), 1);
01499
01500 found:
01501
01502
01503 if (base_is_ptr)
01504 base = build1 (INDIRECT_REF, record_type, base);
01505 base = build (COMPONENT_REF, field_type, base, f, NULL_TREE);
01506
01507 t = maybe_fold_offset_to_array_ref (base, offset, orig_type);
01508 if (t)
01509 return t;
01510 return maybe_fold_offset_to_component_ref (field_type, base, offset,
01511 orig_type, false);
01512 }
01513
01514
01515
01516
01517
01518 static tree
01519 maybe_fold_stmt_indirect (tree expr, tree base, tree offset)
01520 {
01521 tree t;
01522
01523
01524
01525
01526 base = fold (base);
01527 STRIP_NOPS (base);
01528 TREE_OPERAND (expr, 0) = base;
01529
01530
01531 t = fold_read_from_constant_string (expr);
01532 if (t)
01533 return t;
01534
01535
01536 if (TREE_CODE (base) == PLUS_EXPR)
01537 {
01538 tree offset2;
01539
01540 offset2 = TREE_OPERAND (base, 1);
01541 if (TREE_CODE (offset2) != INTEGER_CST)
01542 return NULL_TREE;
01543 base = TREE_OPERAND (base, 0);
01544
01545 offset = int_const_binop (PLUS_EXPR, offset, offset2, 1);
01546 }
01547
01548 if (TREE_CODE (base) == ADDR_EXPR)
01549 {
01550
01551 base = TREE_OPERAND (base, 0);
01552
01553
01554 if (TREE_CODE (base) == CONST_DECL
01555 && is_gimple_min_invariant (DECL_INITIAL (base)))
01556 return DECL_INITIAL (base);
01557
01558
01559 t = maybe_fold_offset_to_array_ref (base, offset, TREE_TYPE (expr));
01560 if (t)
01561 return t;
01562
01563
01564 t = maybe_fold_offset_to_component_ref (TREE_TYPE (base), base, offset,
01565 TREE_TYPE (expr), false);
01566 if (t)
01567 return t;
01568
01569
01570
01571
01572 if (integer_zerop (offset)
01573 && lang_hooks.types_compatible_p (TREE_TYPE (base),
01574 TREE_TYPE (expr)))
01575 return base;
01576 }
01577 else
01578 {
01579
01580
01581
01582
01583
01584
01585
01586 t = base;
01587 STRIP_NOPS (t);
01588 if (TREE_CODE (t) == ADDR_EXPR
01589 && TREE_CODE (TREE_OPERAND (t, 0)) == STRING_CST)
01590 {
01591
01592
01593
01594
01595
01596
01597
01598 return integer_zero_node;
01599 }
01600
01601
01602 if (POINTER_TYPE_P (TREE_TYPE (base)))
01603 {
01604 t = maybe_fold_offset_to_component_ref (TREE_TYPE (TREE_TYPE (base)),
01605 base, offset,
01606 TREE_TYPE (expr), true);
01607 if (t)
01608 return t;
01609 }
01610 }
01611
01612
01613 return NULL_TREE;
01614 }
01615
01616
01617
01618
01619
01620
01621
01622
01623
01624
01625
01626
01627
01628
01629
01630 static tree
01631 maybe_fold_stmt_addition (tree expr)
01632 {
01633 tree op0 = TREE_OPERAND (expr, 0);
01634 tree op1 = TREE_OPERAND (expr, 1);
01635 tree ptr_type = TREE_TYPE (expr);
01636 tree ptd_type;
01637 tree t;
01638 bool subtract = (TREE_CODE (expr) == MINUS_EXPR);
01639
01640
01641 if (!POINTER_TYPE_P (ptr_type))
01642 return NULL_TREE;
01643
01644 if (INTEGRAL_TYPE_P (TREE_TYPE (op0)))
01645 {
01646 if (subtract)
01647 return NULL_TREE;
01648 t = op0, op0 = op1, op1 = t;
01649 }
01650
01651 if (TREE_CODE (op1) != INTEGER_CST)
01652 return NULL_TREE;
01653
01654 if (TREE_CODE (op0) != ADDR_EXPR)
01655 return NULL_TREE;
01656 op0 = TREE_OPERAND (op0, 0);
01657
01658
01659
01660 while (TREE_CODE (op0) == ARRAY_REF)
01661 {
01662 tree array_obj = TREE_OPERAND (op0, 0);
01663 tree array_idx = TREE_OPERAND (op0, 1);
01664 tree elt_type = TREE_TYPE (op0);
01665 tree elt_size = TYPE_SIZE_UNIT (elt_type);
01666 tree min_idx;
01667
01668 if (TREE_CODE (array_idx) != INTEGER_CST)
01669 break;
01670 if (TREE_CODE (elt_size) != INTEGER_CST)
01671 break;
01672
01673
01674 min_idx = TYPE_DOMAIN (TREE_TYPE (array_obj));
01675 if (min_idx)
01676 {
01677 min_idx = TYPE_MIN_VALUE (min_idx);
01678 if (min_idx)
01679 {
01680 if (TREE_CODE (min_idx) != INTEGER_CST)
01681 break;
01682
01683 array_idx = convert (TREE_TYPE (min_idx), array_idx);
01684 if (!integer_zerop (min_idx))
01685 array_idx = int_const_binop (MINUS_EXPR, array_idx,
01686 min_idx, 0);
01687 }
01688 }
01689
01690
01691 array_idx = convert (sizetype, array_idx);
01692 array_idx = int_const_binop (MULT_EXPR, array_idx, elt_size, 0);
01693
01694
01695
01696
01697
01698 if (subtract
01699 && TYPE_UNSIGNED (TREE_TYPE (op1))
01700 && tree_int_cst_lt (array_idx, op1))
01701 return NULL;
01702 op1 = int_const_binop (subtract ? MINUS_EXPR : PLUS_EXPR,
01703 array_idx, op1, 0);
01704 subtract = false;
01705 op0 = array_obj;
01706 }
01707
01708
01709
01710
01711 if (subtract)
01712 {
01713 if (TYPE_UNSIGNED (TREE_TYPE (op1)))
01714 return NULL;
01715 op1 = fold (build1 (NEGATE_EXPR, TREE_TYPE (op1), op1));
01716
01717 if (TREE_CODE (op1) != INTEGER_CST)
01718 return NULL;
01719 }
01720
01721 ptd_type = TREE_TYPE (ptr_type);
01722
01723
01724 t = maybe_fold_offset_to_array_ref (op0, op1, ptd_type);
01725 if (!t)
01726 t = maybe_fold_offset_to_component_ref (TREE_TYPE (op0), op0, op1,
01727 ptd_type, false);
01728 if (t)
01729 t = build1 (ADDR_EXPR, ptr_type, t);
01730
01731 return t;
01732 }
01733
01734
01735
01736
01737
01738 static tree
01739 fold_stmt_r (tree *expr_p, int *walk_subtrees, void *data)
01740 {
01741 bool *changed_p = data;
01742 tree expr = *expr_p, t;
01743
01744
01745 switch (TREE_CODE (expr))
01746 {
01747 case INDIRECT_REF:
01748 t = walk_tree (&TREE_OPERAND (expr, 0), fold_stmt_r, data, NULL);
01749 if (t)
01750 return t;
01751 *walk_subtrees = 0;
01752
01753 t = maybe_fold_stmt_indirect (expr, TREE_OPERAND (expr, 0),
01754 integer_zero_node);
01755 break;
01756
01757
01758
01759
01760
01761
01762 case ADDR_EXPR:
01763 t = walk_tree (&TREE_OPERAND (expr, 0), fold_stmt_r, data, NULL);
01764 if (t)
01765 return t;
01766 *walk_subtrees = 0;
01767
01768
01769
01770 if (*changed_p)
01771 recompute_tree_invarant_for_addr_expr (expr);
01772 return NULL_TREE;
01773
01774 case PLUS_EXPR:
01775 case MINUS_EXPR:
01776 t = walk_tree (&TREE_OPERAND (expr, 0), fold_stmt_r, data, NULL);
01777 if (t)
01778 return t;
01779 t = walk_tree (&TREE_OPERAND (expr, 1), fold_stmt_r, data, NULL);
01780 if (t)
01781 return t;
01782 *walk_subtrees = 0;
01783
01784 t = maybe_fold_stmt_addition (expr);
01785 break;
01786
01787 case COMPONENT_REF:
01788 t = walk_tree (&TREE_OPERAND (expr, 0), fold_stmt_r, data, NULL);
01789 if (t)
01790 return t;
01791 *walk_subtrees = 0;
01792
01793
01794
01795
01796 {
01797 tree expr_record = TREE_TYPE (TREE_OPERAND (expr, 0));
01798 tree expr_field = TREE_OPERAND (expr, 1);
01799
01800 if (DECL_FIELD_CONTEXT (expr_field) != TYPE_MAIN_VARIANT (expr_record))
01801 {
01802 expr_field = find_compatible_field (expr_record, expr_field);
01803 TREE_OPERAND (expr, 1) = expr_field;
01804 }
01805 }
01806 break;
01807
01808 default:
01809 return NULL_TREE;
01810 }
01811
01812 if (t)
01813 {
01814 *expr_p = t;
01815 *changed_p = true;
01816 }
01817
01818 return NULL_TREE;
01819 }
01820
01821
01822
01823
01824
01825
01826
01827 static bool
01828 get_strlen (tree arg, tree *length, bitmap visited)
01829 {
01830 tree var, def_stmt, val;
01831
01832 if (TREE_CODE (arg) != SSA_NAME)
01833 {
01834 val = c_strlen (arg, 1);
01835 if (!val)
01836 return false;
01837
01838 if (*length && simple_cst_equal (val, *length) != 1)
01839 return false;
01840
01841 *length = val;
01842 return true;
01843 }
01844
01845
01846 if (bitmap_bit_p (visited, SSA_NAME_VERSION (arg)))
01847 return true;
01848 bitmap_set_bit (visited, SSA_NAME_VERSION (arg));
01849
01850 var = arg;
01851 def_stmt = SSA_NAME_DEF_STMT (var);
01852
01853 switch (TREE_CODE (def_stmt))
01854 {
01855 case MODIFY_EXPR:
01856 {
01857 tree len, rhs;
01858
01859
01860
01861
01862 rhs = TREE_OPERAND (def_stmt, 1);
01863 STRIP_NOPS (rhs);
01864 if (TREE_CODE (rhs) == SSA_NAME)
01865 return get_strlen (rhs, length, visited);
01866
01867
01868 len = c_strlen (rhs, 1);
01869 if (len)
01870 {
01871 if (*length && simple_cst_equal (len, *length) != 1)
01872 return false;
01873
01874 *length = len;
01875 return true;
01876 }
01877
01878 break;
01879 }
01880
01881 case PHI_NODE:
01882 {
01883
01884
01885 int i;
01886
01887 for (i = 0; i < PHI_NUM_ARGS (def_stmt); i++)
01888 {
01889 tree arg = PHI_ARG_DEF (def_stmt, i);
01890
01891
01892
01893
01894
01895
01896
01897 if (arg == PHI_RESULT (def_stmt))
01898 continue;
01899
01900 if (!get_strlen (arg, length, visited))
01901 return false;
01902 }
01903
01904 return true;
01905 }
01906
01907 default:
01908 break;
01909 }
01910
01911
01912 return false;
01913 }
01914
01915
01916
01917
01918
01919 static tree
01920 ccp_fold_builtin (tree stmt, tree fn)
01921 {
01922 tree result, strlen_val[2];
01923 tree callee, arglist, a;
01924 int strlen_arg, i;
01925 bitmap visited;
01926 bool ignore;
01927
01928 ignore = TREE_CODE (stmt) != MODIFY_EXPR;
01929
01930
01931
01932 result = fold_builtin (fn, ignore);
01933 if (result)
01934 {
01935 if (ignore)
01936 STRIP_NOPS (result);
01937 return result;
01938 }
01939
01940
01941 callee = get_callee_fndecl (fn);
01942 if (DECL_BUILT_IN_CLASS (callee) == BUILT_IN_MD)
01943 return NULL_TREE;
01944
01945
01946
01947 arglist = TREE_OPERAND (fn, 1);
01948 if (!arglist)
01949 return NULL_TREE;
01950
01951
01952 switch (DECL_FUNCTION_CODE (callee))
01953 {
01954 case BUILT_IN_STRLEN:
01955 case BUILT_IN_FPUTS:
01956 case BUILT_IN_FPUTS_UNLOCKED:
01957 strlen_arg = 1;
01958 break;
01959 case BUILT_IN_STRCPY:
01960 case BUILT_IN_STRNCPY:
01961 strlen_arg = 2;
01962 break;
01963 default:
01964 return NULL_TREE;
01965 }
01966
01967
01968 visited = BITMAP_ALLOC (NULL);
01969
01970 memset (strlen_val, 0, sizeof (strlen_val));
01971 for (i = 0, a = arglist;
01972 strlen_arg;
01973 i++, strlen_arg >>= 1, a = TREE_CHAIN (a))
01974 if (strlen_arg & 1)
01975 {
01976 bitmap_clear (visited);
01977 if (!get_strlen (TREE_VALUE (a), &strlen_val[i], visited))
01978 strlen_val[i] = NULL_TREE;
01979 }
01980
01981 BITMAP_FREE (visited);
01982
01983 result = NULL_TREE;
01984 switch (DECL_FUNCTION_CODE (callee))
01985 {
01986 case BUILT_IN_STRLEN:
01987 if (strlen_val[0])
01988 {
01989 tree new = fold_convert (TREE_TYPE (fn), strlen_val[0]);
01990
01991
01992
01993 if (is_gimple_val (new)
01994 || (is_gimple_cast (new)
01995 && is_gimple_val (TREE_OPERAND (new, 0))))
01996 return new;
01997 }
01998 break;
01999
02000 case BUILT_IN_STRCPY:
02001 if (strlen_val[1] && is_gimple_val (strlen_val[1]))
02002 result = fold_builtin_strcpy (fn, strlen_val[1]);
02003 break;
02004
02005 case BUILT_IN_STRNCPY:
02006 if (strlen_val[1] && is_gimple_val (strlen_val[1]))
02007 result = fold_builtin_strncpy (fn, strlen_val[1]);
02008 break;
02009
02010 case BUILT_IN_FPUTS:
02011 result = fold_builtin_fputs (arglist,
02012 TREE_CODE (stmt) != MODIFY_EXPR, 0,
02013 strlen_val[0]);
02014 break;
02015
02016 case BUILT_IN_FPUTS_UNLOCKED:
02017 result = fold_builtin_fputs (arglist,
02018 TREE_CODE (stmt) != MODIFY_EXPR, 1,
02019 strlen_val[0]);
02020 break;
02021
02022 default:
02023 gcc_unreachable ();
02024 }
02025
02026 if (result && ignore)
02027 result = fold_ignored_result (result);
02028 return result;
02029 }
02030
02031
02032
02033
02034
02035
02036 bool
02037 fold_stmt (tree *stmt_p)
02038 {
02039 tree rhs, result, stmt;
02040 bool changed = false;
02041
02042 stmt = *stmt_p;
02043
02044
02045
02046 if (walk_tree (stmt_p, fold_stmt_r, &changed, NULL))
02047 {
02048 *stmt_p
02049 = build_function_call_expr (implicit_built_in_decls[BUILT_IN_TRAP],
02050 NULL);
02051 return true;
02052 }
02053
02054 rhs = get_rhs (stmt);
02055 if (!rhs)
02056 return changed;
02057 result = NULL_TREE;
02058
02059 if (TREE_CODE (rhs) == CALL_EXPR)
02060 {
02061 tree callee;
02062
02063
02064
02065 callee = get_callee_fndecl (rhs);
02066 if (callee && DECL_BUILT_IN (callee))
02067 result = ccp_fold_builtin (stmt, rhs);
02068 else
02069 {
02070
02071
02072
02073
02074
02075
02076
02077 callee = TREE_OPERAND (rhs, 0);
02078 if (TREE_CODE (callee) == OBJ_TYPE_REF
02079 && lang_hooks.fold_obj_type_ref
02080 && TREE_CODE (OBJ_TYPE_REF_OBJECT (callee)) == ADDR_EXPR
02081 && DECL_P (TREE_OPERAND
02082 (OBJ_TYPE_REF_OBJECT (callee), 0)))
02083 {
02084 tree t;
02085
02086
02087
02088
02089
02090
02091 t = TREE_TYPE (TREE_TYPE (OBJ_TYPE_REF_OBJECT (callee)));
02092 t = lang_hooks.fold_obj_type_ref (callee, t);
02093 if (t)
02094 {
02095 TREE_OPERAND (rhs, 0) = t;
02096 changed = true;
02097 }
02098 }
02099 }
02100 }
02101
02102
02103 if (result == NULL_TREE)
02104 result = fold (rhs);
02105
02106
02107
02108
02109 STRIP_USELESS_TYPE_CONVERSION (result);
02110
02111 if (result != rhs)
02112 changed |= set_rhs (stmt_p, result);
02113
02114 return changed;
02115 }
02116
02117
02118
02119
02120
02121
02122 static tree
02123 convert_to_gimple_builtin (block_stmt_iterator *si_p, tree expr)
02124 {
02125 tree_stmt_iterator ti;
02126 tree stmt = bsi_stmt (*si_p);
02127 tree tmp, stmts = NULL;
02128
02129 push_gimplify_context ();
02130 tmp = get_initialized_tmp_var (expr, &stmts, NULL);
02131 pop_gimplify_context (NULL);
02132
02133
02134 for (ti = tsi_start (stmts); !tsi_end_p (ti); tsi_next (&ti))
02135 {
02136 find_new_referenced_vars (tsi_stmt_ptr (ti));
02137 mark_new_vars_to_rename (tsi_stmt (ti), vars_to_rename);
02138 }
02139
02140 if (EXPR_HAS_LOCATION (stmt))
02141 annotate_all_with_locus (&stmts, EXPR_LOCATION (stmt));
02142
02143 bsi_insert_before (si_p, stmts, BSI_SAME_STMT);
02144
02145 return tmp;
02146 }
02147
02148
02149
02150
02151
02152 static void
02153 execute_fold_all_builtins (void)
02154 {
02155 bool cfg_changed = false;
02156 basic_block bb;
02157 FOR_EACH_BB (bb)
02158 {
02159 block_stmt_iterator i;
02160 for (i = bsi_start (bb); !bsi_end_p (i); bsi_next (&i))
02161 {
02162 tree *stmtp = bsi_stmt_ptr (i);
02163 tree call = get_rhs (*stmtp);
02164 tree callee, result;
02165
02166 if (!call || TREE_CODE (call) != CALL_EXPR)
02167 continue;
02168 callee = get_callee_fndecl (call);
02169 if (!callee || DECL_BUILT_IN_CLASS (callee) != BUILT_IN_NORMAL)
02170 continue;
02171
02172 result = ccp_fold_builtin (*stmtp, call);
02173 if (!result)
02174 switch (DECL_FUNCTION_CODE (callee))
02175 {
02176 case BUILT_IN_CONSTANT_P:
02177
02178
02179
02180 result = integer_zero_node;
02181 break;
02182
02183 default:
02184 continue;
02185 }
02186
02187 if (dump_file && (dump_flags & TDF_DETAILS))
02188 {
02189 fprintf (dump_file, "Simplified\n ");
02190 print_generic_stmt (dump_file, *stmtp, dump_flags);
02191 }
02192
02193 if (!set_rhs (stmtp, result))
02194 {
02195 result = convert_to_gimple_builtin (&i, result);
02196 if (result && !set_rhs (stmtp, result))
02197 abort ();
02198 }
02199 modify_stmt (*stmtp);
02200 if (maybe_clean_eh_stmt (*stmtp)
02201 && tree_purge_dead_eh_edges (bb))
02202 cfg_changed = true;
02203
02204 if (dump_file && (dump_flags & TDF_DETAILS))
02205 {
02206 fprintf (dump_file, "to\n ");
02207 print_generic_stmt (dump_file, *stmtp, dump_flags);
02208 fprintf (dump_file, "\n");
02209 }
02210 }
02211 }
02212
02213
02214 if (cfg_changed)
02215 cleanup_tree_cfg ();
02216 }
02217
02218
02219 struct tree_opt_pass pass_fold_builtins =
02220 {
02221 "fab",
02222 NULL,
02223 execute_fold_all_builtins,
02224 NULL,
02225 NULL,
02226 0,
02227 0,
02228 PROP_cfg | PROP_ssa | PROP_alias,
02229 0,
02230 0,
02231 0,
02232 TODO_dump_func
02233 | TODO_verify_ssa
02234 | TODO_rename_vars,
02235 0
02236 };