Mercurial > hg > CbC > CbC_gcc
comparison gcc/tree-ssa-loop-ivopts.c @ 131:84e7813d76e9
gcc-8.2
author | mir3636 |
---|---|
date | Thu, 25 Oct 2018 07:37:49 +0900 |
parents | 04ced10e8804 |
children | 1830386684a0 |
comparison
equal
deleted
inserted
replaced
111:04ced10e8804 | 131:84e7813d76e9 |
---|---|
1 /* Induction variable optimizations. | 1 /* Induction variable optimizations. |
2 Copyright (C) 2003-2017 Free Software Foundation, Inc. | 2 Copyright (C) 2003-2018 Free Software Foundation, Inc. |
3 | 3 |
4 This file is part of GCC. | 4 This file is part of GCC. |
5 | 5 |
6 GCC is free software; you can redistribute it and/or modify it | 6 GCC is free software; you can redistribute it and/or modify it |
7 under the terms of the GNU General Public License as published by the | 7 under the terms of the GNU General Public License as published by the |
164 | 164 |
165 /* Types of uses. */ | 165 /* Types of uses. */ |
166 enum use_type | 166 enum use_type |
167 { | 167 { |
168 USE_NONLINEAR_EXPR, /* Use in a nonlinear expression. */ | 168 USE_NONLINEAR_EXPR, /* Use in a nonlinear expression. */ |
169 USE_ADDRESS, /* Use in an address. */ | 169 USE_REF_ADDRESS, /* Use is an address for an explicit memory |
170 reference. */ | |
171 USE_PTR_ADDRESS, /* Use is a pointer argument to a function in | |
172 cases where the expansion of the function | |
173 will turn the argument into a normal address. */ | |
170 USE_COMPARE /* Use is a compare. */ | 174 USE_COMPARE /* Use is a compare. */ |
171 }; | 175 }; |
172 | 176 |
173 /* Cost of a computation. */ | 177 /* Cost of a computation. */ |
174 struct comp_cost | 178 struct comp_cost |
360 struct iv_use | 364 struct iv_use |
361 { | 365 { |
362 unsigned id; /* The id of the use. */ | 366 unsigned id; /* The id of the use. */ |
363 unsigned group_id; /* The group id the use belongs to. */ | 367 unsigned group_id; /* The group id the use belongs to. */ |
364 enum use_type type; /* Type of the use. */ | 368 enum use_type type; /* Type of the use. */ |
369 tree mem_type; /* The memory type to use when testing whether an | |
370 address is legitimate, and what the address's | |
371 cost is. */ | |
365 struct iv *iv; /* The induction variable it is based on. */ | 372 struct iv *iv; /* The induction variable it is based on. */ |
366 gimple *stmt; /* Statement in that it occurs. */ | 373 gimple *stmt; /* Statement in that it occurs. */ |
367 tree *op_p; /* The place where it occurs. */ | 374 tree *op_p; /* The place where it occurs. */ |
368 | 375 |
369 tree addr_base; /* Base address with const offset stripped. */ | 376 tree addr_base; /* Base address with const offset stripped. */ |
370 unsigned HOST_WIDE_INT addr_offset; | 377 poly_uint64_pod addr_offset; |
371 /* Const offset stripped from base address. */ | 378 /* Const offset stripped from base address. */ |
372 }; | 379 }; |
373 | 380 |
374 /* Group of uses. */ | 381 /* Group of uses. */ |
375 struct iv_group | 382 struct iv_group |
504 { | 511 { |
505 static inline hashval_t hash (const iv_inv_expr_ent *); | 512 static inline hashval_t hash (const iv_inv_expr_ent *); |
506 static inline bool equal (const iv_inv_expr_ent *, const iv_inv_expr_ent *); | 513 static inline bool equal (const iv_inv_expr_ent *, const iv_inv_expr_ent *); |
507 }; | 514 }; |
508 | 515 |
516 /* Return true if uses of type TYPE represent some form of address. */ | |
517 | |
518 inline bool | |
519 address_p (use_type type) | |
520 { | |
521 return type == USE_REF_ADDRESS || type == USE_PTR_ADDRESS; | |
522 } | |
523 | |
509 /* Hash function for loop invariant expressions. */ | 524 /* Hash function for loop invariant expressions. */ |
510 | 525 |
511 inline hashval_t | 526 inline hashval_t |
512 iv_inv_expr_hasher::hash (const iv_inv_expr_ent *expr) | 527 iv_inv_expr_hasher::hash (const iv_inv_expr_ent *expr) |
513 { | 528 { |
766 { | 781 { |
767 group = data->vgroups[i]; | 782 group = data->vgroups[i]; |
768 fprintf (file, "Group %d:\n", group->id); | 783 fprintf (file, "Group %d:\n", group->id); |
769 if (group->type == USE_NONLINEAR_EXPR) | 784 if (group->type == USE_NONLINEAR_EXPR) |
770 fprintf (file, " Type:\tGENERIC\n"); | 785 fprintf (file, " Type:\tGENERIC\n"); |
771 else if (group->type == USE_ADDRESS) | 786 else if (group->type == USE_REF_ADDRESS) |
772 fprintf (file, " Type:\tADDRESS\n"); | 787 fprintf (file, " Type:\tREFERENCE ADDRESS\n"); |
788 else if (group->type == USE_PTR_ADDRESS) | |
789 fprintf (file, " Type:\tPOINTER ARGUMENT ADDRESS\n"); | |
773 else | 790 else |
774 { | 791 { |
775 gcc_assert (group->type == USE_COMPARE); | 792 gcc_assert (group->type == USE_COMPARE); |
776 fprintf (file, " Type:\tCOMPARE\n"); | 793 fprintf (file, " Type:\tCOMPARE\n"); |
777 } | 794 } |
965 if (!expr) | 982 if (!expr) |
966 return false; | 983 return false; |
967 | 984 |
968 code = TREE_CODE (expr); | 985 code = TREE_CODE (expr); |
969 codeclass = TREE_CODE_CLASS (code); | 986 codeclass = TREE_CODE_CLASS (code); |
987 | |
988 if (code == CALL_EXPR) | |
989 { | |
990 tree arg; | |
991 call_expr_arg_iterator iter; | |
992 FOR_EACH_CALL_EXPR_ARG (arg, iter, expr) | |
993 if (contains_abnormal_ssa_name_p (arg)) | |
994 return true; | |
995 return false; | |
996 } | |
970 | 997 |
971 if (code == SSA_NAME) | 998 if (code == SSA_NAME) |
972 return SSA_NAME_OCCURS_IN_ABNORMAL_PHI (expr) != 0; | 999 return SSA_NAME_OCCURS_IN_ABNORMAL_PHI (expr) != 0; |
973 | 1000 |
974 if (code == INTEGER_CST | 1001 if (code == INTEGER_CST |
1125 case MINUS_EXPR: | 1152 case MINUS_EXPR: |
1126 /* Pointer addition is done solely using POINTER_PLUS_EXPR. */ | 1153 /* Pointer addition is done solely using POINTER_PLUS_EXPR. */ |
1127 gcc_unreachable (); | 1154 gcc_unreachable (); |
1128 | 1155 |
1129 default: | 1156 default: |
1157 if (POLY_INT_CST_P (expr)) | |
1158 return NULL_TREE; | |
1130 return fold_convert (ptr_type_node, expr); | 1159 return fold_convert (ptr_type_node, expr); |
1131 } | 1160 } |
1132 } | 1161 } |
1133 | 1162 |
1134 /* Return true if address expression with non-DECL_P operand appears | 1163 /* Return true if address expression with non-DECL_P operand appears |
1409 return false; | 1438 return false; |
1410 | 1439 |
1411 /* If STMT could throw, then do not consider STMT as defining a GIV. | 1440 /* If STMT could throw, then do not consider STMT as defining a GIV. |
1412 While this will suppress optimizations, we can not safely delete this | 1441 While this will suppress optimizations, we can not safely delete this |
1413 GIV and associated statements, even if it appears it is not used. */ | 1442 GIV and associated statements, even if it appears it is not used. */ |
1414 if (stmt_could_throw_p (stmt)) | 1443 if (stmt_could_throw_p (cfun, stmt)) |
1415 return false; | 1444 return false; |
1416 | 1445 |
1417 return true; | 1446 return true; |
1418 } | 1447 } |
1419 | 1448 |
1498 return true; | 1527 return true; |
1499 } | 1528 } |
1500 | 1529 |
1501 /* Records a use of TYPE at *USE_P in STMT whose value is IV in GROUP. | 1530 /* Records a use of TYPE at *USE_P in STMT whose value is IV in GROUP. |
1502 For address type use, ADDR_BASE is the stripped IV base, ADDR_OFFSET | 1531 For address type use, ADDR_BASE is the stripped IV base, ADDR_OFFSET |
1503 is the const offset stripped from IV base; for other types use, both | 1532 is the const offset stripped from IV base and MEM_TYPE is the type |
1504 are zero by default. */ | 1533 of the memory being addressed. For uses of other types, ADDR_BASE |
1534 and ADDR_OFFSET are zero by default and MEM_TYPE is NULL_TREE. */ | |
1505 | 1535 |
1506 static struct iv_use * | 1536 static struct iv_use * |
1507 record_use (struct iv_group *group, tree *use_p, struct iv *iv, | 1537 record_use (struct iv_group *group, tree *use_p, struct iv *iv, |
1508 gimple *stmt, enum use_type type, tree addr_base, | 1538 gimple *stmt, enum use_type type, tree mem_type, |
1509 unsigned HOST_WIDE_INT addr_offset) | 1539 tree addr_base, poly_uint64 addr_offset) |
1510 { | 1540 { |
1511 struct iv_use *use = XCNEW (struct iv_use); | 1541 struct iv_use *use = XCNEW (struct iv_use); |
1512 | 1542 |
1513 use->id = group->vuses.length (); | 1543 use->id = group->vuses.length (); |
1514 use->group_id = group->id; | 1544 use->group_id = group->id; |
1515 use->type = type; | 1545 use->type = type; |
1546 use->mem_type = mem_type; | |
1516 use->iv = iv; | 1547 use->iv = iv; |
1517 use->stmt = stmt; | 1548 use->stmt = stmt; |
1518 use->op_p = use_p; | 1549 use->op_p = use_p; |
1519 use->addr_base = addr_base; | 1550 use->addr_base = addr_base; |
1520 use->addr_offset = addr_offset; | 1551 use->addr_offset = addr_offset; |
1565 data->vgroups.safe_push (group); | 1596 data->vgroups.safe_push (group); |
1566 return group; | 1597 return group; |
1567 } | 1598 } |
1568 | 1599 |
1569 /* Record a use of TYPE at *USE_P in STMT whose value is IV in a group. | 1600 /* Record a use of TYPE at *USE_P in STMT whose value is IV in a group. |
1570 New group will be created if there is no existing group for the use. */ | 1601 New group will be created if there is no existing group for the use. |
1602 MEM_TYPE is the type of memory being addressed, or NULL if this | |
1603 isn't an address reference. */ | |
1571 | 1604 |
1572 static struct iv_use * | 1605 static struct iv_use * |
1573 record_group_use (struct ivopts_data *data, tree *use_p, | 1606 record_group_use (struct ivopts_data *data, tree *use_p, |
1574 struct iv *iv, gimple *stmt, enum use_type type) | 1607 struct iv *iv, gimple *stmt, enum use_type type, |
1608 tree mem_type) | |
1575 { | 1609 { |
1576 tree addr_base = NULL; | 1610 tree addr_base = NULL; |
1577 struct iv_group *group = NULL; | 1611 struct iv_group *group = NULL; |
1578 unsigned HOST_WIDE_INT addr_offset = 0; | 1612 poly_uint64 addr_offset = 0; |
1579 | 1613 |
1580 /* Record non address type use in a new group. */ | 1614 /* Record non address type use in a new group. */ |
1581 if (type == USE_ADDRESS && iv->base_object) | 1615 if (address_p (type)) |
1582 { | 1616 { |
1583 unsigned int i; | 1617 unsigned int i; |
1584 | 1618 |
1585 addr_base = strip_offset (iv->base, &addr_offset); | 1619 addr_base = strip_offset (iv->base, &addr_offset); |
1586 for (i = 0; i < data->vgroups.length (); i++) | 1620 for (i = 0; i < data->vgroups.length (); i++) |
1587 { | 1621 { |
1588 struct iv_use *use; | 1622 struct iv_use *use; |
1589 | 1623 |
1590 group = data->vgroups[i]; | 1624 group = data->vgroups[i]; |
1591 use = group->vuses[0]; | 1625 use = group->vuses[0]; |
1592 if (use->type != USE_ADDRESS || !use->iv->base_object) | 1626 if (!address_p (use->type)) |
1593 continue; | 1627 continue; |
1594 | 1628 |
1595 /* Check if it has the same stripped base and step. */ | 1629 /* Check if it has the same stripped base and step. */ |
1596 if (operand_equal_p (iv->base_object, use->iv->base_object, 0) | 1630 if (operand_equal_p (iv->base_object, use->iv->base_object, 0) |
1597 && operand_equal_p (iv->step, use->iv->step, 0) | 1631 && operand_equal_p (iv->step, use->iv->step, 0) |
1603 } | 1637 } |
1604 | 1638 |
1605 if (!group) | 1639 if (!group) |
1606 group = record_group (data, type); | 1640 group = record_group (data, type); |
1607 | 1641 |
1608 return record_use (group, use_p, iv, stmt, type, addr_base, addr_offset); | 1642 return record_use (group, use_p, iv, stmt, type, mem_type, |
1643 addr_base, addr_offset); | |
1609 } | 1644 } |
1610 | 1645 |
1611 /* Checks whether the use OP is interesting and if so, records it. */ | 1646 /* Checks whether the use OP is interesting and if so, records it. */ |
1612 | 1647 |
1613 static struct iv_use * | 1648 static struct iv_use * |
1637 } | 1672 } |
1638 | 1673 |
1639 stmt = SSA_NAME_DEF_STMT (op); | 1674 stmt = SSA_NAME_DEF_STMT (op); |
1640 gcc_assert (gimple_code (stmt) == GIMPLE_PHI || is_gimple_assign (stmt)); | 1675 gcc_assert (gimple_code (stmt) == GIMPLE_PHI || is_gimple_assign (stmt)); |
1641 | 1676 |
1642 use = record_group_use (data, NULL, iv, stmt, USE_NONLINEAR_EXPR); | 1677 use = record_group_use (data, NULL, iv, stmt, USE_NONLINEAR_EXPR, NULL_TREE); |
1643 iv->nonlin_use = use; | 1678 iv->nonlin_use = use; |
1644 return use; | 1679 return use; |
1645 } | 1680 } |
1646 | 1681 |
1647 /* Indicate how compare type iv_use can be handled. */ | 1682 /* Indicate how compare type iv_use can be handled. */ |
1753 find_interesting_uses_op (data, *var_p); | 1788 find_interesting_uses_op (data, *var_p); |
1754 find_interesting_uses_op (data, *bound_p); | 1789 find_interesting_uses_op (data, *bound_p); |
1755 return; | 1790 return; |
1756 } | 1791 } |
1757 | 1792 |
1758 record_group_use (data, var_p, var_iv, stmt, USE_COMPARE); | 1793 record_group_use (data, var_p, var_iv, stmt, USE_COMPARE, NULL_TREE); |
1759 /* Record compare type iv_use for iv on the other side of comparison. */ | 1794 /* Record compare type iv_use for iv on the other side of comparison. */ |
1760 if (ret == COMP_IV_EXPR_2) | 1795 if (ret == COMP_IV_EXPR_2) |
1761 record_group_use (data, bound_p, bound_iv, stmt, USE_COMPARE); | 1796 record_group_use (data, bound_p, bound_iv, stmt, USE_COMPARE, NULL_TREE); |
1762 } | 1797 } |
1763 | 1798 |
1764 /* Returns the outermost loop EXPR is obviously invariant in | 1799 /* Returns the outermost loop EXPR is obviously invariant in |
1765 relative to the loop LOOP, i.e. if all its operands are defined | 1800 relative to the loop LOOP, i.e. if all its operands are defined |
1766 outside of the returned loop. Returns NULL if EXPR is not | 1801 outside of the returned loop. Returns NULL if EXPR is not |
2163 return false; | 2198 return false; |
2164 *mul = wi::sext (wi::divmod_trunc (p0, p1, SIGNED, &res), precision); | 2199 *mul = wi::sext (wi::divmod_trunc (p0, p1, SIGNED, &res), precision); |
2165 return res == 0; | 2200 return res == 0; |
2166 | 2201 |
2167 default: | 2202 default: |
2203 if (POLY_INT_CST_P (top) | |
2204 && POLY_INT_CST_P (bot) | |
2205 && constant_multiple_p (wi::to_poly_widest (top), | |
2206 wi::to_poly_widest (bot), mul)) | |
2207 return true; | |
2208 | |
2168 return false; | 2209 return false; |
2169 } | 2210 } |
2170 } | 2211 } |
2171 | 2212 |
2172 /* Return true if memory reference REF with step STEP may be unaligned. */ | 2213 /* Return true if memory reference REF with step STEP may be unaligned. */ |
2365 civ = alloc_iv (data, base, step); | 2406 civ = alloc_iv (data, base, step); |
2366 /* Fail if base object of this memory reference is unknown. */ | 2407 /* Fail if base object of this memory reference is unknown. */ |
2367 if (civ->base_object == NULL_TREE) | 2408 if (civ->base_object == NULL_TREE) |
2368 goto fail; | 2409 goto fail; |
2369 | 2410 |
2370 record_group_use (data, op_p, civ, stmt, USE_ADDRESS); | 2411 record_group_use (data, op_p, civ, stmt, USE_REF_ADDRESS, TREE_TYPE (*op_p)); |
2371 return; | 2412 return; |
2372 | 2413 |
2373 fail: | 2414 fail: |
2374 for_each_index (op_p, idx_record_use, data); | 2415 for_each_index (op_p, idx_record_use, data); |
2375 } | 2416 } |
2386 FOR_EACH_PHI_OR_STMT_USE (use_p, stmt, iter, SSA_OP_USE) | 2427 FOR_EACH_PHI_OR_STMT_USE (use_p, stmt, iter, SSA_OP_USE) |
2387 { | 2428 { |
2388 op = USE_FROM_PTR (use_p); | 2429 op = USE_FROM_PTR (use_p); |
2389 record_invariant (data, op, false); | 2430 record_invariant (data, op, false); |
2390 } | 2431 } |
2432 } | |
2433 | |
2434 /* CALL calls an internal function. If operand *OP_P will become an | |
2435 address when the call is expanded, return the type of the memory | |
2436 being addressed, otherwise return null. */ | |
2437 | |
2438 static tree | |
2439 get_mem_type_for_internal_fn (gcall *call, tree *op_p) | |
2440 { | |
2441 switch (gimple_call_internal_fn (call)) | |
2442 { | |
2443 case IFN_MASK_LOAD: | |
2444 if (op_p == gimple_call_arg_ptr (call, 0)) | |
2445 return TREE_TYPE (gimple_call_lhs (call)); | |
2446 return NULL_TREE; | |
2447 | |
2448 case IFN_MASK_STORE: | |
2449 if (op_p == gimple_call_arg_ptr (call, 0)) | |
2450 return TREE_TYPE (gimple_call_arg (call, 3)); | |
2451 return NULL_TREE; | |
2452 | |
2453 default: | |
2454 return NULL_TREE; | |
2455 } | |
2456 } | |
2457 | |
2458 /* IV is a (non-address) iv that describes operand *OP_P of STMT. | |
2459 Return true if the operand will become an address when STMT | |
2460 is expanded and record the associated address use if so. */ | |
2461 | |
2462 static bool | |
2463 find_address_like_use (struct ivopts_data *data, gimple *stmt, tree *op_p, | |
2464 struct iv *iv) | |
2465 { | |
2466 /* Fail if base object of this memory reference is unknown. */ | |
2467 if (iv->base_object == NULL_TREE) | |
2468 return false; | |
2469 | |
2470 tree mem_type = NULL_TREE; | |
2471 if (gcall *call = dyn_cast <gcall *> (stmt)) | |
2472 if (gimple_call_internal_p (call)) | |
2473 mem_type = get_mem_type_for_internal_fn (call, op_p); | |
2474 if (mem_type) | |
2475 { | |
2476 iv = alloc_iv (data, iv->base, iv->step); | |
2477 record_group_use (data, op_p, iv, stmt, USE_PTR_ADDRESS, mem_type); | |
2478 return true; | |
2479 } | |
2480 return false; | |
2391 } | 2481 } |
2392 | 2482 |
2393 /* Finds interesting uses of induction variables in the statement STMT. */ | 2483 /* Finds interesting uses of induction variables in the statement STMT. */ |
2394 | 2484 |
2395 static void | 2485 static void |
2472 | 2562 |
2473 iv = get_iv (data, op); | 2563 iv = get_iv (data, op); |
2474 if (!iv) | 2564 if (!iv) |
2475 continue; | 2565 continue; |
2476 | 2566 |
2477 find_interesting_uses_op (data, op); | 2567 if (!find_address_like_use (data, stmt, use_p->use, iv)) |
2568 find_interesting_uses_op (data, op); | |
2478 } | 2569 } |
2479 } | 2570 } |
2480 | 2571 |
2481 /* Finds interesting uses of induction variables outside of loops | 2572 /* Finds interesting uses of induction variables outside of loops |
2482 on loop exit edge EXIT. */ | 2573 on loop exit edge EXIT. */ |
2501 mode for memory reference represented by USE. */ | 2592 mode for memory reference represented by USE. */ |
2502 | 2593 |
2503 static GTY (()) vec<rtx, va_gc> *addr_list; | 2594 static GTY (()) vec<rtx, va_gc> *addr_list; |
2504 | 2595 |
2505 static bool | 2596 static bool |
2506 addr_offset_valid_p (struct iv_use *use, HOST_WIDE_INT offset) | 2597 addr_offset_valid_p (struct iv_use *use, poly_int64 offset) |
2507 { | 2598 { |
2508 rtx reg, addr; | 2599 rtx reg, addr; |
2509 unsigned list_index; | 2600 unsigned list_index; |
2510 addr_space_t as = TYPE_ADDR_SPACE (TREE_TYPE (use->iv->base)); | 2601 addr_space_t as = TYPE_ADDR_SPACE (TREE_TYPE (use->iv->base)); |
2511 machine_mode addr_mode, mem_mode = TYPE_MODE (TREE_TYPE (*use->op_p)); | 2602 machine_mode addr_mode, mem_mode = TYPE_MODE (use->mem_type); |
2512 | 2603 |
2513 list_index = (unsigned) as * MAX_MACHINE_MODE + (unsigned) mem_mode; | 2604 list_index = (unsigned) as * MAX_MACHINE_MODE + (unsigned) mem_mode; |
2514 if (list_index >= vec_safe_length (addr_list)) | 2605 if (list_index >= vec_safe_length (addr_list)) |
2515 vec_safe_grow_cleared (addr_list, list_index + MAX_MACHINE_MODE); | 2606 vec_safe_grow_cleared (addr_list, list_index + MAX_MACHINE_MODE); |
2516 | 2607 |
2535 group_compare_offset (const void *a, const void *b) | 2626 group_compare_offset (const void *a, const void *b) |
2536 { | 2627 { |
2537 const struct iv_use *const *u1 = (const struct iv_use *const *) a; | 2628 const struct iv_use *const *u1 = (const struct iv_use *const *) a; |
2538 const struct iv_use *const *u2 = (const struct iv_use *const *) b; | 2629 const struct iv_use *const *u2 = (const struct iv_use *const *) b; |
2539 | 2630 |
2540 if ((*u1)->addr_offset != (*u2)->addr_offset) | 2631 return compare_sizes_for_sort ((*u1)->addr_offset, (*u2)->addr_offset); |
2541 return (*u1)->addr_offset < (*u2)->addr_offset ? -1 : 1; | |
2542 else | |
2543 return 0; | |
2544 } | 2632 } |
2545 | 2633 |
2546 /* Check if small groups should be split. Return true if no group | 2634 /* Check if small groups should be split. Return true if no group |
2547 contains more than two uses with distinct addr_offsets. Return | 2635 contains more than two uses with distinct addr_offsets. Return |
2548 false otherwise. We want to split such groups because: | 2636 false otherwise. We want to split such groups because: |
2566 { | 2654 { |
2567 group = data->vgroups[i]; | 2655 group = data->vgroups[i]; |
2568 if (group->vuses.length () == 1) | 2656 if (group->vuses.length () == 1) |
2569 continue; | 2657 continue; |
2570 | 2658 |
2571 gcc_assert (group->type == USE_ADDRESS); | 2659 gcc_assert (address_p (group->type)); |
2572 if (group->vuses.length () == 2) | 2660 if (group->vuses.length () == 2) |
2573 { | 2661 { |
2574 if (group->vuses[0]->addr_offset > group->vuses[1]->addr_offset) | 2662 if (compare_sizes_for_sort (group->vuses[0]->addr_offset, |
2663 group->vuses[1]->addr_offset) > 0) | |
2575 std::swap (group->vuses[0], group->vuses[1]); | 2664 std::swap (group->vuses[0], group->vuses[1]); |
2576 } | 2665 } |
2577 else | 2666 else |
2578 group->vuses.qsort (group_compare_offset); | 2667 group->vuses.qsort (group_compare_offset); |
2579 | 2668 |
2581 continue; | 2670 continue; |
2582 | 2671 |
2583 distinct = 1; | 2672 distinct = 1; |
2584 for (pre = group->vuses[0], j = 1; j < group->vuses.length (); j++) | 2673 for (pre = group->vuses[0], j = 1; j < group->vuses.length (); j++) |
2585 { | 2674 { |
2586 if (group->vuses[j]->addr_offset != pre->addr_offset) | 2675 if (maybe_ne (group->vuses[j]->addr_offset, pre->addr_offset)) |
2587 { | 2676 { |
2588 pre = group->vuses[j]; | 2677 pre = group->vuses[j]; |
2589 distinct++; | 2678 distinct++; |
2590 } | 2679 } |
2591 | 2680 |
2617 use->id = 0; | 2706 use->id = 0; |
2618 use->group_id = group->id; | 2707 use->group_id = group->id; |
2619 if (group->vuses.length () == 1) | 2708 if (group->vuses.length () == 1) |
2620 continue; | 2709 continue; |
2621 | 2710 |
2622 gcc_assert (group->type == USE_ADDRESS); | 2711 gcc_assert (address_p (use->type)); |
2623 | 2712 |
2624 for (j = 1; j < group->vuses.length ();) | 2713 for (j = 1; j < group->vuses.length ();) |
2625 { | 2714 { |
2626 struct iv_use *next = group->vuses[j]; | 2715 struct iv_use *next = group->vuses[j]; |
2627 HOST_WIDE_INT offset = next->addr_offset - use->addr_offset; | 2716 poly_int64 offset = next->addr_offset - use->addr_offset; |
2628 | 2717 |
2629 /* Split group if aksed to, or the offset against the first | 2718 /* Split group if aksed to, or the offset against the first |
2630 use can't fit in offset part of addressing mode. IV uses | 2719 use can't fit in offset part of addressing mode. IV uses |
2631 having the same offset are still kept in one group. */ | 2720 having the same offset are still kept in one group. */ |
2632 if (offset != 0 && | 2721 if (maybe_ne (offset, 0) |
2633 (split_p || !addr_offset_valid_p (use, offset))) | 2722 && (split_p || !addr_offset_valid_p (use, offset))) |
2634 { | 2723 { |
2635 if (!new_group) | 2724 if (!new_group) |
2636 new_group = record_group (data, group->type); | 2725 new_group = record_group (data, group->type); |
2637 group->vuses.ordered_remove (j); | 2726 group->vuses.ordered_remove (j); |
2638 new_group->vuses.safe_push (next); | 2727 new_group->vuses.safe_push (next); |
2689 is true, assume we are inside an address. If TOP_COMPREF is true, assume | 2778 is true, assume we are inside an address. If TOP_COMPREF is true, assume |
2690 we are at the top-level of the processed address. */ | 2779 we are at the top-level of the processed address. */ |
2691 | 2780 |
2692 static tree | 2781 static tree |
2693 strip_offset_1 (tree expr, bool inside_addr, bool top_compref, | 2782 strip_offset_1 (tree expr, bool inside_addr, bool top_compref, |
2694 HOST_WIDE_INT *offset) | 2783 poly_int64 *offset) |
2695 { | 2784 { |
2696 tree op0 = NULL_TREE, op1 = NULL_TREE, tmp, step; | 2785 tree op0 = NULL_TREE, op1 = NULL_TREE, tmp, step; |
2697 enum tree_code code; | 2786 enum tree_code code; |
2698 tree type, orig_type = TREE_TYPE (expr); | 2787 tree type, orig_type = TREE_TYPE (expr); |
2699 HOST_WIDE_INT off0, off1, st; | 2788 poly_int64 off0, off1; |
2789 HOST_WIDE_INT st; | |
2700 tree orig_expr = expr; | 2790 tree orig_expr = expr; |
2701 | 2791 |
2702 STRIP_NOPS (expr); | 2792 STRIP_NOPS (expr); |
2703 | 2793 |
2704 type = TREE_TYPE (expr); | 2794 type = TREE_TYPE (expr); |
2705 code = TREE_CODE (expr); | 2795 code = TREE_CODE (expr); |
2706 *offset = 0; | 2796 *offset = 0; |
2707 | 2797 |
2708 switch (code) | 2798 switch (code) |
2709 { | 2799 { |
2710 case INTEGER_CST: | |
2711 if (!cst_and_fits_in_hwi (expr) | |
2712 || integer_zerop (expr)) | |
2713 return orig_expr; | |
2714 | |
2715 *offset = int_cst_value (expr); | |
2716 return build_int_cst (orig_type, 0); | |
2717 | |
2718 case POINTER_PLUS_EXPR: | 2800 case POINTER_PLUS_EXPR: |
2719 case PLUS_EXPR: | 2801 case PLUS_EXPR: |
2720 case MINUS_EXPR: | 2802 case MINUS_EXPR: |
2721 op0 = TREE_OPERAND (expr, 0); | 2803 op0 = TREE_OPERAND (expr, 0); |
2722 op1 = TREE_OPERAND (expr, 1); | 2804 op1 = TREE_OPERAND (expr, 1); |
2830 /* ??? Offset operand? */ | 2912 /* ??? Offset operand? */ |
2831 inside_addr = false; | 2913 inside_addr = false; |
2832 break; | 2914 break; |
2833 | 2915 |
2834 default: | 2916 default: |
2917 if (ptrdiff_tree_p (expr, offset) && maybe_ne (*offset, 0)) | |
2918 return build_int_cst (orig_type, 0); | |
2835 return orig_expr; | 2919 return orig_expr; |
2836 } | 2920 } |
2837 | 2921 |
2838 /* Default handling of expressions for that we want to recurse into | 2922 /* Default handling of expressions for that we want to recurse into |
2839 the first operand. */ | 2923 the first operand. */ |
2859 } | 2943 } |
2860 | 2944 |
2861 /* Strips constant offsets from EXPR and stores them to OFFSET. */ | 2945 /* Strips constant offsets from EXPR and stores them to OFFSET. */ |
2862 | 2946 |
2863 tree | 2947 tree |
2864 strip_offset (tree expr, unsigned HOST_WIDE_INT *offset) | 2948 strip_offset (tree expr, poly_uint64_pod *offset) |
2865 { | 2949 { |
2866 HOST_WIDE_INT off; | 2950 poly_int64 off; |
2867 tree core = strip_offset_1 (expr, false, false, &off); | 2951 tree core = strip_offset_1 (expr, false, false, &off); |
2868 *offset = off; | 2952 *offset = off; |
2869 return core; | 2953 return core; |
2870 } | 2954 } |
2871 | 2955 |
2962 static iv_inv_expr_ent * | 3046 static iv_inv_expr_ent * |
2963 get_loop_invariant_expr (struct ivopts_data *data, tree inv_expr) | 3047 get_loop_invariant_expr (struct ivopts_data *data, tree inv_expr) |
2964 { | 3048 { |
2965 STRIP_NOPS (inv_expr); | 3049 STRIP_NOPS (inv_expr); |
2966 | 3050 |
2967 if (TREE_CODE (inv_expr) == INTEGER_CST || TREE_CODE (inv_expr) == SSA_NAME) | 3051 if (poly_int_tree_p (inv_expr) |
3052 || TREE_CODE (inv_expr) == SSA_NAME) | |
2968 return NULL; | 3053 return NULL; |
2969 | 3054 |
2970 /* Don't strip constant part away as we used to. */ | 3055 /* Don't strip constant part away as we used to. */ |
2971 | 3056 |
2972 /* Stores EXPR in DATA->inv_expr_tab, return pointer to iv_inv_expr_ent. */ | 3057 /* Stores EXPR in DATA->inv_expr_tab, return pointer to iv_inv_expr_ent. */ |
3059 } | 3144 } |
3060 cand->important = important; | 3145 cand->important = important; |
3061 cand->incremented_at = incremented_at; | 3146 cand->incremented_at = incremented_at; |
3062 data->vcands.safe_push (cand); | 3147 data->vcands.safe_push (cand); |
3063 | 3148 |
3064 if (TREE_CODE (step) != INTEGER_CST) | 3149 if (!poly_int_tree_p (step)) |
3065 { | 3150 { |
3066 find_inv_vars (data, &step, &cand->inv_vars); | 3151 find_inv_vars (data, &step, &cand->inv_vars); |
3067 | 3152 |
3068 iv_inv_expr_ent *inv_expr = get_loop_invariant_expr (data, step); | 3153 iv_inv_expr_ent *inv_expr = get_loop_invariant_expr (data, step); |
3069 /* Share bitmap between inv_vars and inv_exprs for cand. */ | 3154 /* Share bitmap between inv_vars and inv_exprs for cand. */ |
3135 ones, we must ensure that it is incremented once per iteration. | 3220 ones, we must ensure that it is incremented once per iteration. |
3136 It must not be in an inner nested loop, or one side of an if | 3221 It must not be in an inner nested loop, or one side of an if |
3137 statement. */ | 3222 statement. */ |
3138 if (use_bb->loop_father != data->current_loop | 3223 if (use_bb->loop_father != data->current_loop |
3139 || !dominated_by_p (CDI_DOMINATORS, data->current_loop->latch, use_bb) | 3224 || !dominated_by_p (CDI_DOMINATORS, data->current_loop->latch, use_bb) |
3140 || stmt_can_throw_internal (use->stmt) | 3225 || stmt_can_throw_internal (cfun, use->stmt) |
3141 || !cst_and_fits_in_hwi (step)) | 3226 || !cst_and_fits_in_hwi (step)) |
3142 return; | 3227 return; |
3143 | 3228 |
3144 cstepi = int_cst_value (step); | 3229 cstepi = int_cst_value (step); |
3145 | 3230 |
3146 mem_mode = TYPE_MODE (TREE_TYPE (*use->op_p)); | 3231 mem_mode = TYPE_MODE (use->mem_type); |
3147 if (((USE_LOAD_PRE_INCREMENT (mem_mode) | 3232 if (((USE_LOAD_PRE_INCREMENT (mem_mode) |
3148 || USE_STORE_PRE_INCREMENT (mem_mode)) | 3233 || USE_STORE_PRE_INCREMENT (mem_mode)) |
3149 && GET_MODE_SIZE (mem_mode) == cstepi) | 3234 && known_eq (GET_MODE_SIZE (mem_mode), cstepi)) |
3150 || ((USE_LOAD_PRE_DECREMENT (mem_mode) | 3235 || ((USE_LOAD_PRE_DECREMENT (mem_mode) |
3151 || USE_STORE_PRE_DECREMENT (mem_mode)) | 3236 || USE_STORE_PRE_DECREMENT (mem_mode)) |
3152 && GET_MODE_SIZE (mem_mode) == -cstepi)) | 3237 && known_eq (GET_MODE_SIZE (mem_mode), -cstepi))) |
3153 { | 3238 { |
3154 enum tree_code code = MINUS_EXPR; | 3239 enum tree_code code = MINUS_EXPR; |
3155 tree new_base; | 3240 tree new_base; |
3156 tree new_step = step; | 3241 tree new_step = step; |
3157 | 3242 |
3166 add_candidate_1 (data, new_base, step, important, IP_BEFORE_USE, use, | 3251 add_candidate_1 (data, new_base, step, important, IP_BEFORE_USE, use, |
3167 use->stmt); | 3252 use->stmt); |
3168 } | 3253 } |
3169 if (((USE_LOAD_POST_INCREMENT (mem_mode) | 3254 if (((USE_LOAD_POST_INCREMENT (mem_mode) |
3170 || USE_STORE_POST_INCREMENT (mem_mode)) | 3255 || USE_STORE_POST_INCREMENT (mem_mode)) |
3171 && GET_MODE_SIZE (mem_mode) == cstepi) | 3256 && known_eq (GET_MODE_SIZE (mem_mode), cstepi)) |
3172 || ((USE_LOAD_POST_DECREMENT (mem_mode) | 3257 || ((USE_LOAD_POST_DECREMENT (mem_mode) |
3173 || USE_STORE_POST_DECREMENT (mem_mode)) | 3258 || USE_STORE_POST_DECREMENT (mem_mode)) |
3174 && GET_MODE_SIZE (mem_mode) == -cstepi)) | 3259 && known_eq (GET_MODE_SIZE (mem_mode), -cstepi))) |
3175 { | 3260 { |
3176 add_candidate_1 (data, base, step, important, IP_AFTER_USE, use, | 3261 add_candidate_1 (data, base, step, important, IP_AFTER_USE, use, |
3177 use->stmt); | 3262 use->stmt); |
3178 } | 3263 } |
3179 } | 3264 } |
3387 /* Adds candidates based on the value of USE's iv. */ | 3472 /* Adds candidates based on the value of USE's iv. */ |
3388 | 3473 |
3389 static void | 3474 static void |
3390 add_iv_candidate_for_use (struct ivopts_data *data, struct iv_use *use) | 3475 add_iv_candidate_for_use (struct ivopts_data *data, struct iv_use *use) |
3391 { | 3476 { |
3392 unsigned HOST_WIDE_INT offset; | 3477 poly_uint64 offset; |
3393 tree base; | 3478 tree base; |
3394 tree basetype; | 3479 tree basetype; |
3395 struct iv *iv = use->iv; | 3480 struct iv *iv = use->iv; |
3396 | 3481 |
3397 add_candidate (data, iv->base, iv->step, false, use); | 3482 add_candidate (data, iv->base, iv->step, false, use); |
3406 record_common_cand (data, build_int_cst (basetype, 0), iv->step, use); | 3491 record_common_cand (data, build_int_cst (basetype, 0), iv->step, use); |
3407 | 3492 |
3408 /* Record common candidate with constant offset stripped in base. | 3493 /* Record common candidate with constant offset stripped in base. |
3409 Like the use itself, we also add candidate directly for it. */ | 3494 Like the use itself, we also add candidate directly for it. */ |
3410 base = strip_offset (iv->base, &offset); | 3495 base = strip_offset (iv->base, &offset); |
3411 if (offset || base != iv->base) | 3496 if (maybe_ne (offset, 0U) || base != iv->base) |
3412 { | 3497 { |
3413 record_common_cand (data, base, iv->step, use); | 3498 record_common_cand (data, base, iv->step, use); |
3414 add_candidate (data, base, iv->step, false, use); | 3499 add_candidate (data, base, iv->step, false, use); |
3415 } | 3500 } |
3416 | 3501 |
3425 base = TREE_OPERAND (base, 1); | 3510 base = TREE_OPERAND (base, 1); |
3426 step = fold_convert (sizetype, step); | 3511 step = fold_convert (sizetype, step); |
3427 record_common_cand (data, base, step, use); | 3512 record_common_cand (data, base, step, use); |
3428 /* Also record common candidate with offset stripped. */ | 3513 /* Also record common candidate with offset stripped. */ |
3429 base = strip_offset (base, &offset); | 3514 base = strip_offset (base, &offset); |
3430 if (offset) | 3515 if (maybe_ne (offset, 0U)) |
3431 record_common_cand (data, base, step, use); | 3516 record_common_cand (data, base, step, use); |
3432 } | 3517 } |
3433 | 3518 |
3434 /* At last, add auto-incremental candidates. Make such variables | 3519 /* At last, add auto-incremental candidates. Make such variables |
3435 important since other iv uses with same base object may be based | 3520 important since other iv uses with same base object may be based |
3436 on it. */ | 3521 on it. */ |
3437 if (use != NULL && use->type == USE_ADDRESS) | 3522 if (use != NULL && address_p (use->type)) |
3438 add_autoinc_candidates (data, iv->base, iv->step, true, use); | 3523 add_autoinc_candidates (data, iv->base, iv->step, true, use); |
3439 } | 3524 } |
3440 | 3525 |
3441 /* Adds candidates based on the uses. */ | 3526 /* Adds candidates based on the uses. */ |
3442 | 3527 |
3795 | 3880 |
3796 /* If the conversion is not noop, perform it. */ | 3881 /* If the conversion is not noop, perform it. */ |
3797 if (TYPE_PRECISION (utype) < TYPE_PRECISION (ctype)) | 3882 if (TYPE_PRECISION (utype) < TYPE_PRECISION (ctype)) |
3798 { | 3883 { |
3799 if (cand->orig_iv != NULL && CONVERT_EXPR_P (cbase) | 3884 if (cand->orig_iv != NULL && CONVERT_EXPR_P (cbase) |
3800 && (CONVERT_EXPR_P (cstep) || TREE_CODE (cstep) == INTEGER_CST)) | 3885 && (CONVERT_EXPR_P (cstep) || poly_int_tree_p (cstep))) |
3801 { | 3886 { |
3802 tree inner_base, inner_step, inner_type; | 3887 tree inner_base, inner_step, inner_type; |
3803 inner_base = TREE_OPERAND (cbase, 0); | 3888 inner_base = TREE_OPERAND (cbase, 0); |
3804 if (CONVERT_EXPR_P (cstep)) | 3889 if (CONVERT_EXPR_P (cstep)) |
3805 inner_step = TREE_OPERAND (cstep, 0); | 3890 inner_step = TREE_OPERAND (cstep, 0); |
3899 get_use_type (struct iv_use *use) | 3984 get_use_type (struct iv_use *use) |
3900 { | 3985 { |
3901 tree base_type = TREE_TYPE (use->iv->base); | 3986 tree base_type = TREE_TYPE (use->iv->base); |
3902 tree type; | 3987 tree type; |
3903 | 3988 |
3904 if (use->type == USE_ADDRESS) | 3989 if (use->type == USE_REF_ADDRESS) |
3905 { | 3990 { |
3906 /* The base_type may be a void pointer. Create a pointer type based on | 3991 /* The base_type may be a void pointer. Create a pointer type based on |
3907 the mem_ref instead. */ | 3992 the mem_ref instead. */ |
3908 type = build_pointer_type (TREE_TYPE (*use->op_p)); | 3993 type = build_pointer_type (TREE_TYPE (*use->op_p)); |
3909 gcc_assert (TYPE_ADDR_SPACE (TREE_TYPE (type)) | 3994 gcc_assert (TYPE_ADDR_SPACE (TREE_TYPE (type)) |
4053 if (SSA_VAR_P (expr)) | 4138 if (SSA_VAR_P (expr)) |
4054 return no_cost; | 4139 return no_cost; |
4055 | 4140 |
4056 if (is_gimple_min_invariant (expr)) | 4141 if (is_gimple_min_invariant (expr)) |
4057 { | 4142 { |
4058 if (TREE_CODE (expr) == INTEGER_CST) | 4143 if (poly_int_tree_p (expr)) |
4059 return comp_cost (integer_cost [speed], 0); | 4144 return comp_cost (integer_cost [speed], 0); |
4060 | 4145 |
4061 if (TREE_CODE (expr) == ADDR_EXPR) | 4146 if (TREE_CODE (expr) == ADDR_EXPR) |
4062 { | 4147 { |
4063 tree obj = TREE_OPERAND (expr, 0); | 4148 tree obj = TREE_OPERAND (expr, 0); |
4218 { | 4303 { |
4219 unsigned costs[AINC_NONE]; | 4304 unsigned costs[AINC_NONE]; |
4220 }; | 4305 }; |
4221 | 4306 |
4222 static comp_cost | 4307 static comp_cost |
4223 get_address_cost_ainc (HOST_WIDE_INT ainc_step, HOST_WIDE_INT ainc_offset, | 4308 get_address_cost_ainc (poly_int64 ainc_step, poly_int64 ainc_offset, |
4224 machine_mode addr_mode, machine_mode mem_mode, | 4309 machine_mode addr_mode, machine_mode mem_mode, |
4225 addr_space_t as, bool speed) | 4310 addr_space_t as, bool speed) |
4226 { | 4311 { |
4227 if (!USE_LOAD_PRE_DECREMENT (mem_mode) | 4312 if (!USE_LOAD_PRE_DECREMENT (mem_mode) |
4228 && !USE_STORE_PRE_DECREMENT (mem_mode) | 4313 && !USE_STORE_PRE_DECREMENT (mem_mode) |
4291 = address_cost (addr, mem_mode, as, speed); | 4376 = address_cost (addr, mem_mode, as, speed); |
4292 } | 4377 } |
4293 ainc_cost_data_list[idx] = data; | 4378 ainc_cost_data_list[idx] = data; |
4294 } | 4379 } |
4295 | 4380 |
4296 HOST_WIDE_INT msize = GET_MODE_SIZE (mem_mode); | 4381 poly_int64 msize = GET_MODE_SIZE (mem_mode); |
4297 if (ainc_offset == 0 && msize == ainc_step) | 4382 if (known_eq (ainc_offset, 0) && known_eq (msize, ainc_step)) |
4298 return comp_cost (data->costs[AINC_POST_INC], 0); | 4383 return comp_cost (data->costs[AINC_POST_INC], 0); |
4299 if (ainc_offset == 0 && msize == -ainc_step) | 4384 if (known_eq (ainc_offset, 0) && known_eq (msize, -ainc_step)) |
4300 return comp_cost (data->costs[AINC_POST_DEC], 0); | 4385 return comp_cost (data->costs[AINC_POST_DEC], 0); |
4301 if (ainc_offset == msize && msize == ainc_step) | 4386 if (known_eq (ainc_offset, msize) && known_eq (msize, ainc_step)) |
4302 return comp_cost (data->costs[AINC_PRE_INC], 0); | 4387 return comp_cost (data->costs[AINC_PRE_INC], 0); |
4303 if (ainc_offset == -msize && msize == -ainc_step) | 4388 if (known_eq (ainc_offset, -msize) && known_eq (msize, -ainc_step)) |
4304 return comp_cost (data->costs[AINC_PRE_DEC], 0); | 4389 return comp_cost (data->costs[AINC_PRE_DEC], 0); |
4305 | 4390 |
4306 return infinite_cost; | 4391 return infinite_cost; |
4307 } | 4392 } |
4308 | 4393 |
4327 tree comp_inv = NULL_TREE, type = aff_var->type; | 4412 tree comp_inv = NULL_TREE, type = aff_var->type; |
4328 comp_cost var_cost = no_cost, cost = no_cost; | 4413 comp_cost var_cost = no_cost, cost = no_cost; |
4329 struct mem_address parts = {NULL_TREE, integer_one_node, | 4414 struct mem_address parts = {NULL_TREE, integer_one_node, |
4330 NULL_TREE, NULL_TREE, NULL_TREE}; | 4415 NULL_TREE, NULL_TREE, NULL_TREE}; |
4331 machine_mode addr_mode = TYPE_MODE (type); | 4416 machine_mode addr_mode = TYPE_MODE (type); |
4332 machine_mode mem_mode = TYPE_MODE (TREE_TYPE (*use->op_p)); | 4417 machine_mode mem_mode = TYPE_MODE (use->mem_type); |
4333 addr_space_t as = TYPE_ADDR_SPACE (TREE_TYPE (use->iv->base)); | 4418 addr_space_t as = TYPE_ADDR_SPACE (TREE_TYPE (use->iv->base)); |
4419 /* Only true if ratio != 1. */ | |
4420 bool ok_with_ratio_p = false; | |
4421 bool ok_without_ratio_p = false; | |
4334 | 4422 |
4335 if (!aff_combination_const_p (aff_inv)) | 4423 if (!aff_combination_const_p (aff_inv)) |
4336 { | 4424 { |
4337 parts.index = integer_one_node; | 4425 parts.index = integer_one_node; |
4338 /* Addressing mode "base + index". */ | 4426 /* Addressing mode "base + index". */ |
4339 if (valid_mem_ref_p (mem_mode, as, &parts)) | 4427 ok_without_ratio_p = valid_mem_ref_p (mem_mode, as, &parts); |
4428 if (ratio != 1) | |
4340 { | 4429 { |
4341 parts.step = wide_int_to_tree (type, ratio); | 4430 parts.step = wide_int_to_tree (type, ratio); |
4342 /* Addressing mode "base + index << scale". */ | 4431 /* Addressing mode "base + index << scale". */ |
4343 if (ratio != 1 && !valid_mem_ref_p (mem_mode, as, &parts)) | 4432 ok_with_ratio_p = valid_mem_ref_p (mem_mode, as, &parts); |
4433 if (!ok_with_ratio_p) | |
4344 parts.step = NULL_TREE; | 4434 parts.step = NULL_TREE; |
4345 | 4435 } |
4346 if (aff_inv->offset != 0) | 4436 if (ok_with_ratio_p || ok_without_ratio_p) |
4437 { | |
4438 if (maybe_ne (aff_inv->offset, 0)) | |
4347 { | 4439 { |
4348 parts.offset = wide_int_to_tree (sizetype, aff_inv->offset); | 4440 parts.offset = wide_int_to_tree (sizetype, aff_inv->offset); |
4349 /* Addressing mode "base + index [<< scale] + offset". */ | 4441 /* Addressing mode "base + index [<< scale] + offset". */ |
4350 if (!valid_mem_ref_p (mem_mode, as, &parts)) | 4442 if (!valid_mem_ref_p (mem_mode, as, &parts)) |
4351 parts.offset = NULL_TREE; | 4443 parts.offset = NULL_TREE; |
4374 else | 4466 else |
4375 parts.index = NULL_TREE; | 4467 parts.index = NULL_TREE; |
4376 } | 4468 } |
4377 else | 4469 else |
4378 { | 4470 { |
4379 if (can_autoinc && ratio == 1 && cst_and_fits_in_hwi (cand->iv->step)) | 4471 poly_int64 ainc_step; |
4380 { | 4472 if (can_autoinc |
4381 HOST_WIDE_INT ainc_step = int_cst_value (cand->iv->step); | 4473 && ratio == 1 |
4382 HOST_WIDE_INT ainc_offset = (aff_inv->offset).to_shwi (); | 4474 && ptrdiff_tree_p (cand->iv->step, &ainc_step)) |
4475 { | |
4476 poly_int64 ainc_offset = (aff_inv->offset).force_shwi (); | |
4383 | 4477 |
4384 if (stmt_after_increment (data->current_loop, cand, use->stmt)) | 4478 if (stmt_after_increment (data->current_loop, cand, use->stmt)) |
4385 ainc_offset += ainc_step; | 4479 ainc_offset += ainc_step; |
4386 cost = get_address_cost_ainc (ainc_step, ainc_offset, | 4480 cost = get_address_cost_ainc (ainc_step, ainc_offset, |
4387 addr_mode, mem_mode, as, speed); | 4481 addr_mode, mem_mode, as, speed); |
4438 gcc_assert (memory_address_addr_space_p (mem_mode, addr, as)); | 4532 gcc_assert (memory_address_addr_space_p (mem_mode, addr, as)); |
4439 cost += address_cost (addr, mem_mode, as, speed); | 4533 cost += address_cost (addr, mem_mode, as, speed); |
4440 | 4534 |
4441 if (parts.symbol != NULL_TREE) | 4535 if (parts.symbol != NULL_TREE) |
4442 cost.complexity += 1; | 4536 cost.complexity += 1; |
4443 if (parts.step != NULL_TREE && !integer_onep (parts.step)) | 4537 /* Don't increase the complexity of adding a scaled index if it's |
4538 the only kind of index that the target allows. */ | |
4539 if (parts.step != NULL_TREE && ok_without_ratio_p) | |
4444 cost.complexity += 1; | 4540 cost.complexity += 1; |
4445 if (parts.base != NULL_TREE && parts.index != NULL_TREE) | 4541 if (parts.base != NULL_TREE && parts.index != NULL_TREE) |
4446 cost.complexity += 1; | 4542 cost.complexity += 1; |
4447 if (parts.offset != NULL_TREE && !integer_zerop (parts.offset)) | 4543 if (parts.offset != NULL_TREE && !integer_zerop (parts.offset)) |
4448 cost.complexity += 1; | 4544 cost.complexity += 1; |
4455 expected cost more accurate. */ | 4551 expected cost more accurate. */ |
4456 | 4552 |
4457 static comp_cost | 4553 static comp_cost |
4458 get_scaled_computation_cost_at (ivopts_data *data, gimple *at, comp_cost cost) | 4554 get_scaled_computation_cost_at (ivopts_data *data, gimple *at, comp_cost cost) |
4459 { | 4555 { |
4460 int loop_freq = data->current_loop->header->frequency; | 4556 int loop_freq = data->current_loop->header->count.to_frequency (cfun); |
4461 int bb_freq = gimple_bb (at)->frequency; | 4557 int bb_freq = gimple_bb (at)->count.to_frequency (cfun); |
4462 if (loop_freq != 0) | 4558 if (loop_freq != 0) |
4463 { | 4559 { |
4464 gcc_assert (cost.scratch <= cost.cost); | 4560 gcc_assert (cost.scratch <= cost.cost); |
4465 int scaled_cost | 4561 int scaled_cost |
4466 = cost.scratch + (cost.cost - cost.scratch) * bb_freq / loop_freq; | 4562 = cost.scratch + (cost.cost - cost.scratch) * bb_freq / loop_freq; |
4935 tree_to_aff_combination (fold_convert (nit_type, b), nit_type, &tmpb); | 5031 tree_to_aff_combination (fold_convert (nit_type, b), nit_type, &tmpb); |
4936 aff_combination_scale (&nit, -1); | 5032 aff_combination_scale (&nit, -1); |
4937 aff_combination_scale (&tmpa, -1); | 5033 aff_combination_scale (&tmpa, -1); |
4938 aff_combination_add (&tmpb, &tmpa); | 5034 aff_combination_add (&tmpb, &tmpa); |
4939 aff_combination_add (&tmpb, &nit); | 5035 aff_combination_add (&tmpb, &nit); |
4940 if (tmpb.n != 0 || tmpb.offset != 1) | 5036 if (tmpb.n != 0 || maybe_ne (tmpb.offset, 1)) |
4941 return false; | 5037 return false; |
4942 | 5038 |
4943 /* Finally, check that CAND->IV->BASE - CAND->IV->STEP * A does not | 5039 /* Finally, check that CAND->IV->BASE - CAND->IV->STEP * A does not |
4944 overflow. */ | 5040 overflow. */ |
4945 offset = fold_build2 (MULT_EXPR, TREE_TYPE (cand->iv->step), | 5041 offset = fold_build2 (MULT_EXPR, TREE_TYPE (cand->iv->step), |
5205 switch (group->type) | 5301 switch (group->type) |
5206 { | 5302 { |
5207 case USE_NONLINEAR_EXPR: | 5303 case USE_NONLINEAR_EXPR: |
5208 return determine_group_iv_cost_generic (data, group, cand); | 5304 return determine_group_iv_cost_generic (data, group, cand); |
5209 | 5305 |
5210 case USE_ADDRESS: | 5306 case USE_REF_ADDRESS: |
5307 case USE_PTR_ADDRESS: | |
5211 return determine_group_iv_cost_address (data, group, cand); | 5308 return determine_group_iv_cost_address (data, group, cand); |
5212 | 5309 |
5213 case USE_COMPARE: | 5310 case USE_COMPARE: |
5214 return determine_group_iv_cost_cond (data, group, cand); | 5311 return determine_group_iv_cost_cond (data, group, cand); |
5215 | 5312 |
5223 | 5320 |
5224 static bool | 5321 static bool |
5225 autoinc_possible_for_pair (struct ivopts_data *data, struct iv_use *use, | 5322 autoinc_possible_for_pair (struct ivopts_data *data, struct iv_use *use, |
5226 struct iv_cand *cand) | 5323 struct iv_cand *cand) |
5227 { | 5324 { |
5228 if (use->type != USE_ADDRESS) | 5325 if (!address_p (use->type)) |
5229 return false; | 5326 return false; |
5230 | 5327 |
5231 bool can_autoinc = false; | 5328 bool can_autoinc = false; |
5232 get_computation_cost (data, use, cand, true, NULL, &can_autoinc, NULL); | 5329 get_computation_cost (data, use, cand, true, NULL, &can_autoinc, NULL); |
5233 return can_autoinc; | 5330 return can_autoinc; |
6832 | 6929 |
6833 unshare_aff_combination (&aff_inv); | 6930 unshare_aff_combination (&aff_inv); |
6834 unshare_aff_combination (&aff_var); | 6931 unshare_aff_combination (&aff_var); |
6835 /* Prefer CSE opportunity than loop invariant by adding offset at last | 6932 /* Prefer CSE opportunity than loop invariant by adding offset at last |
6836 so that iv_uses have different offsets can be CSEed. */ | 6933 so that iv_uses have different offsets can be CSEed. */ |
6837 widest_int offset = aff_inv.offset; | 6934 poly_widest_int offset = aff_inv.offset; |
6838 aff_inv.offset = 0; | 6935 aff_inv.offset = 0; |
6839 | 6936 |
6840 gimple_seq stmt_list = NULL, seq = NULL; | 6937 gimple_seq stmt_list = NULL, seq = NULL; |
6841 tree comp_op1 = aff_combination_to_tree (&aff_inv); | 6938 tree comp_op1 = aff_combination_to_tree (&aff_inv); |
6842 tree comp_op2 = aff_combination_to_tree (&aff_var); | 6939 tree comp_op2 = aff_combination_to_tree (&aff_var); |
6981 gsi_move_before (&gsi_iv, &gsi); | 7078 gsi_move_before (&gsi_iv, &gsi); |
6982 | 7079 |
6983 cand->pos = IP_BEFORE_USE; | 7080 cand->pos = IP_BEFORE_USE; |
6984 cand->incremented_at = use->stmt; | 7081 cand->incremented_at = use->stmt; |
6985 } | 7082 } |
7083 | |
7084 /* Return the alias pointer type that should be used for a MEM_REF | |
7085 associated with USE, which has type USE_PTR_ADDRESS. */ | |
7086 | |
7087 static tree | |
7088 get_alias_ptr_type_for_ptr_address (iv_use *use) | |
7089 { | |
7090 gcall *call = as_a <gcall *> (use->stmt); | |
7091 switch (gimple_call_internal_fn (call)) | |
7092 { | |
7093 case IFN_MASK_LOAD: | |
7094 case IFN_MASK_STORE: | |
7095 /* The second argument contains the correct alias type. */ | |
7096 gcc_assert (use->op_p = gimple_call_arg_ptr (call, 0)); | |
7097 return TREE_TYPE (gimple_call_arg (call, 1)); | |
7098 | |
7099 default: | |
7100 gcc_unreachable (); | |
7101 } | |
7102 } | |
7103 | |
6986 | 7104 |
6987 /* Rewrites USE (address that is an iv) using candidate CAND. */ | 7105 /* Rewrites USE (address that is an iv) using candidate CAND. */ |
6988 | 7106 |
6989 static void | 7107 static void |
6990 rewrite_use_address (struct ivopts_data *data, | 7108 rewrite_use_address (struct ivopts_data *data, |
7010 of the use -- but these will use pointer types, so they are recognized | 7128 of the use -- but these will use pointer types, so they are recognized |
7011 by the create_mem_ref heuristics anyway. */ | 7129 by the create_mem_ref heuristics anyway. */ |
7012 tree iv = var_at_stmt (data->current_loop, cand, use->stmt); | 7130 tree iv = var_at_stmt (data->current_loop, cand, use->stmt); |
7013 tree base_hint = (cand->iv->base_object) ? iv : NULL_TREE; | 7131 tree base_hint = (cand->iv->base_object) ? iv : NULL_TREE; |
7014 gimple_stmt_iterator bsi = gsi_for_stmt (use->stmt); | 7132 gimple_stmt_iterator bsi = gsi_for_stmt (use->stmt); |
7015 tree type = TREE_TYPE (*use->op_p); | 7133 tree type = use->mem_type; |
7016 unsigned int align = get_object_alignment (*use->op_p); | 7134 tree alias_ptr_type; |
7017 if (align != TYPE_ALIGN (type)) | 7135 if (use->type == USE_PTR_ADDRESS) |
7018 type = build_aligned_type (type, align); | 7136 alias_ptr_type = get_alias_ptr_type_for_ptr_address (use); |
7019 | 7137 else |
7020 tree ref = create_mem_ref (&bsi, type, &aff, | 7138 { |
7021 reference_alias_ptr_type (*use->op_p), | 7139 gcc_assert (type == TREE_TYPE (*use->op_p)); |
7140 unsigned int align = get_object_alignment (*use->op_p); | |
7141 if (align != TYPE_ALIGN (type)) | |
7142 type = build_aligned_type (type, align); | |
7143 alias_ptr_type = reference_alias_ptr_type (*use->op_p); | |
7144 } | |
7145 tree ref = create_mem_ref (&bsi, type, &aff, alias_ptr_type, | |
7022 iv, base_hint, data->speed); | 7146 iv, base_hint, data->speed); |
7023 | 7147 |
7024 copy_ref_info (ref, *use->op_p); | 7148 if (use->type == USE_PTR_ADDRESS) |
7149 { | |
7150 ref = fold_build1 (ADDR_EXPR, build_pointer_type (use->mem_type), ref); | |
7151 ref = fold_convert (get_use_type (use), ref); | |
7152 ref = force_gimple_operand_gsi (&bsi, ref, true, NULL_TREE, | |
7153 true, GSI_SAME_STMT); | |
7154 } | |
7155 else | |
7156 copy_ref_info (ref, *use->op_p); | |
7157 | |
7025 *use->op_p = ref; | 7158 *use->op_p = ref; |
7026 } | 7159 } |
7027 | 7160 |
7028 /* Rewrites USE (the condition such that one of the arguments is an iv) using | 7161 /* Rewrites USE (the condition such that one of the arguments is an iv) using |
7029 candidate CAND. */ | 7162 candidate CAND. */ |
7095 { | 7228 { |
7096 rewrite_use_nonlinear_expr (data, group->vuses[j], cand); | 7229 rewrite_use_nonlinear_expr (data, group->vuses[j], cand); |
7097 update_stmt (group->vuses[j]->stmt); | 7230 update_stmt (group->vuses[j]->stmt); |
7098 } | 7231 } |
7099 } | 7232 } |
7100 else if (group->type == USE_ADDRESS) | 7233 else if (address_p (group->type)) |
7101 { | 7234 { |
7102 for (j = 0; j < group->vuses.length (); j++) | 7235 for (j = 0; j < group->vuses.length (); j++) |
7103 { | 7236 { |
7104 rewrite_use_address (data, group->vuses[j], cand); | 7237 rewrite_use_address (data, group->vuses[j], cand); |
7105 update_stmt (group->vuses[j]->stmt); | 7238 update_stmt (group->vuses[j]->stmt); |
7143 { | 7276 { |
7144 bitmap_set_bit (toremove, SSA_NAME_VERSION (info->iv->ssa_name)); | 7277 bitmap_set_bit (toremove, SSA_NAME_VERSION (info->iv->ssa_name)); |
7145 | 7278 |
7146 tree def = info->iv->ssa_name; | 7279 tree def = info->iv->ssa_name; |
7147 | 7280 |
7148 if (MAY_HAVE_DEBUG_STMTS && SSA_NAME_DEF_STMT (def)) | 7281 if (MAY_HAVE_DEBUG_BIND_STMTS && SSA_NAME_DEF_STMT (def)) |
7149 { | 7282 { |
7150 imm_use_iterator imm_iter; | 7283 imm_use_iterator imm_iter; |
7151 use_operand_p use_p; | 7284 use_operand_p use_p; |
7152 gimple *stmt; | 7285 gimple *stmt; |
7153 int count = 0; | 7286 int count = 0; |
7400 edge exit = single_dom_exit (loop); | 7533 edge exit = single_dom_exit (loop); |
7401 basic_block *body; | 7534 basic_block *body; |
7402 | 7535 |
7403 gcc_assert (!data->niters); | 7536 gcc_assert (!data->niters); |
7404 data->current_loop = loop; | 7537 data->current_loop = loop; |
7405 data->loop_loc = find_loop_location (loop); | 7538 data->loop_loc = find_loop_location (loop).get_location_t (); |
7406 data->speed = optimize_loop_for_speed_p (loop); | 7539 data->speed = optimize_loop_for_speed_p (loop); |
7407 | 7540 |
7408 if (dump_file && (dump_flags & TDF_DETAILS)) | 7541 if (dump_file && (dump_flags & TDF_DETAILS)) |
7409 { | 7542 { |
7410 fprintf (dump_file, "Processing loop %d", loop->num); | 7543 fprintf (dump_file, "Processing loop %d", loop->num); |