}
}
+/* 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
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)
}
}
-/* 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
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,
/* 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