aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/ipa-cp.c48
-rw-r--r--gcc/ipa-prop.c148
-rw-r--r--gcc/ipa-prop.h11
-rw-r--r--gcc/testsuite/gfortran.dg/ipcp-array-2.f9045
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" } }