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
00044
00045 static tree
00046 extract_component (block_stmt_iterator *bsi, tree t, bool imagpart_p)
00047 {
00048 tree ret, inner_type;
00049
00050 inner_type = TREE_TYPE (TREE_TYPE (t));
00051 switch (TREE_CODE (t))
00052 {
00053 case COMPLEX_CST:
00054 ret = (imagpart_p ? TREE_IMAGPART (t) : TREE_REALPART (t));
00055 break;
00056
00057 case COMPLEX_EXPR:
00058 ret = TREE_OPERAND (t, imagpart_p);
00059 break;
00060
00061 case VAR_DECL:
00062 case PARM_DECL:
00063 ret = build1 ((imagpart_p ? IMAGPART_EXPR : REALPART_EXPR),
00064 inner_type, t);
00065 break;
00066
00067 default:
00068 gcc_unreachable ();
00069 }
00070
00071 return gimplify_val (bsi, inner_type, ret);
00072 }
00073
00074
00075
00076 static void
00077 update_complex_assignment (block_stmt_iterator *bsi, tree r, tree i)
00078 {
00079 tree stmt = bsi_stmt (*bsi);
00080 tree type;
00081
00082 if (TREE_CODE (stmt) == RETURN_EXPR)
00083 stmt = TREE_OPERAND (stmt, 0);
00084
00085 type = TREE_TYPE (TREE_OPERAND (stmt, 1));
00086 TREE_OPERAND (stmt, 1) = build (COMPLEX_EXPR, type, r, i);
00087 modify_stmt (stmt);
00088 }
00089
00090
00091
00092
00093
00094
00095 static void
00096 expand_complex_addition (block_stmt_iterator *bsi, tree inner_type,
00097 tree ar, tree ai, tree br, tree bi,
00098 enum tree_code code)
00099 {
00100 tree rr, ri;
00101
00102 rr = gimplify_build2 (bsi, code, inner_type, ar, br);
00103 ri = gimplify_build2 (bsi, code, inner_type, ai, bi);
00104
00105 update_complex_assignment (bsi, rr, ri);
00106 }
00107
00108
00109
00110
00111 static void
00112 expand_complex_libcall (block_stmt_iterator *bsi, tree ar, tree ai,
00113 tree br, tree bi, enum tree_code code)
00114 {
00115 enum machine_mode mode;
00116 enum built_in_function bcode;
00117 tree args, fn, stmt, type;
00118
00119 args = tree_cons (NULL, bi, NULL);
00120 args = tree_cons (NULL, br, args);
00121 args = tree_cons (NULL, ai, args);
00122 args = tree_cons (NULL, ar, args);
00123
00124 stmt = bsi_stmt (*bsi);
00125 type = TREE_TYPE (TREE_OPERAND (stmt, 1));
00126
00127 mode = TYPE_MODE (type);
00128 gcc_assert (GET_MODE_CLASS (mode) == MODE_COMPLEX_FLOAT);
00129 if (code == MULT_EXPR)
00130 bcode = BUILT_IN_COMPLEX_MUL_MIN + mode - MIN_MODE_COMPLEX_FLOAT;
00131 else if (code == RDIV_EXPR)
00132 bcode = BUILT_IN_COMPLEX_DIV_MIN + mode - MIN_MODE_COMPLEX_FLOAT;
00133 else
00134 gcc_unreachable ();
00135 fn = built_in_decls[bcode];
00136
00137 TREE_OPERAND (stmt, 1)
00138 = build3 (CALL_EXPR, type, build_fold_addr_expr (fn), args, NULL);
00139 modify_stmt (stmt);
00140 }
00141
00142
00143
00144
00145
00146 static void
00147 expand_complex_multiplication (block_stmt_iterator *bsi, tree inner_type,
00148 tree ar, tree ai, tree br, tree bi)
00149 {
00150 tree t1, t2, t3, t4, rr, ri;
00151
00152 if (flag_complex_method == 2 && SCALAR_FLOAT_TYPE_P (inner_type))
00153 {
00154 expand_complex_libcall (bsi, ar, ai, br, bi, MULT_EXPR);
00155 return;
00156 }
00157
00158 t1 = gimplify_build2 (bsi, MULT_EXPR, inner_type, ar, br);
00159 t2 = gimplify_build2 (bsi, MULT_EXPR, inner_type, ai, bi);
00160 t3 = gimplify_build2 (bsi, MULT_EXPR, inner_type, ar, bi);
00161
00162
00163
00164 if (ar == br && ai == bi)
00165 t4 = t3;
00166 else
00167 t4 = gimplify_build2 (bsi, MULT_EXPR, inner_type, ai, br);
00168
00169 rr = gimplify_build2 (bsi, MINUS_EXPR, inner_type, t1, t2);
00170 ri = gimplify_build2 (bsi, PLUS_EXPR, inner_type, t3, t4);
00171
00172 update_complex_assignment (bsi, rr, ri);
00173 }
00174
00175
00176
00177
00178
00179
00180 static void
00181 expand_complex_div_straight (block_stmt_iterator *bsi, tree inner_type,
00182 tree ar, tree ai, tree br, tree bi,
00183 enum tree_code code)
00184 {
00185 tree rr, ri, div, t1, t2, t3;
00186
00187 t1 = gimplify_build2 (bsi, MULT_EXPR, inner_type, br, br);
00188 t2 = gimplify_build2 (bsi, MULT_EXPR, inner_type, bi, bi);
00189 div = gimplify_build2 (bsi, PLUS_EXPR, inner_type, t1, t2);
00190
00191 t1 = gimplify_build2 (bsi, MULT_EXPR, inner_type, ar, br);
00192 t2 = gimplify_build2 (bsi, MULT_EXPR, inner_type, ai, bi);
00193 t3 = gimplify_build2 (bsi, PLUS_EXPR, inner_type, t1, t2);
00194 rr = gimplify_build2 (bsi, code, inner_type, t3, div);
00195
00196 t1 = gimplify_build2 (bsi, MULT_EXPR, inner_type, ai, br);
00197 t2 = gimplify_build2 (bsi, MULT_EXPR, inner_type, ar, bi);
00198 t3 = gimplify_build2 (bsi, MINUS_EXPR, inner_type, t1, t2);
00199 ri = gimplify_build2 (bsi, code, inner_type, t3, div);
00200
00201 update_complex_assignment (bsi, rr, ri);
00202 }
00203
00204
00205
00206
00207 static void
00208 expand_complex_div_wide (block_stmt_iterator *bsi, tree inner_type,
00209 tree ar, tree ai, tree br, tree bi,
00210 enum tree_code code)
00211 {
00212 tree rr, ri, ratio, div, t1, t2, tr, ti, cond;
00213 basic_block bb_cond, bb_true, bb_false, bb_join;
00214
00215
00216 t1 = gimplify_build1 (bsi, ABS_EXPR, inner_type, br);
00217 t2 = gimplify_build1 (bsi, ABS_EXPR, inner_type, bi);
00218 cond = fold (build (LT_EXPR, boolean_type_node, t1, t2));
00219 STRIP_NOPS (cond);
00220
00221 bb_cond = bb_true = bb_false = bb_join = NULL;
00222 rr = ri = tr = ti = NULL;
00223 if (!TREE_CONSTANT (cond))
00224 {
00225 edge e;
00226
00227 cond = build (COND_EXPR, void_type_node, cond, NULL, NULL);
00228 bsi_insert_before (bsi, cond, BSI_SAME_STMT);
00229
00230
00231 e = split_block (bsi->bb, cond);
00232 bb_cond = e->src;
00233 bb_join = e->dest;
00234 bb_true = create_empty_bb (bb_cond);
00235 bb_false = create_empty_bb (bb_true);
00236
00237 t1 = build (GOTO_EXPR, void_type_node, tree_block_label (bb_true));
00238 t2 = build (GOTO_EXPR, void_type_node, tree_block_label (bb_false));
00239 COND_EXPR_THEN (cond) = t1;
00240 COND_EXPR_ELSE (cond) = t2;
00241
00242
00243 e->flags = EDGE_TRUE_VALUE;
00244 redirect_edge_succ (e, bb_true);
00245 make_edge (bb_cond, bb_false, EDGE_FALSE_VALUE);
00246 make_edge (bb_true, bb_join, EDGE_FALLTHRU);
00247 make_edge (bb_false, bb_join, EDGE_FALLTHRU);
00248
00249
00250
00251 if (dom_info_available_p (CDI_DOMINATORS))
00252 {
00253 set_immediate_dominator (CDI_DOMINATORS, bb_true, bb_cond);
00254 set_immediate_dominator (CDI_DOMINATORS, bb_false, bb_cond);
00255 }
00256
00257 rr = make_rename_temp (inner_type, NULL);
00258 ri = make_rename_temp (inner_type, NULL);
00259 }
00260
00261
00262
00263
00264
00265
00266
00267
00268 if (bb_true || integer_nonzerop (cond))
00269 {
00270 if (bb_true)
00271 {
00272 *bsi = bsi_last (bb_true);
00273 bsi_insert_after (bsi, build_empty_stmt (), BSI_NEW_STMT);
00274 }
00275
00276 ratio = gimplify_build2 (bsi, code, inner_type, br, bi);
00277
00278 t1 = gimplify_build2 (bsi, MULT_EXPR, inner_type, br, ratio);
00279 div = gimplify_build2 (bsi, PLUS_EXPR, inner_type, t1, bi);
00280
00281 t1 = gimplify_build2 (bsi, MULT_EXPR, inner_type, ar, ratio);
00282 tr = gimplify_build2 (bsi, PLUS_EXPR, inner_type, t1, ai);
00283
00284 t1 = gimplify_build2 (bsi, MULT_EXPR, inner_type, ai, ratio);
00285 ti = gimplify_build2 (bsi, MINUS_EXPR, inner_type, t1, ar);
00286
00287 tr = gimplify_build2 (bsi, code, inner_type, tr, div);
00288 ti = gimplify_build2 (bsi, code, inner_type, ti, div);
00289
00290 if (bb_true)
00291 {
00292 t1 = build (MODIFY_EXPR, inner_type, rr, tr);
00293 bsi_insert_before (bsi, t1, BSI_SAME_STMT);
00294 t1 = build (MODIFY_EXPR, inner_type, ri, ti);
00295 bsi_insert_before (bsi, t1, BSI_SAME_STMT);
00296 bsi_remove (bsi);
00297 }
00298 }
00299
00300
00301
00302
00303
00304
00305
00306
00307 if (bb_false || integer_zerop (cond))
00308 {
00309 if (bb_false)
00310 {
00311 *bsi = bsi_last (bb_false);
00312 bsi_insert_after (bsi, build_empty_stmt (), BSI_NEW_STMT);
00313 }
00314
00315 ratio = gimplify_build2 (bsi, code, inner_type, bi, br);
00316
00317 t1 = gimplify_build2 (bsi, MULT_EXPR, inner_type, bi, ratio);
00318 div = gimplify_build2 (bsi, PLUS_EXPR, inner_type, t1, br);
00319
00320 t1 = gimplify_build2 (bsi, MULT_EXPR, inner_type, ai, ratio);
00321 tr = gimplify_build2 (bsi, PLUS_EXPR, inner_type, t1, ar);
00322
00323 t1 = gimplify_build2 (bsi, MULT_EXPR, inner_type, ar, ratio);
00324 ti = gimplify_build2 (bsi, MINUS_EXPR, inner_type, ai, t1);
00325
00326 tr = gimplify_build2 (bsi, code, inner_type, tr, div);
00327 ti = gimplify_build2 (bsi, code, inner_type, ti, div);
00328
00329 if (bb_false)
00330 {
00331 t1 = build (MODIFY_EXPR, inner_type, rr, tr);
00332 bsi_insert_before (bsi, t1, BSI_SAME_STMT);
00333 t1 = build (MODIFY_EXPR, inner_type, ri, ti);
00334 bsi_insert_before (bsi, t1, BSI_SAME_STMT);
00335 bsi_remove (bsi);
00336 }
00337 }
00338
00339 if (bb_join)
00340 *bsi = bsi_start (bb_join);
00341 else
00342 rr = tr, ri = ti;
00343
00344 update_complex_assignment (bsi, rr, ri);
00345 }
00346
00347
00348
00349 static void
00350 expand_complex_division (block_stmt_iterator *bsi, tree inner_type,
00351 tree ar, tree ai, tree br, tree bi,
00352 enum tree_code code)
00353 {
00354 switch (flag_complex_method)
00355 {
00356 case 0:
00357
00358 expand_complex_div_straight (bsi, inner_type, ar, ai, br, bi, code);
00359 break;
00360
00361 case 2:
00362 if (SCALAR_FLOAT_TYPE_P (inner_type))
00363 {
00364 expand_complex_libcall (bsi, ar, ai, br, bi, code);
00365 return;
00366 }
00367
00368
00369 case 1:
00370
00371 expand_complex_div_wide (bsi, inner_type, ar, ai, br, bi, code);
00372 break;
00373
00374 default:
00375 gcc_unreachable ();
00376 }
00377 }
00378
00379
00380
00381
00382
00383 static void
00384 expand_complex_negation (block_stmt_iterator *bsi, tree inner_type,
00385 tree ar, tree ai)
00386 {
00387 tree rr, ri;
00388
00389 rr = gimplify_build1 (bsi, NEGATE_EXPR, inner_type, ar);
00390 ri = gimplify_build1 (bsi, NEGATE_EXPR, inner_type, ai);
00391
00392 update_complex_assignment (bsi, rr, ri);
00393 }
00394
00395
00396
00397
00398
00399 static void
00400 expand_complex_conjugate (block_stmt_iterator *bsi, tree inner_type,
00401 tree ar, tree ai)
00402 {
00403 tree ri;
00404
00405 ri = gimplify_build1 (bsi, NEGATE_EXPR, inner_type, ai);
00406
00407 update_complex_assignment (bsi, ar, ri);
00408 }
00409
00410
00411
00412 static void
00413 expand_complex_comparison (block_stmt_iterator *bsi, tree ar, tree ai,
00414 tree br, tree bi, enum tree_code code)
00415 {
00416 tree cr, ci, cc, stmt, expr, type;
00417
00418 cr = gimplify_build2 (bsi, code, boolean_type_node, ar, br);
00419 ci = gimplify_build2 (bsi, code, boolean_type_node, ai, bi);
00420 cc = gimplify_build2 (bsi,
00421 (code == EQ_EXPR ? TRUTH_AND_EXPR : TRUTH_OR_EXPR),
00422 boolean_type_node, cr, ci);
00423
00424 stmt = expr = bsi_stmt (*bsi);
00425
00426 switch (TREE_CODE (stmt))
00427 {
00428 case RETURN_EXPR:
00429 expr = TREE_OPERAND (stmt, 0);
00430
00431 case MODIFY_EXPR:
00432 type = TREE_TYPE (TREE_OPERAND (expr, 1));
00433 TREE_OPERAND (expr, 1) = fold_convert (type, cc);
00434 break;
00435 case COND_EXPR:
00436 TREE_OPERAND (stmt, 0) = cc;
00437 break;
00438 default:
00439 gcc_unreachable ();
00440 }
00441
00442 modify_stmt (stmt);
00443 }
00444
00445
00446
00447 static void
00448 expand_complex_operations_1 (block_stmt_iterator *bsi)
00449 {
00450 tree stmt = bsi_stmt (*bsi);
00451 tree rhs, type, inner_type;
00452 tree ac, ar, ai, bc, br, bi;
00453 enum tree_code code;
00454
00455 switch (TREE_CODE (stmt))
00456 {
00457 case RETURN_EXPR:
00458 stmt = TREE_OPERAND (stmt, 0);
00459 if (!stmt)
00460 return;
00461 if (TREE_CODE (stmt) != MODIFY_EXPR)
00462 return;
00463
00464
00465 case MODIFY_EXPR:
00466 rhs = TREE_OPERAND (stmt, 1);
00467 break;
00468
00469 case COND_EXPR:
00470 rhs = TREE_OPERAND (stmt, 0);
00471 break;
00472
00473 default:
00474 return;
00475 }
00476
00477 type = TREE_TYPE (rhs);
00478 code = TREE_CODE (rhs);
00479
00480
00481 switch (code)
00482 {
00483 case PLUS_EXPR:
00484 case MINUS_EXPR:
00485 case MULT_EXPR:
00486 case TRUNC_DIV_EXPR:
00487 case CEIL_DIV_EXPR:
00488 case FLOOR_DIV_EXPR:
00489 case ROUND_DIV_EXPR:
00490 case RDIV_EXPR:
00491 case NEGATE_EXPR:
00492 case CONJ_EXPR:
00493 if (TREE_CODE (type) != COMPLEX_TYPE)
00494 return;
00495 inner_type = TREE_TYPE (type);
00496 break;
00497
00498 case EQ_EXPR:
00499 case NE_EXPR:
00500 inner_type = TREE_TYPE (TREE_OPERAND (rhs, 1));
00501 if (TREE_CODE (inner_type) != COMPLEX_TYPE)
00502 return;
00503 break;
00504
00505 default:
00506 return;
00507 }
00508
00509
00510
00511 ac = TREE_OPERAND (rhs, 0);
00512 ar = extract_component (bsi, ac, 0);
00513 ai = extract_component (bsi, ac, 1);
00514
00515 if (TREE_CODE_CLASS (code) == tcc_unary)
00516 bc = br = bi = NULL;
00517 else
00518 {
00519 bc = TREE_OPERAND (rhs, 1);
00520 if (ac == bc)
00521 br = ar, bi = ai;
00522 else
00523 {
00524 br = extract_component (bsi, bc, 0);
00525 bi = extract_component (bsi, bc, 1);
00526 }
00527 }
00528
00529 switch (code)
00530 {
00531 case PLUS_EXPR:
00532 case MINUS_EXPR:
00533 expand_complex_addition (bsi, inner_type, ar, ai, br, bi, code);
00534 break;
00535
00536 case MULT_EXPR:
00537 expand_complex_multiplication (bsi, inner_type, ar, ai, br, bi);
00538 break;
00539
00540 case TRUNC_DIV_EXPR:
00541 case CEIL_DIV_EXPR:
00542 case FLOOR_DIV_EXPR:
00543 case ROUND_DIV_EXPR:
00544 case RDIV_EXPR:
00545 expand_complex_division (bsi, inner_type, ar, ai, br, bi, code);
00546 break;
00547
00548 case NEGATE_EXPR:
00549 expand_complex_negation (bsi, inner_type, ar, ai);
00550 break;
00551
00552 case CONJ_EXPR:
00553 expand_complex_conjugate (bsi, inner_type, ar, ai);
00554 break;
00555
00556 case EQ_EXPR:
00557 case NE_EXPR:
00558 expand_complex_comparison (bsi, ar, ai, br, bi, code);
00559 break;
00560
00561 default:
00562 gcc_unreachable ();
00563 }
00564 }
00565
00566
00567
00568 static tree
00569 build_replicated_const (tree type, tree inner_type, HOST_WIDE_INT value)
00570 {
00571 int width = tree_low_cst (TYPE_SIZE (inner_type), 1);
00572 int n = HOST_BITS_PER_WIDE_INT / width;
00573 unsigned HOST_WIDE_INT low, high, mask;
00574 tree ret;
00575
00576 gcc_assert (n);
00577
00578 if (width == HOST_BITS_PER_WIDE_INT)
00579 low = value;
00580 else
00581 {
00582 mask = ((HOST_WIDE_INT)1 << width) - 1;
00583 low = (unsigned HOST_WIDE_INT) ~0 / mask * (value & mask);
00584 }
00585
00586 if (TYPE_PRECISION (type) < HOST_BITS_PER_WIDE_INT)
00587 low &= ((HOST_WIDE_INT)1 << TYPE_PRECISION (type)) - 1, high = 0;
00588 else if (TYPE_PRECISION (type) == HOST_BITS_PER_WIDE_INT)
00589 high = 0;
00590 else if (TYPE_PRECISION (type) == 2 * HOST_BITS_PER_WIDE_INT)
00591 high = low;
00592 else
00593 gcc_unreachable ();
00594
00595 ret = build_int_cst_wide (type, low, high);
00596 return ret;
00597 }
00598
00599 static GTY(()) tree vector_inner_type;
00600 static GTY(()) tree vector_last_type;
00601 static GTY(()) int vector_last_nunits;
00602
00603
00604
00605 static tree
00606 build_word_mode_vector_type (int nunits)
00607 {
00608 if (!vector_inner_type)
00609 vector_inner_type = lang_hooks.types.type_for_mode (word_mode, 1);
00610 else if (vector_last_nunits == nunits)
00611 {
00612 gcc_assert (TREE_CODE (vector_last_type) == VECTOR_TYPE);
00613 return vector_last_type;
00614 }
00615
00616
00617
00618 vector_last_nunits = nunits;
00619 vector_last_type = type_hash_canon (nunits,
00620 build_vector_type (vector_inner_type,
00621 nunits));
00622 return vector_last_type;
00623 }
00624
00625 typedef tree (*elem_op_func) (block_stmt_iterator *,
00626 tree, tree, tree, tree, tree, enum tree_code);
00627
00628 static inline tree
00629 tree_vec_extract (block_stmt_iterator *bsi, tree type,
00630 tree t, tree bitsize, tree bitpos)
00631 {
00632 if (bitpos)
00633 return gimplify_build3 (bsi, BIT_FIELD_REF, type, t, bitsize, bitpos);
00634 else
00635 return gimplify_build1 (bsi, VIEW_CONVERT_EXPR, type, t);
00636 }
00637
00638 static tree
00639 do_unop (block_stmt_iterator *bsi, tree inner_type, tree a,
00640 tree b ATTRIBUTE_UNUSED, tree bitpos, tree bitsize,
00641 enum tree_code code)
00642 {
00643 a = tree_vec_extract (bsi, inner_type, a, bitsize, bitpos);
00644 return gimplify_build1 (bsi, code, inner_type, a);
00645 }
00646
00647 static tree
00648 do_binop (block_stmt_iterator *bsi, tree inner_type, tree a, tree b,
00649 tree bitpos, tree bitsize, enum tree_code code)
00650 {
00651 a = tree_vec_extract (bsi, inner_type, a, bitsize, bitpos);
00652 b = tree_vec_extract (bsi, inner_type, b, bitsize, bitpos);
00653 return gimplify_build2 (bsi, code, inner_type, a, b);
00654 }
00655
00656
00657
00658
00659
00660
00661
00662
00663
00664
00665
00666
00667
00668
00669 static tree
00670 do_plus_minus (block_stmt_iterator *bsi, tree word_type, tree a, tree b,
00671 tree bitpos ATTRIBUTE_UNUSED, tree bitsize ATTRIBUTE_UNUSED,
00672 enum tree_code code)
00673 {
00674 tree inner_type = TREE_TYPE (TREE_TYPE (a));
00675 unsigned HOST_WIDE_INT max;
00676 tree low_bits, high_bits, a_low, b_low, result_low, signs;
00677
00678 max = GET_MODE_MASK (TYPE_MODE (inner_type));
00679 low_bits = build_replicated_const (word_type, inner_type, max >> 1);
00680 high_bits = build_replicated_const (word_type, inner_type, max & ~(max >> 1));
00681
00682 a = tree_vec_extract (bsi, word_type, a, bitsize, bitpos);
00683 b = tree_vec_extract (bsi, word_type, b, bitsize, bitpos);
00684
00685 signs = gimplify_build2 (bsi, BIT_XOR_EXPR, word_type, a, b);
00686 b_low = gimplify_build2 (bsi, BIT_AND_EXPR, word_type, b, low_bits);
00687 if (code == PLUS_EXPR)
00688 a_low = gimplify_build2 (bsi, BIT_AND_EXPR, word_type, a, low_bits);
00689 else
00690 {
00691 a_low = gimplify_build2 (bsi, BIT_IOR_EXPR, word_type, a, high_bits);
00692 signs = gimplify_build1 (bsi, BIT_NOT_EXPR, word_type, signs);
00693 }
00694
00695 signs = gimplify_build2 (bsi, BIT_AND_EXPR, word_type, signs, high_bits);
00696 result_low = gimplify_build2 (bsi, code, word_type, a_low, b_low);
00697 return gimplify_build2 (bsi, BIT_XOR_EXPR, word_type, result_low, signs);
00698 }
00699
00700 static tree
00701 do_negate (block_stmt_iterator *bsi, tree word_type, tree b,
00702 tree unused ATTRIBUTE_UNUSED, tree bitpos ATTRIBUTE_UNUSED,
00703 tree bitsize ATTRIBUTE_UNUSED,
00704 enum tree_code code ATTRIBUTE_UNUSED)
00705 {
00706 tree inner_type = TREE_TYPE (TREE_TYPE (b));
00707 HOST_WIDE_INT max;
00708 tree low_bits, high_bits, b_low, result_low, signs;
00709
00710 max = GET_MODE_MASK (TYPE_MODE (inner_type));
00711 low_bits = build_replicated_const (word_type, inner_type, max >> 1);
00712 high_bits = build_replicated_const (word_type, inner_type, max & ~(max >> 1));
00713
00714 b = tree_vec_extract (bsi, word_type, b, bitsize, bitpos);
00715
00716 b_low = gimplify_build2 (bsi, BIT_AND_EXPR, word_type, b, low_bits);
00717 signs = gimplify_build1 (bsi, BIT_NOT_EXPR, word_type, b);
00718 signs = gimplify_build2 (bsi, BIT_AND_EXPR, word_type, signs, high_bits);
00719 result_low = gimplify_build2 (bsi, MINUS_EXPR, word_type, high_bits, b_low);
00720 return gimplify_build2 (bsi, BIT_XOR_EXPR, word_type, result_low, signs);
00721 }
00722
00723
00724
00725 static tree
00726 expand_vector_piecewise (block_stmt_iterator *bsi, elem_op_func f,
00727 tree type, tree inner_type,
00728 tree a, tree b, enum tree_code code)
00729 {
00730 tree head, *chain = &head;
00731 tree part_width = TYPE_SIZE (inner_type);
00732 tree index = bitsize_int (0);
00733 int nunits = TYPE_VECTOR_SUBPARTS (type);
00734 int delta = tree_low_cst (part_width, 1)
00735 / tree_low_cst (TYPE_SIZE (TREE_TYPE (type)), 1);
00736 int i;
00737
00738 for (i = 0; i < nunits;
00739 i += delta, index = int_const_binop (PLUS_EXPR, index, part_width, 0))
00740 {
00741 tree result = f (bsi, inner_type, a, b, index, part_width, code);
00742 *chain = tree_cons (NULL_TREE, result, NULL_TREE);
00743 chain = &TREE_CHAIN (*chain);
00744 }
00745
00746 return build1 (CONSTRUCTOR, type, head);
00747 }
00748
00749
00750
00751
00752 static tree
00753 expand_vector_parallel (block_stmt_iterator *bsi, elem_op_func f, tree type,
00754 tree a, tree b,
00755 enum tree_code code)
00756 {
00757 tree result, compute_type;
00758 enum machine_mode mode;
00759 int n_words = tree_low_cst (TYPE_SIZE_UNIT (type), 1) / UNITS_PER_WORD;
00760
00761
00762
00763
00764
00765 if (TYPE_MODE (TREE_TYPE (type)) == word_mode)
00766 return expand_vector_piecewise (bsi, f,
00767 type, TREE_TYPE (type),
00768 a, b, code);
00769 else if (n_words > 1)
00770 {
00771 tree word_type = build_word_mode_vector_type (n_words);
00772 result = expand_vector_piecewise (bsi, f,
00773 word_type, TREE_TYPE (word_type),
00774 a, b, code);
00775 result = gimplify_val (bsi, word_type, result);
00776 }
00777 else
00778 {
00779
00780 mode = mode_for_size (tree_low_cst (TYPE_SIZE (type), 1), MODE_INT, 0);
00781 compute_type = lang_hooks.types.type_for_mode (mode, 1);
00782 result = f (bsi, compute_type, a, b, NULL_TREE, NULL_TREE, code);
00783 }
00784
00785 return build1 (VIEW_CONVERT_EXPR, type, result);
00786 }
00787
00788
00789
00790
00791
00792
00793 static tree
00794 expand_vector_addition (block_stmt_iterator *bsi,
00795 elem_op_func f, elem_op_func f_parallel,
00796 tree type, tree a, tree b, enum tree_code code)
00797 {
00798 int parts_per_word = UNITS_PER_WORD
00799 / tree_low_cst (TYPE_SIZE_UNIT (TREE_TYPE (type)), 1);
00800
00801 if (INTEGRAL_TYPE_P (TREE_TYPE (type))
00802 && parts_per_word >= 4
00803 && TYPE_VECTOR_SUBPARTS (type) >= 4)
00804 return expand_vector_parallel (bsi, f_parallel,
00805 type, a, b, code);
00806 else
00807 return expand_vector_piecewise (bsi, f,
00808 type, TREE_TYPE (type),
00809 a, b, code);
00810 }
00811
00812
00813
00814 static tree
00815 type_for_widest_vector_mode (enum machine_mode inner_mode, optab op)
00816 {
00817 enum machine_mode best_mode = VOIDmode, mode;
00818 int best_nunits = 0;
00819
00820 if (GET_MODE_CLASS (inner_mode) == MODE_FLOAT)
00821 mode = MIN_MODE_VECTOR_FLOAT;
00822 else
00823 mode = MIN_MODE_VECTOR_INT;
00824
00825 for (; mode != VOIDmode; mode = GET_MODE_WIDER_MODE (mode))
00826 if (GET_MODE_INNER (mode) == inner_mode
00827 && GET_MODE_NUNITS (mode) > best_nunits
00828 && op->handlers[mode].insn_code != CODE_FOR_nothing)
00829 best_mode = mode, best_nunits = GET_MODE_NUNITS (mode);
00830
00831 if (best_mode == VOIDmode)
00832 return NULL_TREE;
00833 else
00834 return lang_hooks.types.type_for_mode (best_mode, 1);
00835 }
00836
00837
00838
00839 static void
00840 expand_vector_operations_1 (block_stmt_iterator *bsi)
00841 {
00842 tree stmt = bsi_stmt (*bsi);
00843 tree *p_rhs, rhs, type, compute_type;
00844 enum tree_code code;
00845 enum machine_mode compute_mode;
00846 optab op;
00847
00848 switch (TREE_CODE (stmt))
00849 {
00850 case RETURN_EXPR:
00851 stmt = TREE_OPERAND (stmt, 0);
00852 if (!stmt || TREE_CODE (stmt) != MODIFY_EXPR)
00853 return;
00854
00855
00856
00857 case MODIFY_EXPR:
00858 p_rhs = &TREE_OPERAND (stmt, 1);
00859 rhs = *p_rhs;
00860 break;
00861
00862 default:
00863 return;
00864 }
00865
00866 type = TREE_TYPE (rhs);
00867 if (TREE_CODE (type) != VECTOR_TYPE)
00868 return;
00869
00870 code = TREE_CODE (rhs);
00871 if (TREE_CODE_CLASS (code) != tcc_unary
00872 && TREE_CODE_CLASS (code) != tcc_binary)
00873 return;
00874
00875 if (code == NOP_EXPR || code == VIEW_CONVERT_EXPR)
00876 return;
00877
00878 gcc_assert (code != CONVERT_EXPR);
00879 op = optab_for_tree_code (code, type);
00880
00881
00882
00883
00884 if (op == NULL
00885 && code == NEGATE_EXPR
00886 && INTEGRAL_TYPE_P (TREE_TYPE (type)))
00887 op = optab_for_tree_code (MINUS_EXPR, type);
00888
00889
00890 compute_type = type;
00891 if (TYPE_MODE (type) == BLKmode && op)
00892 {
00893 tree vector_compute_type
00894 = type_for_widest_vector_mode (TYPE_MODE (TREE_TYPE (type)), op);
00895 if (vector_compute_type != NULL_TREE)
00896 compute_type = vector_compute_type;
00897 }
00898
00899 compute_mode = TYPE_MODE (compute_type);
00900
00901
00902
00903
00904 if (compute_type == type)
00905 {
00906 if ((GET_MODE_CLASS (compute_mode) == MODE_VECTOR_INT
00907 || GET_MODE_CLASS (compute_mode) == MODE_VECTOR_FLOAT)
00908 && op != NULL
00909 && op->handlers[compute_mode].insn_code != CODE_FOR_nothing)
00910 return;
00911 else
00912 {
00913
00914 compute_type = TREE_TYPE (type);
00915 compute_mode = TYPE_MODE (compute_type);
00916 }
00917 }
00918
00919
00920
00921
00922 if (GET_MODE_CLASS (compute_mode) != MODE_VECTOR_INT
00923 && GET_MODE_CLASS (compute_mode) != MODE_VECTOR_FLOAT)
00924 switch (code)
00925 {
00926 case PLUS_EXPR:
00927 case MINUS_EXPR:
00928 if (TYPE_TRAP_SIGNED (type))
00929 break;
00930
00931 *p_rhs = expand_vector_addition (bsi, do_binop, do_plus_minus, type,
00932 TREE_OPERAND (rhs, 0),
00933 TREE_OPERAND (rhs, 1), code);
00934 modify_stmt (bsi_stmt (*bsi));
00935 return;
00936
00937 case NEGATE_EXPR:
00938 if (TYPE_TRAP_SIGNED (type))
00939 break;
00940
00941 *p_rhs = expand_vector_addition (bsi, do_unop, do_negate, type,
00942 TREE_OPERAND (rhs, 0),
00943 NULL_TREE, code);
00944 modify_stmt (bsi_stmt (*bsi));
00945 return;
00946
00947 case BIT_AND_EXPR:
00948 case BIT_IOR_EXPR:
00949 case BIT_XOR_EXPR:
00950 *p_rhs = expand_vector_parallel (bsi, do_binop, type,
00951 TREE_OPERAND (rhs, 0),
00952 TREE_OPERAND (rhs, 1), code);
00953 modify_stmt (bsi_stmt (*bsi));
00954 return;
00955
00956 case BIT_NOT_EXPR:
00957 *p_rhs = expand_vector_parallel (bsi, do_unop, type,
00958 TREE_OPERAND (rhs, 0),
00959 NULL_TREE, code);
00960 modify_stmt (bsi_stmt (*bsi));
00961 return;
00962
00963 default:
00964 break;
00965 }
00966
00967 if (TREE_CODE_CLASS (code) == tcc_unary)
00968 *p_rhs = expand_vector_piecewise (bsi, do_unop, type, compute_type,
00969 TREE_OPERAND (rhs, 0),
00970 NULL_TREE, code);
00971 else
00972 *p_rhs = expand_vector_piecewise (bsi, do_binop, type, compute_type,
00973 TREE_OPERAND (rhs, 0),
00974 TREE_OPERAND (rhs, 1), code);
00975
00976 modify_stmt (bsi_stmt (*bsi));
00977 }
00978
00979 static void
00980 expand_vector_operations (void)
00981 {
00982 block_stmt_iterator bsi;
00983 basic_block bb;
00984
00985 FOR_EACH_BB (bb)
00986 {
00987 for (bsi = bsi_start (bb); !bsi_end_p (bsi); bsi_next (&bsi))
00988 expand_vector_operations_1 (&bsi);
00989 }
00990 }
00991
00992 static void
00993 tree_lower_operations (void)
00994 {
00995 int old_last_basic_block = last_basic_block;
00996 block_stmt_iterator bsi;
00997 basic_block bb;
00998
00999 FOR_EACH_BB (bb)
01000 {
01001 if (bb->index >= old_last_basic_block)
01002 continue;
01003 for (bsi = bsi_start (bb); !bsi_end_p (bsi); bsi_next (&bsi))
01004 {
01005 expand_complex_operations_1 (&bsi);
01006 expand_vector_operations_1 (&bsi);
01007 }
01008 }
01009 }
01010
01011
01012 struct tree_opt_pass pass_lower_vector_ssa =
01013 {
01014 "vector",
01015 NULL,
01016 expand_vector_operations,
01017 NULL,
01018 NULL,
01019 0,
01020 0,
01021 PROP_cfg,
01022 0,
01023 0,
01024 0,
01025 TODO_dump_func | TODO_rename_vars
01026 | TODO_ggc_collect | TODO_verify_ssa
01027 | TODO_verify_stmts | TODO_verify_flow,
01028 0
01029 };
01030
01031 struct tree_opt_pass pass_pre_expand =
01032 {
01033 "oplower",
01034 0,
01035 tree_lower_operations,
01036 NULL,
01037 NULL,
01038 0,
01039 0,
01040 PROP_cfg,
01041 0,
01042 0,
01043 0,
01044 TODO_dump_func | TODO_ggc_collect
01045 | TODO_verify_stmts,
01046 0
01047 };
01048
01049 #include "gt-tree-complex.h"