00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "config.h"
00023 #include "system.h"
00024 #include "coretypes.h"
00025 #include "tm.h"
00026 #include "errors.h"
00027 #include "ggc.h"
00028 #include "tree.h"
00029 #include "target.h"
00030 #include "rtl.h"
00031 #include "basic-block.h"
00032 #include "diagnostic.h"
00033 #include "tree-flow.h"
00034 #include "tree-dump.h"
00035 #include "timevar.h"
00036 #include "cfgloop.h"
00037 #include "expr.h"
00038 #include "optabs.h"
00039 #include "tree-data-ref.h"
00040 #include "tree-chrec.h"
00041 #include "tree-scalar-evolution.h"
00042 #include "tree-vectorizer.h"
00043 #include "langhooks.h"
00044 #include "tree-pass.h"
00045 #include "toplev.h"
00046
00047
00048 static bool vect_transform_stmt (tree, block_stmt_iterator *);
00049 static void vect_align_data_ref (tree);
00050 static tree vect_create_destination_var (tree, tree);
00051 static tree vect_create_data_ref_ptr
00052 (tree, block_stmt_iterator *, tree, tree *, bool);
00053 static tree vect_create_index_for_vector_ref (loop_vec_info);
00054 static tree vect_create_addr_base_for_vector_ref (tree, tree *, tree);
00055 static tree vect_get_new_vect_var (tree, enum vect_var_kind, const char *);
00056 static tree vect_get_vec_def_for_operand (tree, tree);
00057 static tree vect_init_vector (tree, tree);
00058 static void vect_finish_stmt_generation
00059 (tree stmt, tree vec_stmt, block_stmt_iterator *bsi);
00060
00061
00062 static void vect_generate_tmps_on_preheader
00063 (loop_vec_info, tree *, tree *, tree *);
00064 static tree vect_build_loop_niters (loop_vec_info);
00065 static void vect_update_ivs_after_vectorizer (loop_vec_info, tree, edge);
00066 static tree vect_gen_niters_for_prolog_loop (loop_vec_info, tree);
00067 static void vect_update_inits_of_dr (struct data_reference *, tree niters);
00068 static void vect_update_inits_of_drs (loop_vec_info, tree);
00069 static void vect_do_peeling_for_alignment (loop_vec_info, struct loops *);
00070 static void vect_do_peeling_for_loop_bound
00071 (loop_vec_info, tree *, struct loops *);
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081 static tree
00082 vect_get_new_vect_var (tree type, enum vect_var_kind var_kind, const char *name)
00083 {
00084 const char *prefix;
00085 int prefix_len;
00086 tree new_vect_var;
00087
00088 if (var_kind == vect_simple_var)
00089 prefix = "vect_";
00090 else
00091 prefix = "vect_p";
00092
00093 prefix_len = strlen (prefix);
00094
00095 if (name)
00096 new_vect_var = create_tmp_var (type, concat (prefix, name, NULL));
00097 else
00098 new_vect_var = create_tmp_var (type, prefix);
00099
00100 return new_vect_var;
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 static tree
00130 vect_create_index_for_vector_ref (loop_vec_info loop_vinfo)
00131 {
00132 tree init, step;
00133 block_stmt_iterator incr_bsi;
00134 bool insert_after;
00135 tree indx_before_incr, indx_after_incr;
00136 struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo);
00137 tree incr;
00138
00139
00140
00141
00142
00143 init = integer_zero_node;
00144 step = integer_one_node;
00145
00146 standard_iv_increment_position (loop, &incr_bsi, &insert_after);
00147 create_iv (init, step, NULL_TREE, loop, &incr_bsi, insert_after,
00148 &indx_before_incr, &indx_after_incr);
00149 incr = bsi_stmt (incr_bsi);
00150 get_stmt_operands (incr);
00151 set_stmt_info (stmt_ann (incr), new_stmt_vec_info (incr, loop_vinfo));
00152
00153 return indx_before_incr;
00154 }
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175 static tree
00176 vect_create_addr_base_for_vector_ref (tree stmt,
00177 tree *new_stmt_list,
00178 tree offset)
00179 {
00180 stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
00181 struct data_reference *dr = STMT_VINFO_DATA_REF (stmt_info);
00182 tree data_ref_base =
00183 unshare_expr (STMT_VINFO_VECT_DR_BASE_ADDRESS (stmt_info));
00184 tree base_name = build_fold_indirect_ref (data_ref_base);
00185 tree ref = DR_REF (dr);
00186 tree scalar_type = TREE_TYPE (ref);
00187 tree scalar_ptr_type = build_pointer_type (scalar_type);
00188 tree vec_stmt;
00189 tree new_temp;
00190 tree addr_base, addr_expr;
00191 tree dest, new_stmt;
00192 tree base_offset = unshare_expr (STMT_VINFO_VECT_INIT_OFFSET (stmt_info));
00193
00194
00195 dest = create_tmp_var (TREE_TYPE (base_offset), "base_off");
00196 add_referenced_tmp_var (dest);
00197 base_offset = force_gimple_operand (base_offset, &new_stmt, false, dest);
00198 append_to_statement_list_force (new_stmt, new_stmt_list);
00199
00200 if (offset)
00201 {
00202 tree tmp = create_tmp_var (TREE_TYPE (base_offset), "offset");
00203 add_referenced_tmp_var (tmp);
00204 offset = fold (build2 (MULT_EXPR, TREE_TYPE (offset), offset,
00205 STMT_VINFO_VECT_STEP (stmt_info)));
00206 base_offset = fold (build2 (PLUS_EXPR, TREE_TYPE (base_offset),
00207 base_offset, offset));
00208 base_offset = force_gimple_operand (base_offset, &new_stmt, false, tmp);
00209 append_to_statement_list_force (new_stmt, new_stmt_list);
00210 }
00211
00212
00213 addr_base = fold (build2 (PLUS_EXPR, TREE_TYPE (data_ref_base), data_ref_base,
00214 base_offset));
00215
00216
00217 addr_expr = vect_get_new_vect_var (scalar_ptr_type, vect_pointer_var,
00218 get_name (base_name));
00219 add_referenced_tmp_var (addr_expr);
00220 vec_stmt = build2 (MODIFY_EXPR, void_type_node, addr_expr, addr_base);
00221 new_temp = make_ssa_name (addr_expr, vec_stmt);
00222 TREE_OPERAND (vec_stmt, 0) = new_temp;
00223 append_to_statement_list_force (vec_stmt, new_stmt_list);
00224
00225 if (vect_print_dump_info (REPORT_DETAILS, UNKNOWN_LOC))
00226 {
00227 fprintf (vect_dump, "created ");
00228 print_generic_expr (vect_dump, vec_stmt, TDF_SLIM);
00229 }
00230 return new_temp;
00231 }
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241 static void
00242 vect_align_data_ref (tree stmt)
00243 {
00244 stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
00245 struct data_reference *dr = STMT_VINFO_DATA_REF (stmt_info);
00246
00247
00248
00249 gcc_assert (aligned_access_p (dr));
00250 }
00251
00252
00253
00254
00255
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274
00275
00276
00277
00278
00279
00280
00281
00282
00283
00284
00285
00286
00287
00288
00289
00290
00291
00292
00293
00294
00295
00296
00297
00298 static tree
00299 vect_create_data_ref_ptr (tree stmt, block_stmt_iterator *bsi, tree offset,
00300 tree *initial_address, bool only_init)
00301 {
00302 tree base_name;
00303 stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
00304 loop_vec_info loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_info);
00305 struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo);
00306 tree vectype = STMT_VINFO_VECTYPE (stmt_info);
00307 tree vect_ptr_type;
00308 tree vect_ptr;
00309 tree tag;
00310 v_may_def_optype v_may_defs = STMT_V_MAY_DEF_OPS (stmt);
00311 v_must_def_optype v_must_defs = STMT_V_MUST_DEF_OPS (stmt);
00312 vuse_optype vuses = STMT_VUSE_OPS (stmt);
00313 int nvuses, nv_may_defs, nv_must_defs;
00314 int i;
00315 tree new_temp;
00316 tree vec_stmt;
00317 tree new_stmt_list = NULL_TREE;
00318 tree idx;
00319 edge pe = loop_preheader_edge (loop);
00320 basic_block new_bb;
00321 tree vect_ptr_init;
00322 tree vectype_size;
00323 tree ptr_update;
00324 tree data_ref_ptr;
00325 tree type, tmp, size;
00326
00327 base_name = build_fold_indirect_ref (unshare_expr (
00328 STMT_VINFO_VECT_DR_BASE_ADDRESS (stmt_info)));
00329
00330 if (vect_print_dump_info (REPORT_DETAILS, UNKNOWN_LOC))
00331 {
00332 tree data_ref_base = base_name;
00333 fprintf (vect_dump, "create array_ref of type: ");
00334 print_generic_expr (vect_dump, vectype, TDF_SLIM);
00335 if (TREE_CODE (data_ref_base) == VAR_DECL)
00336 fprintf (vect_dump, " vectorizing a one dimensional array ref: ");
00337 else if (TREE_CODE (data_ref_base) == ARRAY_REF)
00338 fprintf (vect_dump, " vectorizing a multidimensional array ref: ");
00339 else if (TREE_CODE (data_ref_base) == COMPONENT_REF)
00340 fprintf (vect_dump, " vectorizing a record based array ref: ");
00341 else if (TREE_CODE (data_ref_base) == SSA_NAME)
00342 fprintf (vect_dump, " vectorizing a pointer ref: ");
00343 print_generic_expr (vect_dump, base_name, TDF_SLIM);
00344 }
00345
00348 vect_ptr_type = build_pointer_type (vectype);
00349 vect_ptr = vect_get_new_vect_var (vect_ptr_type, vect_pointer_var,
00350 get_name (base_name));
00351 add_referenced_tmp_var (vect_ptr);
00352
00353
00356 tag = STMT_VINFO_MEMTAG (stmt_info);
00357 gcc_assert (tag);
00358 get_var_ann (vect_ptr)->type_mem_tag = tag;
00359
00360
00361
00362 nvuses = NUM_VUSES (vuses);
00363 nv_may_defs = NUM_V_MAY_DEFS (v_may_defs);
00364 nv_must_defs = NUM_V_MUST_DEFS (v_must_defs);
00365 for (i = 0; i < nvuses; i++)
00366 {
00367 tree use = VUSE_OP (vuses, i);
00368 if (TREE_CODE (use) == SSA_NAME)
00369 bitmap_set_bit (vars_to_rename, var_ann (SSA_NAME_VAR (use))->uid);
00370 }
00371 for (i = 0; i < nv_may_defs; i++)
00372 {
00373 tree def = V_MAY_DEF_RESULT (v_may_defs, i);
00374 if (TREE_CODE (def) == SSA_NAME)
00375 bitmap_set_bit (vars_to_rename, var_ann (SSA_NAME_VAR (def))->uid);
00376 }
00377 for (i = 0; i < nv_must_defs; i++)
00378 {
00379 tree def = V_MUST_DEF_RESULT (v_must_defs, i);
00380 if (TREE_CODE (def) == SSA_NAME)
00381 bitmap_set_bit (vars_to_rename, var_ann (SSA_NAME_VAR (def))->uid);
00382 }
00383
00384
00388
00389 new_temp = vect_create_addr_base_for_vector_ref (stmt, &new_stmt_list,
00390 offset);
00391 pe = loop_preheader_edge (loop);
00392 new_bb = bsi_insert_on_edge_immediate (pe, new_stmt_list);
00393 gcc_assert (!new_bb);
00394 *initial_address = new_temp;
00395
00396
00397 vec_stmt = fold_convert (vect_ptr_type, new_temp);
00398 vec_stmt = build2 (MODIFY_EXPR, void_type_node, vect_ptr, vec_stmt);
00399 new_temp = make_ssa_name (vect_ptr, vec_stmt);
00400 TREE_OPERAND (vec_stmt, 0) = new_temp;
00401 new_bb = bsi_insert_on_edge_immediate (pe, vec_stmt);
00402 gcc_assert (!new_bb);
00403 vect_ptr_init = TREE_OPERAND (vec_stmt, 0);
00404
00405
00408 if (only_init)
00409 return vect_ptr_init;
00410
00411 idx = vect_create_index_for_vector_ref (loop_vinfo);
00412
00413
00414 tmp = create_tmp_var (integer_type_node, "update");
00415 add_referenced_tmp_var (tmp);
00416 size = TYPE_SIZE (vect_ptr_type);
00417 type = lang_hooks.types.type_for_size (tree_low_cst (size, 1), 1);
00418 ptr_update = create_tmp_var (type, "update");
00419 add_referenced_tmp_var (ptr_update);
00420 vectype_size = TYPE_SIZE_UNIT (vectype);
00421 vec_stmt = build2 (MULT_EXPR, integer_type_node, idx, vectype_size);
00422 vec_stmt = build2 (MODIFY_EXPR, void_type_node, tmp, vec_stmt);
00423 new_temp = make_ssa_name (tmp, vec_stmt);
00424 TREE_OPERAND (vec_stmt, 0) = new_temp;
00425 bsi_insert_before (bsi, vec_stmt, BSI_SAME_STMT);
00426 vec_stmt = fold_convert (type, new_temp);
00427 vec_stmt = build2 (MODIFY_EXPR, void_type_node, ptr_update, vec_stmt);
00428 new_temp = make_ssa_name (ptr_update, vec_stmt);
00429 TREE_OPERAND (vec_stmt, 0) = new_temp;
00430 bsi_insert_before (bsi, vec_stmt, BSI_SAME_STMT);
00431
00432
00433 vec_stmt = build2 (PLUS_EXPR, vect_ptr_type, vect_ptr_init, new_temp);
00434 vec_stmt = build2 (MODIFY_EXPR, void_type_node, vect_ptr, vec_stmt);
00435 new_temp = make_ssa_name (vect_ptr, vec_stmt);
00436 TREE_OPERAND (vec_stmt, 0) = new_temp;
00437 bsi_insert_before (bsi, vec_stmt, BSI_SAME_STMT);
00438 data_ref_ptr = TREE_OPERAND (vec_stmt, 0);
00439
00440 return data_ref_ptr;
00441 }
00442
00443
00444
00445
00446
00447
00448 static tree
00449 vect_create_destination_var (tree scalar_dest, tree vectype)
00450 {
00451 tree vec_dest;
00452 const char *new_name;
00453
00454 gcc_assert (TREE_CODE (scalar_dest) == SSA_NAME);
00455
00456 new_name = get_name (scalar_dest);
00457 if (!new_name)
00458 new_name = "var_";
00459 vec_dest = vect_get_new_vect_var (vectype, vect_simple_var, new_name);
00460 add_referenced_tmp_var (vec_dest);
00461
00462 return vec_dest;
00463 }
00464
00465
00466
00467
00468
00469
00470
00471
00472 static tree
00473 vect_init_vector (tree stmt, tree vector_var)
00474 {
00475 stmt_vec_info stmt_vinfo = vinfo_for_stmt (stmt);
00476 loop_vec_info loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_vinfo);
00477 struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo);
00478 tree new_var;
00479 tree init_stmt;
00480 tree vectype = STMT_VINFO_VECTYPE (stmt_vinfo);
00481 tree vec_oprnd;
00482 edge pe;
00483 tree new_temp;
00484 basic_block new_bb;
00485
00486 new_var = vect_get_new_vect_var (vectype, vect_simple_var, "cst_");
00487 add_referenced_tmp_var (new_var);
00488
00489 init_stmt = build2 (MODIFY_EXPR, vectype, new_var, vector_var);
00490 new_temp = make_ssa_name (new_var, init_stmt);
00491 TREE_OPERAND (init_stmt, 0) = new_temp;
00492
00493 pe = loop_preheader_edge (loop);
00494 new_bb = bsi_insert_on_edge_immediate (pe, init_stmt);
00495 gcc_assert (!new_bb);
00496
00497 if (vect_print_dump_info (REPORT_DETAILS, UNKNOWN_LOC))
00498 {
00499 fprintf (vect_dump, "created new init_stmt: ");
00500 print_generic_expr (vect_dump, init_stmt, TDF_SLIM);
00501 }
00502
00503 vec_oprnd = TREE_OPERAND (init_stmt, 0);
00504 return vec_oprnd;
00505 }
00506
00507
00508
00509
00510
00511
00512
00513
00514
00515
00516
00517
00518
00519 static tree
00520 vect_get_vec_def_for_operand (tree op, tree stmt)
00521 {
00522 tree vec_oprnd;
00523 tree vec_stmt;
00524 tree def_stmt;
00525 stmt_vec_info def_stmt_info = NULL;
00526 stmt_vec_info stmt_vinfo = vinfo_for_stmt (stmt);
00527 tree vectype = STMT_VINFO_VECTYPE (stmt_vinfo);
00528 int nunits = GET_MODE_NUNITS (TYPE_MODE (vectype));
00529 loop_vec_info loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_vinfo);
00530 struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo);
00531 basic_block bb;
00532 tree vec_inv;
00533 tree t = NULL_TREE;
00534 tree def;
00535 int i;
00536
00537 if (vect_print_dump_info (REPORT_DETAILS, UNKNOWN_LOC))
00538 {
00539 fprintf (vect_dump, "vect_get_vec_def_for_operand: ");
00540 print_generic_expr (vect_dump, op, TDF_SLIM);
00541 }
00542
00545 if (TREE_CODE (op) == INTEGER_CST || TREE_CODE (op) == REAL_CST)
00546 {
00547
00548
00549 tree vec_cst;
00550
00551
00552 if (vect_print_dump_info (REPORT_DETAILS, UNKNOWN_LOC))
00553 fprintf (vect_dump, "Create vector_cst. nunits = %d", nunits);
00554
00555 for (i = nunits - 1; i >= 0; --i)
00556 {
00557 t = tree_cons (NULL_TREE, op, t);
00558 }
00559 vec_cst = build_vector (vectype, t);
00560 return vect_init_vector (stmt, vec_cst);
00561 }
00562
00563 gcc_assert (TREE_CODE (op) == SSA_NAME);
00564
00567 def_stmt = SSA_NAME_DEF_STMT (op);
00568 def_stmt_info = vinfo_for_stmt (def_stmt);
00569
00570 if (vect_print_dump_info (REPORT_DETAILS, UNKNOWN_LOC))
00571 {
00572 fprintf (vect_dump, "vect_get_vec_def_for_operand: def_stmt: ");
00573 print_generic_expr (vect_dump, def_stmt, TDF_SLIM);
00574 }
00575
00576
00579 if (def_stmt_info)
00580 {
00581
00582
00583 vec_stmt = STMT_VINFO_VEC_STMT (def_stmt_info);
00584 gcc_assert (vec_stmt);
00585 vec_oprnd = TREE_OPERAND (vec_stmt, 0);
00586 return vec_oprnd;
00587 }
00588
00589
00593 bb = bb_for_stmt (def_stmt);
00594 if (TREE_CODE (def_stmt) == PHI_NODE && flow_bb_inside_loop_p (loop, bb))
00595 {
00596 if (vect_print_dump_info (REPORT_DETAILS, UNKNOWN_LOC))
00597 fprintf (vect_dump, "reduction/induction - unsupported.");
00598 internal_error ("no support for reduction/induction");
00599 }
00600
00601
00605 switch (TREE_CODE (def_stmt))
00606 {
00607 case PHI_NODE:
00608 def = PHI_RESULT (def_stmt);
00609 break;
00610 case MODIFY_EXPR:
00611 def = TREE_OPERAND (def_stmt, 0);
00612 break;
00613 case NOP_EXPR:
00614 def = TREE_OPERAND (def_stmt, 0);
00615 gcc_assert (IS_EMPTY_STMT (def_stmt));
00616 def = op;
00617 break;
00618 default:
00619 if (vect_print_dump_info (REPORT_DETAILS, UNKNOWN_LOC))
00620 {
00621 fprintf (vect_dump, "unsupported defining stmt: ");
00622 print_generic_expr (vect_dump, def_stmt, TDF_SLIM);
00623 }
00624 internal_error ("unsupported defining stmt");
00625 }
00626
00627
00628
00629
00630 if (vect_print_dump_info (REPORT_DETAILS, UNKNOWN_LOC))
00631 fprintf (vect_dump, "Create vector_inv.");
00632
00633 for (i = nunits - 1; i >= 0; --i)
00634 {
00635 t = tree_cons (NULL_TREE, def, t);
00636 }
00637
00638 vec_inv = build_constructor (vectype, t);
00639 return vect_init_vector (stmt, vec_inv);
00640 }
00641
00642
00643
00644
00645
00646
00647 static void
00648 vect_finish_stmt_generation (tree stmt, tree vec_stmt, block_stmt_iterator *bsi)
00649 {
00650 bsi_insert_before (bsi, vec_stmt, BSI_SAME_STMT);
00651
00652 if (vect_print_dump_info (REPORT_DETAILS, UNKNOWN_LOC))
00653 {
00654 fprintf (vect_dump, "add new stmt: ");
00655 print_generic_expr (vect_dump, vec_stmt, TDF_SLIM);
00656 }
00657
00658 #ifdef ENABLE_CHECKING
00659
00660 gcc_assert (stmt == bsi_stmt (*bsi));
00661 #endif
00662
00663 #ifdef USE_MAPPED_LOCATION
00664 SET_EXPR_LOCATION (vec_stmt, EXPR_LOCUS (stmt));
00665 #else
00666 SET_EXPR_LOCUS (vec_stmt, EXPR_LOCUS (stmt));
00667 #endif
00668 }
00669
00670
00671
00672
00673
00674
00675
00676
00677
00678 bool
00679 vectorizable_assignment (tree stmt, block_stmt_iterator *bsi, tree *vec_stmt)
00680 {
00681 tree vec_dest;
00682 tree scalar_dest;
00683 tree op;
00684 tree vec_oprnd;
00685 stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
00686 tree vectype = STMT_VINFO_VECTYPE (stmt_info);
00687 loop_vec_info loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_info);
00688 tree new_temp;
00689
00690
00691
00692 if (TREE_CODE (stmt) != MODIFY_EXPR)
00693 return false;
00694
00695 scalar_dest = TREE_OPERAND (stmt, 0);
00696 if (TREE_CODE (scalar_dest) != SSA_NAME)
00697 return false;
00698
00699 op = TREE_OPERAND (stmt, 1);
00700 if (!vect_is_simple_use (op, loop_vinfo, NULL))
00701 {
00702 if (vect_print_dump_info (REPORT_DETAILS, UNKNOWN_LOC))
00703 fprintf (vect_dump, "use not simple.");
00704 return false;
00705 }
00706
00707 if (!vec_stmt)
00708 {
00709 STMT_VINFO_TYPE (stmt_info) = assignment_vec_info_type;
00710 return true;
00711 }
00712
00714 if (vect_print_dump_info (REPORT_DETAILS, UNKNOWN_LOC))
00715 fprintf (vect_dump, "transform assignment.");
00716
00717
00718 vec_dest = vect_create_destination_var (scalar_dest, vectype);
00719
00720
00721 op = TREE_OPERAND (stmt, 1);
00722 vec_oprnd = vect_get_vec_def_for_operand (op, stmt);
00723
00724
00725 *vec_stmt = build2 (MODIFY_EXPR, vectype, vec_dest, vec_oprnd);
00726 new_temp = make_ssa_name (vec_dest, *vec_stmt);
00727 TREE_OPERAND (*vec_stmt, 0) = new_temp;
00728 vect_finish_stmt_generation (stmt, *vec_stmt, bsi);
00729
00730 return true;
00731 }
00732
00733
00734
00735
00736
00737
00738
00739
00740
00741 bool
00742 vectorizable_operation (tree stmt, block_stmt_iterator *bsi, tree *vec_stmt)
00743 {
00744 tree vec_dest;
00745 tree scalar_dest;
00746 tree operation;
00747 tree op0, op1 = NULL;
00748 tree vec_oprnd0, vec_oprnd1=NULL;
00749 stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
00750 tree vectype = STMT_VINFO_VECTYPE (stmt_info);
00751 loop_vec_info loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_info);
00752 int i;
00753 enum tree_code code;
00754 enum machine_mode vec_mode;
00755 tree new_temp;
00756 int op_type;
00757 tree op;
00758 optab optab;
00759
00760
00761 if (TREE_CODE (stmt) != MODIFY_EXPR)
00762 return false;
00763
00764 if (TREE_CODE (TREE_OPERAND (stmt, 0)) != SSA_NAME)
00765 return false;
00766
00767 operation = TREE_OPERAND (stmt, 1);
00768 code = TREE_CODE (operation);
00769 optab = optab_for_tree_code (code, vectype);
00770
00771
00772 op_type = TREE_CODE_LENGTH (code);
00773 if (op_type != unary_op && op_type != binary_op)
00774 {
00775 if (vect_print_dump_info (REPORT_DETAILS, UNKNOWN_LOC))
00776 fprintf (vect_dump, "num. args = %d (not unary/binary op).", op_type);
00777 return false;
00778 }
00779
00780 for (i = 0; i < op_type; i++)
00781 {
00782 op = TREE_OPERAND (operation, i);
00783 if (!vect_is_simple_use (op, loop_vinfo, NULL))
00784 {
00785 if (vect_print_dump_info (REPORT_DETAILS, UNKNOWN_LOC))
00786 fprintf (vect_dump, "use not simple.");
00787 return false;
00788 }
00789 }
00790
00791
00792 if (!optab)
00793 {
00794 if (vect_print_dump_info (REPORT_DETAILS, UNKNOWN_LOC))
00795 fprintf (vect_dump, "no optab.");
00796 return false;
00797 }
00798 vec_mode = TYPE_MODE (vectype);
00799 if (optab->handlers[(int) vec_mode].insn_code == CODE_FOR_nothing)
00800 {
00801 if (vect_print_dump_info (REPORT_DETAILS, UNKNOWN_LOC))
00802 fprintf (vect_dump, "op not supported by target.");
00803 return false;
00804 }
00805
00806 if (!vec_stmt)
00807 {
00808 STMT_VINFO_TYPE (stmt_info) = op_vec_info_type;
00809 return true;
00810 }
00811
00814 if (vect_print_dump_info (REPORT_DETAILS, UNKNOWN_LOC))
00815 fprintf (vect_dump, "transform binary/unary operation.");
00816
00817
00818 scalar_dest = TREE_OPERAND (stmt, 0);
00819 vec_dest = vect_create_destination_var (scalar_dest, vectype);
00820
00821
00822 op0 = TREE_OPERAND (operation, 0);
00823 vec_oprnd0 = vect_get_vec_def_for_operand (op0, stmt);
00824
00825 if (op_type == binary_op)
00826 {
00827 op1 = TREE_OPERAND (operation, 1);
00828 vec_oprnd1 = vect_get_vec_def_for_operand (op1, stmt);
00829 }
00830
00831
00832
00833 if (op_type == binary_op)
00834 *vec_stmt = build2 (MODIFY_EXPR, vectype, vec_dest,
00835 build2 (code, vectype, vec_oprnd0, vec_oprnd1));
00836 else
00837 *vec_stmt = build2 (MODIFY_EXPR, vectype, vec_dest,
00838 build1 (code, vectype, vec_oprnd0));
00839 new_temp = make_ssa_name (vec_dest, *vec_stmt);
00840 TREE_OPERAND (*vec_stmt, 0) = new_temp;
00841 vect_finish_stmt_generation (stmt, *vec_stmt, bsi);
00842
00843 return true;
00844 }
00845
00846
00847
00848
00849
00850
00851
00852
00853
00854
00855 bool
00856 vectorizable_store (tree stmt, block_stmt_iterator *bsi, tree *vec_stmt)
00857 {
00858 tree scalar_dest;
00859 tree data_ref;
00860 tree op;
00861 tree vec_oprnd1;
00862 stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
00863 struct data_reference *dr = STMT_VINFO_DATA_REF (stmt_info);
00864 tree vectype = STMT_VINFO_VECTYPE (stmt_info);
00865 loop_vec_info loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_info);
00866 enum machine_mode vec_mode;
00867 tree dummy;
00868 enum dr_alignment_support alignment_support_cheme;
00869
00870
00871
00872 if (TREE_CODE (stmt) != MODIFY_EXPR)
00873 return false;
00874
00875 scalar_dest = TREE_OPERAND (stmt, 0);
00876 if (TREE_CODE (scalar_dest) != ARRAY_REF
00877 && TREE_CODE (scalar_dest) != INDIRECT_REF)
00878 return false;
00879
00880 op = TREE_OPERAND (stmt, 1);
00881 if (!vect_is_simple_use (op, loop_vinfo, NULL))
00882 {
00883 if (vect_print_dump_info (REPORT_DETAILS, UNKNOWN_LOC))
00884 fprintf (vect_dump, "use not simple.");
00885 return false;
00886 }
00887
00888 vec_mode = TYPE_MODE (vectype);
00889
00890
00891 if (mov_optab->handlers[(int)vec_mode].insn_code == CODE_FOR_nothing)
00892 return false;
00893
00894 if (!STMT_VINFO_DATA_REF (stmt_info))
00895 return false;
00896
00897
00898 if (!vec_stmt)
00899 {
00900 STMT_VINFO_TYPE (stmt_info) = store_vec_info_type;
00901 return true;
00902 }
00903
00906 if (vect_print_dump_info (REPORT_DETAILS, UNKNOWN_LOC))
00907 fprintf (vect_dump, "transform store");
00908
00909 alignment_support_cheme = vect_supportable_dr_alignment (dr);
00910 gcc_assert (alignment_support_cheme);
00911 gcc_assert (alignment_support_cheme = dr_aligned);
00912
00913
00914 vec_oprnd1 = vect_get_vec_def_for_operand (op, stmt);
00915
00916
00917
00918 vect_align_data_ref (stmt);
00919 data_ref = vect_create_data_ref_ptr (stmt, bsi, NULL_TREE, &dummy, false);
00920 data_ref = build_fold_indirect_ref (data_ref);
00921
00922
00923 *vec_stmt = build2 (MODIFY_EXPR, vectype, data_ref, vec_oprnd1);
00924 vect_finish_stmt_generation (stmt, *vec_stmt, bsi);
00925
00926 return true;
00927 }
00928
00929
00930
00931
00932
00933
00934
00935
00936
00937
00938 bool
00939 vectorizable_load (tree stmt, block_stmt_iterator *bsi, tree *vec_stmt)
00940 {
00941 tree scalar_dest;
00942 tree vec_dest = NULL;
00943 tree data_ref = NULL;
00944 tree op;
00945 stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
00946 struct data_reference *dr = STMT_VINFO_DATA_REF (stmt_info);
00947 tree vectype = STMT_VINFO_VECTYPE (stmt_info);
00948 tree new_temp;
00949 int mode;
00950 tree init_addr;
00951 tree new_stmt;
00952 tree dummy;
00953 basic_block new_bb;
00954 loop_vec_info loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_info);
00955 struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo);
00956 edge pe = loop_preheader_edge (loop);
00957 enum dr_alignment_support alignment_support_cheme;
00958
00959
00960
00961 if (TREE_CODE (stmt) != MODIFY_EXPR)
00962 return false;
00963
00964 scalar_dest = TREE_OPERAND (stmt, 0);
00965 if (TREE_CODE (scalar_dest) != SSA_NAME)
00966 return false;
00967
00968 op = TREE_OPERAND (stmt, 1);
00969 if (TREE_CODE (op) != ARRAY_REF && TREE_CODE (op) != INDIRECT_REF)
00970 return false;
00971
00972 if (!STMT_VINFO_DATA_REF (stmt_info))
00973 return false;
00974
00975 mode = (int) TYPE_MODE (vectype);
00976
00977
00978
00979 if (mov_optab->handlers[mode].insn_code == CODE_FOR_nothing)
00980 {
00981 if (vect_print_dump_info (REPORT_DETAILS, LOOP_LOC (loop_vinfo)))
00982 fprintf (vect_dump, "Aligned load, but unsupported type.");
00983 return false;
00984 }
00985
00986 if (!vec_stmt)
00987 {
00988 STMT_VINFO_TYPE (stmt_info) = load_vec_info_type;
00989 return true;
00990 }
00991
00994 if (vect_print_dump_info (REPORT_DETAILS, UNKNOWN_LOC))
00995 fprintf (vect_dump, "transform load.");
00996
00997 alignment_support_cheme = vect_supportable_dr_alignment (dr);
00998 gcc_assert (alignment_support_cheme);
00999
01000 if (alignment_support_cheme == dr_aligned
01001 || alignment_support_cheme == dr_unaligned_supported)
01002 {
01003
01004
01005
01006
01007
01008
01009
01010
01011
01012 vec_dest = vect_create_destination_var (scalar_dest, vectype);
01013 data_ref = vect_create_data_ref_ptr (stmt, bsi, NULL_TREE, &dummy, false);
01014 if (aligned_access_p (dr))
01015 data_ref = build_fold_indirect_ref (data_ref);
01016 else
01017 {
01018 int mis = DR_MISALIGNMENT (dr);
01019 tree tmis = (mis == -1 ? size_zero_node : size_int (mis));
01020 tmis = size_binop (MULT_EXPR, tmis, size_int(BITS_PER_UNIT));
01021 data_ref = build2 (MISALIGNED_INDIRECT_REF, vectype, data_ref, tmis);
01022 }
01023 new_stmt = build2 (MODIFY_EXPR, vectype, vec_dest, data_ref);
01024 new_temp = make_ssa_name (vec_dest, new_stmt);
01025 TREE_OPERAND (new_stmt, 0) = new_temp;
01026 vect_finish_stmt_generation (stmt, new_stmt, bsi);
01027 }
01028 else if (alignment_support_cheme == dr_unaligned_software_pipeline)
01029 {
01030
01031
01032
01033
01034
01035
01036
01037
01038
01039
01040
01041
01042
01043
01044
01045 tree offset;
01046 tree magic;
01047 tree phi_stmt;
01048 tree msq_init;
01049 tree msq, lsq;
01050 tree dataref_ptr;
01051 tree params;
01052
01053
01054 vec_dest = vect_create_destination_var (scalar_dest, vectype);
01055 data_ref = vect_create_data_ref_ptr (stmt, bsi, NULL_TREE,
01056 &init_addr, true);
01057 data_ref = build1 (ALIGN_INDIRECT_REF, vectype, data_ref);
01058 new_stmt = build2 (MODIFY_EXPR, vectype, vec_dest, data_ref);
01059 new_temp = make_ssa_name (vec_dest, new_stmt);
01060 TREE_OPERAND (new_stmt, 0) = new_temp;
01061 new_bb = bsi_insert_on_edge_immediate (pe, new_stmt);
01062 gcc_assert (!new_bb);
01063 msq_init = TREE_OPERAND (new_stmt, 0);
01064
01065
01066
01067 offset = build_int_cst (integer_type_node,
01068 GET_MODE_NUNITS (TYPE_MODE (vectype)));
01069 offset = int_const_binop (MINUS_EXPR, offset, integer_one_node, 1);
01070 vec_dest = vect_create_destination_var (scalar_dest, vectype);
01071 dataref_ptr = vect_create_data_ref_ptr (stmt, bsi, offset, &dummy, false);
01072 data_ref = build1 (ALIGN_INDIRECT_REF, vectype, dataref_ptr);
01073 new_stmt = build2 (MODIFY_EXPR, vectype, vec_dest, data_ref);
01074 new_temp = make_ssa_name (vec_dest, new_stmt);
01075 TREE_OPERAND (new_stmt, 0) = new_temp;
01076 vect_finish_stmt_generation (stmt, new_stmt, bsi);
01077 lsq = TREE_OPERAND (new_stmt, 0);
01078
01079
01080
01081 if (targetm.vectorize.builtin_mask_for_load)
01082 {
01083
01084 tree builtin_decl;
01085 params = build_tree_list (NULL_TREE, init_addr);
01086 vec_dest = vect_create_destination_var (scalar_dest, vectype);
01087 builtin_decl = targetm.vectorize.builtin_mask_for_load ();
01088 new_stmt = build_function_call_expr (builtin_decl, params);
01089 new_stmt = build2 (MODIFY_EXPR, vectype, vec_dest, new_stmt);
01090 new_temp = make_ssa_name (vec_dest, new_stmt);
01091 TREE_OPERAND (new_stmt, 0) = new_temp;
01092 new_bb = bsi_insert_on_edge_immediate (pe, new_stmt);
01093 gcc_assert (!new_bb);
01094 magic = TREE_OPERAND (new_stmt, 0);
01095
01096
01097
01098 mark_call_clobbered_vars_to_rename ();
01099 }
01100 else
01101 {
01102
01103
01104 magic = dataref_ptr;
01105 }
01106
01107
01108
01109 vec_dest = vect_create_destination_var (scalar_dest, vectype);
01110 msq = make_ssa_name (vec_dest, NULL_TREE);
01111 phi_stmt = create_phi_node (msq, loop->header);
01112 SSA_NAME_DEF_STMT (msq) = phi_stmt;
01113 add_phi_arg (phi_stmt, msq_init, loop_preheader_edge (loop));
01114 add_phi_arg (phi_stmt, lsq, loop_latch_edge (loop));
01115
01116
01117
01118 vec_dest = vect_create_destination_var (scalar_dest, vectype);
01119 new_stmt = build3 (REALIGN_LOAD_EXPR, vectype, msq, lsq, magic);
01120 new_stmt = build2 (MODIFY_EXPR, vectype, vec_dest, new_stmt);
01121 new_temp = make_ssa_name (vec_dest, new_stmt);
01122 TREE_OPERAND (new_stmt, 0) = new_temp;
01123 vect_finish_stmt_generation (stmt, new_stmt, bsi);
01124 }
01125 else
01126 gcc_unreachable ();
01127
01128 *vec_stmt = new_stmt;
01129 return true;
01130 }
01131
01132
01133
01134
01135
01136
01137 bool
01138 vect_transform_stmt (tree stmt, block_stmt_iterator *bsi)
01139 {
01140 bool is_store = false;
01141 tree vec_stmt = NULL_TREE;
01142 stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
01143 bool done;
01144
01145 switch (STMT_VINFO_TYPE (stmt_info))
01146 {
01147 case op_vec_info_type:
01148 done = vectorizable_operation (stmt, bsi, &vec_stmt);
01149 gcc_assert (done);
01150 break;
01151
01152 case assignment_vec_info_type:
01153 done = vectorizable_assignment (stmt, bsi, &vec_stmt);
01154 gcc_assert (done);
01155 break;
01156
01157 case load_vec_info_type:
01158 done = vectorizable_load (stmt, bsi, &vec_stmt);
01159 gcc_assert (done);
01160 break;
01161
01162 case store_vec_info_type:
01163 done = vectorizable_store (stmt, bsi, &vec_stmt);
01164 gcc_assert (done);
01165 is_store = true;
01166 break;
01167 default:
01168 if (vect_print_dump_info (REPORT_DETAILS, UNKNOWN_LOC))
01169 fprintf (vect_dump, "stmt not supported.");
01170 gcc_unreachable ();
01171 }
01172
01173 STMT_VINFO_VEC_STMT (stmt_info) = vec_stmt;
01174
01175 return is_store;
01176 }
01177
01178
01179
01180
01181
01182 static tree
01183 vect_build_loop_niters (loop_vec_info loop_vinfo)
01184 {
01185 tree ni_name, stmt, var;
01186 edge pe;
01187 struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo);
01188 tree ni = unshare_expr (LOOP_VINFO_NITERS (loop_vinfo));
01189
01190 var = create_tmp_var (TREE_TYPE (ni), "niters");
01191 add_referenced_tmp_var (var);
01192 ni_name = force_gimple_operand (ni, &stmt, false, var);
01193
01194 pe = loop_preheader_edge (loop);
01195 if (stmt)
01196 {
01197 basic_block new_bb = bsi_insert_on_edge_immediate (pe, stmt);
01198 gcc_assert (!new_bb);
01199 }
01200
01201 return ni_name;
01202 }
01203
01204
01205
01206
01207
01208
01209
01210
01211
01212
01213 static void
01214 vect_generate_tmps_on_preheader (loop_vec_info loop_vinfo,
01215 tree *ni_name_ptr,
01216 tree *ratio_mult_vf_name_ptr,
01217 tree *ratio_name_ptr)
01218 {
01219
01220 edge pe;
01221 basic_block new_bb;
01222 tree stmt, ni_name;
01223 tree var;
01224 tree ratio_name;
01225 tree ratio_mult_vf_name;
01226 struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo);
01227 tree ni = LOOP_VINFO_NITERS (loop_vinfo);
01228 int vf = LOOP_VINFO_VECT_FACTOR (loop_vinfo);
01229 tree log_vf = build_int_cst (unsigned_type_node, exact_log2 (vf));
01230
01231 pe = loop_preheader_edge (loop);
01232
01233
01234
01235
01236 ni_name = vect_build_loop_niters (loop_vinfo);
01237
01238
01239
01240 var = create_tmp_var (TREE_TYPE (ni), "bnd");
01241 add_referenced_tmp_var (var);
01242 ratio_name = make_ssa_name (var, NULL_TREE);
01243 stmt = build2 (MODIFY_EXPR, void_type_node, ratio_name,
01244 build2 (RSHIFT_EXPR, TREE_TYPE (ni_name), ni_name, log_vf));
01245 SSA_NAME_DEF_STMT (ratio_name) = stmt;
01246
01247 pe = loop_preheader_edge (loop);
01248 new_bb = bsi_insert_on_edge_immediate (pe, stmt);
01249 gcc_assert (!new_bb);
01250
01251
01252
01253 var = create_tmp_var (TREE_TYPE (ni), "ratio_mult_vf");
01254 add_referenced_tmp_var (var);
01255 ratio_mult_vf_name = make_ssa_name (var, NULL_TREE);
01256 stmt = build2 (MODIFY_EXPR, void_type_node, ratio_mult_vf_name,
01257 build2 (LSHIFT_EXPR, TREE_TYPE (ratio_name), ratio_name, log_vf));
01258 SSA_NAME_DEF_STMT (ratio_mult_vf_name) = stmt;
01259
01260 pe = loop_preheader_edge (loop);
01261 new_bb = bsi_insert_on_edge_immediate (pe, stmt);
01262 gcc_assert (!new_bb);
01263
01264 *ni_name_ptr = ni_name;
01265 *ratio_mult_vf_name_ptr = ratio_mult_vf_name;
01266 *ratio_name_ptr = ratio_name;
01267
01268 return;
01269 }
01270
01271
01272
01273
01274
01275
01276
01277
01278
01279
01280
01281
01282
01283
01284
01285
01286
01287
01288
01289
01290
01291
01292
01293
01294
01295
01296
01297
01298
01299
01300
01301
01302
01303
01304
01305
01306
01307
01308
01309
01310
01311
01312
01313 static void
01314 vect_update_ivs_after_vectorizer (loop_vec_info loop_vinfo, tree niters,
01315 edge update_e)
01316 {
01317 struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo);
01318 basic_block exit_bb = loop->exit_edges[0]->dest;
01319 tree phi, phi1;
01320 basic_block update_bb = update_e->dest;
01321
01322
01323
01324
01325 gcc_assert (EDGE_COUNT (exit_bb->preds) == 1);
01326
01327 for (phi = phi_nodes (loop->header), phi1 = phi_nodes (update_bb);
01328 phi && phi1;
01329 phi = PHI_CHAIN (phi), phi1 = PHI_CHAIN (phi1))
01330 {
01331 tree access_fn = NULL;
01332 tree evolution_part;
01333 tree init_expr;
01334 tree step_expr;
01335 tree var, stmt, ni, ni_name;
01336 block_stmt_iterator last_bsi;
01337
01338
01339 if (!is_gimple_reg (SSA_NAME_VAR (PHI_RESULT (phi))))
01340 {
01341 if (vect_print_dump_info (REPORT_DETAILS, UNKNOWN_LOC))
01342 fprintf (vect_dump, "virtual phi. skip.");
01343 continue;
01344 }
01345
01346 access_fn = analyze_scalar_evolution (loop, PHI_RESULT (phi));
01347 gcc_assert (access_fn);
01348 evolution_part =
01349 unshare_expr (evolution_part_in_loop_num (access_fn, loop->num));
01350 gcc_assert (evolution_part != NULL_TREE);
01351
01352
01353
01354 gcc_assert (!tree_is_chrec (evolution_part));
01355
01356 step_expr = evolution_part;
01357 init_expr = unshare_expr (initial_condition_in_loop_num (access_fn,
01358 loop->num));
01359
01360 ni = build2 (PLUS_EXPR, TREE_TYPE (init_expr),
01361 build2 (MULT_EXPR, TREE_TYPE (niters),
01362 niters, step_expr), init_expr);
01363
01364 var = create_tmp_var (TREE_TYPE (init_expr), "tmp");
01365 add_referenced_tmp_var (var);
01366
01367 ni_name = force_gimple_operand (ni, &stmt, false, var);
01368
01369
01370 last_bsi = bsi_last (exit_bb);
01371 if (stmt)
01372 bsi_insert_before (&last_bsi, stmt, BSI_SAME_STMT);
01373
01374
01375 gcc_assert (PHI_ARG_DEF_FROM_EDGE (phi1, update_e) ==
01376 PHI_ARG_DEF_FROM_EDGE (phi, EDGE_SUCC (loop->latch, 0)));
01377 SET_PHI_ARG_DEF (phi1, update_e->dest_idx, ni_name);
01378 }
01379 }
01380
01381
01382
01383
01384
01385
01386
01387
01388
01389
01390
01391
01392 static void
01393 vect_do_peeling_for_loop_bound (loop_vec_info loop_vinfo, tree *ratio,
01394 struct loops *loops)
01395 {
01396
01397 tree ni_name, ratio_mult_vf_name;
01398 struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo);
01399 struct loop *new_loop;
01400 edge update_e;
01401 #ifdef ENABLE_CHECKING
01402 int loop_num;
01403 #endif
01404
01405 if (vect_print_dump_info (REPORT_DETAILS, UNKNOWN_LOC))
01406 fprintf (vect_dump, "=== vect_transtorm_for_unknown_loop_bound ===");
01407
01408
01409
01410
01411
01412
01413 vect_generate_tmps_on_preheader (loop_vinfo, &ni_name,
01414 &ratio_mult_vf_name, ratio);
01415
01416
01417 loop->pre_header = loop_preheader_edge (loop)->src;
01418 loop->pre_header_edges[0] = loop_preheader_edge (loop);
01419
01420 #ifdef ENABLE_CHECKING
01421 loop_num = loop->num;
01422 #endif
01423 new_loop = slpeel_tree_peel_loop_to_edge (loop, loops, loop->exit_edges[0],
01424 ratio_mult_vf_name, ni_name, false);
01425 #ifdef ENABLE_CHECKING
01426 gcc_assert (new_loop);
01427 gcc_assert (loop_num == loop->num);
01428 slpeel_verify_cfg_after_peeling (loop, new_loop);
01429 #endif
01430
01431
01432
01433
01434
01435
01436
01437 if (EDGE_PRED (new_loop->pre_header, 0)->src == loop->exit_edges[0]->dest)
01438 update_e = EDGE_PRED (new_loop->pre_header, 0);
01439 else
01440 update_e = EDGE_PRED (new_loop->pre_header, 1);
01441
01442
01443
01444 vect_update_ivs_after_vectorizer (loop_vinfo, ratio_mult_vf_name, update_e);
01445
01446
01447 scev_reset ();
01448
01449 return;
01450 }
01451
01452
01453
01454
01455
01456
01457
01458
01459
01460
01461
01462
01463
01464
01465
01466
01467
01468
01469
01470
01471 static tree
01472 vect_gen_niters_for_prolog_loop (loop_vec_info loop_vinfo, tree loop_niters)
01473 {
01474 struct data_reference *dr = LOOP_VINFO_UNALIGNED_DR (loop_vinfo);
01475 int vf = LOOP_VINFO_VECT_FACTOR (loop_vinfo);
01476 struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo);
01477 tree var, stmt;
01478 tree iters, iters_name;
01479 edge pe;
01480 basic_block new_bb;
01481 tree dr_stmt = DR_STMT (dr);
01482 stmt_vec_info stmt_info = vinfo_for_stmt (dr_stmt);
01483 tree vectype = STMT_VINFO_VECTYPE (stmt_info);
01484 int vectype_align = TYPE_ALIGN (vectype) / BITS_PER_UNIT;
01485 tree elem_misalign;
01486 tree byte_misalign;
01487 tree new_stmts = NULL_TREE;
01488 tree start_addr =
01489 vect_create_addr_base_for_vector_ref (dr_stmt, &new_stmts, NULL_TREE);
01490 tree ptr_type = TREE_TYPE (start_addr);
01491 tree size = TYPE_SIZE (ptr_type);
01492 tree type = lang_hooks.types.type_for_size (tree_low_cst (size, 1), 1);
01493 tree vectype_size_minus_1 = build_int_cst (type, vectype_align - 1);
01494 tree vf_minus_1 = build_int_cst (unsigned_type_node, vf - 1);
01495 tree niters_type = TREE_TYPE (loop_niters);
01496 tree elem_size_log =
01497 build_int_cst (unsigned_type_node, exact_log2 (vectype_align/vf));
01498 tree vf_tree = build_int_cst (unsigned_type_node, vf);
01499
01500 pe = loop_preheader_edge (loop);
01501 new_bb = bsi_insert_on_edge_immediate (pe, new_stmts);
01502 gcc_assert (!new_bb);
01503
01504
01505 byte_misalign = build2 (BIT_AND_EXPR, type, start_addr, vectype_size_minus_1);
01506
01507
01508 elem_misalign =
01509 build2 (RSHIFT_EXPR, unsigned_type_node, byte_misalign, elem_size_log);
01510
01511
01512 iters = build2 (MINUS_EXPR, unsigned_type_node, vf_tree, elem_misalign);
01513 iters = build2 (BIT_AND_EXPR, unsigned_type_node, iters, vf_minus_1);
01514 iters = fold_convert (niters_type, iters);
01515
01516
01517
01518
01519
01520 if (TREE_CODE (loop_niters) != INTEGER_CST)
01521 iters = build2 (MIN_EXPR, niters_type, iters, loop_niters);
01522
01523 var = create_tmp_var (niters_type, "prolog_loop_niters");
01524 add_referenced_tmp_var (var);
01525 iters_name = force_gimple_operand (iters, &stmt, false, var);
01526
01527
01528 pe = loop_preheader_edge (loop);
01529 if (stmt)
01530 {
01531 basic_block new_bb = bsi_insert_on_edge_immediate (pe, stmt);
01532 gcc_assert (!new_bb);
01533 }
01534
01535 return iters_name;
01536 }
01537
01538
01539
01540
01541
01542
01543
01544
01545
01546 static void
01547 vect_update_inits_of_dr (struct data_reference *dr, tree niters)
01548 {
01549 stmt_vec_info stmt_info = vinfo_for_stmt (DR_STMT (dr));
01550 tree offset = STMT_VINFO_VECT_INIT_OFFSET (stmt_info);
01551
01552 niters = fold (build2 (MULT_EXPR, TREE_TYPE (niters), niters,
01553 STMT_VINFO_VECT_STEP (stmt_info)));
01554 offset = fold (build2 (PLUS_EXPR, TREE_TYPE (offset), offset, niters));
01555 STMT_VINFO_VECT_INIT_OFFSET (stmt_info) = offset;
01556 }
01557
01558
01559
01560
01561
01562
01563
01564
01565
01566
01567 static void
01568 vect_update_inits_of_drs (loop_vec_info loop_vinfo, tree niters)
01569 {
01570 unsigned int i;
01571 varray_type loop_write_datarefs = LOOP_VINFO_DATAREF_WRITES (loop_vinfo);
01572 varray_type loop_read_datarefs = LOOP_VINFO_DATAREF_READS (loop_vinfo);
01573
01574 if (vect_dump && (dump_flags & TDF_DETAILS))
01575 fprintf (vect_dump, "=== vect_update_inits_of_dr ===");
01576
01577 for (i = 0; i < VARRAY_ACTIVE_SIZE (loop_write_datarefs); i++)
01578 {
01579 struct data_reference *dr = VARRAY_GENERIC_PTR (loop_write_datarefs, i);
01580 vect_update_inits_of_dr (dr, niters);
01581 }
01582
01583 for (i = 0; i < VARRAY_ACTIVE_SIZE (loop_read_datarefs); i++)
01584 {
01585 struct data_reference *dr = VARRAY_GENERIC_PTR (loop_read_datarefs, i);
01586 vect_update_inits_of_dr (dr, niters);
01587 }
01588 }
01589
01590
01591
01592
01593
01594
01595
01596
01597
01598
01599 static void
01600 vect_do_peeling_for_alignment (loop_vec_info loop_vinfo, struct loops *loops)
01601 {
01602 struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo);
01603 tree niters_of_prolog_loop, ni_name;
01604 tree n_iters;
01605 struct loop *new_loop;
01606
01607 if (vect_print_dump_info (REPORT_DETAILS, UNKNOWN_LOC))
01608 fprintf (vect_dump, "=== vect_do_peeling_for_alignment ===");
01609
01610 ni_name = vect_build_loop_niters (loop_vinfo);
01611 niters_of_prolog_loop = vect_gen_niters_for_prolog_loop (loop_vinfo, ni_name);
01612
01613
01614 new_loop =
01615 slpeel_tree_peel_loop_to_edge (loop, loops, loop_preheader_edge (loop),
01616 niters_of_prolog_loop, ni_name, true);
01617 #ifdef ENABLE_CHECKING
01618 gcc_assert (new_loop);
01619 slpeel_verify_cfg_after_peeling (new_loop, loop);
01620 #endif
01621
01622
01623 n_iters = LOOP_VINFO_NITERS (loop_vinfo);
01624 LOOP_VINFO_NITERS (loop_vinfo) =
01625 build2 (MINUS_EXPR, TREE_TYPE (n_iters), n_iters, niters_of_prolog_loop);
01626
01627
01628 vect_update_inits_of_drs (loop_vinfo, niters_of_prolog_loop);
01629
01630
01631 scev_reset ();
01632
01633 return;
01634 }
01635
01636
01637
01638
01639
01640
01641
01642
01643 void
01644 vect_transform_loop (loop_vec_info loop_vinfo,
01645 struct loops *loops ATTRIBUTE_UNUSED)
01646 {
01647 struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo);
01648 basic_block *bbs = LOOP_VINFO_BBS (loop_vinfo);
01649 int nbbs = loop->num_nodes;
01650 block_stmt_iterator si;
01651 int i;
01652 tree ratio = NULL;
01653 int vectorization_factor = LOOP_VINFO_VECT_FACTOR (loop_vinfo);
01654
01655 if (vect_print_dump_info (REPORT_DETAILS, UNKNOWN_LOC))
01656 fprintf (vect_dump, "=== vec_transform_loop ===");
01657
01658
01659
01660
01661
01662 if (LOOP_DO_PEELING_FOR_ALIGNMENT (loop_vinfo))
01663 vect_do_peeling_for_alignment (loop_vinfo, loops);
01664
01665
01666
01667
01668
01669
01670
01671
01672
01673 if (!LOOP_VINFO_NITERS_KNOWN_P (loop_vinfo)
01674 || (LOOP_VINFO_NITERS_KNOWN_P (loop_vinfo)
01675 && LOOP_VINFO_INT_NITERS (loop_vinfo) % vectorization_factor != 0))
01676 vect_do_peeling_for_loop_bound (loop_vinfo, &ratio, loops);
01677 else
01678 ratio = build_int_cst (TREE_TYPE (LOOP_VINFO_NITERS (loop_vinfo)),
01679 LOOP_VINFO_INT_NITERS (loop_vinfo) / vectorization_factor);
01680
01681
01682
01683
01684 gcc_assert (EDGE_COUNT (loop->header->preds) == 2);
01685
01686 loop_split_edge_with (loop_preheader_edge (loop), NULL);
01687
01688
01689
01690
01691
01692
01693
01694 for (i = 0; i < nbbs; i++)
01695 {
01696 basic_block bb = bbs[i];
01697
01698 for (si = bsi_start (bb); !bsi_end_p (si);)
01699 {
01700 tree stmt = bsi_stmt (si);
01701 stmt_vec_info stmt_info;
01702 bool is_store;
01703
01704 if (vect_print_dump_info (REPORT_DETAILS, UNKNOWN_LOC))
01705 {
01706 fprintf (vect_dump, "------>vectorizing statement: ");
01707 print_generic_expr (vect_dump, stmt, TDF_SLIM);
01708 }
01709 stmt_info = vinfo_for_stmt (stmt);
01710 gcc_assert (stmt_info);
01711 if (!STMT_VINFO_RELEVANT_P (stmt_info))
01712 {
01713 bsi_next (&si);
01714 continue;
01715 }
01716 #ifdef ENABLE_CHECKING
01717
01718
01719 gcc_assert
01720 (GET_MODE_NUNITS (TYPE_MODE (STMT_VINFO_VECTYPE (stmt_info)))
01721 == vectorization_factor);
01722 #endif
01723
01724 if (vect_print_dump_info (REPORT_DETAILS, UNKNOWN_LOC))
01725 fprintf (vect_dump, "transform statement.");
01726
01727 is_store = vect_transform_stmt (stmt, &si);
01728 if (is_store)
01729 {
01730
01731 stmt_ann_t ann = stmt_ann (stmt);
01732 free (stmt_info);
01733 set_stmt_info (ann, NULL);
01734 bsi_remove (&si);
01735 continue;
01736 }
01737
01738 bsi_next (&si);
01739 }
01740 }
01741
01742 slpeel_make_loop_iterate_ntimes (loop, ratio);
01743
01744 if (vect_print_dump_info (REPORT_VECTORIZED_LOOPS, LOOP_LOC (loop_vinfo)))
01745 fprintf (vect_dump, "LOOP VECTORIZED.");
01746 }