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 "ggc.h"
00027 #include "tree.h"
00028 #include "target.h"
00029 #include "rtl.h"
00030 #include "basic-block.h"
00031 #include "diagnostic.h"
00032 #include "tree-flow.h"
00033 #include "tree-dump.h"
00034 #include "timevar.h"
00035 #include "cfgloop.h"
00036 #include "expr.h"
00037 #include "optabs.h"
00038 #include "recog.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 #include "real.h"
00047
00048
00049 static bool vect_transform_stmt (tree, block_stmt_iterator *);
00050 static void vect_align_data_ref (tree);
00051 static tree vect_create_destination_var (tree, tree);
00052 static tree vect_create_data_ref_ptr
00053 (tree, block_stmt_iterator *, tree, tree *, bool);
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, 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 static bool vect_is_simple_cond (tree, loop_vec_info);
00061 static void update_vuses_to_preheader (tree, struct loop*);
00062 static void vect_create_epilog_for_reduction (tree, tree, enum tree_code, tree);
00063 static tree get_initial_def_for_reduction (tree, tree, tree *);
00064
00065
00066 static void vect_generate_tmps_on_preheader
00067 (loop_vec_info, tree *, tree *, tree *);
00068 static tree vect_build_loop_niters (loop_vec_info);
00069 static void vect_update_ivs_after_vectorizer (loop_vec_info, tree, edge);
00070 static tree vect_gen_niters_for_prolog_loop (loop_vec_info, tree);
00071 static void vect_update_init_of_dr (struct data_reference *, tree niters);
00072 static void vect_update_inits_of_drs (loop_vec_info, tree);
00073 static void vect_do_peeling_for_alignment (loop_vec_info, struct loops *);
00074 static void vect_do_peeling_for_loop_bound
00075 (loop_vec_info, tree *, struct loops *);
00076 static int vect_min_worthwhile_factor (enum tree_code);
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086 static tree
00087 vect_get_new_vect_var (tree type, enum vect_var_kind var_kind, const char *name)
00088 {
00089 const char *prefix;
00090 tree new_vect_var;
00091
00092 switch (var_kind)
00093 {
00094 case vect_simple_var:
00095 prefix = "vect_";
00096 break;
00097 case vect_scalar_var:
00098 prefix = "stmp_";
00099 break;
00100 case vect_pointer_var:
00101 prefix = "vect_p";
00102 break;
00103 default:
00104 gcc_unreachable ();
00105 }
00106
00107 if (name)
00108 new_vect_var = create_tmp_var (type, concat (prefix, name, NULL));
00109 else
00110 new_vect_var = create_tmp_var (type, prefix);
00111
00112 return new_vect_var;
00113 }
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134 static tree
00135 vect_create_addr_base_for_vector_ref (tree stmt,
00136 tree *new_stmt_list,
00137 tree offset)
00138 {
00139 stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
00140 struct data_reference *dr = STMT_VINFO_DATA_REF (stmt_info);
00141 tree data_ref_base = unshare_expr (DR_BASE_ADDRESS (dr));
00142 tree base_name = build_fold_indirect_ref (data_ref_base);
00143 tree ref = DR_REF (dr);
00144 tree scalar_type = TREE_TYPE (ref);
00145 tree scalar_ptr_type = build_pointer_type (scalar_type);
00146 tree vec_stmt;
00147 tree new_temp;
00148 tree addr_base, addr_expr;
00149 tree dest, new_stmt;
00150 tree base_offset = unshare_expr (DR_OFFSET (dr));
00151 tree init = unshare_expr (DR_INIT (dr));
00152
00153
00154 base_offset = size_binop (PLUS_EXPR, base_offset, init);
00155 dest = create_tmp_var (TREE_TYPE (base_offset), "base_off");
00156 add_referenced_var (dest);
00157 base_offset = force_gimple_operand (base_offset, &new_stmt, false, dest);
00158 append_to_statement_list_force (new_stmt, new_stmt_list);
00159
00160 if (offset)
00161 {
00162 tree tmp = create_tmp_var (TREE_TYPE (base_offset), "offset");
00163 add_referenced_var (tmp);
00164 offset = fold_build2 (MULT_EXPR, TREE_TYPE (offset), offset,
00165 DR_STEP (dr));
00166 base_offset = fold_build2 (PLUS_EXPR, TREE_TYPE (base_offset),
00167 base_offset, offset);
00168 base_offset = force_gimple_operand (base_offset, &new_stmt, false, tmp);
00169 append_to_statement_list_force (new_stmt, new_stmt_list);
00170 }
00171
00172
00173 addr_base = fold_build2 (PLUS_EXPR, TREE_TYPE (data_ref_base), data_ref_base,
00174 base_offset);
00175
00176
00177 addr_expr = vect_get_new_vect_var (scalar_ptr_type, vect_pointer_var,
00178 get_name (base_name));
00179 add_referenced_var (addr_expr);
00180 vec_stmt = build2 (MODIFY_EXPR, void_type_node, addr_expr, addr_base);
00181 new_temp = make_ssa_name (addr_expr, vec_stmt);
00182 TREE_OPERAND (vec_stmt, 0) = new_temp;
00183 append_to_statement_list_force (vec_stmt, new_stmt_list);
00184
00185 if (vect_print_dump_info (REPORT_DETAILS))
00186 {
00187 fprintf (vect_dump, "created ");
00188 print_generic_expr (vect_dump, vec_stmt, TDF_SLIM);
00189 }
00190 return new_temp;
00191 }
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201 static void
00202 vect_align_data_ref (tree stmt)
00203 {
00204 stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
00205 struct data_reference *dr = STMT_VINFO_DATA_REF (stmt_info);
00206
00207
00208
00209 gcc_assert (aligned_access_p (dr));
00210 }
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250 static tree
00251 vect_create_data_ref_ptr (tree stmt,
00252 block_stmt_iterator *bsi ATTRIBUTE_UNUSED,
00253 tree offset, tree *initial_address, bool only_init)
00254 {
00255 tree base_name;
00256 stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
00257 loop_vec_info loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_info);
00258 struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo);
00259 tree vectype = STMT_VINFO_VECTYPE (stmt_info);
00260 tree vect_ptr_type;
00261 tree vect_ptr;
00262 tree tag;
00263 tree new_temp;
00264 tree vec_stmt;
00265 tree new_stmt_list = NULL_TREE;
00266 edge pe = loop_preheader_edge (loop);
00267 basic_block new_bb;
00268 tree vect_ptr_init;
00269 struct data_reference *dr = STMT_VINFO_DATA_REF (stmt_info);
00270
00271 base_name = build_fold_indirect_ref (unshare_expr (DR_BASE_ADDRESS (dr)));
00272
00273 if (vect_print_dump_info (REPORT_DETAILS))
00274 {
00275 tree data_ref_base = base_name;
00276 fprintf (vect_dump, "create vector-pointer variable to type: ");
00277 print_generic_expr (vect_dump, vectype, TDF_SLIM);
00278 if (TREE_CODE (data_ref_base) == VAR_DECL)
00279 fprintf (vect_dump, " vectorizing a one dimensional array ref: ");
00280 else if (TREE_CODE (data_ref_base) == ARRAY_REF)
00281 fprintf (vect_dump, " vectorizing a multidimensional array ref: ");
00282 else if (TREE_CODE (data_ref_base) == COMPONENT_REF)
00283 fprintf (vect_dump, " vectorizing a record based array ref: ");
00284 else if (TREE_CODE (data_ref_base) == SSA_NAME)
00285 fprintf (vect_dump, " vectorizing a pointer ref: ");
00286 print_generic_expr (vect_dump, base_name, TDF_SLIM);
00287 }
00288
00291 vect_ptr_type = build_pointer_type (vectype);
00292 vect_ptr = vect_get_new_vect_var (vect_ptr_type, vect_pointer_var,
00293 get_name (base_name));
00294 add_referenced_var (vect_ptr);
00295
00296
00300 tag = DR_MEMTAG (dr);
00301 gcc_assert (tag);
00302
00303
00304
00305 if (!MTAG_P (tag))
00306 new_type_alias (vect_ptr, tag, DR_REF (dr));
00307 else
00308 var_ann (vect_ptr)->symbol_mem_tag = tag;
00309
00310 var_ann (vect_ptr)->subvars = DR_SUBVARS (dr);
00311
00315
00316 new_temp = vect_create_addr_base_for_vector_ref (stmt, &new_stmt_list,
00317 offset);
00318 pe = loop_preheader_edge (loop);
00319 new_bb = bsi_insert_on_edge_immediate (pe, new_stmt_list);
00320 gcc_assert (!new_bb);
00321 *initial_address = new_temp;
00322
00323
00324 vec_stmt = fold_convert (vect_ptr_type, new_temp);
00325 vec_stmt = build2 (MODIFY_EXPR, void_type_node, vect_ptr, vec_stmt);
00326 vect_ptr_init = make_ssa_name (vect_ptr, vec_stmt);
00327 TREE_OPERAND (vec_stmt, 0) = vect_ptr_init;
00328 new_bb = bsi_insert_on_edge_immediate (pe, vec_stmt);
00329 gcc_assert (!new_bb);
00330
00331
00334 if (only_init)
00335 {
00336
00337 if (DR_PTR_INFO (dr))
00338 duplicate_ssa_name_ptr_info (vect_ptr_init, DR_PTR_INFO (dr));
00339 return vect_ptr_init;
00340 }
00341 else
00342 {
00343 block_stmt_iterator incr_bsi;
00344 bool insert_after;
00345 tree indx_before_incr, indx_after_incr;
00346 tree incr;
00347
00348 standard_iv_increment_position (loop, &incr_bsi, &insert_after);
00349 create_iv (vect_ptr_init,
00350 fold_convert (vect_ptr_type, TYPE_SIZE_UNIT (vectype)),
00351 NULL_TREE, loop, &incr_bsi, insert_after,
00352 &indx_before_incr, &indx_after_incr);
00353 incr = bsi_stmt (incr_bsi);
00354 set_stmt_info (stmt_ann (incr),
00355 new_stmt_vec_info (incr, loop_vinfo));
00356
00357
00358 if (DR_PTR_INFO (dr))
00359 {
00360 duplicate_ssa_name_ptr_info (indx_before_incr, DR_PTR_INFO (dr));
00361 duplicate_ssa_name_ptr_info (indx_after_incr, DR_PTR_INFO (dr));
00362 }
00363 merge_alias_info (vect_ptr_init, indx_before_incr);
00364 merge_alias_info (vect_ptr_init, indx_after_incr);
00365
00366 return indx_before_incr;
00367 }
00368 }
00369
00370
00371
00372
00373
00374
00375 static tree
00376 vect_create_destination_var (tree scalar_dest, tree vectype)
00377 {
00378 tree vec_dest;
00379 const char *new_name;
00380 tree type;
00381 enum vect_var_kind kind;
00382
00383 kind = vectype ? vect_simple_var : vect_scalar_var;
00384 type = vectype ? vectype : TREE_TYPE (scalar_dest);
00385
00386 gcc_assert (TREE_CODE (scalar_dest) == SSA_NAME);
00387
00388 new_name = get_name (scalar_dest);
00389 if (!new_name)
00390 new_name = "var_";
00391 vec_dest = vect_get_new_vect_var (type, vect_simple_var, new_name);
00392 add_referenced_var (vec_dest);
00393
00394 return vec_dest;
00395 }
00396
00397
00398
00399
00400
00401
00402
00403
00404 static tree
00405 vect_init_vector (tree stmt, tree vector_var)
00406 {
00407 stmt_vec_info stmt_vinfo = vinfo_for_stmt (stmt);
00408 loop_vec_info loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_vinfo);
00409 struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo);
00410 tree new_var;
00411 tree init_stmt;
00412 tree vectype = STMT_VINFO_VECTYPE (stmt_vinfo);
00413 tree vec_oprnd;
00414 edge pe;
00415 tree new_temp;
00416 basic_block new_bb;
00417
00418 new_var = vect_get_new_vect_var (vectype, vect_simple_var, "cst_");
00419 add_referenced_var (new_var);
00420
00421 init_stmt = build2 (MODIFY_EXPR, vectype, new_var, vector_var);
00422 new_temp = make_ssa_name (new_var, init_stmt);
00423 TREE_OPERAND (init_stmt, 0) = new_temp;
00424
00425 pe = loop_preheader_edge (loop);
00426 new_bb = bsi_insert_on_edge_immediate (pe, init_stmt);
00427 gcc_assert (!new_bb);
00428
00429 if (vect_print_dump_info (REPORT_DETAILS))
00430 {
00431 fprintf (vect_dump, "created new init_stmt: ");
00432 print_generic_expr (vect_dump, init_stmt, TDF_SLIM);
00433 }
00434
00435 vec_oprnd = TREE_OPERAND (init_stmt, 0);
00436 return vec_oprnd;
00437 }
00438
00439
00440
00441
00442
00443
00444
00445
00446
00447
00448
00449
00450
00451 static tree
00452 vect_get_vec_def_for_operand (tree op, tree stmt, tree *scalar_def)
00453 {
00454 tree vec_oprnd;
00455 tree vec_stmt;
00456 tree def_stmt;
00457 stmt_vec_info def_stmt_info = NULL;
00458 stmt_vec_info stmt_vinfo = vinfo_for_stmt (stmt);
00459 tree vectype = STMT_VINFO_VECTYPE (stmt_vinfo);
00460 int nunits = TYPE_VECTOR_SUBPARTS (vectype);
00461 loop_vec_info loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_vinfo);
00462 struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo);
00463 tree vec_inv;
00464 tree vec_cst;
00465 tree t = NULL_TREE;
00466 tree def;
00467 int i;
00468 enum vect_def_type dt;
00469 bool is_simple_use;
00470
00471 if (vect_print_dump_info (REPORT_DETAILS))
00472 {
00473 fprintf (vect_dump, "vect_get_vec_def_for_operand: ");
00474 print_generic_expr (vect_dump, op, TDF_SLIM);
00475 }
00476
00477 is_simple_use = vect_is_simple_use (op, loop_vinfo, &def_stmt, &def, &dt);
00478 gcc_assert (is_simple_use);
00479 if (vect_print_dump_info (REPORT_DETAILS))
00480 {
00481 if (def)
00482 {
00483 fprintf (vect_dump, "def = ");
00484 print_generic_expr (vect_dump, def, TDF_SLIM);
00485 }
00486 if (def_stmt)
00487 {
00488 fprintf (vect_dump, " def_stmt = ");
00489 print_generic_expr (vect_dump, def_stmt, TDF_SLIM);
00490 }
00491 }
00492
00493 switch (dt)
00494 {
00495
00496 case vect_constant_def:
00497 {
00498 if (scalar_def)
00499 *scalar_def = op;
00500
00501
00502 if (vect_print_dump_info (REPORT_DETAILS))
00503 fprintf (vect_dump, "Create vector_cst. nunits = %d", nunits);
00504
00505 for (i = nunits - 1; i >= 0; --i)
00506 {
00507 t = tree_cons (NULL_TREE, op, t);
00508 }
00509 vec_cst = build_vector (vectype, t);
00510 return vect_init_vector (stmt, vec_cst);
00511 }
00512
00513
00514 case vect_invariant_def:
00515 {
00516 if (scalar_def)
00517 *scalar_def = def;
00518
00519
00520 if (vect_print_dump_info (REPORT_DETAILS))
00521 fprintf (vect_dump, "Create vector_inv.");
00522
00523 for (i = nunits - 1; i >= 0; --i)
00524 {
00525 t = tree_cons (NULL_TREE, def, t);
00526 }
00527
00528
00529 vec_inv = build_constructor_from_list (vectype, t);
00530 return vect_init_vector (stmt, vec_inv);
00531 }
00532
00533
00534 case vect_loop_def:
00535 {
00536 if (scalar_def)
00537 *scalar_def = def_stmt;
00538
00539
00540 def_stmt_info = vinfo_for_stmt (def_stmt);
00541 vec_stmt = STMT_VINFO_VEC_STMT (def_stmt_info);
00542 gcc_assert (vec_stmt);
00543 vec_oprnd = TREE_OPERAND (vec_stmt, 0);
00544 return vec_oprnd;
00545 }
00546
00547
00548 case vect_reduction_def:
00549 {
00550 gcc_assert (TREE_CODE (def_stmt) == PHI_NODE);
00551
00552
00553 op = PHI_ARG_DEF_FROM_EDGE (def_stmt, loop_preheader_edge (loop));
00554 return get_initial_def_for_reduction (stmt, op, scalar_def);
00555 }
00556
00557
00558 case vect_induction_def:
00559 {
00560 if (vect_print_dump_info (REPORT_DETAILS))
00561 fprintf (vect_dump, "induction - unsupported.");
00562 internal_error ("no support for induction");
00563 }
00564
00565 default:
00566 gcc_unreachable ();
00567 }
00568 }
00569
00570
00571
00572
00573
00574
00575 static void
00576 vect_finish_stmt_generation (tree stmt, tree vec_stmt, block_stmt_iterator *bsi)
00577 {
00578 bsi_insert_before (bsi, vec_stmt, BSI_SAME_STMT);
00579
00580 if (vect_print_dump_info (REPORT_DETAILS))
00581 {
00582 fprintf (vect_dump, "add new stmt: ");
00583 print_generic_expr (vect_dump, vec_stmt, TDF_SLIM);
00584 }
00585
00586
00587 gcc_assert (stmt == bsi_stmt (*bsi));
00588
00589 #ifdef USE_MAPPED_LOCATION
00590 SET_EXPR_LOCATION (vec_stmt, EXPR_LOCATION (stmt));
00591 #else
00592 SET_EXPR_LOCUS (vec_stmt, EXPR_LOCUS (stmt));
00593 #endif
00594 }
00595
00596
00597 #define ADJUST_IN_EPILOG 1
00598
00599
00600
00601
00602
00603
00604
00605
00606
00607
00608
00609
00610
00611
00612
00613
00614
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 static tree
00643 get_initial_def_for_reduction (tree stmt, tree init_val, tree *scalar_def)
00644 {
00645 stmt_vec_info stmt_vinfo = vinfo_for_stmt (stmt);
00646 tree vectype = STMT_VINFO_VECTYPE (stmt_vinfo);
00647 int nunits = GET_MODE_NUNITS (TYPE_MODE (vectype));
00648 int nelements;
00649 enum tree_code code = TREE_CODE (TREE_OPERAND (stmt, 1));
00650 tree type = TREE_TYPE (init_val);
00651 tree def;
00652 tree vec, t = NULL_TREE;
00653 bool need_epilog_adjust;
00654 int i;
00655
00656 gcc_assert (INTEGRAL_TYPE_P (type) || SCALAR_FLOAT_TYPE_P (type));
00657
00658 switch (code)
00659 {
00660 case WIDEN_SUM_EXPR:
00661 case DOT_PROD_EXPR:
00662 case PLUS_EXPR:
00663 if (INTEGRAL_TYPE_P (type))
00664 def = build_int_cst (type, 0);
00665 else
00666 def = build_real (type, dconst0);
00667
00668 #ifdef ADJUST_IN_EPILOG
00669
00670
00671 nelements = nunits;
00672 need_epilog_adjust = true;
00673 #else
00674
00675
00676 nelements = nunits - 1;
00677 need_epilog_adjust = false;
00678 #endif
00679 break;
00680
00681 case MIN_EXPR:
00682 case MAX_EXPR:
00683 def = init_val;
00684 nelements = nunits;
00685 need_epilog_adjust = false;
00686 break;
00687
00688 default:
00689 gcc_unreachable ();
00690 }
00691
00692 for (i = nelements - 1; i >= 0; --i)
00693 t = tree_cons (NULL_TREE, def, t);
00694
00695 if (nelements == nunits - 1)
00696 {
00697
00698 t = tree_cons (NULL_TREE, init_val, t);
00699 nelements += 1;
00700 }
00701 gcc_assert (nelements == nunits);
00702
00703 if (TREE_CODE (init_val) == INTEGER_CST || TREE_CODE (init_val) == REAL_CST)
00704 vec = build_vector (vectype, t);
00705 else
00706 vec = build_constructor_from_list (vectype, t);
00707
00708 if (!need_epilog_adjust)
00709 *scalar_def = NULL_TREE;
00710 else
00711 *scalar_def = init_val;
00712
00713 return vect_init_vector (stmt, vec);
00714 }
00715
00716
00717
00718
00719
00720
00721
00722
00723
00724
00725
00726
00727
00728
00729
00730
00731
00732
00733
00734
00735
00736
00737
00738
00739
00740
00741
00742
00743
00744
00745
00746
00747
00748
00749
00750
00751
00752
00753
00754
00755
00756
00757
00758
00759
00760
00761
00762
00763
00764
00765 static void
00766 vect_create_epilog_for_reduction (tree vect_def, tree stmt,
00767 enum tree_code reduc_code, tree reduction_phi)
00768 {
00769 stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
00770 tree vectype;
00771 enum machine_mode mode;
00772 loop_vec_info loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_info);
00773 struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo);
00774 basic_block exit_bb;
00775 tree scalar_dest;
00776 tree scalar_type;
00777 tree new_phi;
00778 block_stmt_iterator exit_bsi;
00779 tree vec_dest;
00780 tree new_temp;
00781 tree new_name;
00782 tree epilog_stmt;
00783 tree new_scalar_dest, exit_phi;
00784 tree bitsize, bitpos, bytesize;
00785 enum tree_code code = TREE_CODE (TREE_OPERAND (stmt, 1));
00786 tree scalar_initial_def;
00787 tree vec_initial_def;
00788 tree orig_name;
00789 imm_use_iterator imm_iter;
00790 use_operand_p use_p;
00791 bool extract_scalar_result;
00792 tree reduction_op;
00793 tree orig_stmt;
00794 tree use_stmt;
00795 tree operation = TREE_OPERAND (stmt, 1);
00796 int op_type;
00797
00798 op_type = TREE_CODE_LENGTH (TREE_CODE (operation));
00799 reduction_op = TREE_OPERAND (operation, op_type-1);
00800 vectype = get_vectype_for_scalar_type (TREE_TYPE (reduction_op));
00801 mode = TYPE_MODE (vectype);
00802
00803
00804
00805
00806
00807
00808
00809 vec_initial_def = vect_get_vec_def_for_operand (reduction_op, stmt,
00810 &scalar_initial_def);
00811 add_phi_arg (reduction_phi, vec_initial_def, loop_preheader_edge (loop));
00812
00813
00814 add_phi_arg (reduction_phi, vect_def, loop_latch_edge (loop));
00815
00816 if (vect_print_dump_info (REPORT_DETAILS))
00817 {
00818 fprintf (vect_dump, "transform reduction: created def-use cycle:");
00819 print_generic_expr (vect_dump, reduction_phi, TDF_SLIM);
00820 fprintf (vect_dump, "\n");
00821 print_generic_expr (vect_dump, SSA_NAME_DEF_STMT (vect_def), TDF_SLIM);
00822 }
00823
00824
00825
00826
00827
00828
00829
00830
00831
00832
00833
00834
00835
00836
00837
00838
00839
00840
00841
00842
00843
00844
00845
00846
00847
00848
00849
00850
00851
00852
00853
00854
00855 exit_bb = loop->single_exit->dest;
00856 new_phi = create_phi_node (SSA_NAME_VAR (vect_def), exit_bb);
00857 SET_PHI_ARG_DEF (new_phi, loop->single_exit->dest_idx, vect_def);
00858 exit_bsi = bsi_start (exit_bb);
00859
00860
00861
00862
00863
00864
00865
00866
00867
00868
00869 orig_stmt = STMT_VINFO_RELATED_STMT (stmt_info);
00870 if (!orig_stmt)
00871 {
00872
00873 orig_stmt = stmt;
00874 }
00875 else
00876 {
00877
00878 stmt_vec_info stmt_vinfo = vinfo_for_stmt (orig_stmt);
00879 gcc_assert (STMT_VINFO_IN_PATTERN_P (stmt_vinfo));
00880 gcc_assert (STMT_VINFO_RELATED_STMT (stmt_vinfo) == stmt);
00881 }
00882 code = TREE_CODE (TREE_OPERAND (orig_stmt, 1));
00883 scalar_dest = TREE_OPERAND (orig_stmt, 0);
00884 scalar_type = TREE_TYPE (scalar_dest);
00885 new_scalar_dest = vect_create_destination_var (scalar_dest, NULL);
00886 bitsize = TYPE_SIZE (scalar_type);
00887 bytesize = TYPE_SIZE_UNIT (scalar_type);
00888
00889
00890
00891
00892 if (reduc_code < NUM_TREE_CODES)
00893 {
00894
00895
00896
00897 if (vect_print_dump_info (REPORT_DETAILS))
00898 fprintf (vect_dump, "Reduce using direct vector reduction.");
00899
00900 vec_dest = vect_create_destination_var (scalar_dest, vectype);
00901 epilog_stmt = build2 (MODIFY_EXPR, vectype, vec_dest,
00902 build1 (reduc_code, vectype, PHI_RESULT (new_phi)));
00903 new_temp = make_ssa_name (vec_dest, epilog_stmt);
00904 TREE_OPERAND (epilog_stmt, 0) = new_temp;
00905 bsi_insert_after (&exit_bsi, epilog_stmt, BSI_NEW_STMT);
00906
00907 extract_scalar_result = true;
00908 }
00909 else
00910 {
00911 enum tree_code shift_code = 0;
00912 bool have_whole_vector_shift = true;
00913 int bit_offset;
00914 int element_bitsize = tree_low_cst (bitsize, 1);
00915 int vec_size_in_bits = tree_low_cst (TYPE_SIZE (vectype), 1);
00916 tree vec_temp;
00917
00918 if (vec_shr_optab->handlers[mode].insn_code != CODE_FOR_nothing)
00919 shift_code = VEC_RSHIFT_EXPR;
00920 else
00921 have_whole_vector_shift = false;
00922
00923
00924
00925
00926
00927
00928
00929 if (!VECTOR_MODE_P (mode))
00930 have_whole_vector_shift = false;
00931 else
00932 {
00933 optab optab = optab_for_tree_code (code, vectype);
00934 if (optab->handlers[mode].insn_code == CODE_FOR_nothing)
00935 have_whole_vector_shift = false;
00936 }
00937
00938 if (have_whole_vector_shift)
00939 {
00940
00941
00942
00943
00944
00945
00946
00947 if (vect_print_dump_info (REPORT_DETAILS))
00948 fprintf (vect_dump, "Reduce using vector shifts");
00949
00950 vec_dest = vect_create_destination_var (scalar_dest, vectype);
00951 new_temp = PHI_RESULT (new_phi);
00952
00953 for (bit_offset = vec_size_in_bits/2;
00954 bit_offset >= element_bitsize;
00955 bit_offset /= 2)
00956 {
00957 tree bitpos = size_int (bit_offset);
00958
00959 epilog_stmt = build2 (MODIFY_EXPR, vectype, vec_dest,
00960 build2 (shift_code, vectype, new_temp, bitpos));
00961 new_name = make_ssa_name (vec_dest, epilog_stmt);
00962 TREE_OPERAND (epilog_stmt, 0) = new_name;
00963 bsi_insert_after (&exit_bsi, epilog_stmt, BSI_NEW_STMT);
00964
00965 epilog_stmt = build2 (MODIFY_EXPR, vectype, vec_dest,
00966 build2 (code, vectype, new_name, new_temp));
00967 new_temp = make_ssa_name (vec_dest, epilog_stmt);
00968 TREE_OPERAND (epilog_stmt, 0) = new_temp;
00969 bsi_insert_after (&exit_bsi, epilog_stmt, BSI_NEW_STMT);
00970 }
00971
00972 extract_scalar_result = true;
00973 }
00974 else
00975 {
00976 tree rhs;
00977
00978
00979
00980
00981
00982
00983
00984
00985
00986
00987
00988 if (vect_print_dump_info (REPORT_DETAILS))
00989 fprintf (vect_dump, "Reduce using scalar code. ");
00990
00991 vec_temp = PHI_RESULT (new_phi);
00992 vec_size_in_bits = tree_low_cst (TYPE_SIZE (vectype), 1);
00993 rhs = build3 (BIT_FIELD_REF, scalar_type, vec_temp, bitsize,
00994 bitsize_zero_node);
00995 BIT_FIELD_REF_UNSIGNED (rhs) = TYPE_UNSIGNED (scalar_type);
00996 epilog_stmt = build2 (MODIFY_EXPR, scalar_type, new_scalar_dest, rhs);
00997 new_temp = make_ssa_name (new_scalar_dest, epilog_stmt);
00998 TREE_OPERAND (epilog_stmt, 0) = new_temp;
00999 bsi_insert_after (&exit_bsi, epilog_stmt, BSI_NEW_STMT);
01000
01001 for (bit_offset = element_bitsize;
01002 bit_offset < vec_size_in_bits;
01003 bit_offset += element_bitsize)
01004 {
01005 tree bitpos = bitsize_int (bit_offset);
01006 tree rhs = build3 (BIT_FIELD_REF, scalar_type, vec_temp, bitsize,
01007 bitpos);
01008
01009 BIT_FIELD_REF_UNSIGNED (rhs) = TYPE_UNSIGNED (scalar_type);
01010 epilog_stmt = build2 (MODIFY_EXPR, scalar_type, new_scalar_dest,
01011 rhs);
01012 new_name = make_ssa_name (new_scalar_dest, epilog_stmt);
01013 TREE_OPERAND (epilog_stmt, 0) = new_name;
01014 bsi_insert_after (&exit_bsi, epilog_stmt, BSI_NEW_STMT);
01015
01016 epilog_stmt = build2 (MODIFY_EXPR, scalar_type, new_scalar_dest,
01017 build2 (code, scalar_type, new_name, new_temp));
01018 new_temp = make_ssa_name (new_scalar_dest, epilog_stmt);
01019 TREE_OPERAND (epilog_stmt, 0) = new_temp;
01020 bsi_insert_after (&exit_bsi, epilog_stmt, BSI_NEW_STMT);
01021 }
01022
01023 extract_scalar_result = false;
01024 }
01025 }
01026
01027
01028
01029
01030 if (extract_scalar_result)
01031 {
01032 tree rhs;
01033
01034 if (vect_print_dump_info (REPORT_DETAILS))
01035 fprintf (vect_dump, "extract scalar result");
01036
01037 if (BYTES_BIG_ENDIAN)
01038 bitpos = size_binop (MULT_EXPR,
01039 bitsize_int (TYPE_VECTOR_SUBPARTS (vectype) - 1),
01040 TYPE_SIZE (scalar_type));
01041 else
01042 bitpos = bitsize_zero_node;
01043
01044 rhs = build3 (BIT_FIELD_REF, scalar_type, new_temp, bitsize, bitpos);
01045 BIT_FIELD_REF_UNSIGNED (rhs) = TYPE_UNSIGNED (scalar_type);
01046 epilog_stmt = build2 (MODIFY_EXPR, scalar_type, new_scalar_dest, rhs);
01047 new_temp = make_ssa_name (new_scalar_dest, epilog_stmt);
01048 TREE_OPERAND (epilog_stmt, 0) = new_temp;
01049 bsi_insert_after (&exit_bsi, epilog_stmt, BSI_NEW_STMT);
01050 }
01051
01052
01053
01054
01055
01056
01057
01058
01059 if (scalar_initial_def)
01060 {
01061 epilog_stmt = build2 (MODIFY_EXPR, scalar_type, new_scalar_dest,
01062 build2 (code, scalar_type, new_temp, scalar_initial_def));
01063 new_temp = make_ssa_name (new_scalar_dest, epilog_stmt);
01064 TREE_OPERAND (epilog_stmt, 0) = new_temp;
01065 bsi_insert_after (&exit_bsi, epilog_stmt, BSI_NEW_STMT);
01066 }
01067
01068
01069
01070
01071
01072
01073 exit_phi = NULL;
01074 FOR_EACH_IMM_USE_FAST (use_p, imm_iter, scalar_dest)
01075 {
01076 if (!flow_bb_inside_loop_p (loop, bb_for_stmt (USE_STMT (use_p))))
01077 {
01078 exit_phi = USE_STMT (use_p);
01079 break;
01080 }
01081 }
01082
01083 gcc_assert (exit_phi);
01084
01085 orig_name = PHI_RESULT (exit_phi);
01086 FOR_EACH_IMM_USE_STMT (use_stmt, imm_iter, orig_name)
01087 FOR_EACH_IMM_USE_ON_STMT (use_p, imm_iter)
01088 SET_USE (use_p, new_temp);
01089 }
01090
01091
01092
01093
01094
01095
01096
01097
01098
01099
01100
01101
01102
01103
01104
01105
01106
01107
01108
01109
01110
01111
01112
01113
01114
01115
01116
01117
01118
01119
01120
01121
01122
01123
01124
01125
01126
01127
01128
01129
01130
01131
01132 bool
01133 vectorizable_reduction (tree stmt, block_stmt_iterator *bsi, tree *vec_stmt)
01134 {
01135 tree vec_dest;
01136 tree scalar_dest;
01137 tree op;
01138 tree loop_vec_def0, loop_vec_def1;
01139 stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
01140 tree vectype = STMT_VINFO_VECTYPE (stmt_info);
01141 loop_vec_info loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_info);
01142 struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo);
01143 tree operation;
01144 enum tree_code code, orig_code, epilog_reduc_code = 0;
01145 enum machine_mode vec_mode;
01146 int op_type;
01147 optab optab, reduc_optab;
01148 tree new_temp;
01149 tree def, def_stmt;
01150 enum vect_def_type dt;
01151 tree new_phi;
01152 tree scalar_type;
01153 bool is_simple_use;
01154 tree orig_stmt;
01155 stmt_vec_info orig_stmt_info;
01156 tree expr = NULL_TREE;
01157 int i;
01158
01159
01160
01161
01162 if (STMT_VINFO_RELEVANT_P (stmt_info))
01163 return false;
01164
01165 if (!STMT_VINFO_LIVE_P (stmt_info))
01166 return false;
01167
01168
01169 if (STMT_VINFO_DEF_TYPE (stmt_info) != vect_reduction_def)
01170 return false;
01171
01172
01173
01174
01175
01176
01177
01178
01179 orig_stmt = STMT_VINFO_RELATED_STMT (stmt_info);
01180 if (orig_stmt)
01181 {
01182 orig_stmt_info = vinfo_for_stmt (orig_stmt);
01183 gcc_assert (STMT_VINFO_RELATED_STMT (orig_stmt_info) == stmt);
01184 gcc_assert (STMT_VINFO_IN_PATTERN_P (orig_stmt_info));
01185 gcc_assert (!STMT_VINFO_IN_PATTERN_P (stmt_info));
01186 }
01187
01188
01189
01190
01191
01192 gcc_assert (TREE_CODE (stmt) == MODIFY_EXPR);
01193
01194 operation = TREE_OPERAND (stmt, 1);
01195 code = TREE_CODE (operation);
01196 op_type = TREE_CODE_LENGTH (code);
01197
01198 if (op_type != binary_op && op_type != ternary_op)
01199 return false;
01200 scalar_dest = TREE_OPERAND (stmt, 0);
01201 scalar_type = TREE_TYPE (scalar_dest);
01202
01203
01204
01205 for (i = 0; i < op_type-1; i++)
01206 {
01207 op = TREE_OPERAND (operation, i);
01208 is_simple_use = vect_is_simple_use (op, loop_vinfo, &def_stmt, &def, &dt);
01209 gcc_assert (is_simple_use);
01210 gcc_assert (dt == vect_loop_def || dt == vect_invariant_def ||
01211 dt == vect_constant_def);
01212 }
01213
01214 op = TREE_OPERAND (operation, i);
01215 is_simple_use = vect_is_simple_use (op, loop_vinfo, &def_stmt, &def, &dt);
01216 gcc_assert (is_simple_use);
01217 gcc_assert (dt == vect_reduction_def);
01218 gcc_assert (TREE_CODE (def_stmt) == PHI_NODE);
01219 if (orig_stmt)
01220 gcc_assert (orig_stmt == vect_is_simple_reduction (loop, def_stmt));
01221 else
01222 gcc_assert (stmt == vect_is_simple_reduction (loop, def_stmt));
01223
01224 if (STMT_VINFO_LIVE_P (vinfo_for_stmt (def_stmt)))
01225 return false;
01226
01227
01228
01229
01230 optab = optab_for_tree_code (code, vectype);
01231 if (!optab)
01232 {
01233 if (vect_print_dump_info (REPORT_DETAILS))
01234 fprintf (vect_dump, "no optab.");
01235 return false;
01236 }
01237 vec_mode = TYPE_MODE (vectype);
01238 if (optab->handlers[(int) vec_mode].insn_code == CODE_FOR_nothing)
01239 {
01240 if (vect_print_dump_info (REPORT_DETAILS))
01241 fprintf (vect_dump, "op not supported by target.");
01242 if (GET_MODE_SIZE (vec_mode) != UNITS_PER_WORD
01243 || LOOP_VINFO_VECT_FACTOR (loop_vinfo)
01244 < vect_min_worthwhile_factor (code))
01245 return false;
01246 if (vect_print_dump_info (REPORT_DETAILS))
01247 fprintf (vect_dump, "proceeding using word mode.");
01248 }
01249
01250
01251 if (!VECTOR_MODE_P (TYPE_MODE (vectype))
01252 && LOOP_VINFO_VECT_FACTOR (loop_vinfo)
01253 < vect_min_worthwhile_factor (code))
01254 {
01255 if (vect_print_dump_info (REPORT_DETAILS))
01256 fprintf (vect_dump, "not worthwhile without SIMD support.");
01257 return false;
01258 }
01259
01260
01261
01262
01263
01264
01265
01266
01267
01268
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 if (orig_stmt)
01295 {
01296
01297
01298 orig_code = TREE_CODE (TREE_OPERAND (orig_stmt, 1));
01299 vectype = get_vectype_for_scalar_type (TREE_TYPE (def));
01300 vec_mode = TYPE_MODE (vectype);
01301 }
01302 else
01303 {
01304
01305
01306 orig_code = code;
01307 }
01308
01309 if (!reduction_code_for_scalar_code (orig_code, &epilog_reduc_code))
01310 return false;
01311 reduc_optab = optab_for_tree_code (epilog_reduc_code, vectype);
01312 if (!reduc_optab)
01313 {
01314 if (vect_print_dump_info (REPORT_DETAILS))
01315 fprintf (vect_dump, "no optab for reduction.");
01316 epilog_reduc_code = NUM_TREE_CODES;
01317 }
01318 if (reduc_optab->handlers[(int) vec_mode].insn_code == CODE_FOR_nothing)
01319 {
01320 if (vect_print_dump_info (REPORT_DETAILS))
01321 fprintf (vect_dump, "reduc op not supported by target.");
01322 epilog_reduc_code = NUM_TREE_CODES;
01323 }
01324
01325 if (!vec_stmt)
01326 {
01327 STMT_VINFO_TYPE (stmt_info) = reduc_vec_info_type;
01328 return true;
01329 }
01330
01333 if (vect_print_dump_info (REPORT_DETAILS))
01334 fprintf (vect_dump, "transform reduction.");
01335
01336
01337 vec_dest = vect_create_destination_var (scalar_dest, vectype);
01338
01339
01340 new_phi = create_phi_node (vec_dest, loop->header);
01341
01342
01343 op = TREE_OPERAND (operation, 0);
01344 loop_vec_def0 = vect_get_vec_def_for_operand (op, stmt, NULL);
01345 if (op_type == binary_op)
01346 expr = build2 (code, vectype, loop_vec_def0, PHI_RESULT (new_phi));
01347 else if (op_type == ternary_op)
01348 {
01349 op = TREE_OPERAND (operation, 1);
01350 loop_vec_def1 = vect_get_vec_def_for_operand (op, stmt, NULL);
01351 expr = build3 (code, vectype, loop_vec_def0, loop_vec_def1,
01352 PHI_RESULT (new_phi));
01353 }
01354
01355
01356 *vec_stmt = build2 (MODIFY_EXPR, vectype, vec_dest, expr);
01357 new_temp = make_ssa_name (vec_dest, *vec_stmt);
01358 TREE_OPERAND (*vec_stmt, 0) = new_temp;
01359 vect_finish_stmt_generation (stmt, *vec_stmt, bsi);
01360
01361
01362
01363 vect_create_epilog_for_reduction (new_temp, stmt, epilog_reduc_code, new_phi);
01364 return true;
01365 }
01366
01367
01368
01369
01370
01371
01372
01373
01374
01375 bool
01376 vectorizable_assignment (tree stmt, block_stmt_iterator *bsi, tree *vec_stmt)
01377 {
01378 tree vec_dest;
01379 tree scalar_dest;
01380 tree op;
01381 tree vec_oprnd;
01382 stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
01383 tree vectype = STMT_VINFO_VECTYPE (stmt_info);
01384 loop_vec_info loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_info);
01385 tree new_temp;
01386 tree def, def_stmt;
01387 enum vect_def_type dt;
01388
01389
01390 if (!STMT_VINFO_RELEVANT_P (stmt_info))
01391 return false;
01392
01393 gcc_assert (STMT_VINFO_DEF_TYPE (stmt_info) == vect_loop_def);
01394
01395 if (TREE_CODE (stmt) != MODIFY_EXPR)
01396 return false;
01397
01398 scalar_dest = TREE_OPERAND (stmt, 0);
01399 if (TREE_CODE (scalar_dest) != SSA_NAME)
01400 return false;
01401
01402 op = TREE_OPERAND (stmt, 1);
01403 if (!vect_is_simple_use (op, loop_vinfo, &def_stmt, &def, &dt))
01404 {
01405 if (vect_print_dump_info (REPORT_DETAILS))
01406 fprintf (vect_dump, "use not simple.");
01407 return false;
01408 }
01409
01410 if (!vec_stmt)
01411 {
01412 STMT_VINFO_TYPE (stmt_info) = assignment_vec_info_type;
01413 return true;
01414 }
01415
01417 if (vect_print_dump_info (REPORT_DETAILS))
01418 fprintf (vect_dump, "transform assignment.");
01419
01420
01421 vec_dest = vect_create_destination_var (scalar_dest, vectype);
01422
01423
01424 op = TREE_OPERAND (stmt, 1);
01425 vec_oprnd = vect_get_vec_def_for_operand (op, stmt, NULL);
01426
01427
01428 *vec_stmt = build2 (MODIFY_EXPR, vectype, vec_dest, vec_oprnd);
01429 new_temp = make_ssa_name (vec_dest, *vec_stmt);
01430 TREE_OPERAND (*vec_stmt, 0) = new_temp;
01431 vect_finish_stmt_generation (stmt, *vec_stmt, bsi);
01432
01433 return true;
01434 }
01435
01436
01437
01438
01439
01440
01441
01442 static int
01443 vect_min_worthwhile_factor (enum tree_code code)
01444 {
01445 switch (code)
01446 {
01447 case PLUS_EXPR:
01448 case MINUS_EXPR:
01449 case NEGATE_EXPR:
01450 return 4;
01451
01452 case BIT_AND_EXPR:
01453 case BIT_IOR_EXPR:
01454 case BIT_XOR_EXPR:
01455 case BIT_NOT_EXPR:
01456 return 2;
01457
01458 default:
01459 return INT_MAX;
01460 }
01461 }
01462
01463
01464
01465
01466
01467
01468
01469
01470
01471 bool
01472 vectorizable_operation (tree stmt, block_stmt_iterator *bsi, tree *vec_stmt)
01473 {
01474 tree vec_dest;
01475 tree scalar_dest;
01476 tree operation;
01477 tree op0, op1 = NULL;
01478 tree vec_oprnd0, vec_oprnd1=NULL;
01479 stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
01480 tree vectype = STMT_VINFO_VECTYPE (stmt_info);
01481 loop_vec_info loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_info);
01482 int i;
01483 enum tree_code code;
01484 enum machine_mode vec_mode;
01485 tree new_temp;
01486 int op_type;
01487 tree op;
01488 optab optab;
01489 int icode;
01490 enum machine_mode optab_op2_mode;
01491 tree def, def_stmt;
01492 enum vect_def_type dt;
01493
01494
01495 if (!STMT_VINFO_RELEVANT_P (stmt_info))
01496 return false;
01497
01498 gcc_assert (STMT_VINFO_DEF_TYPE (stmt_info) == vect_loop_def);
01499
01500 if (STMT_VINFO_LIVE_P (stmt_info))
01501 {
01502
01503 if (vect_print_dump_info (REPORT_DETAILS))
01504 fprintf (vect_dump, "value used after loop.");
01505 return false;
01506 }
01507
01508 if (TREE_CODE (stmt) != MODIFY_EXPR)
01509 return false;
01510
01511 if (TREE_CODE (TREE_OPERAND (stmt, 0)) != SSA_NAME)
01512 return false;
01513
01514 operation = TREE_OPERAND (stmt, 1);
01515 code = TREE_CODE (operation);
01516 optab = optab_for_tree_code (code, vectype);
01517
01518
01519 op_type = TREE_CODE_LENGTH (code);
01520 if (op_type != unary_op && op_type != binary_op)
01521 {
01522 if (vect_print_dump_info (REPORT_DETAILS))
01523 fprintf (vect_dump, "num. args = %d (not unary/binary op).", op_type);
01524 return false;
01525 }
01526
01527 for (i = 0; i < op_type; i++)
01528 {
01529 op = TREE_OPERAND (operation, i);
01530 if (!vect_is_simple_use (op, loop_vinfo, &def_stmt, &def, &dt))
01531 {
01532 if (vect_print_dump_info (REPORT_DETAILS))
01533 fprintf (vect_dump, "use not simple.");
01534 return false;
01535 }
01536 }
01537
01538
01539 if (!optab)
01540 {
01541 if (vect_print_dump_info (REPORT_DETAILS))
01542 fprintf (vect_dump, "no optab.");
01543 return false;
01544 }
01545 vec_mode = TYPE_MODE (vectype);
01546 icode = (int) optab->handlers[(int) vec_mode].insn_code;
01547 if (icode == CODE_FOR_nothing)
01548 {
01549 if (vect_print_dump_info (REPORT_DETAILS))
01550 fprintf (vect_dump, "op not supported by target.");
01551 if (GET_MODE_SIZE (vec_mode) != UNITS_PER_WORD
01552 || LOOP_VINFO_VECT_FACTOR (loop_vinfo)
01553 < vect_min_worthwhile_factor (code))
01554 return false;
01555 if (vect_print_dump_info (REPORT_DETAILS))
01556 fprintf (vect_dump, "proceeding using word mode.");
01557 }
01558
01559
01560 if (!VECTOR_MODE_P (TYPE_MODE (vectype))
01561 && LOOP_VINFO_VECT_FACTOR (loop_vinfo)
01562 < vect_min_worthwhile_factor (code))
01563 {
01564 if (vect_print_dump_info (REPORT_DETAILS))
01565 fprintf (vect_dump, "not worthwhile without SIMD support.");
01566 return false;
01567 }
01568
01569 if (code == LSHIFT_EXPR || code == RSHIFT_EXPR)
01570 {
01571
01572 if (!VECTOR_MODE_P (vec_mode))
01573 return false;
01574
01575
01576
01577 optab_op2_mode = insn_data[icode].operand[2].mode;
01578 if (! (VECTOR_MODE_P (optab_op2_mode)
01579 || dt == vect_constant_def
01580 || dt == vect_invariant_def))
01581 {
01582 if (vect_print_dump_info (REPORT_DETAILS))
01583 fprintf (vect_dump, "operand mode requires invariant argument.");
01584 return false;
01585 }
01586 }
01587
01588 if (!vec_stmt)
01589 {
01590 STMT_VINFO_TYPE (stmt_info) = op_vec_info_type;
01591 return true;
01592 }
01593
01596 if (vect_print_dump_info (REPORT_DETAILS))
01597 fprintf (vect_dump, "transform binary/unary operation.");
01598
01599
01600 scalar_dest = TREE_OPERAND (stmt, 0);
01601 vec_dest = vect_create_destination_var (scalar_dest, vectype);
01602
01603
01604 op0 = TREE_OPERAND (operation, 0);
01605 vec_oprnd0 = vect_get_vec_def_for_operand (op0, stmt, NULL);
01606
01607 if (op_type == binary_op)
01608 {
01609 op1 = TREE_OPERAND (operation, 1);
01610
01611 if (code == LSHIFT_EXPR || code == RSHIFT_EXPR)
01612 {
01613
01614
01615
01616
01617
01618 optab_op2_mode = insn_data[icode].operand[2].mode;
01619 if (!VECTOR_MODE_P (optab_op2_mode))
01620 {
01621 if (vect_print_dump_info (REPORT_DETAILS))
01622 fprintf (vect_dump, "operand 1 using scalar mode.");
01623 vec_oprnd1 = op1;
01624 }
01625 }
01626
01627 if (!vec_oprnd1)
01628 vec_oprnd1 = vect_get_vec_def_for_operand (op1, stmt, NULL);
01629 }
01630
01631
01632
01633 if (op_type == binary_op)
01634 *vec_stmt = build2 (MODIFY_EXPR, vectype, vec_dest,
01635 build2 (code, vectype, vec_oprnd0, vec_oprnd1));
01636 else
01637 *vec_stmt = build2 (MODIFY_EXPR, vectype, vec_dest,
01638 build1 (code, vectype, vec_oprnd0));
01639 new_temp = make_ssa_name (vec_dest, *vec_stmt);
01640 TREE_OPERAND (*vec_stmt, 0) = new_temp;
01641 vect_finish_stmt_generation (stmt, *vec_stmt, bsi);
01642
01643 return true;
01644 }
01645
01646
01647
01648
01649
01650
01651
01652
01653
01654
01655 bool
01656 vectorizable_store (tree stmt, block_stmt_iterator *bsi, tree *vec_stmt)
01657 {
01658 tree scalar_dest;
01659 tree data_ref;
01660 tree op;
01661 tree vec_oprnd1;
01662 stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
01663 struct data_reference *dr = STMT_VINFO_DATA_REF (stmt_info);
01664 tree vectype = STMT_VINFO_VECTYPE (stmt_info);
01665 loop_vec_info loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_info);
01666 enum machine_mode vec_mode;
01667 tree dummy;
01668 enum dr_alignment_support alignment_support_cheme;
01669 ssa_op_iter iter;
01670 tree def, def_stmt;
01671 enum vect_def_type dt;
01672
01673
01674
01675 if (TREE_CODE (stmt) != MODIFY_EXPR)
01676 return false;
01677
01678 scalar_dest = TREE_OPERAND (stmt, 0);
01679 if (TREE_CODE (scalar_dest) != ARRAY_REF
01680 && TREE_CODE (scalar_dest) != INDIRECT_REF)
01681 return false;
01682
01683 op = TREE_OPERAND (stmt, 1);
01684 if (!vect_is_simple_use (op, loop_vinfo, &def_stmt, &def, &dt))
01685 {
01686 if (vect_print_dump_info (REPORT_DETAILS))
01687 fprintf (vect_dump, "use not simple.");
01688 return false;
01689 }
01690
01691 vec_mode = TYPE_MODE (vectype);
01692
01693
01694 if (mov_optab->handlers[(int)vec_mode].insn_code == CODE_FOR_nothing)
01695 return false;
01696
01697 if (!STMT_VINFO_DATA_REF (stmt_info))
01698 return false;
01699
01700
01701 if (!vec_stmt)
01702 {
01703 STMT_VINFO_TYPE (stmt_info) = store_vec_info_type;
01704 return true;
01705 }
01706
01709 if (vect_print_dump_info (REPORT_DETAILS))
01710 fprintf (vect_dump, "transform store");
01711
01712 alignment_support_cheme = vect_supportable_dr_alignment (dr);
01713 gcc_assert (alignment_support_cheme);
01714 gcc_assert (alignment_support_cheme == dr_aligned);
01715
01716
01717 vec_oprnd1 = vect_get_vec_def_for_operand (op, stmt, NULL);
01718
01719
01720
01721 vect_align_data_ref (stmt);
01722 data_ref = vect_create_data_ref_ptr (stmt, bsi, NULL_TREE, &dummy, false);
01723 data_ref = build_fold_indirect_ref (data_ref);
01724
01725
01726 *vec_stmt = build2 (MODIFY_EXPR, vectype, data_ref, vec_oprnd1);
01727 vect_finish_stmt_generation (stmt, *vec_stmt, bsi);
01728
01729
01730
01731
01732
01733 copy_virtual_operands (*vec_stmt, stmt);
01734
01735 FOR_EACH_SSA_TREE_OPERAND (def, stmt, iter, SSA_OP_VMAYDEF)
01736 {
01737 SSA_NAME_DEF_STMT (def) = *vec_stmt;
01738
01739
01740
01741
01742 mark_sym_for_renaming (SSA_NAME_VAR (def));
01743 }
01744
01745 return true;
01746 }
01747
01748
01749
01750
01751
01752
01753
01754
01755
01756
01757 bool
01758 vectorizable_load (tree stmt, block_stmt_iterator *bsi, tree *vec_stmt)
01759 {
01760 tree scalar_dest;
01761 tree vec_dest = NULL;
01762 tree data_ref = NULL;
01763 tree op;
01764 stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
01765 struct data_reference *dr = STMT_VINFO_DATA_REF (stmt_info);
01766 tree vectype = STMT_VINFO_VECTYPE (stmt_info);
01767 tree new_temp;
01768 int mode;
01769 tree init_addr;
01770 tree new_stmt;
01771 tree dummy;
01772 basic_block new_bb;
01773 loop_vec_info loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_info);
01774 struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo);
01775 edge pe = loop_preheader_edge (loop);
01776 enum dr_alignment_support alignment_support_cheme;
01777
01778
01779 if (!STMT_VINFO_RELEVANT_P (stmt_info))
01780 return false;
01781
01782 gcc_assert (STMT_VINFO_DEF_TYPE (stmt_info) == vect_loop_def);
01783
01784 if (STMT_VINFO_LIVE_P (stmt_info))
01785 {
01786
01787 if (vect_print_dump_info (REPORT_DETAILS))
01788 fprintf (vect_dump, "value used after loop.");
01789 return false;
01790 }
01791
01792 if (TREE_CODE (stmt) != MODIFY_EXPR)
01793 return false;
01794
01795 scalar_dest = TREE_OPERAND (stmt, 0);
01796 if (TREE_CODE (scalar_dest) != SSA_NAME)
01797 return false;
01798
01799 op = TREE_OPERAND (stmt, 1);
01800 if (TREE_CODE (op) != ARRAY_REF && TREE_CODE (op) != INDIRECT_REF)
01801 return false;
01802
01803 if (!STMT_VINFO_DATA_REF (stmt_info))
01804 return false;
01805
01806 mode = (int) TYPE_MODE (vectype);
01807
01808
01809
01810 if (mov_optab->handlers[mode].insn_code == CODE_FOR_nothing)
01811 {
01812 if (vect_print_dump_info (REPORT_DETAILS))
01813 fprintf (vect_dump, "Aligned load, but unsupported type.");
01814 return false;
01815 }
01816
01817 if (!vec_stmt)
01818 {
01819 STMT_VINFO_TYPE (stmt_info) = load_vec_info_type;
01820 return true;
01821 }
01822
01825 if (vect_print_dump_info (REPORT_DETAILS))
01826 fprintf (vect_dump, "transform load.");
01827
01828 alignment_support_cheme = vect_supportable_dr_alignment (dr);
01829 gcc_assert (alignment_support_cheme);
01830
01831 if (alignment_support_cheme == dr_aligned
01832 || alignment_support_cheme == dr_unaligned_supported)
01833 {
01834
01835
01836
01837
01838
01839
01840
01841
01842
01843 vec_dest = vect_create_destination_var (scalar_dest, vectype);
01844 data_ref = vect_create_data_ref_ptr (stmt, bsi, NULL_TREE, &dummy, false);
01845 if (aligned_access_p (dr))
01846 data_ref = build_fold_indirect_ref (data_ref);
01847 else
01848 {
01849 int mis = DR_MISALIGNMENT (dr);
01850 tree tmis = (mis == -1 ? size_zero_node : size_int (mis));
01851 tmis = size_binop (MULT_EXPR, tmis, size_int(BITS_PER_UNIT));
01852 data_ref = build2 (MISALIGNED_INDIRECT_REF, vectype, data_ref, tmis);
01853 }
01854 new_stmt = build2 (MODIFY_EXPR, vectype, vec_dest, data_ref);
01855 new_temp = make_ssa_name (vec_dest, new_stmt);
01856 TREE_OPERAND (new_stmt, 0) = new_temp;
01857 vect_finish_stmt_generation (stmt, new_stmt, bsi);
01858 copy_virtual_operands (new_stmt, stmt);
01859 }
01860 else if (alignment_support_cheme == dr_unaligned_software_pipeline)
01861 {
01862
01863
01864
01865
01866
01867
01868
01869
01870
01871
01872
01873
01874
01875
01876
01877 tree offset;
01878 tree magic;
01879 tree phi_stmt;
01880 tree msq_init;
01881 tree msq, lsq;
01882 tree dataref_ptr;
01883 tree params;
01884
01885
01886 vec_dest = vect_create_destination_var (scalar_dest, vectype);
01887 data_ref = vect_create_data_ref_ptr (stmt, bsi, NULL_TREE,
01888 &init_addr, true);
01889 data_ref = build1 (ALIGN_INDIRECT_REF, vectype, data_ref);
01890 new_stmt = build2 (MODIFY_EXPR, vectype, vec_dest, data_ref);
01891 new_temp = make_ssa_name (vec_dest, new_stmt);
01892 TREE_OPERAND (new_stmt, 0) = new_temp;
01893 new_bb = bsi_insert_on_edge_immediate (pe, new_stmt);
01894 gcc_assert (!new_bb);
01895 msq_init = TREE_OPERAND (new_stmt, 0);
01896 copy_virtual_operands (new_stmt, stmt);
01897 update_vuses_to_preheader (new_stmt, loop);
01898
01899
01900
01901 offset = size_int (TYPE_VECTOR_SUBPARTS (vectype) - 1);
01902 vec_dest = vect_create_destination_var (scalar_dest, vectype);
01903 dataref_ptr = vect_create_data_ref_ptr (stmt, bsi, offset, &dummy, false);
01904 data_ref = build1 (ALIGN_INDIRECT_REF, vectype, dataref_ptr);
01905 new_stmt = build2 (MODIFY_EXPR, vectype, vec_dest, data_ref);
01906 new_temp = make_ssa_name (vec_dest, new_stmt);
01907 TREE_OPERAND (new_stmt, 0) = new_temp;
01908 vect_finish_stmt_generation (stmt, new_stmt, bsi);
01909 lsq = TREE_OPERAND (new_stmt, 0);
01910 copy_virtual_operands (new_stmt, stmt);
01911
01912
01913
01914 if (targetm.vectorize.builtin_mask_for_load)
01915 {
01916
01917 tree builtin_decl;
01918 params = build_tree_list (NULL_TREE, init_addr);
01919 vec_dest = vect_create_destination_var (scalar_dest, vectype);
01920 builtin_decl = targetm.vectorize.builtin_mask_for_load ();
01921 new_stmt = build_function_call_expr (builtin_decl, params);
01922 new_stmt = build2 (MODIFY_EXPR, vectype, vec_dest, new_stmt);
01923 new_temp = make_ssa_name (vec_dest, new_stmt);
01924 TREE_OPERAND (new_stmt, 0) = new_temp;
01925 new_bb = bsi_insert_on_edge_immediate (pe, new_stmt);
01926 gcc_assert (!new_bb);
01927 magic = TREE_OPERAND (new_stmt, 0);
01928
01929
01930
01931
01932
01933
01934 gcc_assert (TREE_READONLY (builtin_decl));
01935 }
01936 else
01937 {
01938
01939
01940 magic = dataref_ptr;
01941 }
01942
01943
01944
01945 vec_dest = vect_create_destination_var (scalar_dest, vectype);
01946 msq = make_ssa_name (vec_dest, NULL_TREE);
01947 phi_stmt = create_phi_node (msq, loop->header);
01948 SSA_NAME_DEF_STMT (msq) = phi_stmt;
01949 add_phi_arg (phi_stmt, msq_init, loop_preheader_edge (loop));
01950 add_phi_arg (phi_stmt, lsq, loop_latch_edge (loop));
01951
01952
01953
01954 vec_dest = vect_create_destination_var (scalar_dest, vectype);
01955 new_stmt = build3 (REALIGN_LOAD_EXPR, vectype, msq, lsq, magic);
01956 new_stmt = build2 (MODIFY_EXPR, vectype, vec_dest, new_stmt);
01957 new_temp = make_ssa_name (vec_dest, new_stmt);
01958 TREE_OPERAND (new_stmt, 0) = new_temp;
01959 vect_finish_stmt_generation (stmt, new_stmt, bsi);
01960 }
01961 else
01962 gcc_unreachable ();
01963
01964 *vec_stmt = new_stmt;
01965 return true;
01966 }
01967
01968
01969
01970
01971
01972
01973
01974 bool
01975 vectorizable_live_operation (tree stmt,
01976 block_stmt_iterator *bsi ATTRIBUTE_UNUSED,
01977 tree *vec_stmt ATTRIBUTE_UNUSED)
01978 {
01979 tree operation;
01980 stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
01981 loop_vec_info loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_info);
01982 int i;
01983 enum tree_code code;
01984 int op_type;
01985 tree op;
01986 tree def, def_stmt;
01987 enum vect_def_type dt;
01988
01989 if (!STMT_VINFO_LIVE_P (stmt_info))
01990 return false;
01991
01992 if (TREE_CODE (stmt) != MODIFY_EXPR)
01993 return false;
01994
01995 if (TREE_CODE (TREE_OPERAND (stmt, 0)) != SSA_NAME)
01996 return false;
01997
01998 operation = TREE_OPERAND (stmt, 1);
01999 code = TREE_CODE (operation);
02000
02001 op_type = TREE_CODE_LENGTH (code);
02002
02003
02004
02005
02006
02007 for (i = 0; i < op_type; i++)
02008 {
02009 op = TREE_OPERAND (operation, i);
02010 if (!vect_is_simple_use (op, loop_vinfo, &def_stmt, &def, &dt))
02011 {
02012 if (vect_print_dump_info (REPORT_DETAILS))
02013 fprintf (vect_dump, "use not simple.");
02014 return false;
02015 }
02016
02017 if (dt != vect_invariant_def && dt != vect_constant_def)
02018 return false;
02019 }
02020
02021
02022 return true;
02023 }
02024
02025
02026
02027
02028
02029
02030
02031
02032
02033
02034
02035 static bool
02036 vect_is_simple_cond (tree cond, loop_vec_info loop_vinfo)
02037 {
02038 tree lhs, rhs;
02039 tree def;
02040 enum vect_def_type dt;
02041
02042 if (!COMPARISON_CLASS_P (cond))
02043 return false;
02044
02045 lhs = TREE_OPERAND (cond, 0);
02046 rhs = TREE_OPERAND (cond, 1);
02047
02048 if (TREE_CODE (lhs) == SSA_NAME)
02049 {
02050 tree lhs_def_stmt = SSA_NAME_DEF_STMT (lhs);
02051 if (!vect_is_simple_use (lhs, loop_vinfo, &lhs_def_stmt, &def, &dt))
02052 return false;
02053 }
02054 else if (TREE_CODE (lhs) != INTEGER_CST && TREE_CODE (lhs) != REAL_CST)
02055 return false;
02056
02057 if (TREE_CODE (rhs) == SSA_NAME)
02058 {
02059 tree rhs_def_stmt = SSA_NAME_DEF_STMT (rhs);
02060 if (!vect_is_simple_use (rhs, loop_vinfo, &rhs_def_stmt, &def, &dt))
02061 return false;
02062 }
02063 else if (TREE_CODE (rhs) != INTEGER_CST && TREE_CODE (rhs) != REAL_CST)
02064 return false;
02065
02066 return true;
02067 }
02068
02069
02070
02071
02072
02073
02074
02075
02076
02077
02078 bool
02079 vectorizable_condition (tree stmt, block_stmt_iterator *bsi, tree *vec_stmt)
02080 {
02081 tree scalar_dest = NULL_TREE;
02082 tree vec_dest = NULL_TREE;
02083 tree op = NULL_TREE;
02084 tree cond_expr, then_clause, else_clause;
02085 stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
02086 tree vectype = STMT_VINFO_VECTYPE (stmt_info);
02087 tree vec_cond_lhs, vec_cond_rhs, vec_then_clause, vec_else_clause;
02088 tree vec_compare, vec_cond_expr;
02089 tree new_temp;
02090 loop_vec_info loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_info);
02091 enum machine_mode vec_mode;
02092 tree def;
02093 enum vect_def_type dt;
02094
02095 if (!STMT_VINFO_RELEVANT_P (stmt_info))
02096 return false;
02097
02098 gcc_assert (STMT_VINFO_DEF_TYPE (stmt_info) == vect_loop_def);
02099
02100 if (STMT_VINFO_LIVE_P (stmt_info))
02101 {
02102
02103 if (vect_print_dump_info (REPORT_DETAILS))
02104 fprintf (vect_dump, "value used after loop.");
02105 return false;
02106 }
02107
02108 if (TREE_CODE (stmt) != MODIFY_EXPR)
02109 return false;
02110
02111 op = TREE_OPERAND (stmt, 1);
02112
02113 if (TREE_CODE (op) != COND_EXPR)
02114 return false;
02115
02116 cond_expr = TREE_OPERAND (op, 0);
02117 then_clause = TREE_OPERAND (op, 1);
02118 else_clause = TREE_OPERAND (op, 2);
02119
02120 if (!vect_is_simple_cond (cond_expr, loop_vinfo))
02121 return false;
02122
02123
02124
02125 if (TREE_TYPE (TREE_OPERAND (cond_expr, 0)) != TREE_TYPE (vectype))
02126 return false;
02127
02128 if (TREE_CODE (then_clause) == SSA_NAME)
02129 {
02130 tree then_def_stmt = SSA_NAME_DEF_STMT (then_clause);
02131 if (!vect_is_simple_use (then_clause, loop_vinfo,
02132 &then_def_stmt, &def, &dt))
02133 return false;
02134 }
02135 else if (TREE_CODE (then_clause) != INTEGER_CST
02136 && TREE_CODE (then_clause) != REAL_CST)
02137 return false;
02138
02139 if (TREE_CODE (else_clause) == SSA_NAME)
02140 {
02141 tree else_def_stmt = SSA_NAME_DEF_STMT (else_clause);
02142 if (!vect_is_simple_use (else_clause, loop_vinfo,
02143 &else_def_stmt, &def, &dt))
02144 return false;
02145 }
02146 else if (TREE_CODE (else_clause) != INTEGER_CST
02147 && TREE_CODE (else_clause) != REAL_CST)
02148 return false;
02149
02150
02151 vec_mode = TYPE_MODE (vectype);
02152
02153 if (!vec_stmt)
02154 {
02155 STMT_VINFO_TYPE (stmt_info) = condition_vec_info_type;
02156 return expand_vec_cond_expr_p (op, vec_mode);
02157 }
02158
02159
02160
02161
02162 scalar_dest = TREE_OPERAND (stmt, 0);
02163 vec_dest = vect_create_destination_var (scalar_dest, vectype);
02164
02165
02166 vec_cond_lhs =
02167 vect_get_vec_def_for_operand (TREE_OPERAND (cond_expr, 0), stmt, NULL);
02168 vec_cond_rhs =
02169 vect_get_vec_def_for_operand (TREE_OPERAND (cond_expr, 1), stmt, NULL);
02170 vec_then_clause = vect_get_vec_def_for_operand (then_clause, stmt, NULL);
02171 vec_else_clause = vect_get_vec_def_for_operand (else_clause, stmt, NULL);
02172
02173
02174 vec_compare = build2 (TREE_CODE (cond_expr), vectype,
02175 vec_cond_lhs, vec_cond_rhs);
02176 vec_cond_expr = build3 (VEC_COND_EXPR, vectype,
02177 vec_compare, vec_then_clause, vec_else_clause);
02178
02179 *vec_stmt = build2 (MODIFY_EXPR, vectype, vec_dest, vec_cond_expr);
02180 new_temp = make_ssa_name (vec_dest, *vec_stmt);
02181 TREE_OPERAND (*vec_stmt, 0) = new_temp;
02182 vect_finish_stmt_generation (stmt, *vec_stmt, bsi);
02183
02184 return true;
02185 }
02186
02187
02188
02189
02190
02191 bool
02192 vect_transform_stmt (tree stmt, block_stmt_iterator *bsi)
02193 {
02194 bool is_store = false;
02195 tree vec_stmt = NULL_TREE;
02196 stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
02197 tree orig_stmt_in_pattern;
02198 bool done;
02199
02200 if (STMT_VINFO_RELEVANT_P (stmt_info))
02201 {
02202 switch (STMT_VINFO_TYPE (stmt_info))
02203 {
02204 case op_vec_info_type:
02205 done = vectorizable_operation (stmt, bsi, &vec_stmt);
02206 gcc_assert (done);
02207 break;
02208
02209 case assignment_vec_info_type:
02210 done = vectorizable_assignment (stmt, bsi, &vec_stmt);
02211 gcc_assert (done);
02212 break;
02213
02214 case load_vec_info_type:
02215 done = vectorizable_load (stmt, bsi, &vec_stmt);
02216 gcc_assert (done);
02217 break;
02218
02219 case store_vec_info_type:
02220 done = vectorizable_store (stmt, bsi, &vec_stmt);
02221 gcc_assert (done);
02222 is_store = true;
02223 break;
02224
02225 case condition_vec_info_type:
02226 done = vectorizable_condition (stmt, bsi, &vec_stmt);
02227 gcc_assert (done);
02228 break;
02229
02230 default:
02231 if (vect_print_dump_info (REPORT_DETAILS))
02232 fprintf (vect_dump, "stmt not supported.");
02233 gcc_unreachable ();
02234 }
02235
02236 gcc_assert (vec_stmt);
02237 STMT_VINFO_VEC_STMT (stmt_info) = vec_stmt;
02238 orig_stmt_in_pattern = STMT_VINFO_RELATED_STMT (stmt_info);
02239 if (orig_stmt_in_pattern)
02240 {
02241 stmt_vec_info stmt_vinfo = vinfo_for_stmt (orig_stmt_in_pattern);
02242 if (STMT_VINFO_IN_PATTERN_P (stmt_vinfo))
02243 {
02244 gcc_assert (STMT_VINFO_RELATED_STMT (stmt_vinfo) == stmt);
02245
02246
02247
02248
02249
02250
02251
02252 STMT_VINFO_VEC_STMT (stmt_vinfo) = vec_stmt;
02253 }
02254 }
02255 }
02256
02257 if (STMT_VINFO_LIVE_P (stmt_info))
02258 {
02259 switch (STMT_VINFO_TYPE (stmt_info))
02260 {
02261 case reduc_vec_info_type:
02262 done = vectorizable_reduction (stmt, bsi, &vec_stmt);
02263 gcc_assert (done);
02264 break;
02265
02266 default:
02267 done = vectorizable_live_operation (stmt, bsi, &vec_stmt);
02268 gcc_assert (done);
02269 }
02270
02271 if (vec_stmt)
02272 {
02273 gcc_assert (!STMT_VINFO_VEC_STMT (stmt_info));
02274 STMT_VINFO_VEC_STMT (stmt_info) = vec_stmt;
02275 }
02276 }
02277
02278 return is_store;
02279 }
02280
02281
02282
02283
02284
02285 static tree
02286 vect_build_loop_niters (loop_vec_info loop_vinfo)
02287 {
02288 tree ni_name, stmt, var;
02289 edge pe;
02290 struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo);
02291 tree ni = unshare_expr (LOOP_VINFO_NITERS (loop_vinfo));
02292
02293 var = create_tmp_var (TREE_TYPE (ni), "niters");
02294 add_referenced_var (var);
02295 ni_name = force_gimple_operand (ni, &stmt, false, var);
02296
02297 pe = loop_preheader_edge (loop);
02298 if (stmt)
02299 {
02300 basic_block new_bb = bsi_insert_on_edge_immediate (pe, stmt);
02301 gcc_assert (!new_bb);
02302 }
02303
02304 return ni_name;
02305 }
02306
02307
02308
02309
02310
02311
02312
02313
02314
02315
02316 static void
02317 vect_generate_tmps_on_preheader (loop_vec_info loop_vinfo,
02318 tree *ni_name_ptr,
02319 tree *ratio_mult_vf_name_ptr,
02320 tree *ratio_name_ptr)
02321 {
02322
02323 edge pe;
02324 basic_block new_bb;
02325 tree stmt, ni_name;
02326 tree var;
02327 tree ratio_name;
02328 tree ratio_mult_vf_name;
02329 struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo);
02330 tree ni = LOOP_VINFO_NITERS (loop_vinfo);
02331 int vf = LOOP_VINFO_VECT_FACTOR (loop_vinfo);
02332 tree log_vf;
02333
02334 pe = loop_preheader_edge (loop);
02335
02336
02337
02338
02339 ni_name = vect_build_loop_niters (loop_vinfo);
02340 log_vf = build_int_cst (TREE_TYPE (ni), exact_log2 (vf));
02341
02342
02343
02344 var = create_tmp_var (TREE_TYPE (ni), "bnd");
02345 add_referenced_var (var);
02346 ratio_name = make_ssa_name (var, NULL_TREE);
02347 stmt = build2 (MODIFY_EXPR, void_type_node, ratio_name,
02348 build2 (RSHIFT_EXPR, TREE_TYPE (ni_name), ni_name, log_vf));
02349 SSA_NAME_DEF_STMT (ratio_name) = stmt;
02350
02351 pe = loop_preheader_edge (loop);
02352 new_bb = bsi_insert_on_edge_immediate (pe, stmt);
02353 gcc_assert (!new_bb);
02354
02355
02356
02357 var = create_tmp_var (TREE_TYPE (ni), "ratio_mult_vf");
02358 add_referenced_var (var);
02359 ratio_mult_vf_name = make_ssa_name (var, NULL_TREE);
02360 stmt = build2 (MODIFY_EXPR, void_type_node, ratio_mult_vf_name,
02361 build2 (LSHIFT_EXPR, TREE_TYPE (ratio_name), ratio_name, log_vf));
02362 SSA_NAME_DEF_STMT (ratio_mult_vf_name) = stmt;
02363
02364 pe = loop_preheader_edge (loop);
02365 new_bb = bsi_insert_on_edge_immediate (pe, stmt);
02366 gcc_assert (!new_bb);
02367
02368 *ni_name_ptr = ni_name;
02369 *ratio_mult_vf_name_ptr = ratio_mult_vf_name;
02370 *ratio_name_ptr = ratio_name;
02371
02372 return;
02373 }
02374
02375
02376
02377
02378
02379
02380
02381
02382
02383
02384
02385
02386
02387
02388
02389
02390
02391
02392
02393
02394
02395
02396
02397
02398
02399
02400
02401
02402
02403
02404
02405
02406
02407
02408
02409
02410
02411
02412 static void
02413 update_vuses_to_preheader (tree stmt, struct loop *loop)
02414 {
02415 basic_block header_bb = loop->header;
02416 edge preheader_e = loop_preheader_edge (loop);
02417 ssa_op_iter iter;
02418 use_operand_p use_p;
02419
02420 FOR_EACH_SSA_USE_OPERAND (use_p, stmt, iter, SSA_OP_VUSE)
02421 {
02422 tree ssa_name = USE_FROM_PTR (use_p);
02423 tree def_stmt = SSA_NAME_DEF_STMT (ssa_name);
02424 tree name_var = SSA_NAME_VAR (ssa_name);
02425 basic_block bb = bb_for_stmt (def_stmt);
02426
02427
02428 if (!IS_EMPTY_STMT (def_stmt)
02429 && flow_bb_inside_loop_p (loop, bb))
02430 {
02431
02432
02433
02434 tree phi;
02435 bool updated = false;
02436
02437 for (phi = phi_nodes (header_bb); phi; phi = TREE_CHAIN (phi))
02438 {
02439 if (SSA_NAME_VAR (PHI_RESULT (phi)) == name_var)
02440 {
02441 SET_USE (use_p, PHI_ARG_DEF (phi, preheader_e->dest_idx));
02442 updated = true;
02443 break;
02444 }
02445 }
02446 gcc_assert (updated);
02447 }
02448 }
02449 }
02450
02451
02452
02453
02454
02455
02456
02457
02458
02459
02460
02461
02462
02463
02464
02465
02466
02467
02468
02469
02470
02471
02472
02473
02474
02475
02476
02477
02478
02479
02480
02481
02482
02483
02484
02485
02486
02487
02488
02489
02490
02491
02492
02493 static void
02494 vect_update_ivs_after_vectorizer (loop_vec_info loop_vinfo, tree niters,
02495 edge update_e)
02496 {
02497 struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo);
02498 basic_block exit_bb = loop->single_exit->dest;
02499 tree phi, phi1;
02500 basic_block update_bb = update_e->dest;
02501
02502
02503
02504
02505 gcc_assert (single_pred_p (exit_bb));
02506
02507 for (phi = phi_nodes (loop->header), phi1 = phi_nodes (update_bb);
02508 phi && phi1;
02509 phi = PHI_CHAIN (phi), phi1 = PHI_CHAIN (phi1))
02510 {
02511 tree access_fn = NULL;
02512 tree evolution_part;
02513 tree init_expr;
02514 tree step_expr;
02515 tree var, stmt, ni, ni_name;
02516 block_stmt_iterator last_bsi;
02517
02518 if (vect_print_dump_info (REPORT_DETAILS))
02519 {
02520 fprintf (vect_dump, "vect_update_ivs_after_vectorizer: phi: ");
02521 print_generic_expr (vect_dump, phi, TDF_SLIM);
02522 }
02523
02524
02525 if (!is_gimple_reg (SSA_NAME_VAR (PHI_RESULT (phi))))
02526 {
02527 if (vect_print_dump_info (REPORT_DETAILS))
02528 fprintf (vect_dump, "virtual phi. skip.");
02529 continue;
02530 }
02531
02532
02533 if (STMT_VINFO_DEF_TYPE (vinfo_for_stmt (phi)) == vect_reduction_def)
02534 {
02535 if (vect_print_dump_info (REPORT_DETAILS))
02536 fprintf (vect_dump, "reduc phi. skip.");
02537 continue;
02538 }
02539
02540 access_fn = analyze_scalar_evolution (loop, PHI_RESULT (phi));
02541 gcc_assert (access_fn);
02542 evolution_part =
02543 unshare_expr (evolution_part_in_loop_num (access_fn, loop->num));
02544 gcc_assert (evolution_part != NULL_TREE);
02545
02546
02547
02548 gcc_assert (!tree_is_chrec (evolution_part));
02549
02550 step_expr = evolution_part;
02551 init_expr = unshare_expr (initial_condition_in_loop_num (access_fn,
02552 loop->num));
02553
02554 ni = build2 (PLUS_EXPR, TREE_TYPE (init_expr),
02555 build2 (MULT_EXPR, TREE_TYPE (niters),
02556 niters, step_expr), init_expr);
02557
02558 var = create_tmp_var (TREE_TYPE (init_expr), "tmp");
02559 add_referenced_var (var);
02560
02561 ni_name = force_gimple_operand (ni, &stmt, false, var);
02562
02563
02564 last_bsi = bsi_last (exit_bb);
02565 if (stmt)
02566 bsi_insert_before (&last_bsi, stmt, BSI_SAME_STMT);
02567
02568
02569 SET_PHI_ARG_DEF (phi1, update_e->dest_idx, ni_name);
02570 }
02571 }
02572
02573
02574
02575
02576
02577
02578
02579
02580
02581
02582
02583
02584 static void
02585 vect_do_peeling_for_loop_bound (loop_vec_info loop_vinfo, tree *ratio,
02586 struct loops *loops)
02587 {
02588 tree ni_name, ratio_mult_vf_name;
02589 struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo);
02590 struct loop *new_loop;
02591 edge update_e;
02592 basic_block preheader;
02593 int loop_num;
02594
02595 if (vect_print_dump_info (REPORT_DETAILS))
02596 fprintf (vect_dump, "=== vect_do_peeling_for_loop_bound ===");
02597
02598 initialize_original_copy_tables ();
02599
02600
02601
02602
02603
02604
02605 vect_generate_tmps_on_preheader (loop_vinfo, &ni_name,
02606 &ratio_mult_vf_name, ratio);
02607
02608 loop_num = loop->num;
02609 new_loop = slpeel_tree_peel_loop_to_edge (loop, loops, loop->single_exit,
02610 ratio_mult_vf_name, ni_name, false);
02611 gcc_assert (new_loop);
02612 gcc_assert (loop_num == loop->num);
02613 #ifdef ENABLE_CHECKING
02614 slpeel_verify_cfg_after_peeling (loop, new_loop);
02615 #endif
02616
02617
02618
02619
02620
02621
02622
02623 preheader = loop_preheader_edge (new_loop)->src;
02624 if (EDGE_PRED (preheader, 0)->src == loop->single_exit->dest)
02625 update_e = EDGE_PRED (preheader, 0);
02626 else
02627 update_e = EDGE_PRED (preheader, 1);
02628
02629
02630
02631 vect_update_ivs_after_vectorizer (loop_vinfo, ratio_mult_vf_name, update_e);
02632
02633
02634 scev_reset ();
02635
02636 free_original_copy_tables ();
02637 }
02638
02639
02640
02641
02642
02643
02644
02645
02646
02647
02648
02649
02650
02651
02652
02653
02654
02655
02656
02657
02658
02659
02660 static tree
02661 vect_gen_niters_for_prolog_loop (loop_vec_info loop_vinfo, tree loop_niters)
02662 {
02663 struct data_reference *dr = LOOP_VINFO_UNALIGNED_DR (loop_vinfo);
02664 int vf = LOOP_VINFO_VECT_FACTOR (loop_vinfo);
02665 struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo);
02666 tree var, stmt;
02667 tree iters, iters_name;
02668 edge pe;
02669 basic_block new_bb;
02670 tree dr_stmt = DR_STMT (dr);
02671 stmt_vec_info stmt_info = vinfo_for_stmt (dr_stmt);
02672 tree vectype = STMT_VINFO_VECTYPE (stmt_info);
02673 int vectype_align = TYPE_ALIGN (vectype) / BITS_PER_UNIT;
02674 tree niters_type = TREE_TYPE (loop_niters);
02675
02676 pe = loop_preheader_edge (loop);
02677
02678 if (LOOP_PEELING_FOR_ALIGNMENT (loop_vinfo) > 0)
02679 {
02680 int byte_misalign = LOOP_PEELING_FOR_ALIGNMENT (loop_vinfo);
02681 int element_size = vectype_align/vf;
02682 int elem_misalign = byte_misalign / element_size;
02683
02684 if (vect_print_dump_info (REPORT_DETAILS))
02685 fprintf (vect_dump, "known alignment = %d.", byte_misalign);
02686 iters = build_int_cst (niters_type, (vf - elem_misalign)&(vf-1));
02687 }
02688 else
02689 {
02690 tree new_stmts = NULL_TREE;
02691 tree start_addr =
02692 vect_create_addr_base_for_vector_ref (dr_stmt, &new_stmts, NULL_TREE);
02693 tree ptr_type = TREE_TYPE (start_addr);
02694 tree size = TYPE_SIZE (ptr_type);
02695 tree type = lang_hooks.types.type_for_size (tree_low_cst (size, 1), 1);
02696 tree vectype_size_minus_1 = build_int_cst (type, vectype_align - 1);
02697 tree elem_size_log =
02698 build_int_cst (type, exact_log2 (vectype_align/vf));
02699 tree vf_minus_1 = build_int_cst (type, vf - 1);
02700 tree vf_tree = build_int_cst (type, vf);
02701 tree byte_misalign;
02702 tree elem_misalign;
02703
02704 new_bb = bsi_insert_on_edge_immediate (pe, new_stmts);
02705 gcc_assert (!new_bb);
02706
02707
02708 byte_misalign =
02709 build2 (BIT_AND_EXPR, type, start_addr, vectype_size_minus_1);
02710
02711
02712 elem_misalign =
02713 build2 (RSHIFT_EXPR, type, byte_misalign, elem_size_log);
02714
02715
02716 iters = build2 (MINUS_EXPR, type, vf_tree, elem_misalign);
02717 iters = build2 (BIT_AND_EXPR, type, iters, vf_minus_1);
02718 iters = fold_convert (niters_type, iters);
02719 }
02720
02721
02722
02723
02724
02725 if (TREE_CODE (loop_niters) != INTEGER_CST)
02726 iters = build2 (MIN_EXPR, niters_type, iters, loop_niters);
02727
02728 if (vect_print_dump_info (REPORT_DETAILS))
02729 {
02730 fprintf (vect_dump, "niters for prolog loop: ");
02731 print_generic_expr (vect_dump, iters, TDF_SLIM);
02732 }
02733
02734 var = create_tmp_var (niters_type, "prolog_loop_niters");
02735 add_referenced_var (var);
02736 iters_name = force_gimple_operand (iters, &stmt, false, var);
02737
02738
02739 if (stmt)
02740 {
02741 basic_block new_bb = bsi_insert_on_edge_immediate (pe, stmt);
02742 gcc_assert (!new_bb);
02743 }
02744
02745 return iters_name;
02746 }
02747
02748
02749
02750
02751
02752
02753
02754
02755
02756 static void
02757 vect_update_init_of_dr (struct data_reference *dr, tree niters)
02758 {
02759 tree offset = DR_OFFSET (dr);
02760
02761 niters = fold_build2 (MULT_EXPR, TREE_TYPE (niters), niters, DR_STEP (dr));
02762 offset = fold_build2 (PLUS_EXPR, TREE_TYPE (offset), offset, niters);
02763 DR_OFFSET (dr) = offset;
02764 }
02765
02766
02767
02768
02769
02770
02771
02772
02773
02774
02775 static void
02776 vect_update_inits_of_drs (loop_vec_info loop_vinfo, tree niters)
02777 {
02778 unsigned int i;
02779 VEC (data_reference_p, heap) *datarefs = LOOP_VINFO_DATAREFS (loop_vinfo);
02780 struct data_reference *dr;
02781
02782 if (vect_dump && (dump_flags & TDF_DETAILS))
02783 fprintf (vect_dump, "=== vect_update_inits_of_dr ===");
02784
02785 for (i = 0; VEC_iterate (data_reference_p, datarefs, i, dr); i++)
02786 vect_update_init_of_dr (dr, niters);
02787 }
02788
02789
02790
02791
02792
02793
02794
02795
02796
02797
02798 static void
02799 vect_do_peeling_for_alignment (loop_vec_info loop_vinfo, struct loops *loops)
02800 {
02801 struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo);
02802 tree niters_of_prolog_loop, ni_name;
02803 tree n_iters;
02804 struct loop *new_loop;
02805
02806 if (vect_print_dump_info (REPORT_DETAILS))
02807 fprintf (vect_dump, "=== vect_do_peeling_for_alignment ===");
02808
02809 initialize_original_copy_tables ();
02810
02811 ni_name = vect_build_loop_niters (loop_vinfo);
02812 niters_of_prolog_loop = vect_gen_niters_for_prolog_loop (loop_vinfo, ni_name);
02813
02814
02815 new_loop =
02816 slpeel_tree_peel_loop_to_edge (loop, loops, loop_preheader_edge (loop),
02817 niters_of_prolog_loop, ni_name, true);
02818 gcc_assert (new_loop);
02819 #ifdef ENABLE_CHECKING
02820 slpeel_verify_cfg_after_peeling (new_loop, loop);
02821 #endif
02822
02823
02824 n_iters = LOOP_VINFO_NITERS (loop_vinfo);
02825 LOOP_VINFO_NITERS (loop_vinfo) = fold_build2 (MINUS_EXPR,
02826 TREE_TYPE (n_iters), n_iters, niters_of_prolog_loop);
02827
02828
02829 vect_update_inits_of_drs (loop_vinfo, niters_of_prolog_loop);
02830
02831
02832 scev_reset ();
02833
02834 free_original_copy_tables ();
02835 }
02836
02837
02838
02839
02840
02841
02842
02843
02844
02845
02846
02847
02848
02849
02850
02851
02852
02853
02854
02855
02856
02857
02858
02859
02860
02861 static tree
02862 vect_create_cond_for_align_checks (loop_vec_info loop_vinfo,
02863 tree *cond_expr_stmt_list)
02864 {
02865 VEC(tree,heap) *may_misalign_stmts
02866 = LOOP_VINFO_MAY_MISALIGN_STMTS (loop_vinfo);
02867 tree ref_stmt;
02868 int mask = LOOP_VINFO_PTR_MASK (loop_vinfo);
02869 tree mask_cst;
02870 unsigned int i;
02871 tree psize;
02872 tree int_ptrsize_type;
02873 char tmp_name[20];
02874 tree or_tmp_name = NULL_TREE;
02875 tree and_tmp, and_tmp_name, and_stmt;
02876 tree ptrsize_zero;
02877
02878
02879
02880 gcc_assert ((mask != 0) && ((mask & (mask+1)) == 0));
02881
02882
02883
02884 psize = TYPE_SIZE (ptr_type_node);
02885 int_ptrsize_type
02886 = lang_hooks.types.type_for_size (tree_low_cst (psize, 1), 0);
02887
02888
02889
02890
02891 for (i = 0; VEC_iterate (tree, may_misalign_stmts, i, ref_stmt); i++)
02892 {
02893 tree new_stmt_list = NULL_TREE;
02894 tree addr_base;
02895 tree addr_tmp, addr_tmp_name, addr_stmt;
02896 tree or_tmp, new_or_tmp_name, or_stmt;
02897
02898
02899 addr_base = vect_create_addr_base_for_vector_ref (ref_stmt,
02900 &new_stmt_list,
02901 NULL_TREE);
02902
02903 if (new_stmt_list != NULL_TREE)
02904 append_to_statement_list_force (new_stmt_list, cond_expr_stmt_list);
02905
02906 sprintf (tmp_name, "%s%d", "addr2int", i);
02907 addr_tmp = create_tmp_var (int_ptrsize_type, tmp_name);
02908 add_referenced_var (addr_tmp);
02909 addr_tmp_name = make_ssa_name (addr_tmp, NULL_TREE);
02910 addr_stmt = fold_convert (int_ptrsize_type, addr_base);
02911 addr_stmt = build2 (MODIFY_EXPR, void_type_node,
02912 addr_tmp_name, addr_stmt);
02913 SSA_NAME_DEF_STMT (addr_tmp_name) = addr_stmt;
02914 append_to_statement_list_force (addr_stmt, cond_expr_stmt_list);
02915
02916
02917
02918 if (or_tmp_name != NULL_TREE)
02919 {
02920
02921 sprintf (tmp_name, "%s%d", "orptrs", i);
02922 or_tmp = create_tmp_var (int_ptrsize_type, tmp_name);
02923 add_referenced_var (or_tmp);
02924 new_or_tmp_name = make_ssa_name (or_tmp, NULL_TREE);
02925 or_stmt = build2 (MODIFY_EXPR, void_type_node, new_or_tmp_name,
02926 build2 (BIT_IOR_EXPR, int_ptrsize_type,
02927 or_tmp_name,
02928 addr_tmp_name));
02929 SSA_NAME_DEF_STMT (new_or_tmp_name) = or_stmt;
02930 append_to_statement_list_force (or_stmt, cond_expr_stmt_list);
02931 or_tmp_name = new_or_tmp_name;
02932 }
02933 else
02934 or_tmp_name = addr_tmp_name;
02935
02936 }
02937
02938 mask_cst = build_int_cst (int_ptrsize_type, mask);
02939
02940
02941 and_tmp = create_tmp_var (int_ptrsize_type, "andmask" );
02942 add_referenced_var (and_tmp);
02943 and_tmp_name = make_ssa_name (and_tmp, NULL_TREE);
02944
02945 and_stmt = build2 (MODIFY_EXPR, void_type_node,
02946 and_tmp_name,
02947 build2 (BIT_AND_EXPR, int_ptrsize_type,
02948 or_tmp_name, mask_cst));
02949 SSA_NAME_DEF_STMT (and_tmp_name) = and_stmt;
02950 append_to_statement_list_force (and_stmt, cond_expr_stmt_list);
02951
02952
02953
02954 ptrsize_zero = build_int_cst (int_ptrsize_type, 0);
02955 return build2 (EQ_EXPR, boolean_type_node,
02956 and_tmp_name, ptrsize_zero);
02957 }
02958
02959
02960
02961
02962
02963
02964
02965
02966 void
02967 vect_transform_loop (loop_vec_info loop_vinfo,
02968 struct loops *loops ATTRIBUTE_UNUSED)
02969 {
02970 struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo);
02971 basic_block *bbs = LOOP_VINFO_BBS (loop_vinfo);
02972 int nbbs = loop->num_nodes;
02973 block_stmt_iterator si;
02974 int i;
02975 tree ratio = NULL;
02976 int vectorization_factor = LOOP_VINFO_VECT_FACTOR (loop_vinfo);
02977 bitmap_iterator bi;
02978 unsigned int j;
02979
02980 if (vect_print_dump_info (REPORT_DETAILS))
02981 fprintf (vect_dump, "=== vec_transform_loop ===");
02982
02983
02984
02985
02986
02987
02988
02989 if (VEC_length (tree, LOOP_VINFO_MAY_MISALIGN_STMTS (loop_vinfo)))
02990 {
02991 struct loop *nloop;
02992 tree cond_expr;
02993 tree cond_expr_stmt_list = NULL_TREE;
02994 basic_block condition_bb;
02995 block_stmt_iterator cond_exp_bsi;
02996 basic_block merge_bb;
02997 basic_block new_exit_bb;
02998 edge new_exit_e, e;
02999 tree orig_phi, new_phi, arg;
03000
03001 cond_expr = vect_create_cond_for_align_checks (loop_vinfo,
03002 &cond_expr_stmt_list);
03003 initialize_original_copy_tables ();
03004 nloop = loop_version (loops, loop, cond_expr, &condition_bb, true);
03005 free_original_copy_tables();
03006
03015 merge_bb = loop->single_exit->dest;
03016 gcc_assert (EDGE_COUNT (merge_bb->preds) == 2);
03017 new_exit_bb = split_edge (loop->single_exit);
03018 add_bb_to_loop (new_exit_bb, loop->outer);
03019 new_exit_e = loop->single_exit;
03020 e = EDGE_SUCC (new_exit_bb, 0);
03021
03022 for (orig_phi = phi_nodes (merge_bb); orig_phi;
03023 orig_phi = PHI_CHAIN (orig_phi))
03024 {
03025 new_phi = create_phi_node (SSA_NAME_VAR (PHI_RESULT (orig_phi)),
03026 new_exit_bb);
03027 arg = PHI_ARG_DEF_FROM_EDGE (orig_phi, e);
03028 add_phi_arg (new_phi, arg, new_exit_e);
03029 SET_PHI_ARG_DEF (orig_phi, e->dest_idx, PHI_RESULT (new_phi));
03030 }
03031
03034 update_ssa (TODO_update_ssa);
03035 cond_exp_bsi = bsi_last (condition_bb);
03036 bsi_insert_before (&cond_exp_bsi, cond_expr_stmt_list, BSI_SAME_STMT);
03037 }
03038
03039
03040
03041 bitmap_zero (vect_vnames_to_rename);
03042
03043
03044
03045
03046 if (LOOP_PEELING_FOR_ALIGNMENT (loop_vinfo))
03047 vect_do_peeling_for_alignment (loop_vinfo, loops);
03048
03049
03050
03051
03052
03053
03054
03055
03056
03057 if (!LOOP_VINFO_NITERS_KNOWN_P (loop_vinfo)
03058 || (LOOP_VINFO_NITERS_KNOWN_P (loop_vinfo)
03059 && LOOP_VINFO_INT_NITERS (loop_vinfo) % vectorization_factor != 0))
03060 vect_do_peeling_for_loop_bound (loop_vinfo, &ratio, loops);
03061 else
03062 ratio = build_int_cst (TREE_TYPE (LOOP_VINFO_NITERS (loop_vinfo)),
03063 LOOP_VINFO_INT_NITERS (loop_vinfo) / vectorization_factor);
03064
03065
03066
03067
03068 gcc_assert (EDGE_COUNT (loop->header->preds) == 2);
03069
03070 loop_split_edge_with (loop_preheader_edge (loop), NULL);
03071
03072
03073
03074
03075
03076
03077
03078 for (i = 0; i < nbbs; i++)
03079 {
03080 basic_block bb = bbs[i];
03081
03082 for (si = bsi_start (bb); !bsi_end_p (si);)
03083 {
03084 tree stmt = bsi_stmt (si);
03085 stmt_vec_info stmt_info;
03086 bool is_store;
03087
03088 if (vect_print_dump_info (REPORT_DETAILS))
03089 {
03090 fprintf (vect_dump, "------>vectorizing statement: ");
03091 print_generic_expr (vect_dump, stmt, TDF_SLIM);
03092 }
03093 stmt_info = vinfo_for_stmt (stmt);
03094 gcc_assert (stmt_info);
03095 if (!STMT_VINFO_RELEVANT_P (stmt_info)
03096 && !STMT_VINFO_LIVE_P (stmt_info))
03097 {
03098 bsi_next (&si);
03099 continue;
03100 }
03101
03102
03103 gcc_assert
03104 (TYPE_VECTOR_SUBPARTS (STMT_VINFO_VECTYPE (stmt_info))
03105 == (unsigned HOST_WIDE_INT) vectorization_factor);
03106
03107
03108 if (vect_print_dump_info (REPORT_DETAILS))
03109 fprintf (vect_dump, "transform statement.");
03110
03111 is_store = vect_transform_stmt (stmt, &si);
03112 if (is_store)
03113 {
03114
03115 stmt_ann_t ann = stmt_ann (stmt);
03116 free (stmt_info);
03117 set_stmt_info (ann, NULL);
03118 bsi_remove (&si, true);
03119 continue;
03120 }
03121
03122 bsi_next (&si);
03123 }
03124 }
03125
03126 slpeel_make_loop_iterate_ntimes (loop, ratio);
03127
03128 EXECUTE_IF_SET_IN_BITMAP (vect_vnames_to_rename, 0, j, bi)
03129 mark_sym_for_renaming (SSA_NAME_VAR (ssa_name (j)));
03130
03131
03132
03133
03134 update_ssa (TODO_update_ssa);
03135
03136 if (vect_print_dump_info (REPORT_VECTORIZED_LOOPS))
03137 fprintf (vect_dump, "LOOP VECTORIZED.");
03138 }