Mercurial > hg > CbC > CbC_gcc
comparison gcc/tree-vect-generic.c @ 67:f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
author | nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp> |
---|---|
date | Tue, 22 Mar 2011 17:18:12 +0900 |
parents | b7f97abdc517 |
children | 04ced10e8804 |
comparison
equal
deleted
inserted
replaced
65:65488c3d617d | 67:f6334be47118 |
---|---|
1 /* Lower vector operations to scalar operations. | 1 /* Lower vector operations to scalar operations. |
2 Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009 | 2 Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010 |
3 Free Software Foundation, Inc. | 3 Free Software Foundation, Inc. |
4 | 4 |
5 This file is part of GCC. | 5 This file is part of GCC. |
6 | 6 |
7 GCC is free software; you can redistribute it and/or modify it | 7 GCC is free software; you can redistribute it and/or modify it |
21 #include "config.h" | 21 #include "config.h" |
22 #include "system.h" | 22 #include "system.h" |
23 #include "coretypes.h" | 23 #include "coretypes.h" |
24 #include "tree.h" | 24 #include "tree.h" |
25 #include "tm.h" | 25 #include "tm.h" |
26 #include "expr.h" | |
27 #include "insn-codes.h" | |
28 #include "diagnostic.h" | |
29 #include "optabs.h" | |
30 #include "machmode.h" | |
31 #include "langhooks.h" | 26 #include "langhooks.h" |
32 #include "tree-flow.h" | 27 #include "tree-flow.h" |
33 #include "gimple.h" | 28 #include "gimple.h" |
34 #include "tree-iterator.h" | 29 #include "tree-iterator.h" |
35 #include "tree-pass.h" | 30 #include "tree-pass.h" |
36 #include "flags.h" | 31 #include "flags.h" |
37 #include "ggc.h" | 32 #include "ggc.h" |
38 | 33 |
34 /* Need to include rtl.h, expr.h, etc. for optabs. */ | |
35 #include "expr.h" | |
36 #include "optabs.h" | |
39 | 37 |
40 /* Build a constant of type TYPE, made of VALUE's bits replicated | 38 /* Build a constant of type TYPE, made of VALUE's bits replicated |
41 every TYPE_SIZE (INNER_TYPE) bits to fit TYPE's precision. */ | 39 every TYPE_SIZE (INNER_TYPE) bits to fit TYPE's precision. */ |
42 static tree | 40 static tree |
43 build_replicated_const (tree type, tree inner_type, HOST_WIDE_INT value) | 41 build_replicated_const (tree type, tree inner_type, HOST_WIDE_INT value) |
282 type, a, b, code); | 280 type, a, b, code); |
283 else | 281 else |
284 return expand_vector_piecewise (gsi, f, | 282 return expand_vector_piecewise (gsi, f, |
285 type, TREE_TYPE (type), | 283 type, TREE_TYPE (type), |
286 a, b, code); | 284 a, b, code); |
285 } | |
286 | |
287 /* Check if vector VEC consists of all the equal elements and | |
288 that the number of elements corresponds to the type of VEC. | |
289 The function returns first element of the vector | |
290 or NULL_TREE if the vector is not uniform. */ | |
291 static tree | |
292 uniform_vector_p (tree vec) | |
293 { | |
294 tree first, t, els; | |
295 unsigned i; | |
296 | |
297 if (vec == NULL_TREE) | |
298 return NULL_TREE; | |
299 | |
300 if (TREE_CODE (vec) == VECTOR_CST) | |
301 { | |
302 els = TREE_VECTOR_CST_ELTS (vec); | |
303 first = TREE_VALUE (els); | |
304 els = TREE_CHAIN (els); | |
305 | |
306 for (t = els; t; t = TREE_CHAIN (t)) | |
307 if (!operand_equal_p (first, TREE_VALUE (t), 0)) | |
308 return NULL_TREE; | |
309 | |
310 return first; | |
311 } | |
312 | |
313 else if (TREE_CODE (vec) == CONSTRUCTOR) | |
314 { | |
315 first = error_mark_node; | |
316 | |
317 FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (vec), i, t) | |
318 { | |
319 if (i == 0) | |
320 { | |
321 first = t; | |
322 continue; | |
323 } | |
324 if (!operand_equal_p (first, t, 0)) | |
325 return NULL_TREE; | |
326 } | |
327 if (i != TYPE_VECTOR_SUBPARTS (TREE_TYPE (vec))) | |
328 return NULL_TREE; | |
329 | |
330 return first; | |
331 } | |
332 | |
333 return NULL_TREE; | |
287 } | 334 } |
288 | 335 |
289 static tree | 336 static tree |
290 expand_vector_operation (gimple_stmt_iterator *gsi, tree type, tree compute_type, | 337 expand_vector_operation (gimple_stmt_iterator *gsi, tree type, tree compute_type, |
291 gimple assign, enum tree_code code) | 338 gimple assign, enum tree_code code) |
368 mode = MIN_MODE_VECTOR_INT; | 415 mode = MIN_MODE_VECTOR_INT; |
369 | 416 |
370 for (; mode != VOIDmode; mode = GET_MODE_WIDER_MODE (mode)) | 417 for (; mode != VOIDmode; mode = GET_MODE_WIDER_MODE (mode)) |
371 if (GET_MODE_INNER (mode) == inner_mode | 418 if (GET_MODE_INNER (mode) == inner_mode |
372 && GET_MODE_NUNITS (mode) > best_nunits | 419 && GET_MODE_NUNITS (mode) > best_nunits |
373 && optab_handler (op, mode)->insn_code != CODE_FOR_nothing) | 420 && optab_handler (op, mode) != CODE_FOR_nothing) |
374 best_mode = mode, best_nunits = GET_MODE_NUNITS (mode); | 421 best_mode = mode, best_nunits = GET_MODE_NUNITS (mode); |
375 | 422 |
376 if (best_mode == VOIDmode) | 423 if (best_mode == VOIDmode) |
377 return NULL_TREE; | 424 return NULL_TREE; |
378 else | 425 else |
392 { | 439 { |
393 gimple stmt = gsi_stmt (*gsi); | 440 gimple stmt = gsi_stmt (*gsi); |
394 tree lhs, rhs1, rhs2 = NULL, type, compute_type; | 441 tree lhs, rhs1, rhs2 = NULL, type, compute_type; |
395 enum tree_code code; | 442 enum tree_code code; |
396 enum machine_mode compute_mode; | 443 enum machine_mode compute_mode; |
397 optab op; | 444 optab op = NULL; |
398 enum gimple_rhs_class rhs_class; | 445 enum gimple_rhs_class rhs_class; |
399 tree new_rhs; | 446 tree new_rhs; |
400 | 447 |
401 if (gimple_code (stmt) != GIMPLE_ASSIGN) | 448 if (gimple_code (stmt) != GIMPLE_ASSIGN) |
402 return; | 449 return; |
434 if (code == LSHIFT_EXPR | 481 if (code == LSHIFT_EXPR |
435 || code == RSHIFT_EXPR | 482 || code == RSHIFT_EXPR |
436 || code == LROTATE_EXPR | 483 || code == LROTATE_EXPR |
437 || code == RROTATE_EXPR) | 484 || code == RROTATE_EXPR) |
438 { | 485 { |
439 /* If the 2nd argument is vector, we need a vector/vector shift */ | 486 bool vector_scalar_shift; |
487 op = optab_for_tree_code (code, type, optab_scalar); | |
488 | |
489 /* Vector/Scalar shift is supported. */ | |
490 vector_scalar_shift = (op && (optab_handler (op, TYPE_MODE (type)) | |
491 != CODE_FOR_nothing)); | |
492 | |
493 /* If the 2nd argument is vector, we need a vector/vector shift. | |
494 Except all the elements in the second vector are the same. */ | |
440 if (VECTOR_MODE_P (TYPE_MODE (TREE_TYPE (rhs2)))) | 495 if (VECTOR_MODE_P (TYPE_MODE (TREE_TYPE (rhs2)))) |
441 op = optab_for_tree_code (code, type, optab_vector); | 496 { |
442 else | 497 tree first; |
498 gimple def_stmt; | |
499 | |
500 /* Check whether we have vector <op> {x,x,x,x} where x | |
501 could be a scalar variable or a constant. Transform | |
502 vector <op> {x,x,x,x} ==> vector <op> scalar. */ | |
503 if (vector_scalar_shift | |
504 && ((TREE_CODE (rhs2) == VECTOR_CST | |
505 && (first = uniform_vector_p (rhs2)) != NULL_TREE) | |
506 || (TREE_CODE (rhs2) == SSA_NAME | |
507 && (def_stmt = SSA_NAME_DEF_STMT (rhs2)) | |
508 && gimple_assign_single_p (def_stmt) | |
509 && (first = uniform_vector_p | |
510 (gimple_assign_rhs1 (def_stmt))) != NULL_TREE))) | |
511 { | |
512 gimple_assign_set_rhs2 (stmt, first); | |
513 update_stmt (stmt); | |
514 rhs2 = first; | |
515 } | |
516 else | |
517 op = optab_for_tree_code (code, type, optab_vector); | |
518 } | |
519 | |
520 /* Try for a vector/scalar shift, and if we don't have one, see if we | |
521 have a vector/vector shift */ | |
522 else if (!vector_scalar_shift) | |
443 { | 523 { |
444 /* Try for a vector/scalar shift, and if we don't have one, see if we | 524 op = optab_for_tree_code (code, type, optab_vector); |
445 have a vector/vector shift */ | 525 |
446 op = optab_for_tree_code (code, type, optab_scalar); | 526 if (op && (optab_handler (op, TYPE_MODE (type)) |
447 if (!op | 527 != CODE_FOR_nothing)) |
448 || (op->handlers[(int) TYPE_MODE (type)].insn_code | 528 { |
449 == CODE_FOR_nothing)) | 529 /* Transform vector <op> scalar => vector <op> {x,x,x,x}. */ |
450 op = optab_for_tree_code (code, type, optab_vector); | 530 int n_parts = TYPE_VECTOR_SUBPARTS (type); |
531 int part_size = tree_low_cst (TYPE_SIZE (TREE_TYPE (type)), 1); | |
532 tree part_type = lang_hooks.types.type_for_size (part_size, 1); | |
533 tree vect_type = build_vector_type (part_type, n_parts); | |
534 | |
535 rhs2 = fold_convert (part_type, rhs2); | |
536 rhs2 = build_vector_from_val (vect_type, rhs2); | |
537 gimple_assign_set_rhs2 (stmt, rhs2); | |
538 update_stmt (stmt); | |
539 } | |
451 } | 540 } |
452 } | 541 } |
453 else | 542 else |
454 op = optab_for_tree_code (code, type, optab_default); | 543 op = optab_for_tree_code (code, type, optab_default); |
455 | 544 |
498 || GET_MODE_CLASS (compute_mode) == MODE_VECTOR_FRACT | 587 || GET_MODE_CLASS (compute_mode) == MODE_VECTOR_FRACT |
499 || GET_MODE_CLASS (compute_mode) == MODE_VECTOR_UFRACT | 588 || GET_MODE_CLASS (compute_mode) == MODE_VECTOR_UFRACT |
500 || GET_MODE_CLASS (compute_mode) == MODE_VECTOR_ACCUM | 589 || GET_MODE_CLASS (compute_mode) == MODE_VECTOR_ACCUM |
501 || GET_MODE_CLASS (compute_mode) == MODE_VECTOR_UACCUM) | 590 || GET_MODE_CLASS (compute_mode) == MODE_VECTOR_UACCUM) |
502 && op != NULL | 591 && op != NULL |
503 && optab_handler (op, compute_mode)->insn_code != CODE_FOR_nothing) | 592 && optab_handler (op, compute_mode) != CODE_FOR_nothing) |
504 return; | 593 return; |
505 else | 594 else |
506 /* There is no operation in hardware, so fall back to scalars. */ | 595 /* There is no operation in hardware, so fall back to scalars. */ |
507 compute_type = TREE_TYPE (type); | 596 compute_type = TREE_TYPE (type); |
508 } | 597 } |
515 | 604 |
516 /* NOTE: We should avoid using gimple_assign_set_rhs_from_tree. One | 605 /* NOTE: We should avoid using gimple_assign_set_rhs_from_tree. One |
517 way to do it is change expand_vector_operation and its callees to | 606 way to do it is change expand_vector_operation and its callees to |
518 return a tree_code, RHS1 and RHS2 instead of a tree. */ | 607 return a tree_code, RHS1 and RHS2 instead of a tree. */ |
519 gimple_assign_set_rhs_from_tree (gsi, new_rhs); | 608 gimple_assign_set_rhs_from_tree (gsi, new_rhs); |
520 | 609 update_stmt (gsi_stmt (*gsi)); |
521 gimple_set_modified (gsi_stmt (*gsi), true); | |
522 } | 610 } |
523 | 611 |
524 /* Use this to lower vector operations introduced by the vectorizer, | 612 /* Use this to lower vector operations introduced by the vectorizer, |
525 if it may need the bit-twiddling tricks implemented in this file. */ | 613 if it may need the bit-twiddling tricks implemented in this file. */ |
526 | 614 |
533 static unsigned int | 621 static unsigned int |
534 expand_vector_operations (void) | 622 expand_vector_operations (void) |
535 { | 623 { |
536 gimple_stmt_iterator gsi; | 624 gimple_stmt_iterator gsi; |
537 basic_block bb; | 625 basic_block bb; |
626 bool cfg_changed = false; | |
538 | 627 |
539 FOR_EACH_BB (bb) | 628 FOR_EACH_BB (bb) |
540 { | 629 { |
541 for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi)) | 630 for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi)) |
542 { | 631 { |
543 expand_vector_operations_1 (&gsi); | 632 expand_vector_operations_1 (&gsi); |
544 update_stmt_if_modified (gsi_stmt (gsi)); | 633 /* ??? If we do not cleanup EH then we will ICE in |
634 verification. But in reality we have created wrong-code | |
635 as we did not properly transition EH info and edges to | |
636 the piecewise computations. */ | |
637 if (maybe_clean_eh_stmt (gsi_stmt (gsi)) | |
638 && gimple_purge_dead_eh_edges (bb)) | |
639 cfg_changed = true; | |
545 } | 640 } |
546 } | 641 } |
547 return 0; | 642 |
643 return cfg_changed ? TODO_cleanup_cfg : 0; | |
548 } | 644 } |
549 | 645 |
550 struct gimple_opt_pass pass_lower_vector = | 646 struct gimple_opt_pass pass_lower_vector = |
551 { | 647 { |
552 { | 648 { |
560 TV_NONE, /* tv_id */ | 656 TV_NONE, /* tv_id */ |
561 PROP_cfg, /* properties_required */ | 657 PROP_cfg, /* properties_required */ |
562 0, /* properties_provided */ | 658 0, /* properties_provided */ |
563 0, /* properties_destroyed */ | 659 0, /* properties_destroyed */ |
564 0, /* todo_flags_start */ | 660 0, /* todo_flags_start */ |
565 TODO_dump_func | TODO_ggc_collect | 661 TODO_dump_func | TODO_update_ssa /* todo_flags_finish */ |
566 | TODO_verify_stmts /* todo_flags_finish */ | 662 | TODO_verify_ssa |
663 | TODO_verify_stmts | TODO_verify_flow | |
567 } | 664 } |
568 }; | 665 }; |
569 | 666 |
570 struct gimple_opt_pass pass_lower_vector_ssa = | 667 struct gimple_opt_pass pass_lower_vector_ssa = |
571 { | 668 { |