00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "config.h"
00022 #include "system.h"
00023 #include "coretypes.h"
00024 #include "tree.h"
00025 #include "tm.h"
00026 #include "rtl.h"
00027 #include "expr.h"
00028 #include "insn-codes.h"
00029 #include "diagnostic.h"
00030 #include "optabs.h"
00031 #include "machmode.h"
00032 #include "langhooks.h"
00033 #include "tree-flow.h"
00034 #include "tree-gimple.h"
00035 #include "tree-iterator.h"
00036 #include "tree-pass.h"
00037 #include "flags.h"
00038 #include "ggc.h"
00039
00040
00041
00042
00043 static tree
00044 build_replicated_const (tree type, tree inner_type, HOST_WIDE_INT value)
00045 {
00046 int width = tree_low_cst (TYPE_SIZE (inner_type), 1);
00047 int n = HOST_BITS_PER_WIDE_INT / width;
00048 unsigned HOST_WIDE_INT low, high, mask;
00049 tree ret;
00050
00051 gcc_assert (n);
00052
00053 if (width == HOST_BITS_PER_WIDE_INT)
00054 low = value;
00055 else
00056 {
00057 mask = ((HOST_WIDE_INT)1 << width) - 1;
00058 low = (unsigned HOST_WIDE_INT) ~0 / mask * (value & mask);
00059 }
00060
00061 if (TYPE_PRECISION (type) < HOST_BITS_PER_WIDE_INT)
00062 low &= ((HOST_WIDE_INT)1 << TYPE_PRECISION (type)) - 1, high = 0;
00063 else if (TYPE_PRECISION (type) == HOST_BITS_PER_WIDE_INT)
00064 high = 0;
00065 else if (TYPE_PRECISION (type) == 2 * HOST_BITS_PER_WIDE_INT)
00066 high = low;
00067 else
00068 gcc_unreachable ();
00069
00070 ret = build_int_cst_wide (type, low, high);
00071 return ret;
00072 }
00073
00074 static GTY(()) tree vector_inner_type;
00075 static GTY(()) tree vector_last_type;
00076 static GTY(()) int vector_last_nunits;
00077
00078
00079
00080 static tree
00081 build_word_mode_vector_type (int nunits)
00082 {
00083 if (!vector_inner_type)
00084 vector_inner_type = lang_hooks.types.type_for_mode (word_mode, 1);
00085 else if (vector_last_nunits == nunits)
00086 {
00087 gcc_assert (TREE_CODE (vector_last_type) == VECTOR_TYPE);
00088 return vector_last_type;
00089 }
00090
00091
00092
00093 vector_last_nunits = nunits;
00094 vector_last_type = type_hash_canon (nunits,
00095 build_vector_type (vector_inner_type,
00096 nunits));
00097 return vector_last_type;
00098 }
00099
00100 typedef tree (*elem_op_func) (block_stmt_iterator *,
00101 tree, tree, tree, tree, tree, enum tree_code);
00102
00103 static inline tree
00104 tree_vec_extract (block_stmt_iterator *bsi, tree type,
00105 tree t, tree bitsize, tree bitpos)
00106 {
00107 if (bitpos)
00108 return gimplify_build3 (bsi, BIT_FIELD_REF, type, t, bitsize, bitpos);
00109 else
00110 return gimplify_build1 (bsi, VIEW_CONVERT_EXPR, type, t);
00111 }
00112
00113 static tree
00114 do_unop (block_stmt_iterator *bsi, tree inner_type, tree a,
00115 tree b ATTRIBUTE_UNUSED, tree bitpos, tree bitsize,
00116 enum tree_code code)
00117 {
00118 a = tree_vec_extract (bsi, inner_type, a, bitsize, bitpos);
00119 return gimplify_build1 (bsi, code, inner_type, a);
00120 }
00121
00122 static tree
00123 do_binop (block_stmt_iterator *bsi, tree inner_type, tree a, tree b,
00124 tree bitpos, tree bitsize, enum tree_code code)
00125 {
00126 a = tree_vec_extract (bsi, inner_type, a, bitsize, bitpos);
00127 b = tree_vec_extract (bsi, inner_type, b, bitsize, bitpos);
00128 return gimplify_build2 (bsi, code, inner_type, a, b);
00129 }
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144 static tree
00145 do_plus_minus (block_stmt_iterator *bsi, tree word_type, tree a, tree b,
00146 tree bitpos ATTRIBUTE_UNUSED, tree bitsize ATTRIBUTE_UNUSED,
00147 enum tree_code code)
00148 {
00149 tree inner_type = TREE_TYPE (TREE_TYPE (a));
00150 unsigned HOST_WIDE_INT max;
00151 tree low_bits, high_bits, a_low, b_low, result_low, signs;
00152
00153 max = GET_MODE_MASK (TYPE_MODE (inner_type));
00154 low_bits = build_replicated_const (word_type, inner_type, max >> 1);
00155 high_bits = build_replicated_const (word_type, inner_type, max & ~(max >> 1));
00156
00157 a = tree_vec_extract (bsi, word_type, a, bitsize, bitpos);
00158 b = tree_vec_extract (bsi, word_type, b, bitsize, bitpos);
00159
00160 signs = gimplify_build2 (bsi, BIT_XOR_EXPR, word_type, a, b);
00161 b_low = gimplify_build2 (bsi, BIT_AND_EXPR, word_type, b, low_bits);
00162 if (code == PLUS_EXPR)
00163 a_low = gimplify_build2 (bsi, BIT_AND_EXPR, word_type, a, low_bits);
00164 else
00165 {
00166 a_low = gimplify_build2 (bsi, BIT_IOR_EXPR, word_type, a, high_bits);
00167 signs = gimplify_build1 (bsi, BIT_NOT_EXPR, word_type, signs);
00168 }
00169
00170 signs = gimplify_build2 (bsi, BIT_AND_EXPR, word_type, signs, high_bits);
00171 result_low = gimplify_build2 (bsi, code, word_type, a_low, b_low);
00172 return gimplify_build2 (bsi, BIT_XOR_EXPR, word_type, result_low, signs);
00173 }
00174
00175 static tree
00176 do_negate (block_stmt_iterator *bsi, tree word_type, tree b,
00177 tree unused ATTRIBUTE_UNUSED, tree bitpos ATTRIBUTE_UNUSED,
00178 tree bitsize ATTRIBUTE_UNUSED,
00179 enum tree_code code ATTRIBUTE_UNUSED)
00180 {
00181 tree inner_type = TREE_TYPE (TREE_TYPE (b));
00182 HOST_WIDE_INT max;
00183 tree low_bits, high_bits, b_low, result_low, signs;
00184
00185 max = GET_MODE_MASK (TYPE_MODE (inner_type));
00186 low_bits = build_replicated_const (word_type, inner_type, max >> 1);
00187 high_bits = build_replicated_const (word_type, inner_type, max & ~(max >> 1));
00188
00189 b = tree_vec_extract (bsi, word_type, b, bitsize, bitpos);
00190
00191 b_low = gimplify_build2 (bsi, BIT_AND_EXPR, word_type, b, low_bits);
00192 signs = gimplify_build1 (bsi, BIT_NOT_EXPR, word_type, b);
00193 signs = gimplify_build2 (bsi, BIT_AND_EXPR, word_type, signs, high_bits);
00194 result_low = gimplify_build2 (bsi, MINUS_EXPR, word_type, high_bits, b_low);
00195 return gimplify_build2 (bsi, BIT_XOR_EXPR, word_type, result_low, signs);
00196 }
00197
00198
00199
00200 static tree
00201 expand_vector_piecewise (block_stmt_iterator *bsi, elem_op_func f,
00202 tree type, tree inner_type,
00203 tree a, tree b, enum tree_code code)
00204 {
00205 VEC(constructor_elt,gc) *v;
00206 tree part_width = TYPE_SIZE (inner_type);
00207 tree index = bitsize_int (0);
00208 int nunits = TYPE_VECTOR_SUBPARTS (type);
00209 int delta = tree_low_cst (part_width, 1)
00210 / tree_low_cst (TYPE_SIZE (TREE_TYPE (type)), 1);
00211 int i;
00212
00213 v = VEC_alloc(constructor_elt, gc, (nunits + delta - 1) / delta);
00214 for (i = 0; i < nunits;
00215 i += delta, index = int_const_binop (PLUS_EXPR, index, part_width, 0))
00216 {
00217 tree result = f (bsi, inner_type, a, b, index, part_width, code);
00218 constructor_elt *ce = VEC_quick_push (constructor_elt, v, NULL);
00219 ce->index = NULL_TREE;
00220 ce->value = result;
00221 }
00222
00223 return build_constructor (type, v);
00224 }
00225
00226
00227
00228
00229 static tree
00230 expand_vector_parallel (block_stmt_iterator *bsi, elem_op_func f, tree type,
00231 tree a, tree b,
00232 enum tree_code code)
00233 {
00234 tree result, compute_type;
00235 enum machine_mode mode;
00236 int n_words = tree_low_cst (TYPE_SIZE_UNIT (type), 1) / UNITS_PER_WORD;
00237
00238
00239
00240
00241
00242 if (TYPE_MODE (TREE_TYPE (type)) == word_mode)
00243 return expand_vector_piecewise (bsi, f,
00244 type, TREE_TYPE (type),
00245 a, b, code);
00246 else if (n_words > 1)
00247 {
00248 tree word_type = build_word_mode_vector_type (n_words);
00249 result = expand_vector_piecewise (bsi, f,
00250 word_type, TREE_TYPE (word_type),
00251 a, b, code);
00252 result = gimplify_val (bsi, word_type, result);
00253 }
00254 else
00255 {
00256
00257 mode = mode_for_size (tree_low_cst (TYPE_SIZE (type), 1), MODE_INT, 0);
00258 compute_type = lang_hooks.types.type_for_mode (mode, 1);
00259 result = f (bsi, compute_type, a, b, NULL_TREE, NULL_TREE, code);
00260 }
00261
00262 return result;
00263 }
00264
00265
00266
00267
00268
00269
00270 static tree
00271 expand_vector_addition (block_stmt_iterator *bsi,
00272 elem_op_func f, elem_op_func f_parallel,
00273 tree type, tree a, tree b, enum tree_code code)
00274 {
00275 int parts_per_word = UNITS_PER_WORD
00276 / tree_low_cst (TYPE_SIZE_UNIT (TREE_TYPE (type)), 1);
00277
00278 if (INTEGRAL_TYPE_P (TREE_TYPE (type))
00279 && parts_per_word >= 4
00280 && TYPE_VECTOR_SUBPARTS (type) >= 4)
00281 return expand_vector_parallel (bsi, f_parallel,
00282 type, a, b, code);
00283 else
00284 return expand_vector_piecewise (bsi, f,
00285 type, TREE_TYPE (type),
00286 a, b, code);
00287 }
00288
00289 static tree
00290 expand_vector_operation (block_stmt_iterator *bsi, tree type, tree compute_type,
00291 tree rhs, enum tree_code code)
00292 {
00293 enum machine_mode compute_mode = TYPE_MODE (compute_type);
00294
00295
00296
00297
00298 if (GET_MODE_CLASS (compute_mode) != MODE_VECTOR_INT
00299 && GET_MODE_CLASS (compute_mode) != MODE_VECTOR_FLOAT)
00300 switch (code)
00301 {
00302 case PLUS_EXPR:
00303 case MINUS_EXPR:
00304 if (!TYPE_OVERFLOW_TRAPS (type))
00305 return expand_vector_addition (bsi, do_binop, do_plus_minus, type,
00306 TREE_OPERAND (rhs, 0),
00307 TREE_OPERAND (rhs, 1), code);
00308 break;
00309
00310 case NEGATE_EXPR:
00311 if (!TYPE_OVERFLOW_TRAPS (type))
00312 return expand_vector_addition (bsi, do_unop, do_negate, type,
00313 TREE_OPERAND (rhs, 0),
00314 NULL_TREE, code);
00315 break;
00316
00317 case BIT_AND_EXPR:
00318 case BIT_IOR_EXPR:
00319 case BIT_XOR_EXPR:
00320 return expand_vector_parallel (bsi, do_binop, type,
00321 TREE_OPERAND (rhs, 0),
00322 TREE_OPERAND (rhs, 1), code);
00323
00324 case BIT_NOT_EXPR:
00325 return expand_vector_parallel (bsi, do_unop, type,
00326 TREE_OPERAND (rhs, 0),
00327 NULL_TREE, code);
00328
00329 default:
00330 break;
00331 }
00332
00333 if (TREE_CODE_CLASS (code) == tcc_unary)
00334 return expand_vector_piecewise (bsi, do_unop, type, compute_type,
00335 TREE_OPERAND (rhs, 0),
00336 NULL_TREE, code);
00337 else
00338 return expand_vector_piecewise (bsi, do_binop, type, compute_type,
00339 TREE_OPERAND (rhs, 0),
00340 TREE_OPERAND (rhs, 1), code);
00341 }
00342
00343
00344
00345 static tree
00346 type_for_widest_vector_mode (enum machine_mode inner_mode, optab op)
00347 {
00348 enum machine_mode best_mode = VOIDmode, mode;
00349 int best_nunits = 0;
00350
00351 if (SCALAR_FLOAT_MODE_P (inner_mode))
00352 mode = MIN_MODE_VECTOR_FLOAT;
00353 else
00354 mode = MIN_MODE_VECTOR_INT;
00355
00356 for (; mode != VOIDmode; mode = GET_MODE_WIDER_MODE (mode))
00357 if (GET_MODE_INNER (mode) == inner_mode
00358 && GET_MODE_NUNITS (mode) > best_nunits
00359 && op->handlers[mode].insn_code != CODE_FOR_nothing)
00360 best_mode = mode, best_nunits = GET_MODE_NUNITS (mode);
00361
00362 if (best_mode == VOIDmode)
00363 return NULL_TREE;
00364 else
00365 return lang_hooks.types.type_for_mode (best_mode, 1);
00366 }
00367
00368
00369
00370 static void
00371 expand_vector_operations_1 (block_stmt_iterator *bsi)
00372 {
00373 tree stmt = bsi_stmt (*bsi);
00374 tree *p_lhs, *p_rhs, lhs, rhs, type, compute_type;
00375 enum tree_code code;
00376 enum machine_mode compute_mode;
00377 optab op;
00378
00379 switch (TREE_CODE (stmt))
00380 {
00381 case RETURN_EXPR:
00382 stmt = TREE_OPERAND (stmt, 0);
00383 if (!stmt || TREE_CODE (stmt) != MODIFY_EXPR)
00384 return;
00385
00386
00387
00388 case MODIFY_EXPR:
00389 p_lhs = &TREE_OPERAND (stmt, 0);
00390 p_rhs = &TREE_OPERAND (stmt, 1);
00391 lhs = *p_lhs;
00392 rhs = *p_rhs;
00393 break;
00394
00395 default:
00396 return;
00397 }
00398
00399 type = TREE_TYPE (rhs);
00400 if (TREE_CODE (type) != VECTOR_TYPE)
00401 return;
00402
00403 code = TREE_CODE (rhs);
00404 if (TREE_CODE_CLASS (code) != tcc_unary
00405 && TREE_CODE_CLASS (code) != tcc_binary)
00406 return;
00407
00408 if (code == NOP_EXPR || code == VIEW_CONVERT_EXPR)
00409 return;
00410
00411 gcc_assert (code != CONVERT_EXPR);
00412 op = optab_for_tree_code (code, type);
00413
00414
00415
00416 if (code == WIDEN_SUM_EXPR)
00417 type = TREE_TYPE (TREE_OPERAND (rhs, 0));
00418
00419
00420
00421
00422 if (op == NULL
00423 && code == NEGATE_EXPR
00424 && INTEGRAL_TYPE_P (TREE_TYPE (type)))
00425 op = optab_for_tree_code (MINUS_EXPR, type);
00426
00427
00428 compute_type = type;
00429 if (TYPE_MODE (type) == BLKmode && op)
00430 {
00431 tree vector_compute_type
00432 = type_for_widest_vector_mode (TYPE_MODE (TREE_TYPE (type)), op);
00433 if (vector_compute_type != NULL_TREE)
00434 compute_type = vector_compute_type;
00435 }
00436
00437
00438
00439
00440 if (compute_type == type)
00441 {
00442 compute_mode = TYPE_MODE (compute_type);
00443 if ((GET_MODE_CLASS (compute_mode) == MODE_VECTOR_INT
00444 || GET_MODE_CLASS (compute_mode) == MODE_VECTOR_FLOAT)
00445 && op != NULL
00446 && op->handlers[compute_mode].insn_code != CODE_FOR_nothing)
00447 return;
00448 else
00449
00450 compute_type = TREE_TYPE (type);
00451 }
00452
00453 gcc_assert (code != VEC_LSHIFT_EXPR && code != VEC_RSHIFT_EXPR);
00454 rhs = expand_vector_operation (bsi, type, compute_type, rhs, code);
00455 if (lang_hooks.types_compatible_p (TREE_TYPE (lhs), TREE_TYPE (rhs)))
00456 *p_rhs = rhs;
00457 else
00458 *p_rhs = gimplify_build1 (bsi, VIEW_CONVERT_EXPR, TREE_TYPE (lhs), rhs);
00459
00460 mark_stmt_modified (bsi_stmt (*bsi));
00461 }
00462
00463
00464
00465
00466 static bool
00467 gate_expand_vector_operations (void)
00468 {
00469 return flag_tree_vectorize != 0;
00470 }
00471
00472 static unsigned int
00473 expand_vector_operations (void)
00474 {
00475 block_stmt_iterator bsi;
00476 basic_block bb;
00477
00478 FOR_EACH_BB (bb)
00479 {
00480 for (bsi = bsi_start (bb); !bsi_end_p (bsi); bsi_next (&bsi))
00481 {
00482 expand_vector_operations_1 (&bsi);
00483 update_stmt_if_modified (bsi_stmt (bsi));
00484 }
00485 }
00486 return 0;
00487 }
00488
00489 struct tree_opt_pass pass_lower_vector =
00490 {
00491 "veclower",
00492 0,
00493 expand_vector_operations,
00494 NULL,
00495 NULL,
00496 0,
00497 0,
00498 PROP_cfg,
00499 0,
00500 0,
00501 0,
00502 TODO_dump_func | TODO_ggc_collect
00503 | TODO_verify_stmts,
00504 0
00505 };
00506
00507 struct tree_opt_pass pass_lower_vector_ssa =
00508 {
00509 "veclower2",
00510 gate_expand_vector_operations,
00511 expand_vector_operations,
00512 NULL,
00513 NULL,
00514 0,
00515 0,
00516 PROP_cfg,
00517 0,
00518 0,
00519 0,
00520 TODO_dump_func | TODO_update_ssa
00521 | TODO_verify_ssa
00522 | TODO_verify_stmts | TODO_verify_flow,
00523 0
00524 };
00525
00526 #include "gt-tree-vect-generic.h"