diff options
-rw-r--r-- | gcc/ipa-cp.c | 48 | ||||
-rw-r--r-- | gcc/ipa-prop.c | 148 | ||||
-rw-r--r-- | gcc/ipa-prop.h | 11 | ||||
-rw-r--r-- | gcc/testsuite/gfortran.dg/ipcp-array-2.f90 | 45 |
4 files changed, 179 insertions, 73 deletions
diff --git a/gcc/ipa-cp.c b/gcc/ipa-cp.c index c3ee71e..a06b4d1 100644 --- a/gcc/ipa-cp.c +++ b/gcc/ipa-cp.c @@ -1304,6 +1304,26 @@ initialize_node_lattices (struct cgraph_node *node) } } +/* Return true iff X and Y should be considered equal values by IPA-CP. */ + +static bool +values_equal_for_ipcp_p (tree x, tree y) +{ + gcc_checking_assert (x != NULL_TREE && y != NULL_TREE); + + if (x == y) + return true; + + if (TREE_CODE (x) == ADDR_EXPR + && TREE_CODE (y) == ADDR_EXPR + && TREE_CODE (TREE_OPERAND (x, 0)) == CONST_DECL + && TREE_CODE (TREE_OPERAND (y, 0)) == CONST_DECL) + return operand_equal_p (DECL_INITIAL (TREE_OPERAND (x, 0)), + DECL_INITIAL (TREE_OPERAND (y, 0)), 0); + else + return operand_equal_p (x, y, 0); +} + /* Return the result of a (possibly arithmetic) operation on the constant value INPUT. OPERAND is 2nd operand for binary operation. RES_TYPE is the type of the parameter to which the result is passed. Return @@ -1321,6 +1341,14 @@ ipa_get_jf_arith_result (enum tree_code opcode, tree input, tree operand, if (!is_gimple_ip_invariant (input)) return NULL_TREE; + if (opcode == ASSERT_EXPR) + { + if (values_equal_for_ipcp_p (input, operand)) + return input; + else + return NULL_TREE; + } + if (!res_type) { if (TREE_CODE_CLASS (opcode) == tcc_comparison) @@ -1753,26 +1781,6 @@ ipcp_verify_propagated_values (void) } } -/* Return true iff X and Y should be considered equal values by IPA-CP. */ - -static bool -values_equal_for_ipcp_p (tree x, tree y) -{ - gcc_checking_assert (x != NULL_TREE && y != NULL_TREE); - - if (x == y) - return true; - - if (TREE_CODE (x) == ADDR_EXPR - && TREE_CODE (y) == ADDR_EXPR - && TREE_CODE (TREE_OPERAND (x, 0)) == CONST_DECL - && TREE_CODE (TREE_OPERAND (y, 0)) == CONST_DECL) - return operand_equal_p (DECL_INITIAL (TREE_OPERAND (x, 0)), - DECL_INITIAL (TREE_OPERAND (y, 0)), 0); - else - return operand_equal_p (x, y, 0); -} - /* Return true iff X and Y should be considered equal contexts by IPA-CP. */ static bool diff --git a/gcc/ipa-prop.c b/gcc/ipa-prop.c index 904a8f7..130b2f8 100644 --- a/gcc/ipa-prop.c +++ b/gcc/ipa-prop.c @@ -1775,75 +1775,123 @@ analyze_agg_content_value (struct ipa_func_body_info *fbi, stmt = SSA_NAME_DEF_STMT (rhs1); if (!is_gimple_assign (stmt)) - return; + break; rhs1 = gimple_assign_rhs1 (stmt); } - code = gimple_assign_rhs_code (stmt); - switch (gimple_assign_rhs_class (stmt)) + if (gphi *phi = dyn_cast<gphi *> (stmt)) { - case GIMPLE_SINGLE_RHS: - if (is_gimple_ip_invariant (rhs1)) - { - agg_value->pass_through.operand = rhs1; - return; - } - code = NOP_EXPR; - break; + /* Also special case like the following (a is a formal parameter): + + _12 = *a_11(D).dim[0].stride; + ... + # iftmp.22_9 = PHI <_12(2), 1(3)> + ... + parm.6.dim[0].stride = iftmp.22_9; + ... + __x_MOD_foo (&parm.6, b_31(D)); - case GIMPLE_UNARY_RHS: - /* NOTE: A GIMPLE_UNARY_RHS operation might not be tcc_unary - (truth_not_expr is example), GIMPLE_BINARY_RHS does not imply - tcc_binary, this subtleness is somewhat misleading. + The aggregate function describing parm.6.dim[0].stride is encoded as a + PASS-THROUGH jump function with ASSERT_EXPR operation whith operand 1 + (the constant from the PHI node). */ - Since tcc_unary is widely used in IPA-CP code to check an operation - with one operand, here we only allow tc_unary operation to avoid - possible problem. Then we can use (opclass == tc_unary) or not to - distinguish unary and binary. */ - if (TREE_CODE_CLASS (code) != tcc_unary || CONVERT_EXPR_CODE_P (code)) + if (gimple_phi_num_args (phi) != 2) + return; + tree arg0 = gimple_phi_arg_def (phi, 0); + tree arg1 = gimple_phi_arg_def (phi, 1); + tree operand; + + if (is_gimple_ip_invariant (arg1)) + { + operand = arg1; + rhs1 = arg0; + } + else if (is_gimple_ip_invariant (arg0)) + { + operand = arg0; + rhs1 = arg1; + } + else return; rhs1 = get_ssa_def_if_simple_copy (rhs1, &stmt); - break; + if (!is_gimple_assign (stmt)) + return; - case GIMPLE_BINARY_RHS: - { - gimple *rhs1_stmt = stmt; - gimple *rhs2_stmt = stmt; - tree rhs2 = gimple_assign_rhs2 (stmt); + code = ASSERT_EXPR; + agg_value->pass_through.operand = operand; + } + else if (is_gimple_assign (stmt)) + { + code = gimple_assign_rhs_code (stmt); + switch (gimple_assign_rhs_class (stmt)) + { + case GIMPLE_SINGLE_RHS: + if (is_gimple_ip_invariant (rhs1)) + { + agg_value->pass_through.operand = rhs1; + return; + } + code = NOP_EXPR; + break; - rhs1 = get_ssa_def_if_simple_copy (rhs1, &rhs1_stmt); - rhs2 = get_ssa_def_if_simple_copy (rhs2, &rhs2_stmt); + case GIMPLE_UNARY_RHS: + /* NOTE: A GIMPLE_UNARY_RHS operation might not be tcc_unary + (truth_not_expr is example), GIMPLE_BINARY_RHS does not imply + tcc_binary, this subtleness is somewhat misleading. + + Since tcc_unary is widely used in IPA-CP code to check an operation + with one operand, here we only allow tc_unary operation to avoid + possible problem. Then we can use (opclass == tc_unary) or not to + distinguish unary and binary. */ + if (TREE_CODE_CLASS (code) != tcc_unary || CONVERT_EXPR_CODE_P (code)) + return; - if (is_gimple_ip_invariant (rhs2)) - { - agg_value->pass_through.operand = rhs2; - stmt = rhs1_stmt; - } - else if (is_gimple_ip_invariant (rhs1)) + rhs1 = get_ssa_def_if_simple_copy (rhs1, &stmt); + break; + + case GIMPLE_BINARY_RHS: { - if (TREE_CODE_CLASS (code) == tcc_comparison) - code = swap_tree_comparison (code); - else if (!commutative_tree_code (code)) + gimple *rhs1_stmt = stmt; + gimple *rhs2_stmt = stmt; + tree rhs2 = gimple_assign_rhs2 (stmt); + + rhs1 = get_ssa_def_if_simple_copy (rhs1, &rhs1_stmt); + rhs2 = get_ssa_def_if_simple_copy (rhs2, &rhs2_stmt); + + if (is_gimple_ip_invariant (rhs2)) + { + agg_value->pass_through.operand = rhs2; + stmt = rhs1_stmt; + } + else if (is_gimple_ip_invariant (rhs1)) + { + if (TREE_CODE_CLASS (code) == tcc_comparison) + code = swap_tree_comparison (code); + else if (!commutative_tree_code (code)) + return; + + agg_value->pass_through.operand = rhs1; + stmt = rhs2_stmt; + rhs1 = rhs2; + } + else return; - agg_value->pass_through.operand = rhs1; - stmt = rhs2_stmt; - rhs1 = rhs2; + if (TREE_CODE_CLASS (code) != tcc_comparison + && !useless_type_conversion_p (TREE_TYPE (lhs), + TREE_TYPE (rhs1))) + return; } - else - return; + break; - if (TREE_CODE_CLASS (code) != tcc_comparison - && !useless_type_conversion_p (TREE_TYPE (lhs), TREE_TYPE (rhs1))) + default: return; - } - break; - - default: - return; - } + } + } + else + return; if (TREE_CODE (rhs1) != SSA_NAME) index = load_from_unmodified_param_or_agg (fbi, fbi->info, stmt, diff --git a/gcc/ipa-prop.h b/gcc/ipa-prop.h index 56e8055..112a1ba 100644 --- a/gcc/ipa-prop.h +++ b/gcc/ipa-prop.h @@ -94,9 +94,14 @@ struct GTY(()) ipa_pass_through_data /* Number of the caller's formal parameter being passed. */ int formal_id; /* Operation that is performed on the argument before it is passed on. - NOP_EXPR means no operation. Otherwise oper must be a simple binary - arithmetic operation where the caller's parameter is the first operand and - operand field from this structure is the second one. */ + Special values which have other meaning than in normal contexts: + - NOP_EXPR means no operation, not even type conversion. + - ASSERT_EXPR means that only the value in operand is allowed to pass + through (without any change), for all other values the result is + unknown. + Otherwise operation must be a simple binary or unary arithmetic operation + where the caller's parameter is the first operand and (for binary + operations) the operand field from this structure is the second one. */ enum tree_code operation; /* When the passed value is a pointer, it is set to true only when we are certain that no write to the object it points to has occurred since the diff --git a/gcc/testsuite/gfortran.dg/ipcp-array-2.f90 b/gcc/testsuite/gfortran.dg/ipcp-array-2.f90 new file mode 100644 index 0000000..9af8fff --- /dev/null +++ b/gcc/testsuite/gfortran.dg/ipcp-array-2.f90 @@ -0,0 +1,45 @@ +! { dg-do compile } +! { dg-options "-O3 -fno-inline -fwhole-program -fdump-ipa-cp-details -fdump-tree-lversion-details" } + +module x + implicit none +contains + subroutine foo(a, b) + real :: a(:,:) + real :: b + integer :: i,j + b = 0. + do j=1,size(a,2) + do i=1,size(a,1) + b = b + a(i,j) * i * j + end do + end do + end subroutine foo + + subroutine bar(a, b) + real :: a(:,:) + real :: b + call foo (a,b) + end subroutine bar + +end module x + +program main + use x + implicit none + integer :: n, m + real, dimension(4,3) :: a + real, dimension(3,4) :: c + real :: b + call random_number(a) + call bar(a,b) + print *,b + + call random_number(c) + call bar(c,b) + print *,b + +end program main + +! { dg-final { scan-ipa-dump "op assert_expr 1" "cp" } } +! { dg-final { scan-tree-dump-not "versioned this loop for when certain strides are 1" "lversion" } } |