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
00038
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
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191 #include "config.h"
00192 #include "system.h"
00193 #include "coretypes.h"
00194 #include "tm.h"
00195 #include "tree.h"
00196 #include "flags.h"
00197 #include "rtl.h"
00198 #include "tm_p.h"
00199 #include "ggc.h"
00200 #include "basic-block.h"
00201 #include "output.h"
00202 #include "expr.h"
00203 #include "function.h"
00204 #include "diagnostic.h"
00205 #include "timevar.h"
00206 #include "tree-dump.h"
00207 #include "tree-flow.h"
00208 #include "tree-pass.h"
00209 #include "tree-ssa-propagate.h"
00210 #include "langhooks.h"
00211 #include "target.h"
00212 #include "toplev.h"
00213
00214
00215
00216 typedef enum
00217 {
00218 UNINITIALIZED = 0,
00219 UNDEFINED,
00220 UNKNOWN_VAL,
00221 CONSTANT,
00222 VARYING
00223 } ccp_lattice_t;
00224
00225
00226
00227
00228
00229
00230
00231 static prop_value_t *const_val;
00232
00233
00234 static bool do_store_ccp;
00235
00236
00237
00238 static void
00239 dump_lattice_value (FILE *outf, const char *prefix, prop_value_t val)
00240 {
00241 switch (val.lattice_val)
00242 {
00243 case UNINITIALIZED:
00244 fprintf (outf, "%sUNINITIALIZED", prefix);
00245 break;
00246 case UNDEFINED:
00247 fprintf (outf, "%sUNDEFINED", prefix);
00248 break;
00249 case VARYING:
00250 fprintf (outf, "%sVARYING", prefix);
00251 break;
00252 case UNKNOWN_VAL:
00253 fprintf (outf, "%sUNKNOWN_VAL", prefix);
00254 break;
00255 case CONSTANT:
00256 fprintf (outf, "%sCONSTANT ", prefix);
00257 print_generic_expr (outf, val.value, dump_flags);
00258 break;
00259 default:
00260 gcc_unreachable ();
00261 }
00262 }
00263
00264
00265
00266
00267 void debug_lattice_value (prop_value_t val);
00268
00269 void
00270 debug_lattice_value (prop_value_t val)
00271 {
00272 dump_lattice_value (stderr, "", val);
00273 fprintf (stderr, "\n");
00274 }
00275
00276
00277
00278
00279
00280
00281
00282 static bool
00283 ccp_decl_initial_min_invariant (tree t)
00284 {
00285 if (!is_gimple_min_invariant (t))
00286 return false;
00287 if (TREE_CODE (t) == ADDR_EXPR)
00288 {
00289
00290 while (1)
00291 {
00292 t = TREE_OPERAND (t, 0);
00293 if (is_gimple_id (t))
00294 return true;
00295 if (!handled_component_p (t))
00296 return false;
00297 }
00298 }
00299 return true;
00300 }
00301
00302
00303
00304
00305
00306
00307
00308
00309
00310
00311
00312
00313
00314
00315
00316
00317
00318
00319
00320
00321
00322
00323
00324
00325
00326 static prop_value_t
00327 get_default_value (tree var)
00328 {
00329 tree sym = SSA_NAME_VAR (var);
00330 prop_value_t val = { UNINITIALIZED, NULL_TREE, NULL_TREE };
00331
00332 if (!do_store_ccp && !is_gimple_reg (var))
00333 {
00334
00335
00336 val.lattice_val = VARYING;
00337 }
00338 else if (SSA_NAME_VALUE (var)
00339 && is_gimple_min_invariant (SSA_NAME_VALUE (var)))
00340 {
00341 val.lattice_val = CONSTANT;
00342 val.value = SSA_NAME_VALUE (var);
00343 }
00344 else if (TREE_STATIC (sym)
00345 && TREE_READONLY (sym)
00346 && !MTAG_P (sym)
00347 && DECL_INITIAL (sym)
00348 && ccp_decl_initial_min_invariant (DECL_INITIAL (sym)))
00349 {
00350
00351
00352 val.lattice_val = CONSTANT;
00353 val.value = DECL_INITIAL (sym);
00354 val.mem_ref = sym;
00355 }
00356 else
00357 {
00358 tree stmt = SSA_NAME_DEF_STMT (var);
00359
00360 if (IS_EMPTY_STMT (stmt))
00361 {
00362
00363
00364
00365
00366
00367
00368
00369 if (is_gimple_reg (sym) && TREE_CODE (sym) != PARM_DECL)
00370 val.lattice_val = UNDEFINED;
00371 else if (do_store_ccp)
00372 val.lattice_val = UNKNOWN_VAL;
00373 else
00374 val.lattice_val = VARYING;
00375 }
00376 else if (TREE_CODE (stmt) == MODIFY_EXPR
00377 || TREE_CODE (stmt) == PHI_NODE)
00378 {
00379
00380
00381
00382 val.lattice_val = is_gimple_reg (sym) ? UNDEFINED : UNKNOWN_VAL;
00383 }
00384 else
00385 {
00386
00387 val.lattice_val = VARYING;
00388 }
00389 }
00390
00391 return val;
00392 }
00393
00394
00395
00396
00397
00398
00399 static prop_value_t *
00400 get_value (tree var, bool may_use_default_p)
00401 {
00402 prop_value_t *val = &const_val[SSA_NAME_VERSION (var)];
00403 if (may_use_default_p && val->lattice_val == UNINITIALIZED)
00404 *val = get_default_value (var);
00405
00406 return val;
00407 }
00408
00409
00410
00411
00412
00413 static bool
00414 set_lattice_value (tree var, prop_value_t new_val)
00415 {
00416 prop_value_t *old_val = get_value (var, false);
00417
00418
00419
00420
00421
00422
00423
00424
00425
00426
00427
00428
00429 gcc_assert (old_val->lattice_val <= new_val.lattice_val
00430 || (old_val->lattice_val == new_val.lattice_val
00431 && old_val->value == new_val.value
00432 && old_val->mem_ref == new_val.mem_ref)
00433 || (do_store_ccp
00434 && old_val->lattice_val == CONSTANT
00435 && new_val.lattice_val == UNKNOWN_VAL));
00436
00437 if (old_val->lattice_val != new_val.lattice_val)
00438 {
00439 if (dump_file && (dump_flags & TDF_DETAILS))
00440 {
00441 dump_lattice_value (dump_file, "Lattice value changed to ", new_val);
00442 fprintf (dump_file, ". %sdding SSA edges to worklist.\n",
00443 new_val.lattice_val != UNDEFINED ? "A" : "Not a");
00444 }
00445
00446 *old_val = new_val;
00447
00448
00449
00450
00451 return (new_val.lattice_val != UNDEFINED);
00452 }
00453
00454 return false;
00455 }
00456
00457
00458
00459
00460
00461
00462
00463
00464
00465
00466
00467
00468 static ccp_lattice_t
00469 likely_value (tree stmt)
00470 {
00471 bool found_constant;
00472 stmt_ann_t ann;
00473 tree use;
00474 ssa_op_iter iter;
00475
00476 ann = stmt_ann (stmt);
00477
00478
00479
00480 if (ann->has_volatile_ops)
00481 return VARYING;
00482
00483
00484
00485 if (!do_store_ccp
00486 && !ZERO_SSA_OPERANDS (stmt, SSA_OP_ALL_VIRTUALS))
00487 return VARYING;
00488
00489
00490
00491
00492 if (get_call_expr_in (stmt) != NULL_TREE)
00493 return VARYING;
00494
00495
00496
00497 if (TREE_CODE (stmt) != MODIFY_EXPR
00498 && TREE_CODE (stmt) != COND_EXPR
00499 && TREE_CODE (stmt) != SWITCH_EXPR)
00500 return VARYING;
00501
00502 if (is_gimple_min_invariant (get_rhs (stmt)))
00503 return CONSTANT;
00504
00505 found_constant = false;
00506 FOR_EACH_SSA_TREE_OPERAND (use, stmt, iter, SSA_OP_USE|SSA_OP_VUSE)
00507 {
00508 prop_value_t *val = get_value (use, true);
00509
00510 if (val->lattice_val == VARYING)
00511 return VARYING;
00512
00513 if (val->lattice_val == UNKNOWN_VAL)
00514 {
00515
00516 gcc_assert (do_store_ccp);
00517 return UNKNOWN_VAL;
00518 }
00519
00520 if (val->lattice_val == CONSTANT)
00521 found_constant = true;
00522 }
00523
00524 if (found_constant
00525 || ZERO_SSA_OPERANDS (stmt, SSA_OP_USE)
00526 || ZERO_SSA_OPERANDS (stmt, SSA_OP_VUSE))
00527 return CONSTANT;
00528
00529 return UNDEFINED;
00530 }
00531
00532
00533
00534
00535 static void
00536 ccp_initialize (void)
00537 {
00538 basic_block bb;
00539
00540 const_val = XNEWVEC (prop_value_t, num_ssa_names);
00541 memset (const_val, 0, num_ssa_names * sizeof (*const_val));
00542
00543
00544 FOR_EACH_BB (bb)
00545 {
00546 block_stmt_iterator i;
00547
00548 for (i = bsi_start (bb); !bsi_end_p (i); bsi_next (&i))
00549 {
00550 bool is_varying = false;
00551 tree stmt = bsi_stmt (i);
00552
00553 if (likely_value (stmt) == VARYING)
00554
00555 {
00556 tree def;
00557 ssa_op_iter iter;
00558
00559
00560
00561 FOR_EACH_SSA_TREE_OPERAND (def, stmt, iter, SSA_OP_ALL_DEFS)
00562 get_value (def, false)->lattice_val = VARYING;
00563
00564
00565
00566
00567 if (TREE_CODE (stmt) != COND_EXPR
00568 && TREE_CODE (stmt) != SWITCH_EXPR)
00569 is_varying = true;
00570 }
00571
00572 DONT_SIMULATE_AGAIN (stmt) = is_varying;
00573 }
00574 }
00575
00576
00577 FOR_EACH_BB (bb)
00578 {
00579 tree phi;
00580
00581 for (phi = phi_nodes (bb); phi; phi = PHI_CHAIN (phi))
00582 {
00583 int i;
00584 tree arg;
00585 prop_value_t *val = get_value (PHI_RESULT (phi), false);
00586
00587 for (i = 0; i < PHI_NUM_ARGS (phi); i++)
00588 {
00589 arg = PHI_ARG_DEF (phi, i);
00590
00591 if (TREE_CODE (arg) == SSA_NAME
00592 && get_value (arg, false)->lattice_val == VARYING)
00593 {
00594 val->lattice_val = VARYING;
00595 break;
00596 }
00597 }
00598
00599 DONT_SIMULATE_AGAIN (phi) = (val->lattice_val == VARYING);
00600 }
00601 }
00602 }
00603
00604
00605
00606
00607
00608 static void
00609 ccp_finalize (void)
00610 {
00611
00612 substitute_and_fold (const_val, false);
00613
00614 free (const_val);
00615 }
00616
00617
00618
00619
00620
00621
00622
00623
00624
00625
00626
00627
00628
00629
00630
00631
00632
00633
00634
00635
00636
00637
00638
00639
00640
00641
00642
00643
00644
00645
00646
00647
00648
00649
00650
00651
00652
00653 static void
00654 ccp_lattice_meet (prop_value_t *val1, prop_value_t *val2)
00655 {
00656 if (val1->lattice_val == UNDEFINED)
00657 {
00658
00659 *val1 = *val2;
00660 }
00661 else if (val2->lattice_val == UNDEFINED)
00662 {
00663
00664
00665 ;
00666 }
00667 else if (val1->lattice_val == UNKNOWN_VAL
00668 || val2->lattice_val == UNKNOWN_VAL)
00669 {
00670
00671 gcc_assert (do_store_ccp);
00672
00673
00674 val1->lattice_val = UNKNOWN_VAL;
00675 val1->value = NULL_TREE;
00676 val1->mem_ref = NULL_TREE;
00677 }
00678 else if (val1->lattice_val == VARYING
00679 || val2->lattice_val == VARYING)
00680 {
00681
00682 val1->lattice_val = VARYING;
00683 val1->value = NULL_TREE;
00684 val1->mem_ref = NULL_TREE;
00685 }
00686 else if (val1->lattice_val == CONSTANT
00687 && val2->lattice_val == CONSTANT
00688 && simple_cst_equal (val1->value, val2->value) == 1
00689 && (!do_store_ccp
00690 || (val1->mem_ref && val2->mem_ref
00691 && operand_equal_p (val1->mem_ref, val2->mem_ref, 0))))
00692 {
00693
00694
00695
00696
00697
00698 val1->lattice_val = CONSTANT;
00699 val1->value = val1->value;
00700 val1->mem_ref = val1->mem_ref;
00701 }
00702 else
00703 {
00704
00705 val1->lattice_val = VARYING;
00706 val1->value = NULL_TREE;
00707 val1->mem_ref = NULL_TREE;
00708 }
00709 }
00710
00711
00712
00713
00714
00715
00716
00717 static enum ssa_prop_result
00718 ccp_visit_phi_node (tree phi)
00719 {
00720 int i;
00721 prop_value_t *old_val, new_val;
00722
00723 if (dump_file && (dump_flags & TDF_DETAILS))
00724 {
00725 fprintf (dump_file, "\nVisiting PHI node: ");
00726 print_generic_expr (dump_file, phi, dump_flags);
00727 }
00728
00729 old_val = get_value (PHI_RESULT (phi), false);
00730 switch (old_val->lattice_val)
00731 {
00732 case VARYING:
00733 return SSA_PROP_VARYING;
00734
00735 case CONSTANT:
00736 new_val = *old_val;
00737 break;
00738
00739 case UNKNOWN_VAL:
00740
00741
00742
00743
00744
00745
00746 gcc_assert (do_store_ccp);
00747
00748
00749
00750 case UNDEFINED:
00751 case UNINITIALIZED:
00752 new_val.lattice_val = UNDEFINED;
00753 new_val.value = NULL_TREE;
00754 new_val.mem_ref = NULL_TREE;
00755 break;
00756
00757 default:
00758 gcc_unreachable ();
00759 }
00760
00761 for (i = 0; i < PHI_NUM_ARGS (phi); i++)
00762 {
00763
00764
00765 edge e = PHI_ARG_EDGE (phi, i);
00766
00767 if (dump_file && (dump_flags & TDF_DETAILS))
00768 {
00769 fprintf (dump_file,
00770 "\n Argument #%d (%d -> %d %sexecutable)\n",
00771 i, e->src->index, e->dest->index,
00772 (e->flags & EDGE_EXECUTABLE) ? "" : "not ");
00773 }
00774
00775
00776
00777 if (e->flags & EDGE_EXECUTABLE)
00778 {
00779 tree arg = PHI_ARG_DEF (phi, i);
00780 prop_value_t arg_val;
00781
00782 if (is_gimple_min_invariant (arg))
00783 {
00784 arg_val.lattice_val = CONSTANT;
00785 arg_val.value = arg;
00786 arg_val.mem_ref = NULL_TREE;
00787 }
00788 else
00789 arg_val = *(get_value (arg, true));
00790
00791 ccp_lattice_meet (&new_val, &arg_val);
00792
00793 if (dump_file && (dump_flags & TDF_DETAILS))
00794 {
00795 fprintf (dump_file, "\t");
00796 print_generic_expr (dump_file, arg, dump_flags);
00797 dump_lattice_value (dump_file, "\tValue: ", arg_val);
00798 fprintf (dump_file, "\n");
00799 }
00800
00801 if (new_val.lattice_val == VARYING)
00802 break;
00803 }
00804 }
00805
00806 if (dump_file && (dump_flags & TDF_DETAILS))
00807 {
00808 dump_lattice_value (dump_file, "\n PHI node value: ", new_val);
00809 fprintf (dump_file, "\n\n");
00810 }
00811
00812
00813 if (do_store_ccp
00814 && old_val->lattice_val == UNKNOWN_VAL
00815 && new_val.lattice_val == UNDEFINED)
00816 return SSA_PROP_NOT_INTERESTING;
00817
00818
00819 if (set_lattice_value (PHI_RESULT (phi), new_val))
00820 {
00821 if (new_val.lattice_val == VARYING)
00822 return SSA_PROP_VARYING;
00823 else
00824 return SSA_PROP_INTERESTING;
00825 }
00826 else
00827 return SSA_PROP_NOT_INTERESTING;
00828 }
00829
00830
00831
00832
00833
00834
00835
00836
00837
00838
00839
00840 static tree
00841 ccp_fold (tree stmt)
00842 {
00843 tree rhs = get_rhs (stmt);
00844 enum tree_code code = TREE_CODE (rhs);
00845 enum tree_code_class kind = TREE_CODE_CLASS (code);
00846 tree retval = NULL_TREE;
00847
00848 if (TREE_CODE (rhs) == SSA_NAME)
00849 {
00850
00851
00852 return get_value (rhs, true)->value;
00853 }
00854 else if (do_store_ccp && stmt_makes_single_load (stmt))
00855 {
00856
00857
00858 prop_value_t *val = get_value_loaded_by (stmt, const_val);
00859 if (val && val->mem_ref)
00860 {
00861 if (operand_equal_p (val->mem_ref, rhs, 0))
00862 return val->value;
00863
00864
00865
00866 if ((TREE_CODE (rhs) == REALPART_EXPR
00867 || TREE_CODE (rhs) == IMAGPART_EXPR)
00868 && operand_equal_p (val->mem_ref, TREE_OPERAND (rhs, 0), 0))
00869 return fold_build1 (TREE_CODE (rhs), TREE_TYPE (rhs), val->value);
00870 }
00871 return NULL_TREE;
00872 }
00873
00874
00875
00876
00877 if (kind == tcc_unary)
00878 {
00879
00880 tree op0 = TREE_OPERAND (rhs, 0);
00881
00882
00883 if (TREE_CODE (op0) == SSA_NAME)
00884 {
00885 prop_value_t *val = get_value (op0, true);
00886 if (val->lattice_val == CONSTANT)
00887 op0 = get_value (op0, true)->value;
00888 }
00889
00890 if ((code == NOP_EXPR || code == CONVERT_EXPR)
00891 && tree_ssa_useless_type_conversion_1 (TREE_TYPE (rhs),
00892 TREE_TYPE (op0)))
00893 return op0;
00894 return fold_unary (code, TREE_TYPE (rhs), op0);
00895 }
00896
00897
00898
00899 else if (kind == tcc_binary
00900 || kind == tcc_comparison
00901 || code == TRUTH_AND_EXPR
00902 || code == TRUTH_OR_EXPR
00903 || code == TRUTH_XOR_EXPR)
00904 {
00905
00906
00907 tree op0 = TREE_OPERAND (rhs, 0);
00908 tree op1 = TREE_OPERAND (rhs, 1);
00909
00910
00911 if (TREE_CODE (op0) == SSA_NAME)
00912 {
00913 prop_value_t *val = get_value (op0, true);
00914 if (val->lattice_val == CONSTANT)
00915 op0 = val->value;
00916 }
00917
00918 if (TREE_CODE (op1) == SSA_NAME)
00919 {
00920 prop_value_t *val = get_value (op1, true);
00921 if (val->lattice_val == CONSTANT)
00922 op1 = val->value;
00923 }
00924
00925 return fold_binary (code, TREE_TYPE (rhs), op0, op1);
00926 }
00927
00928
00929
00930 else if (code == CALL_EXPR
00931 && TREE_CODE (TREE_OPERAND (rhs, 0)) == ADDR_EXPR
00932 && (TREE_CODE (TREE_OPERAND (TREE_OPERAND (rhs, 0), 0))
00933 == FUNCTION_DECL)
00934 && DECL_BUILT_IN (TREE_OPERAND (TREE_OPERAND (rhs, 0), 0)))
00935 {
00936 if (!ZERO_SSA_OPERANDS (stmt, SSA_OP_USE))
00937 {
00938 tree *orig, var;
00939 tree fndecl, arglist;
00940 size_t i = 0;
00941 ssa_op_iter iter;
00942 use_operand_p var_p;
00943
00944
00945 orig = XNEWVEC (tree, NUM_SSA_OPERANDS (stmt, SSA_OP_USE));
00946 FOR_EACH_SSA_TREE_OPERAND (var, stmt, iter, SSA_OP_USE)
00947 orig[i++] = var;
00948
00949
00950 replace_uses_in (stmt, NULL, const_val);
00951 fndecl = get_callee_fndecl (rhs);
00952 arglist = TREE_OPERAND (rhs, 1);
00953 retval = fold_builtin (fndecl, arglist, false);
00954
00955
00956 i = 0;
00957 FOR_EACH_SSA_USE_OPERAND (var_p, stmt, iter, SSA_OP_USE)
00958 SET_USE (var_p, orig[i++]);
00959 free (orig);
00960 }
00961 }
00962 else
00963 return rhs;
00964
00965
00966 if (retval)
00967 return fold_convert (TREE_TYPE (rhs), retval);
00968
00969
00970 return rhs;
00971 }
00972
00973
00974
00975
00976
00977
00978 static tree
00979 fold_const_aggregate_ref (tree t)
00980 {
00981 prop_value_t *value;
00982 tree base, ctor, idx, field;
00983 unsigned HOST_WIDE_INT cnt;
00984 tree cfield, cval;
00985
00986 switch (TREE_CODE (t))
00987 {
00988 case ARRAY_REF:
00989
00990
00991
00992
00993 base = TREE_OPERAND (t, 0);
00994 switch (TREE_CODE (base))
00995 {
00996 case VAR_DECL:
00997 if (!TREE_READONLY (base)
00998 || TREE_CODE (TREE_TYPE (base)) != ARRAY_TYPE
00999 || !targetm.binds_local_p (base))
01000 return NULL_TREE;
01001
01002 ctor = DECL_INITIAL (base);
01003 break;
01004
01005 case ARRAY_REF:
01006 case COMPONENT_REF:
01007 ctor = fold_const_aggregate_ref (base);
01008 break;
01009
01010 default:
01011 return NULL_TREE;
01012 }
01013
01014 if (ctor == NULL_TREE
01015 || (TREE_CODE (ctor) != CONSTRUCTOR
01016 && TREE_CODE (ctor) != STRING_CST)
01017 || !TREE_STATIC (ctor))
01018 return NULL_TREE;
01019
01020
01021
01022 idx = TREE_OPERAND (t, 1);
01023 switch (TREE_CODE (idx))
01024 {
01025 case SSA_NAME:
01026 if ((value = get_value (idx, true))
01027 && value->lattice_val == CONSTANT
01028 && TREE_CODE (value->value) == INTEGER_CST)
01029 idx = value->value;
01030 else
01031 return NULL_TREE;
01032 break;
01033
01034 case INTEGER_CST:
01035 break;
01036
01037 default:
01038 return NULL_TREE;
01039 }
01040
01041
01042 if (TREE_CODE (ctor) == STRING_CST)
01043 {
01044 if ((TYPE_MODE (TREE_TYPE (t))
01045 == TYPE_MODE (TREE_TYPE (TREE_TYPE (ctor))))
01046 && (GET_MODE_CLASS (TYPE_MODE (TREE_TYPE (TREE_TYPE (ctor))))
01047 == MODE_INT)
01048 && GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (TREE_TYPE (ctor)))) == 1
01049 && compare_tree_int (idx, TREE_STRING_LENGTH (ctor)) < 0)
01050 return build_int_cst (TREE_TYPE (t), (TREE_STRING_POINTER (ctor)
01051 [TREE_INT_CST_LOW (idx)]));
01052 return NULL_TREE;
01053 }
01054
01055
01056 FOR_EACH_CONSTRUCTOR_ELT (CONSTRUCTOR_ELTS (ctor), cnt, cfield, cval)
01057 if (tree_int_cst_equal (cfield, idx))
01058 return cval;
01059 break;
01060
01061 case COMPONENT_REF:
01062
01063
01064
01065
01066 base = TREE_OPERAND (t, 0);
01067 switch (TREE_CODE (base))
01068 {
01069 case VAR_DECL:
01070 if (!TREE_READONLY (base)
01071 || TREE_CODE (TREE_TYPE (base)) != RECORD_TYPE
01072 || !targetm.binds_local_p (base))
01073 return NULL_TREE;
01074
01075 ctor = DECL_INITIAL (base);
01076 break;
01077
01078 case ARRAY_REF:
01079 case COMPONENT_REF:
01080 ctor = fold_const_aggregate_ref (base);
01081 break;
01082
01083 default:
01084 return NULL_TREE;
01085 }
01086
01087 if (ctor == NULL_TREE
01088 || TREE_CODE (ctor) != CONSTRUCTOR
01089 || !TREE_STATIC (ctor))
01090 return NULL_TREE;
01091
01092 field = TREE_OPERAND (t, 1);
01093
01094 FOR_EACH_CONSTRUCTOR_ELT (CONSTRUCTOR_ELTS (ctor), cnt, cfield, cval)
01095 if (cfield == field
01096
01097 && ! DECL_BIT_FIELD (cfield))
01098 return cval;
01099 break;
01100
01101 case REALPART_EXPR:
01102 case IMAGPART_EXPR:
01103 {
01104 tree c = fold_const_aggregate_ref (TREE_OPERAND (t, 0));
01105 if (c && TREE_CODE (c) == COMPLEX_CST)
01106 return fold_build1 (TREE_CODE (t), TREE_TYPE (t), c);
01107 break;
01108 }
01109
01110 default:
01111 break;
01112 }
01113
01114 return NULL_TREE;
01115 }
01116
01117
01118
01119 static prop_value_t
01120 evaluate_stmt (tree stmt)
01121 {
01122 prop_value_t val;
01123 tree simplified = NULL_TREE;
01124 ccp_lattice_t likelyvalue = likely_value (stmt);
01125 bool is_constant;
01126
01127 val.mem_ref = NULL_TREE;
01128
01129 fold_defer_overflow_warnings ();
01130
01131
01132
01133 if (likelyvalue == CONSTANT)
01134 simplified = ccp_fold (stmt);
01135
01136
01137 if (likelyvalue == VARYING)
01138 simplified = get_rhs (stmt);
01139
01140
01141
01142
01143
01144 else if (!simplified)
01145 simplified = fold_const_aggregate_ref (get_rhs (stmt));
01146
01147 is_constant = simplified && is_gimple_min_invariant (simplified);
01148
01149 fold_undefer_overflow_warnings (is_constant, stmt, 0);
01150
01151 if (is_constant)
01152 {
01153
01154 val.lattice_val = CONSTANT;
01155 val.value = simplified;
01156 }
01157 else
01158 {
01159
01160
01161
01162 if (likelyvalue == UNDEFINED || likelyvalue == UNKNOWN_VAL)
01163 val.lattice_val = likelyvalue;
01164 else
01165 val.lattice_val = VARYING;
01166
01167 val.value = NULL_TREE;
01168 }
01169
01170 return val;
01171 }
01172
01173
01174
01175
01176
01177
01178
01179 static enum ssa_prop_result
01180 visit_assignment (tree stmt, tree *output_p)
01181 {
01182 prop_value_t val;
01183 tree lhs, rhs;
01184 enum ssa_prop_result retval;
01185
01186 lhs = TREE_OPERAND (stmt, 0);
01187 rhs = TREE_OPERAND (stmt, 1);
01188
01189 if (TREE_CODE (rhs) == SSA_NAME)
01190 {
01191
01192 prop_value_t *nval = get_value (rhs, true);
01193 val = *nval;
01194 }
01195 else if (do_store_ccp && stmt_makes_single_load (stmt))
01196 {
01197
01198
01199
01200
01201 prop_value_t *nval = get_value_loaded_by (stmt, const_val);
01202
01203 if (nval && nval->mem_ref
01204 && operand_equal_p (nval->mem_ref, rhs, 0))
01205 val = *nval;
01206 else
01207 val = evaluate_stmt (stmt);
01208 }
01209 else
01210
01211 val = evaluate_stmt (stmt);
01212
01213
01214
01215
01216
01217
01218
01219 {
01220 tree orig_lhs = TREE_OPERAND (stmt, 0);
01221
01222 if (TREE_CODE (orig_lhs) == VIEW_CONVERT_EXPR
01223 && val.lattice_val == CONSTANT)
01224 {
01225 tree w = fold_unary (VIEW_CONVERT_EXPR,
01226 TREE_TYPE (TREE_OPERAND (orig_lhs, 0)),
01227 val.value);
01228
01229 orig_lhs = TREE_OPERAND (orig_lhs, 0);
01230 if (w && is_gimple_min_invariant (w))
01231 val.value = w;
01232 else
01233 {
01234 val.lattice_val = VARYING;
01235 val.value = NULL;
01236 }
01237 }
01238
01239 if (val.lattice_val == CONSTANT
01240 && TREE_CODE (orig_lhs) == COMPONENT_REF
01241 && DECL_BIT_FIELD (TREE_OPERAND (orig_lhs, 1)))
01242 {
01243 tree w = widen_bitfield (val.value, TREE_OPERAND (orig_lhs, 1),
01244 orig_lhs);
01245
01246 if (w && is_gimple_min_invariant (w))
01247 val.value = w;
01248 else
01249 {
01250 val.lattice_val = VARYING;
01251 val.value = NULL_TREE;
01252 val.mem_ref = NULL_TREE;
01253 }
01254 }
01255 }
01256
01257 retval = SSA_PROP_NOT_INTERESTING;
01258
01259
01260 if (TREE_CODE (lhs) == SSA_NAME)
01261 {
01262
01263
01264 if (set_lattice_value (lhs, val))
01265 {
01266 *output_p = lhs;
01267 if (val.lattice_val == VARYING)
01268 retval = SSA_PROP_VARYING;
01269 else
01270 retval = SSA_PROP_INTERESTING;
01271 }
01272 }
01273 else if (do_store_ccp && stmt_makes_single_store (stmt))
01274 {
01275
01276
01277
01278 ssa_op_iter i;
01279 tree vdef;
01280 bool changed;
01281
01282
01283 if (val.lattice_val == UNDEFINED)
01284 val.lattice_val = UNKNOWN_VAL;
01285
01286
01287 val.mem_ref = lhs;
01288
01289
01290 changed = false;
01291 FOR_EACH_SSA_TREE_OPERAND (vdef, stmt, i, SSA_OP_VIRTUAL_DEFS)
01292 changed |= set_lattice_value (vdef, val);
01293
01294
01295
01296
01297
01298
01299 *output_p = first_vdef (stmt);
01300 if (changed)
01301 {
01302 if (val.lattice_val == VARYING)
01303 retval = SSA_PROP_VARYING;
01304 else
01305 retval = SSA_PROP_INTERESTING;
01306 }
01307 }
01308
01309 return retval;
01310 }
01311
01312
01313
01314
01315
01316
01317 static enum ssa_prop_result
01318 visit_cond_stmt (tree stmt, edge *taken_edge_p)
01319 {
01320 prop_value_t val;
01321 basic_block block;
01322
01323 block = bb_for_stmt (stmt);
01324 val = evaluate_stmt (stmt);
01325
01326
01327
01328
01329
01330 *taken_edge_p = val.value ? find_taken_edge (block, val.value) : 0;
01331 if (*taken_edge_p)
01332 return SSA_PROP_INTERESTING;
01333 else
01334 return SSA_PROP_VARYING;
01335 }
01336
01337
01338
01339
01340
01341
01342
01343
01344
01345
01346
01347 static enum ssa_prop_result
01348 ccp_visit_stmt (tree stmt, edge *taken_edge_p, tree *output_p)
01349 {
01350 tree def;
01351 ssa_op_iter iter;
01352
01353 if (dump_file && (dump_flags & TDF_DETAILS))
01354 {
01355 fprintf (dump_file, "\nVisiting statement:\n");
01356 print_generic_stmt (dump_file, stmt, dump_flags);
01357 fprintf (dump_file, "\n");
01358 }
01359
01360 if (TREE_CODE (stmt) == MODIFY_EXPR)
01361 {
01362
01363
01364
01365 return visit_assignment (stmt, output_p);
01366 }
01367 else if (TREE_CODE (stmt) == COND_EXPR || TREE_CODE (stmt) == SWITCH_EXPR)
01368 {
01369
01370
01371 return visit_cond_stmt (stmt, taken_edge_p);
01372 }
01373
01374
01375
01376 if (dump_file && (dump_flags & TDF_DETAILS))
01377 fprintf (dump_file, "No interesting values produced. Marked VARYING.\n");
01378
01379
01380
01381
01382 FOR_EACH_SSA_TREE_OPERAND (def, stmt, iter, SSA_OP_ALL_DEFS)
01383 {
01384 prop_value_t v = { VARYING, NULL_TREE, NULL_TREE };
01385 set_lattice_value (def, v);
01386 }
01387
01388 return SSA_PROP_VARYING;
01389 }
01390
01391
01392
01393
01394 static void
01395 execute_ssa_ccp (bool store_ccp)
01396 {
01397 do_store_ccp = store_ccp;
01398 ccp_initialize ();
01399 ssa_propagate (ccp_visit_stmt, ccp_visit_phi_node);
01400 ccp_finalize ();
01401 }
01402
01403
01404 static unsigned int
01405 do_ssa_ccp (void)
01406 {
01407 execute_ssa_ccp (false);
01408 return 0;
01409 }
01410
01411
01412 static bool
01413 gate_ccp (void)
01414 {
01415 return flag_tree_ccp != 0;
01416 }
01417
01418
01419 struct tree_opt_pass pass_ccp =
01420 {
01421 "ccp",
01422 gate_ccp,
01423 do_ssa_ccp,
01424 NULL,
01425 NULL,
01426 0,
01427 TV_TREE_CCP,
01428 PROP_cfg | PROP_ssa | PROP_alias,
01429 0,
01430 PROP_smt_usage,
01431 0,
01432 TODO_cleanup_cfg | TODO_dump_func | TODO_update_ssa
01433 | TODO_ggc_collect | TODO_verify_ssa
01434 | TODO_verify_stmts | TODO_update_smt_usage,
01435 0
01436 };
01437
01438
01439 static unsigned int
01440 do_ssa_store_ccp (void)
01441 {
01442
01443 execute_ssa_ccp (flag_tree_store_ccp != 0);
01444 return 0;
01445 }
01446
01447 static bool
01448 gate_store_ccp (void)
01449 {
01450
01451
01452
01453 return flag_tree_store_ccp != 0 || flag_tree_ccp != 0;
01454 }
01455
01456
01457 struct tree_opt_pass pass_store_ccp =
01458 {
01459 "store_ccp",
01460 gate_store_ccp,
01461 do_ssa_store_ccp,
01462 NULL,
01463 NULL,
01464 0,
01465 TV_TREE_STORE_CCP,
01466 PROP_cfg | PROP_ssa | PROP_alias,
01467 0,
01468 PROP_smt_usage,
01469 0,
01470 TODO_dump_func | TODO_update_ssa
01471 | TODO_ggc_collect | TODO_verify_ssa
01472 | TODO_cleanup_cfg
01473 | TODO_verify_stmts | TODO_update_smt_usage,
01474 0
01475 };
01476
01477
01478
01479
01480
01481 tree
01482 widen_bitfield (tree val, tree field, tree var)
01483 {
01484 unsigned HOST_WIDE_INT var_size, field_size;
01485 tree wide_val;
01486 unsigned HOST_WIDE_INT mask;
01487 unsigned int i;
01488
01489
01490
01491 if (!host_integerp (TYPE_SIZE (TREE_TYPE (var)), 1)
01492 || !host_integerp (DECL_SIZE (field), 1)
01493 || !host_integerp (val, 0))
01494 return NULL_TREE;
01495
01496 var_size = tree_low_cst (TYPE_SIZE (TREE_TYPE (var)), 1);
01497 field_size = tree_low_cst (DECL_SIZE (field), 1);
01498
01499
01500 if (field_size > HOST_BITS_PER_WIDE_INT || var_size > HOST_BITS_PER_WIDE_INT)
01501 return NULL_TREE;
01502
01503 gcc_assert (var_size >= field_size);
01504
01505
01506
01507 if (DECL_UNSIGNED (field)
01508 || !(tree_low_cst (val, 0) & (((HOST_WIDE_INT)1) << (field_size - 1))))
01509 {
01510
01511
01512
01513 for (i = 0, mask = 0; i < field_size; i++)
01514 mask |= ((HOST_WIDE_INT) 1) << i;
01515
01516 wide_val = fold_build2 (BIT_AND_EXPR, TREE_TYPE (var), val,
01517 build_int_cst (TREE_TYPE (var), mask));
01518 }
01519 else
01520 {
01521
01522
01523
01524 for (i = 0, mask = 0; i < (var_size - field_size); i++)
01525 mask |= ((HOST_WIDE_INT) 1) << (var_size - i - 1);
01526
01527 wide_val = fold_build2 (BIT_IOR_EXPR, TREE_TYPE (var), val,
01528 build_int_cst (TREE_TYPE (var), mask));
01529 }
01530
01531 return wide_val;
01532 }
01533
01534
01535
01536
01537
01538
01539 static tree
01540 maybe_fold_offset_to_array_ref (tree base, tree offset, tree orig_type)
01541 {
01542 tree min_idx, idx, elt_offset = integer_zero_node;
01543 tree array_type, elt_type, elt_size;
01544
01545
01546
01547
01548
01549
01550 if (TREE_CODE (base) == ARRAY_REF)
01551 {
01552 tree low_bound = array_ref_low_bound (base);
01553
01554 elt_offset = TREE_OPERAND (base, 1);
01555 if (TREE_CODE (low_bound) != INTEGER_CST
01556 || TREE_CODE (elt_offset) != INTEGER_CST)
01557 return NULL_TREE;
01558
01559 elt_offset = int_const_binop (MINUS_EXPR, elt_offset, low_bound, 0);
01560 base = TREE_OPERAND (base, 0);
01561 }
01562
01563
01564 array_type = TREE_TYPE (base);
01565 if (TREE_CODE (array_type) != ARRAY_TYPE)
01566 return NULL_TREE;
01567 elt_type = TREE_TYPE (array_type);
01568 if (!lang_hooks.types_compatible_p (orig_type, elt_type))
01569 return NULL_TREE;
01570
01571
01572
01573
01574
01575 elt_size = TYPE_SIZE_UNIT (elt_type);
01576 if (integer_zerop (offset))
01577 {
01578 if (TREE_CODE (elt_size) != INTEGER_CST)
01579 elt_size = size_int (TYPE_ALIGN (elt_type));
01580
01581 idx = integer_zero_node;
01582 }
01583 else
01584 {
01585 unsigned HOST_WIDE_INT lquo, lrem;
01586 HOST_WIDE_INT hquo, hrem;
01587
01588 if (TREE_CODE (elt_size) != INTEGER_CST
01589 || div_and_round_double (TRUNC_DIV_EXPR, 1,
01590 TREE_INT_CST_LOW (offset),
01591 TREE_INT_CST_HIGH (offset),
01592 TREE_INT_CST_LOW (elt_size),
01593 TREE_INT_CST_HIGH (elt_size),
01594 &lquo, &hquo, &lrem, &hrem)
01595 || lrem || hrem)
01596 return NULL_TREE;
01597
01598 idx = build_int_cst_wide (NULL_TREE, lquo, hquo);
01599 }
01600
01601
01602
01603
01604 min_idx = integer_zero_node;
01605 if (TYPE_DOMAIN (array_type))
01606 {
01607 if (TYPE_MIN_VALUE (TYPE_DOMAIN (array_type)))
01608 min_idx = TYPE_MIN_VALUE (TYPE_DOMAIN (array_type));
01609 else
01610 min_idx = fold_convert (TYPE_DOMAIN (array_type), min_idx);
01611
01612 if (TREE_CODE (min_idx) != INTEGER_CST)
01613 return NULL_TREE;
01614
01615 idx = fold_convert (TYPE_DOMAIN (array_type), idx);
01616 elt_offset = fold_convert (TYPE_DOMAIN (array_type), elt_offset);
01617 }
01618
01619 if (!integer_zerop (min_idx))
01620 idx = int_const_binop (PLUS_EXPR, idx, min_idx, 0);
01621 if (!integer_zerop (elt_offset))
01622 idx = int_const_binop (PLUS_EXPR, idx, elt_offset, 0);
01623
01624 return build4 (ARRAY_REF, orig_type, base, idx, min_idx,
01625 size_int (tree_low_cst (elt_size, 1)
01626 / (TYPE_ALIGN_UNIT (elt_type))));
01627 }
01628
01629
01630
01631
01632
01633
01634
01635 static tree
01636 maybe_fold_offset_to_component_ref (tree record_type, tree base, tree offset,
01637 tree orig_type, bool base_is_ptr)
01638 {
01639 tree f, t, field_type, tail_array_field, field_offset;
01640
01641 if (TREE_CODE (record_type) != RECORD_TYPE
01642 && TREE_CODE (record_type) != UNION_TYPE
01643 && TREE_CODE (record_type) != QUAL_UNION_TYPE)
01644 return NULL_TREE;
01645
01646
01647 if (lang_hooks.types_compatible_p (record_type, orig_type))
01648 return NULL_TREE;
01649
01650 tail_array_field = NULL_TREE;
01651 for (f = TYPE_FIELDS (record_type); f ; f = TREE_CHAIN (f))
01652 {
01653 int cmp;
01654
01655 if (TREE_CODE (f) != FIELD_DECL)
01656 continue;
01657 if (DECL_BIT_FIELD (f))
01658 continue;
01659
01660 field_offset = byte_position (f);
01661 if (TREE_CODE (field_offset) != INTEGER_CST)
01662 continue;
01663
01664
01665
01666
01667 if (!DECL_FIELD_CONTEXT (f))
01668 continue;
01669
01670
01671 tail_array_field = NULL_TREE;
01672
01673
01674 cmp = tree_int_cst_compare (field_offset, offset);
01675 if (cmp > 0)
01676 continue;
01677
01678 field_type = TREE_TYPE (f);
01679
01680
01681
01682 if (cmp == 0
01683 && lang_hooks.types_compatible_p (orig_type, field_type))
01684 {
01685 if (base_is_ptr)
01686 base = build1 (INDIRECT_REF, record_type, base);
01687 t = build3 (COMPONENT_REF, field_type, base, f, NULL_TREE);
01688 return t;
01689 }
01690
01691
01692 if (!AGGREGATE_TYPE_P (field_type))
01693 continue;
01694
01695
01696
01697
01698 if (TREE_CODE (field_type) == ARRAY_TYPE)
01699 tail_array_field = f;
01700
01701
01702 if (!DECL_SIZE_UNIT (f)
01703 || TREE_CODE (DECL_SIZE_UNIT (f)) != INTEGER_CST)
01704 continue;
01705 t = int_const_binop (MINUS_EXPR, offset, field_offset, 1);
01706 if (!tree_int_cst_lt (t, DECL_SIZE_UNIT (f)))
01707 continue;
01708
01709
01710
01711 offset = t;
01712 goto found;
01713 }
01714
01715 if (!tail_array_field)
01716 return NULL_TREE;
01717
01718 f = tail_array_field;
01719 field_type = TREE_TYPE (f);
01720 offset = int_const_binop (MINUS_EXPR, offset, byte_position (f), 1);
01721
01722 found:
01723
01724
01725 if (base_is_ptr)
01726 base = build1 (INDIRECT_REF, record_type, base);
01727 base = build3 (COMPONENT_REF, field_type, base, f, NULL_TREE);
01728
01729 t = maybe_fold_offset_to_array_ref (base, offset, orig_type);
01730 if (t)
01731 return t;
01732 return maybe_fold_offset_to_component_ref (field_type, base, offset,
01733 orig_type, false);
01734 }
01735
01736
01737
01738
01739
01740 static tree
01741 maybe_fold_stmt_indirect (tree expr, tree base, tree offset)
01742 {
01743 tree t;
01744
01745
01746
01747
01748 base = fold (base);
01749 STRIP_TYPE_NOPS (base);
01750 TREE_OPERAND (expr, 0) = base;
01751
01752
01753 t = fold_read_from_constant_string (expr);
01754 if (t)
01755 return t;
01756
01757
01758 if (TREE_CODE (base) == PLUS_EXPR)
01759 {
01760 tree offset2;
01761
01762 offset2 = TREE_OPERAND (base, 1);
01763 if (TREE_CODE (offset2) != INTEGER_CST)
01764 return NULL_TREE;
01765 base = TREE_OPERAND (base, 0);
01766
01767 offset = int_const_binop (PLUS_EXPR, offset, offset2, 1);
01768 }
01769
01770 if (TREE_CODE (base) == ADDR_EXPR)
01771 {
01772
01773 base = TREE_OPERAND (base, 0);
01774
01775
01776 if (TREE_CODE (base) == CONST_DECL
01777 && ccp_decl_initial_min_invariant (DECL_INITIAL (base)))
01778 return DECL_INITIAL (base);
01779
01780
01781 t = maybe_fold_offset_to_array_ref (base, offset, TREE_TYPE (expr));
01782 if (t)
01783 return t;
01784
01785
01786 t = maybe_fold_offset_to_component_ref (TREE_TYPE (base), base, offset,
01787 TREE_TYPE (expr), false);
01788 if (t)
01789 return t;
01790
01791
01792
01793
01794 if (integer_zerop (offset)
01795 && lang_hooks.types_compatible_p (TREE_TYPE (base),
01796 TREE_TYPE (expr)))
01797 return base;
01798 }
01799 else
01800 {
01801
01802
01803
01804
01805
01806
01807
01808 t = base;
01809 STRIP_NOPS (t);
01810 if (TREE_CODE (t) == ADDR_EXPR
01811 && TREE_CODE (TREE_OPERAND (t, 0)) == STRING_CST)
01812 {
01813
01814
01815
01816
01817
01818
01819
01820 return integer_zero_node;
01821 }
01822
01823
01824 if (POINTER_TYPE_P (TREE_TYPE (base)))
01825 {
01826 t = maybe_fold_offset_to_component_ref (TREE_TYPE (TREE_TYPE (base)),
01827 base, offset,
01828 TREE_TYPE (expr), true);
01829 if (t)
01830 return t;
01831 }
01832 }
01833
01834
01835 return NULL_TREE;
01836 }
01837
01838
01839
01840
01841
01842
01843
01844
01845
01846
01847
01848
01849
01850
01851
01852 static tree
01853 maybe_fold_stmt_addition (tree expr)
01854 {
01855 tree op0 = TREE_OPERAND (expr, 0);
01856 tree op1 = TREE_OPERAND (expr, 1);
01857 tree ptr_type = TREE_TYPE (expr);
01858 tree ptd_type;
01859 tree t;
01860 bool subtract = (TREE_CODE (expr) == MINUS_EXPR);
01861
01862
01863 if (!POINTER_TYPE_P (ptr_type))
01864 return NULL_TREE;
01865
01866 if (INTEGRAL_TYPE_P (TREE_TYPE (op0)))
01867 {
01868 if (subtract)
01869 return NULL_TREE;
01870 t = op0, op0 = op1, op1 = t;
01871 }
01872
01873 if (TREE_CODE (op1) != INTEGER_CST)
01874 return NULL_TREE;
01875
01876 if (TREE_CODE (op0) != ADDR_EXPR)
01877 return NULL_TREE;
01878 op0 = TREE_OPERAND (op0, 0);
01879
01880
01881
01882 while (TREE_CODE (op0) == ARRAY_REF)
01883 {
01884 tree array_obj = TREE_OPERAND (op0, 0);
01885 tree array_idx = TREE_OPERAND (op0, 1);
01886 tree elt_type = TREE_TYPE (op0);
01887 tree elt_size = TYPE_SIZE_UNIT (elt_type);
01888 tree min_idx;
01889
01890 if (TREE_CODE (array_idx) != INTEGER_CST)
01891 break;
01892 if (TREE_CODE (elt_size) != INTEGER_CST)
01893 break;
01894
01895
01896 min_idx = TYPE_DOMAIN (TREE_TYPE (array_obj));
01897 if (min_idx)
01898 {
01899 min_idx = TYPE_MIN_VALUE (min_idx);
01900 if (min_idx)
01901 {
01902 if (TREE_CODE (min_idx) != INTEGER_CST)
01903 break;
01904
01905 array_idx = fold_convert (TREE_TYPE (min_idx), array_idx);
01906 if (!integer_zerop (min_idx))
01907 array_idx = int_const_binop (MINUS_EXPR, array_idx,
01908 min_idx, 0);
01909 }
01910 }
01911
01912
01913 array_idx = fold_convert (sizetype, array_idx);
01914 array_idx = int_const_binop (MULT_EXPR, array_idx, elt_size, 0);
01915
01916
01917
01918
01919
01920 if (subtract
01921 && TYPE_UNSIGNED (TREE_TYPE (op1))
01922 && tree_int_cst_lt (array_idx, op1))
01923 return NULL;
01924 op1 = int_const_binop (subtract ? MINUS_EXPR : PLUS_EXPR,
01925 array_idx, op1, 0);
01926 subtract = false;
01927 op0 = array_obj;
01928 }
01929
01930
01931
01932
01933 if (subtract)
01934 {
01935 if (TYPE_UNSIGNED (TREE_TYPE (op1)))
01936 return NULL;
01937 op1 = fold_unary (NEGATE_EXPR, TREE_TYPE (op1), op1);
01938
01939 if (op1 == NULL || TREE_CODE (op1) != INTEGER_CST)
01940 return NULL;
01941 }
01942
01943 ptd_type = TREE_TYPE (ptr_type);
01944
01945
01946 t = maybe_fold_offset_to_array_ref (op0, op1, ptd_type);
01947 if (!t)
01948 t = maybe_fold_offset_to_component_ref (TREE_TYPE (op0), op0, op1,
01949 ptd_type, false);
01950 if (t)
01951 t = build1 (ADDR_EXPR, ptr_type, t);
01952
01953 return t;
01954 }
01955
01956
01957
01958
01959 struct fold_stmt_r_data
01960 {
01961 tree stmt;
01962 bool *changed_p;
01963 bool *inside_addr_expr_p;
01964 };
01965
01966
01967
01968
01969 static tree
01970 fold_stmt_r (tree *expr_p, int *walk_subtrees, void *data)
01971 {
01972 struct fold_stmt_r_data *fold_stmt_r_data = (struct fold_stmt_r_data *) data;
01973 bool *inside_addr_expr_p = fold_stmt_r_data->inside_addr_expr_p;
01974 bool *changed_p = fold_stmt_r_data->changed_p;
01975 tree expr = *expr_p, t;
01976
01977
01978 switch (TREE_CODE (expr))
01979 {
01980 case INDIRECT_REF:
01981 t = walk_tree (&TREE_OPERAND (expr, 0), fold_stmt_r, data, NULL);
01982 if (t)
01983 return t;
01984 *walk_subtrees = 0;
01985
01986 t = maybe_fold_stmt_indirect (expr, TREE_OPERAND (expr, 0),
01987 integer_zero_node);
01988 break;
01989
01990
01991
01992
01993
01994 case ARRAY_REF:
01995
01996
01997 if (!*inside_addr_expr_p)
01998 t = fold_read_from_constant_string (expr);
01999 else
02000 t = NULL;
02001 break;
02002
02003 case ADDR_EXPR:
02004 *inside_addr_expr_p = true;
02005 t = walk_tree (&TREE_OPERAND (expr, 0), fold_stmt_r, data, NULL);
02006 *inside_addr_expr_p = false;
02007 if (t)
02008 return t;
02009 *walk_subtrees = 0;
02010
02011
02012
02013 if (*changed_p)
02014 recompute_tree_invariant_for_addr_expr (expr);
02015 return NULL_TREE;
02016
02017 case PLUS_EXPR:
02018 case MINUS_EXPR:
02019 t = walk_tree (&TREE_OPERAND (expr, 0), fold_stmt_r, data, NULL);
02020 if (t)
02021 return t;
02022 t = walk_tree (&TREE_OPERAND (expr, 1), fold_stmt_r, data, NULL);
02023 if (t)
02024 return t;
02025 *walk_subtrees = 0;
02026
02027 t = maybe_fold_stmt_addition (expr);
02028 break;
02029
02030 case COMPONENT_REF:
02031 t = walk_tree (&TREE_OPERAND (expr, 0), fold_stmt_r, data, NULL);
02032 if (t)
02033 return t;
02034 *walk_subtrees = 0;
02035
02036
02037
02038
02039 {
02040 tree expr_record = TREE_TYPE (TREE_OPERAND (expr, 0));
02041 tree expr_field = TREE_OPERAND (expr, 1);
02042
02043 if (DECL_FIELD_CONTEXT (expr_field) != TYPE_MAIN_VARIANT (expr_record))
02044 {
02045 expr_field = find_compatible_field (expr_record, expr_field);
02046 TREE_OPERAND (expr, 1) = expr_field;
02047 }
02048 }
02049 break;
02050
02051 case TARGET_MEM_REF:
02052 t = maybe_fold_tmr (expr);
02053 break;
02054
02055 case COND_EXPR:
02056 if (COMPARISON_CLASS_P (TREE_OPERAND (expr, 0)))
02057 {
02058 tree op0 = TREE_OPERAND (expr, 0);
02059 tree tem;
02060 bool set;
02061
02062 fold_defer_overflow_warnings ();
02063 tem = fold_binary (TREE_CODE (op0), TREE_TYPE (op0),
02064 TREE_OPERAND (op0, 0),
02065 TREE_OPERAND (op0, 1));
02066 set = tem && is_gimple_condexpr (tem);
02067 fold_undefer_overflow_warnings (set, fold_stmt_r_data->stmt, 0);
02068 if (set)
02069 TREE_OPERAND (expr, 0) = tem;
02070 t = expr;
02071 break;
02072 }
02073
02074 default:
02075 return NULL_TREE;
02076 }
02077
02078 if (t)
02079 {
02080 *expr_p = t;
02081 *changed_p = true;
02082 }
02083
02084 return NULL_TREE;
02085 }
02086
02087
02088
02089
02090
02091
02092
02093
02094
02095
02096
02097 static bool
02098 get_maxval_strlen (tree arg, tree *length, bitmap visited, int type)
02099 {
02100 tree var, def_stmt, val;
02101
02102 if (TREE_CODE (arg) != SSA_NAME)
02103 {
02104 if (type == 2)
02105 {
02106 val = arg;
02107 if (TREE_CODE (val) != INTEGER_CST
02108 || tree_int_cst_sgn (val) < 0)
02109 return false;
02110 }
02111 else
02112 val = c_strlen (arg, 1);
02113 if (!val)
02114 return false;
02115
02116 if (*length)
02117 {
02118 if (type > 0)
02119 {
02120 if (TREE_CODE (*length) != INTEGER_CST
02121 || TREE_CODE (val) != INTEGER_CST)
02122 return false;
02123
02124 if (tree_int_cst_lt (*length, val))
02125 *length = val;
02126 return true;
02127 }
02128 else if (simple_cst_equal (val, *length) != 1)
02129 return false;
02130 }
02131
02132 *length = val;
02133 return true;
02134 }
02135
02136
02137 if (bitmap_bit_p (visited, SSA_NAME_VERSION (arg)))
02138 return true;
02139 bitmap_set_bit (visited, SSA_NAME_VERSION (arg));
02140
02141 var = arg;
02142 def_stmt = SSA_NAME_DEF_STMT (var);
02143
02144 switch (TREE_CODE (def_stmt))
02145 {
02146 case MODIFY_EXPR:
02147 {
02148 tree rhs;
02149
02150
02151
02152
02153 rhs = TREE_OPERAND (def_stmt, 1);
02154 STRIP_NOPS (rhs);
02155 return get_maxval_strlen (rhs, length, visited, type);
02156 }
02157
02158 case PHI_NODE:
02159 {
02160
02161
02162 int i;
02163
02164 for (i = 0; i < PHI_NUM_ARGS (def_stmt); i++)
02165 {
02166 tree arg = PHI_ARG_DEF (def_stmt, i);
02167
02168
02169
02170
02171
02172
02173
02174 if (arg == PHI_RESULT (def_stmt))
02175 continue;
02176
02177 if (!get_maxval_strlen (arg, length, visited, type))
02178 return false;
02179 }
02180
02181 return true;
02182 }
02183
02184 default:
02185 break;
02186 }
02187
02188
02189 return false;
02190 }
02191
02192
02193
02194
02195
02196 static tree
02197 ccp_fold_builtin (tree stmt, tree fn)
02198 {
02199 tree result, val[3];
02200 tree callee, arglist, a;
02201 int arg_mask, i, type;
02202 bitmap visited;
02203 bool ignore;
02204
02205 ignore = TREE_CODE (stmt) != MODIFY_EXPR;
02206
02207
02208
02209 callee = get_callee_fndecl (fn);
02210 arglist = TREE_OPERAND (fn, 1);
02211 result = fold_builtin (callee, arglist, ignore);
02212 if (result)
02213 {
02214 if (ignore)
02215 STRIP_NOPS (result);
02216 return result;
02217 }
02218
02219
02220 if (DECL_BUILT_IN_CLASS (callee) == BUILT_IN_MD)
02221 return NULL_TREE;
02222
02223
02224
02225 if (!arglist)
02226 return NULL_TREE;
02227
02228
02229 switch (DECL_FUNCTION_CODE (callee))
02230 {
02231 case BUILT_IN_STRLEN:
02232 case BUILT_IN_FPUTS:
02233 case BUILT_IN_FPUTS_UNLOCKED:
02234 arg_mask = 1;
02235 type = 0;
02236 break;
02237 case BUILT_IN_STRCPY:
02238 case BUILT_IN_STRNCPY:
02239 arg_mask = 2;
02240 type = 0;
02241 break;
02242 case BUILT_IN_MEMCPY_CHK:
02243 case BUILT_IN_MEMPCPY_CHK:
02244 case BUILT_IN_MEMMOVE_CHK:
02245 case BUILT_IN_MEMSET_CHK:
02246 case BUILT_IN_STRNCPY_CHK:
02247 arg_mask = 4;
02248 type = 2;
02249 break;
02250 case BUILT_IN_STRCPY_CHK:
02251 case BUILT_IN_STPCPY_CHK:
02252 arg_mask = 2;
02253 type = 1;
02254 break;
02255 case BUILT_IN_SNPRINTF_CHK:
02256 case BUILT_IN_VSNPRINTF_CHK:
02257 arg_mask = 2;
02258 type = 2;
02259 break;
02260 default:
02261 return NULL_TREE;
02262 }
02263
02264
02265 visited = BITMAP_ALLOC (NULL);
02266
02267 memset (val, 0, sizeof (val));
02268 for (i = 0, a = arglist;
02269 arg_mask;
02270 i++, arg_mask >>= 1, a = TREE_CHAIN (a))
02271 if (arg_mask & 1)
02272 {
02273 bitmap_clear (visited);
02274 if (!get_maxval_strlen (TREE_VALUE (a), &val[i], visited, type))
02275 val[i] = NULL_TREE;
02276 }
02277
02278 BITMAP_FREE (visited);
02279
02280 result = NULL_TREE;
02281 switch (DECL_FUNCTION_CODE (callee))
02282 {
02283 case BUILT_IN_STRLEN:
02284 if (val[0])
02285 {
02286 tree new = fold_convert (TREE_TYPE (fn), val[0]);
02287
02288
02289
02290 if (is_gimple_val (new)
02291 || (is_gimple_cast (new)
02292 && is_gimple_val (TREE_OPERAND (new, 0))))
02293 return new;
02294 }
02295 break;
02296
02297 case BUILT_IN_STRCPY:
02298 if (val[1] && is_gimple_val (val[1]))
02299 result = fold_builtin_strcpy (callee, arglist, val[1]);
02300 break;
02301
02302 case BUILT_IN_STRNCPY:
02303 if (val[1] && is_gimple_val (val[1]))
02304 result = fold_builtin_strncpy (callee, arglist, val[1]);
02305 break;
02306
02307 case BUILT_IN_FPUTS:
02308 result = fold_builtin_fputs (arglist,
02309 TREE_CODE (stmt) != MODIFY_EXPR, 0,
02310 val[0]);
02311 break;
02312
02313 case BUILT_IN_FPUTS_UNLOCKED:
02314 result = fold_builtin_fputs (arglist,
02315 TREE_CODE (stmt) != MODIFY_EXPR, 1,
02316 val[0]);
02317 break;
02318
02319 case BUILT_IN_MEMCPY_CHK:
02320 case BUILT_IN_MEMPCPY_CHK:
02321 case BUILT_IN_MEMMOVE_CHK:
02322 case BUILT_IN_MEMSET_CHK:
02323 if (val[2] && is_gimple_val (val[2]))
02324 result = fold_builtin_memory_chk (callee, arglist, val[2], ignore,
02325 DECL_FUNCTION_CODE (callee));
02326 break;
02327
02328 case BUILT_IN_STRCPY_CHK:
02329 case BUILT_IN_STPCPY_CHK:
02330 if (val[1] && is_gimple_val (val[1]))
02331 result = fold_builtin_stxcpy_chk (callee, arglist, val[1], ignore,
02332 DECL_FUNCTION_CODE (callee));
02333 break;
02334
02335 case BUILT_IN_STRNCPY_CHK:
02336 if (val[2] && is_gimple_val (val[2]))
02337 result = fold_builtin_strncpy_chk (arglist, val[2]);
02338 break;
02339
02340 case BUILT_IN_SNPRINTF_CHK:
02341 case BUILT_IN_VSNPRINTF_CHK:
02342 if (val[1] && is_gimple_val (val[1]))
02343 result = fold_builtin_snprintf_chk (arglist, val[1],
02344 DECL_FUNCTION_CODE (callee));
02345 break;
02346
02347 default:
02348 gcc_unreachable ();
02349 }
02350
02351 if (result && ignore)
02352 result = fold_ignored_result (result);
02353 return result;
02354 }
02355
02356
02357
02358
02359
02360
02361 bool
02362 fold_stmt (tree *stmt_p)
02363 {
02364 tree rhs, result, stmt;
02365 struct fold_stmt_r_data fold_stmt_r_data;
02366 bool changed = false;
02367 bool inside_addr_expr = false;
02368
02369 stmt = *stmt_p;
02370
02371 fold_stmt_r_data.stmt = stmt;
02372 fold_stmt_r_data.changed_p = &changed;
02373 fold_stmt_r_data.inside_addr_expr_p = &inside_addr_expr;
02374
02375
02376
02377 if (walk_tree (stmt_p, fold_stmt_r, &fold_stmt_r_data, NULL))
02378 {
02379 *stmt_p
02380 = build_function_call_expr (implicit_built_in_decls[BUILT_IN_TRAP],
02381 NULL);
02382 return true;
02383 }
02384
02385 rhs = get_rhs (stmt);
02386 if (!rhs)
02387 return changed;
02388 result = NULL_TREE;
02389
02390 if (TREE_CODE (rhs) == CALL_EXPR)
02391 {
02392 tree callee;
02393
02394
02395
02396 callee = get_callee_fndecl (rhs);
02397 if (callee && DECL_BUILT_IN (callee))
02398 result = ccp_fold_builtin (stmt, rhs);
02399 else
02400 {
02401
02402
02403
02404
02405
02406
02407
02408
02409
02410 callee = TREE_OPERAND (rhs, 0);
02411 if (TREE_CODE (callee) == OBJ_TYPE_REF
02412 && lang_hooks.fold_obj_type_ref
02413 && TREE_CODE (OBJ_TYPE_REF_OBJECT (callee)) == ADDR_EXPR
02414 && DECL_P (TREE_OPERAND
02415 (OBJ_TYPE_REF_OBJECT (callee), 0)))
02416 {
02417 tree t;
02418
02419
02420
02421
02422
02423
02424 t = TREE_TYPE (TREE_TYPE (OBJ_TYPE_REF_OBJECT (callee)));
02425 t = lang_hooks.fold_obj_type_ref (callee, t);
02426 if (t)
02427 {
02428 TREE_OPERAND (rhs, 0) = t;
02429 changed = true;
02430 }
02431 }
02432 }
02433 }
02434
02435
02436 if (result == NULL_TREE)
02437 result = fold (rhs);
02438
02439
02440
02441
02442 STRIP_USELESS_TYPE_CONVERSION (result);
02443
02444 if (result != rhs)
02445 changed |= set_rhs (stmt_p, result);
02446
02447 return changed;
02448 }
02449
02450
02451
02452
02453
02454 bool
02455 fold_stmt_inplace (tree stmt)
02456 {
02457 tree old_stmt = stmt, rhs, new_rhs;
02458 struct fold_stmt_r_data fold_stmt_r_data;
02459 bool changed = false;
02460 bool inside_addr_expr = false;
02461
02462 fold_stmt_r_data.stmt = stmt;
02463 fold_stmt_r_data.changed_p = &changed;
02464 fold_stmt_r_data.inside_addr_expr_p = &inside_addr_expr;
02465
02466 walk_tree (&stmt, fold_stmt_r, &fold_stmt_r_data, NULL);
02467 gcc_assert (stmt == old_stmt);
02468
02469 rhs = get_rhs (stmt);
02470 if (!rhs || rhs == stmt)
02471 return changed;
02472
02473 new_rhs = fold (rhs);
02474 STRIP_USELESS_TYPE_CONVERSION (new_rhs);
02475 if (new_rhs == rhs)
02476 return changed;
02477
02478 changed |= set_rhs (&stmt, new_rhs);
02479 gcc_assert (stmt == old_stmt);
02480
02481 return changed;
02482 }
02483
02484
02485
02486
02487
02488 static tree
02489 convert_to_gimple_builtin (block_stmt_iterator *si_p, tree expr)
02490 {
02491 tree_stmt_iterator ti;
02492 tree stmt = bsi_stmt (*si_p);
02493 tree tmp, stmts = NULL;
02494
02495 push_gimplify_context ();
02496 tmp = get_initialized_tmp_var (expr, &stmts, NULL);
02497 pop_gimplify_context (NULL);
02498
02499 if (EXPR_HAS_LOCATION (stmt))
02500 annotate_all_with_locus (&stmts, EXPR_LOCATION (stmt));
02501
02502
02503 for (ti = tsi_start (stmts); !tsi_end_p (ti); tsi_next (&ti))
02504 {
02505 tree new_stmt = tsi_stmt (ti);
02506 find_new_referenced_vars (tsi_stmt_ptr (ti));
02507 bsi_insert_before (si_p, new_stmt, BSI_NEW_STMT);
02508 mark_new_vars_to_rename (bsi_stmt (*si_p));
02509 bsi_next (si_p);
02510 }
02511
02512 return tmp;
02513 }
02514
02515
02516
02517
02518
02519 static unsigned int
02520 execute_fold_all_builtins (void)
02521 {
02522 bool cfg_changed = false;
02523 basic_block bb;
02524 FOR_EACH_BB (bb)
02525 {
02526 block_stmt_iterator i;
02527 for (i = bsi_start (bb); !bsi_end_p (i); )
02528 {
02529 tree *stmtp = bsi_stmt_ptr (i);
02530 tree old_stmt = *stmtp;
02531 tree call = get_rhs (*stmtp);
02532 tree callee, result;
02533 enum built_in_function fcode;
02534
02535 if (!call || TREE_CODE (call) != CALL_EXPR)
02536 {
02537 bsi_next (&i);
02538 continue;
02539 }
02540 callee = get_callee_fndecl (call);
02541 if (!callee || DECL_BUILT_IN_CLASS (callee) != BUILT_IN_NORMAL)
02542 {
02543 bsi_next (&i);
02544 continue;
02545 }
02546 fcode = DECL_FUNCTION_CODE (callee);
02547
02548 result = ccp_fold_builtin (*stmtp, call);
02549 if (!result)
02550 switch (DECL_FUNCTION_CODE (callee))
02551 {
02552 case BUILT_IN_CONSTANT_P:
02553
02554
02555
02556 result = integer_zero_node;
02557 break;
02558
02559 default:
02560 bsi_next (&i);
02561 continue;
02562 }
02563
02564 if (dump_file && (dump_flags & TDF_DETAILS))
02565 {
02566 fprintf (dump_file, "Simplified\n ");
02567 print_generic_stmt (dump_file, *stmtp, dump_flags);
02568 }
02569
02570 if (!set_rhs (stmtp, result))
02571 {
02572 result = convert_to_gimple_builtin (&i, result);
02573 if (result)
02574 {
02575 bool ok = set_rhs (stmtp, result);
02576
02577 gcc_assert (ok);
02578 }
02579 }
02580 mark_new_vars_to_rename (*stmtp);
02581 if (maybe_clean_or_replace_eh_stmt (old_stmt, *stmtp)
02582 && tree_purge_dead_eh_edges (bb))
02583 cfg_changed = true;
02584
02585 if (dump_file && (dump_flags & TDF_DETAILS))
02586 {
02587 fprintf (dump_file, "to\n ");
02588 print_generic_stmt (dump_file, *stmtp, dump_flags);
02589 fprintf (dump_file, "\n");
02590 }
02591
02592
02593
02594 call = get_rhs (*stmtp);
02595 if (!call || TREE_CODE (call) != CALL_EXPR)
02596 {
02597 bsi_next (&i);
02598 continue;
02599 }
02600 callee = get_callee_fndecl (call);
02601 if (!callee
02602 || DECL_BUILT_IN_CLASS (callee) != BUILT_IN_NORMAL
02603 || DECL_FUNCTION_CODE (callee) == fcode)
02604 bsi_next (&i);
02605 }
02606 }
02607
02608
02609 if (cfg_changed)
02610 cleanup_tree_cfg ();
02611 return 0;
02612 }
02613
02614
02615 struct tree_opt_pass pass_fold_builtins =
02616 {
02617 "fab",
02618 NULL,
02619 execute_fold_all_builtins,
02620 NULL,
02621 NULL,
02622 0,
02623 0,
02624 PROP_cfg | PROP_ssa | PROP_alias,
02625 0,
02626 0,
02627 0,
02628 TODO_dump_func
02629 | TODO_verify_ssa
02630 | TODO_update_ssa,
02631 0
02632 };